Skip to content

Commit

Permalink
xkbcommon: Switch to MesonToolchain to allow cross-compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
jwillikers committed Sep 3, 2022
1 parent 176de39 commit d5c61fa
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 71 deletions.
132 changes: 72 additions & 60 deletions recipes/xkbcommon/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import os

from conan import ConanFile
from conan.tools import scm, files
from conan.tools.files import copy, get, replace_in_file, rmdir
from conan.tools.layout import basic_layout
from conan.tools.meson import Meson, MesonToolchain
from conan.tools.scm import Version
from conan.errors import ConanInvalidConfiguration
from conans import Meson, tools

required_conan_version = ">=1.50.0"

Expand Down Expand Up @@ -30,20 +34,11 @@ class XkbcommonConan(ConanFile):
"xkbregistry": True,
}

generators = "pkg_config"
_meson = None

@property
def _source_subfolder(self):
return "source_subfolder"

@property
def _build_subfolder(self):
return "build_subfolder"
generators = "PkgConfigDeps", "VirtualBuildEnv", "VirtualRunEnv"

@property
def _has_xkbregistry_option(self):
return scm.Version(self.version) >= "1.0.0"
return Version(self.version) >= "1.0.0"

def config_options(self):
if not self._has_xkbregistry_option:
Expand All @@ -70,80 +65,97 @@ def validate(self):
raise ConanInvalidConfiguration("This library is only compatible with Linux or FreeBSD")

def build_requirements(self):
self.build_requires("meson/0.63.1")
self.build_requires("bison/3.7.6")
if hasattr(self, "settings_build") and self.options.get_safe("wayland"):
self.build_requires("wayland/1.21.0")
self.tool_requires("meson/0.63.0")
self.tool_requires("bison/3.7.6")
self.tool_requires("pkgconf/1.7.4")
if self.options.get_safe("with_wayland"):
self.tool_requires("wayland/1.21.0")

def layout(self):
basic_layout(self, src_folder="src")

def source(self):
files.get(self, **self.conan_data["sources"][self.version], strip_root=True, destination=self._source_subfolder)
get(self, **self.conan_data["sources"][self.version], strip_root=True)

# Conan doesn't provide a `wayland-scanner.pc` file for the package in the _build_ context
files.replace_in_file(self, f"{self._source_subfolder}/meson.build",
"wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true)",
"# wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true)")

files.replace_in_file(self, f"{self._source_subfolder}/meson.build",
"if not wayland_client_dep.found() or not wayland_protocols_dep.found() or not wayland_scanner_dep.found()",
"if not wayland_client_dep.found() or not wayland_protocols_dep.found()")

files.replace_in_file(self, f"{self._source_subfolder}/meson.build",
"wayland_scanner = find_program(wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner'))",
"wayland_scanner = find_program('wayland-scanner')")

def _configure_meson(self):
if self._meson:
return self._meson
defs={
"enable-wayland": self.options.get_safe("with_wayland", False),
"enable-docs": False,
"enable-x11": self.options.with_x11,
"libdir": f"{self.package_folder}/lib",
"default_library": ("shared" if self.options.shared else "static")}
if self._has_xkbregistry_option:
defs["enable-xkbregistry"] = self.options.xkbregistry
def generate(self):
tc = MesonToolchain(self)

tc.project_options["libexecdir"] = "bin"
tc.project_options["libdir"] = "lib"
tc.project_options["datadir"] = "res"
tc.project_options["mandir"] = "res/man"

self._meson = Meson(self)
self._meson.configure(
defs=defs,
source_folder=self._source_subfolder,
build_folder=self._build_subfolder,
pkg_config_paths=self.build_folder)
return self._meson
tc.project_options["enable-docs"] = False
tc.project_options["enable-wayland"] = self.options.get_safe("with_wayland", False)
tc.project_options["enable-x11"] = self.options.with_x11

if self._has_xkbregistry_option:
tc.project_options["enable-xkbregistry"] = self.options.xkbregistry
tc.generate()

def build(self):
with tools.run_environment(self):
meson = self._configure_meson()
meson.build()
# Conan doesn't provide a `wayland-scanner.pc` file for the package in the _build_ context
meson_build_file = os.path.join(self.source_folder, "meson.build")
replace_in_file(self, meson_build_file,
"wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true)",
"# wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true)")

replace_in_file(self, meson_build_file,
"if not wayland_client_dep.found() or not wayland_protocols_dep.found() or not wayland_scanner_dep.found()",
"if not wayland_client_dep.found() or not wayland_protocols_dep.found()")

replace_in_file(self, meson_build_file,
"wayland_scanner = find_program(wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner'))",
"wayland_scanner = find_program('wayland-scanner')")

meson = Meson(self)
meson.configure()
meson.build()

