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 Jul 14, 2022
1 parent a583276 commit 038ec72
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 78 deletions.
140 changes: 72 additions & 68 deletions recipes/xkbcommon/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from conans import ConanFile, Meson, tools
from conans.errors import ConanInvalidConfiguration
import os

required_conan_version = ">=1.36.0"
from conan import ConanFile
from conan.tools.files import get, mkdir, rmdir, save
from conan.tools.gnu.pkgconfigdeps.pc_files_creator import get_pc_files_and_content
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

required_conan_version = ">=1.47.0"


class XkbcommonConan(ConanFile):
Expand All @@ -29,20 +35,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 tools.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 @@ -69,86 +66,93 @@ def validate(self):
raise ConanInvalidConfiguration("This library is only compatible with Linux or FreeBSD")

def build_requirements(self):
self.build_requires("meson/0.61.2")
self.build_requires("bison/3.7.6")
if hasattr(self, "settings_build") and self.options.get_safe("wayland"):
self.build_requires("wayland/1.20.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.20.0")

def layout(self):
basic_layout(self)

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

# Conan doesn't provide a `wayland-scanner.pc` file for the package in the _build_ context
tools.replace_in_file(os.path.join(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)")

tools.replace_in_file(os.path.join(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()")

tools.replace_in_file(os.path.join(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": os.path.join(self.package_folder, "lib"),
"default_library": ("shared" if self.options.shared else "static")}
get(self, **self.conan_data["sources"][self.version], strip_root=True)

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"

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

self.output.info("\n\nDependencies:")
for dependency, ref in self.dependencies.items():
self.output.info(f"{dependency}: {ref}")

# Generate PC files for the tool_requires wayland package to ensure wayland-scanner is found for the build machine.
if self.options.get_safe("with_wayland"):
native_generators_folder = os.path.join(self.generators_folder, "native")
mkdir(self, native_generators_folder)
for pc_name, pc_content in get_pc_files_and_content(self, self.dependencies.build.get("wayland")).items():
save(self, os.path.join(native_generators_folder, pc_name), pc_content)
tc.project_options["build.pkg_config_path"] = native_generators_folder

if self._has_xkbregistry_option:
defs["enable-xkbregistry"] = self.options.xkbregistry

# workaround for https://github.com/conan-io/conan-center-index/issues/3377
# FIXME: do not remove this pkg-config file once xorg recipe fixed
xeyboard_config_pkgfile = os.path.join(self.build_folder, "xkeyboard-config.pc")
if os.path.isfile(xeyboard_config_pkgfile):
os.remove(xeyboard_config_pkgfile)

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-xkbregistry"] = self.options.xkbregistry
tc.generate()

def build(self):
with tools.run_environment(self):
meson = self._configure_meson()
meson.build()
meson = Meson(self)
meson.configure()
meson.build()

def package(self):
self.copy(pattern="LICENSE", dst="licenses", src=self._source_subfolder)
meson = self._configure_meson()
self.copy(pattern="LICENSE", dst="licenses", src=self.source_folder)
meson = Meson(self)
meson.install()
tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig"))
tools.rmdir(os.path.join(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 tools.Version(self.version) >= "1.0.0":
bin_path = os.path.join(self.package_folder, "bin")
self.output.info("Appending PATH environment variable: {}".format(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)

# unofficial, but required to avoid side effects (libxkbcommon component
# "steals" the default global pkg_config name)
Expand Down
9 changes: 4 additions & 5 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)
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)
17 changes: 12 additions & 5 deletions recipes/xkbcommon/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
from conans import ConanFile, CMake, tools
import os

from conan import ConanFile
from conan.tools.build import cross_building
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 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 not cross_building(self):
cmd = os.path.join(self.cpp.build.bindirs[0], "test_package")
self.run(cmd, env="conanrun")

0 comments on commit 038ec72

Please sign in to comment.