Skip to content

Commit

Permalink
(#13427) [cairo] update toolchain
Browse files Browse the repository at this point in the history
* [cairo] update toolchain

* [cairo] update test packages

* [cairo] fix license copy

* [cairo] bump versions

* [cairo] add apple system libs (see comment)

* [cairo] improve apple system libs handling

* [cairo] add dependency on CoreGraphics for apple

* [cairo] address review comments

* [cairo] document patches
  • Loading branch information
planetmarshall authored Oct 28, 2022
1 parent d6542dc commit 7b03f3d
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 118 deletions.
27 changes: 22 additions & 5 deletions recipes/cairo/meson/conandata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,29 @@ sources:
patches:
"1.17.4":
- patch_file: "patches/binutils-2.34-libbfd-fix.patch"
base_path: "source_subfolder/util/cairo-trace"
patch_type: "backport"
patch_description: "fix build with newer versions of bfd"
patch_source: "https://gitlab.freedesktop.org/cairo/cairo/-/commit/e30259f6237571c61992433c110bc6e1ef900244"
base_path: "util/cairo-trace"

- patch_file: "patches/cairo-1.17.4-trace-cflags-fix.patch"
base_path: "source_subfolder/util/cairo-trace"
patch_type: "conan"
patch_description: |
Add missing 'PACKAGE' and 'PACKAGE_VERSION' defines for libbfd headers included by 'lookup-symbol.c'.
base_path: "util/cairo-trace"

- patch_file: "patches/cairo-1.17.4-xlib-xrender-option.patch"
base_path: "source_subfolder"
patch_type: "conan"
patch_description: >-
This patch adds option to enable or disable xlib-xrender component.
Without it 'xrender' is always required when 'xlib' option is enabled. @sh0
- patch_file: "patches/cairo-1.17.4-symbol-lookup-backport.patch"
base_path: "source_subfolder"
patch_type: "backport"
patch_description: "add symbol-lookup option to allow disabling bfd/libiberty usage"
patch_source: "https://gitlab.freedesktop.org/cairo/cairo/-/commit/e0cf7b869fb1c6b73cf4a9aad2fc8aea4ff1f6ee"

- patch_file: "patches/cairo-1.17.4-encoding-backport.patch"
base_path: "source_subfolder"
patch_type: "backport"
patch_description: "use encoding=utf-8 when reading/writing files in helper script"
patch_source: "https://gitlab.freedesktop.org/cairo/cairo/-/commit/9732f4e80f906fab85b97ae55ee44bfd3ee4945e"
203 changes: 100 additions & 103 deletions recipes/cairo/meson/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import contextlib
import glob
import os

from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools import files, microsoft
from conans import tools, Meson, VisualStudioBuildEnvironment

required_conan_version = ">=1.50.0"
from conan.tools.apple import is_apple_os
from conan.tools.env import VirtualBuildEnv
from conan.tools.files import (
apply_conandata_patches,
copy,
export_conandata_patches,
get,
rename,
replace_in_file,
rm,
rmdir)
from conan.tools.gnu import PkgConfigDeps
from conan.tools.layout import basic_layout
from conan.tools.meson import MesonToolchain, Meson
from conan.tools.microsoft import is_msvc, is_msvc_static_runtime
from conan.tools.scm import Version

required_conan_version = ">=1.52.0"


class CairoConan(ConanFile):
Expand Down Expand Up @@ -50,26 +63,17 @@ class CairoConan(ConanFile):
"with_symbol_lookup": False,
"tee": True,
}

generators = "pkg_config"

_meson = None

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

@property
def _build_subfolder(self):
return "build_subfolder"
short_paths = True

@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)

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

def export_sources(self):
for patch in self.conan_data.get("patches", {}).get(self.version, []):
self.copy(patch["patch_file"])
export_conandata_patches(self)

def config_options(self):
del self.settings.compiler.libcxx
Expand All @@ -95,19 +99,19 @@ def configure(self):
def requirements(self):
self.requires("pixman/0.40.0")
if self.options.with_zlib and self.options.with_png:
self.requires("expat/2.4.8")
self.requires("expat/2.4.9")
if self.options.with_lzo:
self.requires("lzo/2.10")
if self.options.with_zlib:
self.requires("zlib/1.2.12")
self.requires("zlib/1.2.13")
if self.options.with_freetype:
self.requires("freetype/2.12.1")
if self.options.with_fontconfig:
self.requires("fontconfig/2.13.93")
if self.options.with_png:
self.requires("libpng/1.6.37")
self.requires("libpng/1.6.38")
if self.options.with_glib:
self.requires("glib/2.73.3")
self.requires("glib/2.74.0")
if self.settings.os == "Linux":
if self.options.with_xlib or self.options.with_xlib_xrender or self.options.with_xcb:
self.requires("xorg/system")
Expand All @@ -121,15 +125,15 @@ def requirements(self):
self.requires("egl/system")