def package(self):
self.copy(pattern="LICENSE", dst="licenses", src=self._source_subfolder)
meson = self._configure_meson()
copy(self, "LICENSE", self.source_folder, os.path.join(self.package_folder, "licenses"))
meson = Meson(self)
meson.install()
files.rmdir(self, f"{self.package_folder}/lib/pkgconfig")
files.rmdir(self, f"{self.package_folder}/share")
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))

def package_info(self):
self.cpp_info.components["libxkbcommon"].set_property("pkg_config_name", "xkbcommon")
self.cpp_info.components["libxkbcommon"].libs = ["xkbcommon"]
self.cpp_info.components["libxkbcommon"].requires = ["xorg::xkeyboard-config"]
self.cpp_info.components["libxkbcommon"].resdirs = ["res"]

# todo Remove in Conan version 1.50.0 where these are set by default for the PkgConfigDeps generator.
self.cpp_info.components["libxkbcommon"].includedirs = ["include"]
self.cpp_info.components["libxkbcommon"].libdirs = ["lib"]

if self.options.with_x11:
self.cpp_info.components["libxkbcommon-x11"].set_property("pkg_config_name", "xkbcommon-x11")
self.cpp_info.components["libxkbcommon-x11"].libs = ["xkbcommon-x11"]
self.cpp_info.components["libxkbcommon-x11"].requires = ["libxkbcommon", "xorg::xcb", "xorg::xcb-xkb"]

# todo Remove in Conan version 1.50.0 where these are set by default for the PkgConfigDeps generator.
self.cpp_info.components["libxkbcommon-x11"].includedirs = ["include"]
self.cpp_info.components["libxkbcommon-x11"].libdirs = ["lib"]
if self.options.get_safe("xkbregistry"):
self.cpp_info.components["libxkbregistry"].set_property("pkg_config_name", "xkbregistry")
self.cpp_info.components["libxkbregistry"].libs = ["xkbregistry"]
self.cpp_info.components["libxkbregistry"].requires = ["libxml2::libxml2"]

# todo Remove in Conan version 1.50.0 where these are set by default for the PkgConfigDeps generator.
self.cpp_info.components["libxkbregistry"].includedirs = ["include"]
self.cpp_info.components["libxkbregistry"].libdirs = ["lib"]
if self.options.get_safe("with_wayland", False):
# FIXME: This generates just executable, but I need to use the requirements to pass Conan checks
self.cpp_info.components["xkbcli-interactive-wayland"].libs = []
self.cpp_info.components["xkbcli-interactive-wayland"].includedirs = []
self.cpp_info.components["xkbcli-interactive-wayland"].requires = ["wayland::wayland", "wayland-protocols::wayland-protocols"]

if scm.Version(self.version) >= "1.0.0":
bin_path = f"{self.package_folder}/bin"
self.output.info(f"Appending PATH environment variable: {bin_path}")
self.env_info.PATH.append(bin_path)
if Version(self.version) >= "1.0.0":
bindir = os.path.join(self.package_folder, "bin")
self.buildenv_info.prepend_path("PATH", bindir)
self.runenv_info.prepend_path("PATH", bindir)
self.output.info(f"Appending PATH environment variable: {bindir}")
self.env_info.PATH.append(bindir)

# unofficial, but required to avoid side effects (libxkbcommon component
# "steals" the default global pkg_config name)
Expand Down
11 changes: 5 additions & 6 deletions recipes/xkbcommon/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(test_package)
cmake_minimum_required(VERSION 3.15)
project(test_package LANGUAGES CXX)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
find_package(xkbcommon REQUIRED COMPONENTS libxkbcommon)

add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
add_executable(test_package test_package.cpp)
target_link_libraries(test_package PRIVATE xkbcommon::libxkbcommon)
20 changes: 15 additions & 5 deletions recipes/xkbcommon/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
from conans import ConanFile, CMake, tools
import os

from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import CMake
from conan.tools.layout import cmake_layout


class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake"
generators = "CMakeToolchain", "CMakeDeps", "VirtualBuildEnv", "VirtualRunEnv"

def requirements(self):
self.requires(self.tested_reference_str)

def layout(self):
cmake_layout(self)

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if not tools.cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)
if can_run(self):
cmd = os.path.join(self.cpp.build.bindirs[0], "test_package")
self.run(cmd, env="conanrun")
8 changes: 8 additions & 0 deletions recipes/xkbcommon/all/test_v1_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.1)
project(test_package)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
19 changes: 19 additions & 0 deletions recipes/xkbcommon/all/test_v1_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os

from conans import ConanFile, CMake
from conan.tools.build import cross_building


class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake"

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if not cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)

0 comments on commit d5c61fa

Please sign in to comment.