def build_requirements(self):
self.tool_requires("meson/0.63.1")
self.tool_requires("pkgconf/1.7.4")
self.tool_requires("meson/0.63.3")
self.tool_requires("pkgconf/1.9.3")

def validate(self):
if self.options.get_safe("with_xlib_xrender") and not self.options.get_safe("with_xlib"):
raise ConanInvalidConfiguration("'with_xlib_xrender' option requires 'with_xlib' option to be enabled as well!")
if self.options.with_glib:
if self.options["glib"].shared:
if microsoft.is_msvc_static_runtime(self):
if is_msvc_static_runtime(self):
raise ConanInvalidConfiguration(
"Linking shared glib with the MSVC static runtime is not supported"
)
Expand All @@ -138,100 +142,93 @@ def validate(self):
"Linking a shared library against static glib can cause unexpected behaviour."
)

@contextlib.contextmanager
def _build_context(self):
if microsoft.is_msvc(self):
env_build = VisualStudioBuildEnvironment(self)
if not self.options.shared:
env_build.flags.append("-DCAIRO_WIN32_STATIC_BUILD")
env_build.cxx_flags.append("-DCAIRO_WIN32_STATIC_BUILD")
with tools.environment_append(env_build.vars):
yield
else:
yield

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

def _configure_meson(self):
def boolean(value):
def generate(self):
def is_enabled(value):
return "enabled" if value else "disabled"

meson = Meson(self)
pkg_deps = PkgConfigDeps(self)
pkg_deps.generate()

defs = dict()
defs["tests"] = "disabled"
defs["zlib"] = boolean(self.options.with_zlib)
defs["png"] = boolean(self.options.with_png)
defs["freetype"] = boolean(self.options.with_freetype)
defs["fontconfig"] = boolean(self.options.with_fontconfig)
options = dict()
options["tests"] = "disabled"
options["zlib"] = is_enabled(self.options.with_zlib)
options["png"] = is_enabled(self.options.with_png)
options["freetype"] = is_enabled(self.options.with_freetype)
options["fontconfig"] = is_enabled(self.options.with_fontconfig)
if self.settings.os == "Linux":
defs["xcb"] = boolean(self.options.get_safe("with_xcb"))
defs["xlib"] = boolean(self.options.get_safe("with_xlib"))
defs["xlib-xrender"] = boolean(self.options.get_safe("with_xlib_xrender"))
options["xcb"] = is_enabled(self.options.with_xcb)
options["xlib"] = is_enabled(self.options.with_xlib)
options["xlib-xrender"] = is_enabled(self.options.with_xlib_xrender)
else:
defs["xcb"] = "disabled"
defs["xlib"] = "disabled"
options["xcb"] = "disabled"
options["xlib"] = "disabled"
if self.options.get_safe("with_opengl") == "desktop":
defs["gl-backend"] = "gl"
options["gl-backend"] = "gl"
elif self.options.get_safe("with_opengl") == "gles2":
defs["gl-backend"] = "glesv2"
options["gl-backend"] = "glesv2"
elif self.options.get_safe("with_opengl") == "gles3":
defs["gl-backend"] = "glesv3"
options["gl-backend"] = "glesv3"
else:
defs["gl-backend"] = "disabled"
defs["glesv2"] = boolean(self.options.get_safe("with_opengl") == "gles2")
defs["glesv3"] = boolean(self.options.get_safe("with_opengl") == "gles3")
defs["tee"] = boolean(self.options.tee)
defs["symbol-lookup"] = boolean(self.options.get_safe("with_symbol_lookup"))
options["gl-backend"] = "disabled"
options["glesv2"] = is_enabled(self.options.get_safe("with_opengl") == "gles2")
options["glesv3"] = is_enabled(self.options.get_safe("with_opengl") == "gles3")
options["tee"] = is_enabled(self.options.tee)
options["symbol-lookup"] = is_enabled(self.options.get_safe("with_symbol_lookup"))

# future options to add, see meson_options.txt.
# for now, disabling explicitly, to avoid non-reproducible auto-detection of system libs
defs["cogl"] = "disabled" # https://gitlab.gnome.org/GNOME/cogl
defs["directfb"] = "disabled"
defs["drm"] = "disabled" # not yet compilable in cairo 1.17.4
defs["openvg"] = "disabled" # https://www.khronos.org/openvg/
defs["qt"] = "disabled" # not yet compilable in cairo 1.17.4
defs["gtk2-utils"] = "disabled"
defs["spectre"] = "disabled" # https://www.freedesktop.org/wiki/Software/libspectre/

meson.configure(
source_folder=self._source_subfolder,
args=["--wrap-mode=nofallback"],
build_folder=self._build_subfolder,
defs=defs,
)
return meson
options["cogl"] = "disabled" # https://gitlab.gnome.org/GNOME/cogl
options["directfb"] = "disabled"
options["drm"] = "disabled" # not yet compilable in cairo 1.17.4
options["openvg"] = "disabled" # https://www.khronos.org/openvg/
options["qt"] = "disabled" # not yet compilable in cairo 1.17.4
options["gtk2-utils"] = "disabled"
options["spectre"] = "disabled" # https://www.freedesktop.org/wiki/Software/libspectre/

meson = MesonToolchain(self)
meson.project_options.update(options)

if is_apple_os(self) and Version(self.version) < "1.17.6":
# This was fixed in the meson build from 1.17.6
meson.c_link_args += ["-framework", "ApplicationServices", "-framework", "CoreFoundation"]

if not self.options.shared:
meson.c_args.append("-DCAIRO_WIN32_STATIC_BUILD")

meson.generate()

env = VirtualBuildEnv(self)
env.generate()

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

def build(self):
files.apply_conandata_patches(self)
apply_conandata_patches(self)

# Dependency freetype2 found: NO found 2.11.0 but need: '>= 9.7.3'
if self.options.with_freetype:
files.replace_in_file(self, "freetype2.pc",
f"Version: {self.deps_cpp_info['freetype'].version}",
"Version: 9.7.3")
with self._build_context():
meson = self._configure_meson()
meson.build()

def _fix_library_names(self):
if microsoft.is_msvc(self):
with tools.chdir(os.path.join(self.package_folder, "lib")):
for filename_old in glob.glob("*.a"):
filename_new = filename_old[3:-2] + ".lib"
self.output.info("rename %s into %s" % (filename_old, filename_new))
files.rename(self, filename_old, filename_new)
replace_in_file(self, os.path.join(self.source_folder, "meson.build"),
"freetype_required_version = '>= 9.7.3'",
f"freetype_required_version = '>= {self.deps_cpp_info['freetype'].version}'")
meson = Meson(self)
meson.configure()
meson.build()

def _fix_library_names(self, path):
if is_msvc(self):
for filename_old in glob.glob(os.path.join(path, "*.a")):
root, _ = os.path.splitext(filename_old)
folder, basename = os.path.split(root)
rename(self, filename_old, os.path.join(folder, basename.replace("lib", "") + ".lib"))

def package(self):
self.copy(pattern="LICENSE", dst="licenses", src=self._source_subfolder)
self.copy("COPYING*", src=self._source_subfolder, dst="licenses", keep_path=False)
with self._build_context():
meson = self._configure_meson()
meson.install()
self._fix_library_names()
files.rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
files.rm(self, "*.pdb", os.path.join(self.package_folder, "bin"))
meson = Meson(self)
meson.install()
self._fix_library_names(os.path.join(self.package_folder, "lib"))
copy(self, "COPYING*", self.source_folder, os.path.join(self.package_folder, "licenses"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rm(self, "*.pdb", os.path.join(self.package_folder, "bin"))

def package_info(self):
base_requirements = {"pixman::pixman"}
Expand Down Expand Up @@ -290,7 +287,7 @@ def add_component_and_base_requirements(component, requirements, system_libs=Non
if self.options.get_safe("with_xlib"):
add_component_and_base_requirements("cairo-xlib-xcb", ["xorg::x11-xcb"])

if tools.is_apple_os(self.settings.os):
if is_apple_os(self):
self.cpp_info.components["cairo-quartz"].set_property("pkg_config_name", "cairo-quartz")
self.cpp_info.components["cairo-quartz"].names["pkg_config"] = "cairo-quartz"
self.cpp_info.components["cairo-quartz"].requires = ["cairo_"]
Expand All @@ -303,7 +300,7 @@ def add_component_and_base_requirements(component, requirements, system_libs=Non
self.cpp_info.components["cairo-quartz-font"].names["pkg_config"] = "cairo-quartz-font"
self.cpp_info.components["cairo-quartz-font"].requires = ["cairo_"]

self.cpp_info.components["cairo_"].frameworks.append("CoreGraphics")
self.cpp_info.components["cairo_"].frameworks += ["ApplicationServices", "CoreFoundation", "CoreGraphics"]

if self.settings.os == "Windows":
self.cpp_info.components["cairo-win32"].set_property("pkg_config_name", "cairo-win32")
Expand Down
5 changes: 1 addition & 4 deletions recipes/cairo/meson/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
cmake_minimum_required(VERSION 3.1.2)
project(test_package C)

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

find_package(cairo CONFIG REQUIRED)

add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} cairo::cairo)
target_link_libraries(${PROJECT_NAME} PRIVATE cairo::cairo)
20 changes: 14 additions & 6 deletions recipes/cairo/meson/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
from conans import ConanFile, CMake, tools
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
from conan.tools.build import can_run
import os


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

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, skip_x64_x86=True):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)

if can_run(self):
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
self.run(bin_path, env="conanrun")
8 changes: 8 additions & 0 deletions recipes/cairo/meson/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.2)
project(test_package C)

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

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/
${CMAKE_CURRENT_BINARY_DIR}/test_package/)
Loading

0 comments on commit 7b03f3d

Please sign in to comment.