infinipaint/conan/conan-skia/recipes/skia/all/conanfile.py
copilot 1c1d63f376
Some checks are pending
Windows Release / windows-x86_64 (push) Waiting to run
Ship 0.8 fog/freistellen and fix Windows CI for friends
Publish the portable zip to public Forgejo from the private GitHub
builder, and force Ninja so MSVC 195 deps build without CMake 4.2.
2026-10-25 18:07:47 +01:00

1065 lines
45 KiB
Python

from conan import ConanFile
from conan.tools.files import apply_conandata_patches, export_conandata_patches, get, copy, rename, mkdir, rmdir, save, replace_in_file
from conan.tools.build.flags import cppstd_flag
from conan.tools.build import check_min_cppstd
from conan.tools.microsoft import is_msvc
from conan.tools.microsoft.visual import msvc_runtime_flag
from conan.tools.apple import is_apple_os, XCRun
from conan.tools.gnu import AutotoolsToolchain
from conan.tools.env import VirtualBuildEnv
from conan.errors import ConanInvalidConfiguration
from os.path import join
import os
import re
import json
class ConanSkia(ConanFile):
name = "skia-infinipaint"
package_type = "library"
# Optional metadata
license = "<Put the package license here>"
author = "<Put your name here> <And your email here>"
url = "<Package recipe repository url here, for issues about the package>"
description = "<Description of skia package here>"
topics = ("<Put some tag here>", "<here>", "<and here>")
# Binary configuration
settings = "os", "compiler", "build_type", "arch"
_skia_options = {
# configurable dependencies
"use_expat" : [True, False],
"use_freetype" : [True, False],
"use_harfbuzz" : [True, False],
"use_icu" : [True, False],
"use_libjpeg_turbo_encode" : [True, False],
"use_libjpeg_turbo_decode" : [True, False],
"use_libpng_encode" : [True, False],
"use_libpng_decode" : [True, False],
"use_libwebp_encode" : [True, False],
"use_libwebp_decode" : [True, False],
"use_zlib" : [True, False],
# system library options
"use_system_expat" : [True, False],
"use_system_freetype": [True, False],
"use_system_harfbuzz" : [True, False],
"use_system_icu" :[True, False],
"use_system_libjpeg_turbo" : [True, False],
"use_system_libpng" : [True, False],
"use_system_libwebp" : [True, False],
"use_system_zlib" : [True, False],
# conan library options
"use_conan_expat" : [True, False],
"use_conan_freetype": [True, False],
"use_conan_fontconfig": [True, False],
"use_conan_harfbuzz" : [True, False],
"use_conan_icu" :[True, False],
"use_conan_libjpeg_turbo" : [True, False],
"use_conan_libpng" : [True, False],
"use_conan_libwebp" : [True, False],
"use_conan_zlib" : [True, False],
# backend options
"use_angle" : [True, False],
"use_gl" : [True, False],
"use_vulkan" : [True, False],
"use_metal" : [True, False],
"use_webgl" : [True, False],
"use_webgpu" : [True, False],
"use_dawn" : [True, False],
"use_direct3d" :[True, False],
"use_piex" : [True, False],
"use_wuffs" : [True, False],
"use_libavif" : [True, False],
"use_libjxl_decode" : [True, False],
"use_ndk_images" : [True, False],
"use_x11" : [True, False],
"use_xps" : [True, False],
"use_dng_sdk" : [True, False],
"use_fontconfig" : [True, False],
"use_fonthost_mac" : [True, False],
"use_perfetto" : [True, False],
"use_egl": [True, False],
# backend toggles
"enable_ganesh" : [True, False],
"enable_graphite" : [True, False],
"enable_pdf" : [True, False],
"enable_winuwp" : [True, False],
"enable_fontmgr_android" : [True, False],
"enable_fontmgr_custom_directory" : [True, False],
"enable_fontmgr_custom_embedded" : [True, False],
"enable_fontmgr_custom_empty" : [True, False],
"enable_fontmgr_fontconfig" : [True, False],
"enable_fontmgr_win" : [True, False],
"enable_fontmgr_win_gdi" : [True, False],
"enable_fontmgr_FontConfigInterface" : [True, False],
# modules
"enable_svg" : [True, False],
"enable_skottie" : [True, False],
"enable_skunicode" : [True, False],
"enable_skshaper" : [True, False],
"enable_bentleyottmann" : [True, False],
"enable_skparagraph" : [True, False],
# canvaskit
"canvaskit_enable_alias_font" : [True, False],
"canvaskit_enable_canvas_bindings" : [True, False],
"canvaskit_enable_effects_deserialization" : [True, False],
"canvaskit_enable_embedded_font" : [True, False],
"canvaskit_enable_font" : [True, False],
"canvaskit_enable_matrix_helper" : [True, False],
"canvaskit_enable_pathops" : [True, False],
"canvaskit_enable_rt_shader" : [True, False],
"canvaskit_enable_skp_serialization" : [True, False],
"canvaskit_enable_sksl_trace" : [True, False],
"canvaskit_enable_paragraph" : [True, False],
"canvaskit_enable_webgpu" : [True, False],
"canvaskit_enable_webgl" : [True, False],
# other options
"enable_precompile" : [True, False],
"enable_optimize_size" : [True, False],
"enable_api_available_macro" : [True, False],
"gl_standard" : ["gl", "gles", "webgl", ""],
}
_skia_default_options = {
# configurable dependencies
"use_icu" : True,
"use_libjpeg_turbo_encode" : True,
"use_libjpeg_turbo_decode" : True,
"use_libpng_encode" : True,
"use_libpng_decode" : True,
"use_libwebp_encode" : True,
"use_libwebp_decode" : True,
"use_zlib" : True,
# system library options
"use_system_expat" : True,
"use_system_freetype": True,
"use_system_harfbuzz" : True,
"use_system_icu" : True,
"use_system_libjpeg_turbo" : True,
"use_system_libpng" : True,
"use_system_libwebp" : True,
"use_system_zlib" : True,
# conan library options
"use_conan_expat" : True,
"use_conan_freetype": True,
"use_conan_fontconfig": True,
"use_conan_harfbuzz" : True,
"use_conan_icu" : True,
"use_conan_libjpeg_turbo" : True,
"use_conan_libpng" : True,
"use_conan_libwebp" : True,
"use_conan_zlib" : True,
# backend options
"use_angle" : False,
"use_gl" : True,
"use_vulkan" : False,
"use_metal" : False,
"use_dawn" : False,
"use_direct3d" : False,
"use_xps" : True,
"use_wuffs" : True,
"use_libavif" : False,
"use_libjxl_decode" : False,
"use_egl": False,
# backend toggles
"enable_ganesh" : True,
"enable_graphite" : False,
"enable_winuwp" : False,
# modules
"enable_skshaper" : True,
"enable_bentleyottmann" : True,
# canvaskit
"canvaskit_enable_alias_font" : True,
"canvaskit_enable_canvas_bindings" : True,
"canvaskit_enable_effects_deserialization" : True,
"canvaskit_enable_embedded_font" : True,
"canvaskit_enable_font" : True,
"canvaskit_enable_matrix_helper" : True,
"canvaskit_enable_pathops" : True,
"canvaskit_enable_rt_shader" : True,
"canvaskit_enable_skp_serialization" : True,
"canvaskit_enable_sksl_trace" : True,
"canvaskit_enable_webgpu " : False,
"canvaskit_enable_webgl " : False,
# other options
"enable_precompile" : True,
"enable_optimize_size" : False,
"enable_api_available_macro" : True,
}
options = {
"shared" : [True, False],
"fPIC" : [True, False],
} | _skia_options
default_options = {
"shared": False,
"fPIC": True,
} | _skia_default_options
def _is_ios_variant(self):
os = self.settings.os
return (os == "iOS" or os == "watchOS" or os == "tvOS" or os == "visionOS")
def _is_ios_variant_simulator(self):
os = self.settings.os
if os == "iOS" and os.sdk == "iphonesimulator":
return True
elif os == "watchOS" and os.sdk == "watchsimulator":
return True
elif os == "tvOS" and os.sdk == "appletvsimulator":
return True
elif os == "visionOS" and os.sdk == "xrsimulator":
return True
return False
def config_options(self):
if self.settings.os == "Windows":
self.options.rm_safe("fPIC")
def validate(self):
if self.settings.compiler.cppstd:
check_min_cppstd(self, 17)
if self.settings.arch == "x86":
pass
elif self.settings.arch == "x86_64":
pass
elif self.settings.arch == "wasm":
pass
elif re.match(r'armv7.*', self.settings.arch.value):
pass
elif re.match(r'armv8.*', self.settings.arch.value):
pass
else:
raise ConanInvalidConfiguration("Unsupported settings.arch")
def configure(self):
os = self.settings.os
arch = self.settings.arch
if self.options.shared:
self.options.rm_safe("fPIC")
if self.options.use_harfbuzz == None:
# Disabled on Emscripten due to false-positive of HAVE_MPROTECT.
# Will revisit once 9.0.0 is added to conancenter.
enabled = (os != "Emscripten")
self.options.use_harfbuzz = enabled
if self.options.use_expat == None:
enabled = (arch != "wasm")
self.options.use_expat = enabled
if self.options.use_freetype == None:
enabled = (os == "Android" or os == "Linux" or arch == "wasm")
self.options.use_freetype = enabled
if self.options.use_webgl == None:
enabled = (arch == "wasm")
self.options.use_webgl = enabled
if self.options.use_webgpu == None:
enabled = (arch == "wasm")
self.options.use_webgpu = enabled
if self.options.use_x11 == None:
enabled = (os == "Linux")
self.options.use_x11 = enabled
if self.options.use_egl == None:
enabled = (os == "Linux")
self.options.use_egl = enabled
if self.options.use_fontconfig == None:
enabled = (os == "Linux")
self.options.use_fontconfig = enabled
if self.options.use_fonthost_mac == None:
enabled = (os == "Macos" or self._is_ios_variant())
self.options.use_fonthost_mac = enabled
if self.options.use_perfetto == None:
enabled = (os == "Macos" or os == "Android" or os == "Linux")
self.options.use_perfetto = enabled
if self.options.enable_pdf == None:
enabled = arch != "wasm"
self.options.enable_pdf = enabled
if self.options.enable_fontmgr_android == None:
enabled = self.options.use_freetype and self.options.use_expat
self.options.enable_fontmgr_android = enabled
if self.options.enable_fontmgr_custom_directory == None:
enabled = self.options.use_freetype
self.options.enable_fontmgr_custom_directory = enabled
if self.options.enable_fontmgr_custom_embedded == None:
enabled = self.options.use_freetype
self.options.enable_fontmgr_custom_embedded = enabled
if self.options.enable_fontmgr_custom_empty == None:
enabled = self.options.use_freetype
self.options.enable_fontmgr_custom_empty = enabled
if self.options.enable_fontmgr_fontconfig == None:
enabled = self.options.use_freetype and self.options.use_fontconfig
self.options.enable_fontmgr_fontconfig = enabled
if self.options.enable_fontmgr_win == None:
enabled = (os == "Windows")
self.options.enable_fontmgr_win = enabled
if self.options.enable_fontmgr_win_gdi == None:
enabled = (os == "Windows") and not self.options.enable_winuwp
self.options.enable_fontmgr_win_gdi = enabled
if self.options.enable_fontmgr_FontConfigInterface == None:
enabled = self.options.use_freetype and self.options.use_fontconfig
self.options.enable_fontmgr_FontConfigInterface = enabled
if self.options.use_piex == None:
enabled = os != "Windows" and arch != "wasm"
self.options.use_piex = enabled
if self.options.use_dng_sdk == None:
enabled = arch != "wasm" and self.options.use_libjpeg_turbo_decode and self.options.use_zlib
self.options.use_dng_sdk = enabled
if self.options.use_ndk_images == None:
enabled = os == "Android" and int(os.api_level.value) >= 30
self.options.use_ndk_images = enabled
if self.options.enable_svg == None:
enabled = not self.options.shared
self.options.enable_svg = enabled
if self.options.enable_skottie == None:
enabled = not self.options.shared
self.options.enable_skottie = enabled
if self.options.enable_skunicode == None:
enabled = self.options.use_icu
self.options.enable_skunicode = enabled
if self.options.enable_skparagraph == None:
enabled = self.options.enable_skshaper and self.options.enable_skunicode and self.options.use_harfbuzz
self.options.enable_skparagraph = enabled
if self.options.canvaskit_enable_paragraph == None:
enabled = self.options.enable_skparagraph
self.options.canvaskit_enable_paragraph = enabled
if self.options.gl_standard == None:
if os == "Macos":
self.options.gl_standard = "gl"
elif self._is_ios_variant():
self.options.gl_standard = "gles"
elif arch == "wasm":
self.options.gl_standard = "webgl"
else:
self.options.gl_standard = ""
# Remove unnecessary system library options.
if self.options.use_expat == False:
self.options.rm_safe("use_system_expat")
elif not self.options.use_system_expat:
self.options.rm_safe("use_conan_expat")
if self.options.use_freetype == False:
self.options.rm_safe("use_system_freetype")
elif not self.options.use_system_freetype:
self.options.rm_safe("use_conan_freetype")
if self.options.use_icu == False:
self.options.rm_safe("use_system_icu")
elif not self.options.use_system_icu:
self.options.rm_safe("use_conan_icu")
if self.options.use_harfbuzz == False:
self.options.rm_safe("use_system_harfbuzz")
elif not self.options.use_system_harfbuzz:
self.options.rm_safe("use_conan_harfbuzz")
if self.options.use_libjpeg_turbo_encode == False and self.options.use_libjpeg_turbo_decode == False:
self.options.rm_safe("use_system_libjpeg_turbo")
elif not self.options.use_system_libjpeg_turbo:
self.options.rm_safe("use_conan_libjpeg_turbo")
if self.options.use_libpng_encode == False and self.options.use_libpng_decode == False:
self.options.rm_safe("use_system_libpng")
elif not self.options.use_system_libpng:
self.options.rm_safe("use_conan_libpng")
if self.options.use_libwebp_encode == False and self.options.use_libwebp_decode == False:
self.options.rm_safe("use_system_libwebp")
elif not self.options.use_system_libwebp:
self.options.rm_safe("use_conan_libwebp")
if self.options.use_zlib == False:
self.options.rm_safe("use_system_zlib")
elif not self.options.use_system_zlib:
self.options.rm_safe("use_conan_zlib")
def export_sources(self):
export_conandata_patches(self)
def source(self):
get(self, **self.conan_data["sources"][self.version], destination=self.source_folder, strip_root=True)
apply_conandata_patches(self)
def requirements(self):
self.tool_requires("depot_tools/[>=20200407]")
self.tool_requires("ninja/[>=1.11.0]")
if self.options.use_harfbuzz and self.options.use_system_harfbuzz and self.options.use_conan_harfbuzz:
self.requires("harfbuzz/11.4.1", options = {"with_subset":True, "with_glib":False})
if self.options.use_freetype and self.options.use_system_freetype and self.options.use_conan_freetype:
self.requires("freetype/2.13.2")
if self.options.use_fontconfig and self.options.use_conan_fontconfig:
self.requires("fontconfig/[>=2.14.2]")
if self.options.use_expat and self.options.use_system_expat and self.options.use_conan_expat:
self.requires("expat/[>=2.5.0]")
if self.options.use_icu and self.options.use_system_icu and self.options.use_conan_icu:
self.requires("icu-infinipaint/77.1")
if (self.options.use_libpng_decode or self.options.use_libpng_encode) and self.options.use_system_libpng and self.options.use_conan_libpng:
self.requires("libpng/[>=1.6.32]")
if (self.options.use_libjpeg_turbo_decode or self.options.use_libjpeg_turbo_encode) and self.options.use_system_libjpeg_turbo and self.options.use_conan_libjpeg_turbo:
self.requires("libjpeg-turbo/[>=3.0.0]")
if (self.options.use_libwebp_decode or self.options.use_libwebp_encode) and self.options.use_system_libwebp and self.options.use_conan_libwebp:
self.requires("libwebp/[>=1.2.4]", options = {"swap_16bit_csp":True})
if self.options.use_zlib and self.options.use_system_zlib and self.options.use_conan_zlib:
self.requires("zlib/[>=1.2.11]")
def layout(self):
src_folder = "src"
build_folder = src_folder
generators_folder = self.folders.generators or "conan"
subproject = self.folders.subproject
self.folders.source = src_folder if not subproject else join(subproject, src_folder)
self.folders.build = build_folder if not subproject else join(subproject, build_folder)
self.folders.generators = join(self.folders.build, generators_folder)
def _get_lower_bool_str(self, cond):
return "true" if cond else "false"
def _collect_link_libs(self, dependency, components):
libs = []
libs += dependency.cpp_info.libs
libs += dependency.cpp_info.system_libs
# The order of components affects link order.
# TODO: Sould we handle inter-component dependencies?
for component in components:
libs += dependency.cpp_info.components[component].libs
libs += dependency.cpp_info.components[component].system_libs
for transitiveDependency in dependency.dependencies.host.values():
libs += transitiveDependency.cpp_info.libs
libs += transitiveDependency.cpp_info.system_libs
# TODO: Is there proper way to determine link order of those components?
for dep in transitiveDependency.cpp_info.components.values():
libs += dep.libs
libs += dep.system_libs
return libs
def _collect_link_frameworks(self, dependency, components):
frameworks = []
frameworks += dependency.cpp_info.frameworks
for component in components:
frameworks += dependency.cpp_info.components[component].frameworks
for transitiveDependency in dependency.dependencies.host.values():
frameworks += transitiveDependency.cpp_info.frameworks
for dep in transitiveDependency.cpp_info.components.values():
frameworks += dep.frameworks
return frameworks
def _link_libs(self, name, components=[]):
libs = []
libs += self._collect_link_libs(self.dependencies[name], components)
ext = ""
if self.settings.os == "Windows":
ext = ".lib"
return [lib + ext for lib in libs]
def _link_frameworks(self, name, components=[]):
frameworks = self._collect_link_frameworks(self.dependencies[name], components)
return [fw + ".framework" for fw in frameworks]
def build(self):
# Optional: reuse a finished out/conan from a prior local build
# (avoids re-hitting googlesource + full ninja). Path = .../out/conan
reuse_out = os.environ.get("SKIA_REUSE_OUT")
if reuse_out and os.path.isdir(reuse_out):
import shutil
dst = join(self.source_folder, "out", "conan")
os.makedirs(join(self.source_folder, "out"), exist_ok=True)
if os.path.isdir(dst):
shutil.rmtree(dst)
shutil.copytree(reuse_out, dst)
return
# activate-emsdk fails on Windows for some reason.
os.environ["GIT_SYNC_DEPS_SKIP_EMSDK"] = "1"
# Default git-sync-deps fans out one thread per dep and hits
# googlesource HTTP 429. Serialize + retry before syncing.
replace_in_file(
self,
join(self.source_folder, "tools", "git-sync-deps"),
"""def multithread(function, list_of_arg_lists):
anything_failed = False
threads = []
def hook(args):
nonlocal anything_failed
anything_failed = True
threading.excepthook = hook
for args in list_of_arg_lists:
thread = threading.Thread(None, function, None, args)
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
if anything_failed:
raise Exception("Thread failure detected")
""",
"""def multithread(function, list_of_arg_lists):
import time
for args in list_of_arg_lists:
last_err = None
for attempt in range(6):
try:
function(*args)
last_err = None
break
except Exception as e:
last_err = e
time.sleep(min(60, 2 ** attempt))
if last_err is not None:
raise last_err
""",
strict=True,
)
self.run("python3 tools/git-sync-deps")
del os.environ["GIT_SYNC_DEPS_SKIP_EMSDK"]
if self.options.use_expat and self.options.use_system_expat and self.options.use_conan_expat:
replace_in_file(self, join(self.source_folder, "third_party", "expat", "BUILD.gn"),
"libs = [ \"expat\" ]", f"libs = {json.dumps(self._link_libs('expat'))}",
strict=False)
if self.options.use_harfbuzz and self.options.use_system_harfbuzz and self.options.use_conan_harfbuzz:
replace_in_file(self, join(self.source_folder, "third_party", "harfbuzz", "BUILD.gn"),
"libs = [ \"harfbuzz\" ]",
f"libs = {json.dumps(self._link_libs('harfbuzz'))}\n " +
f"frameworks = {json.dumps(self._link_frameworks('harfbuzz'))}",
strict=False)
replace_in_file(self, join(self.source_folder, "third_party", "harfbuzz", "BUILD.gn"),
"include_dirs = [ \"/usr/include/harfbuzz\" ]", "include_dirs = [ ]",
strict=False)
replace_in_file(self, join(self.source_folder, "third_party", "harfbuzz", "BUILD.gn"),
"libs += [ \"harfbuzz-subset\" ]", "libs += [ ]",
strict=False)
if self.options.use_freetype and self.options.use_system_freetype and self.options.use_conan_freetype:
replace_in_file(self, join(self.source_folder, "third_party", "freetype2", "BUILD.gn"),
"libs = [ skia_system_freetype2_lib ]", f"libs = {json.dumps(self._link_libs('freetype'))}",
strict=False)
replace_in_file(self, join(self.source_folder, "third_party", "freetype2", "BUILD.gn"),
"include_dirs = [ skia_system_freetype2_include_path ]", "include_dirs = [ ]",
strict=False)
if self.options.use_icu and self.options.use_system_icu and self.options.use_conan_icu:
replace_in_file(self, join(self.source_folder, "third_party", "icu", "BUILD.gn"),
# icu-data must come after other components, otherwise it leaves an undefined symbol in shared library.
"libs = [ \"icuuc\" ]", f"libs = {json.dumps(self._link_libs('icu-infinipaint', components=['icu-uc']))}", # 'icu-data' removed
strict=False)
if (self.options.use_libjpeg_turbo_encode or self.options.use_libjpeg_turbo_decode) and self.options.use_system_libjpeg_turbo and self.options.use_conan_libjpeg_turbo:
replace_in_file(self, join(self.source_folder, "third_party", "libjpeg-turbo", "BUILD.gn"),
"libs = [ \"jpeg\" ]", f"libs = {json.dumps(self._link_libs('libjpeg-turbo', components=['jpeg']))}",
strict=False)
if (self.options.use_libpng_encode or self.options.use_libpng_decode) and self.options.use_system_libpng and self.options.use_conan_libpng:
replace_in_file(self, join(self.source_folder, "third_party", "libpng", "BUILD.gn"),
"libs = [ \"png\" ]", f"libs = {json.dumps(self._link_libs('libpng'))}",
strict=False)
if self.options.use_zlib and self.options.use_system_zlib and self.options.use_conan_zlib:
replace_in_file(self, join(self.source_folder, "third_party", "zlib", "BUILD.gn"),
"libs = [ \"z\" ]", f"libs = {json.dumps(self._link_libs('zlib'))}",
strict=False)
if (self.options.use_libwebp_decode or self.options.use_libwebp_encode) and self.options.use_system_libwebp and self.options.use_conan_libwebp:
replace_in_file(self, join(self.source_folder, "third_party", "libwebp", "BUILD.gn"),
" libs = [\n \"webp\",\n \"webpdemux\",\n \"webpmux\",\n ]",
f" libs = {json.dumps(self._link_libs('libwebp',components=['webp','webpmux','webpdemux','sharpyuv']))}",
strict=False)
if self._is_ios_variant():
if self.settings.arch == "armv8":
replace_in_file(self, join(self.source_folder, "gn", "skia", "BUILD.gn"),
"\"-arch\",\n \"arm64e\",",
"#\"-arch\",\n #\"arm64e\",",
strict=False)
elif self.settings.arch == "armv8.3":
replace_in_file(self, join(self.source_folder, "gn", "skia", "BUILD.gn"),
"\"-arch\",\n \"arm64\",",
"#\"-arch\",\n #\"arm64\",",
strict=False)
args = ""
args += "is_official_build=true\n"
args += f"is_component_build={self._get_lower_bool_str(self.options.shared)}\n"
buildenv = VirtualBuildEnv(self).vars()
cc = buildenv.get("CC", default=None)
cxx = buildenv.get("CXX", default=None)
# Fall back to tools.build:compiler_executables when VirtualBuildEnv
# did not inject CC/CXX (common with only profile [conf]).
try:
executables = self.conf.get("tools.build:compiler_executables", default={}) or {}
except Exception:
executables = {}
if not cc:
cc = executables.get("c")
if not cxx:
cxx = executables.get("cpp")
if cc:
args += f"cc=\"{cc}\"\n"
if cxx:
args += f"cxx=\"{cxx}\"\n"
if ar := buildenv.get("AR", default=None):
args += f"ar=\"{ar}\"\n"
if self.settings.os == "Emscripten":
if emsdk := buildenv.get("EMSDK", default=None):
args += f"skia_emsdk_dir=\"{emsdk}\"\n"
if self.settings.os == "Windows":
winsdk_version = self.conf.get("tools.microsoft:winsdk_version", default=None)
if winsdk_version != None:
args += f"win_sdk_version=\"{winsdk_version}\"\n"
if self.settings.os == "Android":
ndk_path = self.conf.get("tools.android:ndk_path", default=None)
if ndk_path != None:
args += f"ndk = \"{ndk_path}\"\n"
args += f"ndk_api = {self.settings.os.api_level}\n"
if self.settings.os == "iOS":
args += f"target_os = \"ios\"\n"
elif self.settings.os == "tvOS":
args += f"target_os = \"tvos\"\n"
elif self._is_ios_variant():
args += f"target_os = \"ios\"\n"
if self._is_ios_variant_simulator():
args += f"ios_use_simulator = true\n"
if self.settings.arch == "x86":
args += "target_cpu = \"x86\"\n"
elif self.settings.arch == "x86_64":
args += "target_cpu = \"x64\"\n"
elif self.settings.arch == "wasm":
args += "target_cpu = \"wasm\"\n"
elif self.settings.arch == "armv7":
args += "target_cpu = \"arm\"\n"
elif self.settings.arch == "armv8":
args += "target_cpu = \"arm64\"\n"
elif self._is_ios_variant() and self.settings.arch == "armv8.3":
args += "target_cpu = \"arm64\"\n"
else:
raise RuntimeError("Unexpected settings.arch")
if self.settings.os == "Emscripten":
args += f"skia_canvaskit_enable_alias_font = false\n"
args += f"skia_canvaskit_enable_bidi = false\n"
args += f"skia_canvaskit_enable_canvas_bindings = false\n"
args += f"skia_canvaskit_enable_debugger = false\n"
args += f"skia_canvaskit_enable_effects_deserialization = false\n"
args += f"skia_canvaskit_enable_embedded_font = false\n"
args += f"skia_canvaskit_enable_font = false\n"
args += f"skia_canvaskit_enable_matrix_helper = false\n"
args += f"skia_canvaskit_enable_paragraph = false\n"
args += f"skia_canvaskit_enable_pathops = false\n"
args += f"skia_canvaskit_enable_rt_shader = false\n"
args += f"skia_canvaskit_enable_skp_serialization = false\n"
args += f"skia_canvaskit_enable_sksl_trace = false\n"
args += f"skia_canvaskit_enable_webgl = false\n"
args += f"skia_canvaskit_enable_webgpu = false\n"
args += f"skia_canvaskit_force_tracing = false\n"
args += f"skia_canvaskit_include_viewer = false\n"
args += f"skia_canvaskit_legacy_draw_vertices_blend_mode = false\n"
args += f"skia_canvaskit_profile_build = false\n"
if self.settings.os == "Linux" and self.options.use_egl == True:
args += f"skia_use_egl = true\n"
else:
args += f"skia_use_egl = false\n"
if self.settings.os == "Linux" and self.options.use_x11 == True:
args += f"skia_use_x11 = true\n"
else:
args += f"skia_use_x11 = false\n"
cflags = []
ldflags = []
asmflags = []
for dep in self.dependencies.host.values():
cflags += [f"-I{dir}" for dir in dep.cpp_info.includedirs]
cflags += [f"-D{define}" for define in dep.cpp_info.defines]
if is_msvc(self):
ldflags += [f"/LIBPATH:{dir}" for dir in dep.cpp_info.libdirs]
else:
ldflags += [f"-L{dir}" for dir in dep.cpp_info.libdirs]
for component in dep.cpp_info.components.values():
cflags += [f"-I{dir}" for dir in component.includedirs]
cflags += [f"-D{define}" for define in component.defines]
if is_msvc(self):
ldflags += [f"/LIBPATH:{dir}" for dir in component.libdirs]
else:
ldflags += [f"-L{dir}" for dir in component.libdirs]
if is_msvc(self):
cflags += [f"/{msvc_runtime_flag(self)}"]
if not self.options.shared and self.settings.compiler != "msvc":
fpic = self.options.get_safe("fPIC")
if fpic != None:
cflags += ["-fPIC"]
if is_apple_os(self):
min_version_flag = AutotoolsToolchain(self).apple_min_version_flag
cflags += [min_version_flag]
ldflags += [min_version_flag]
asmflags += [min_version_flag]
cflags += [f"-D{define}" for define in self.conf.get("tools.build:defines", default=[], check_type=list)]
ldflags += self.conf.get("tools.build:sharedlinkflags", default=[], check_type=list)
ldflags += self.conf.get("tools.build:exelinkflags", default=[], check_type=list)
linker_scripts = self.conf.get("tools.build:linker_scripts", default=[], check_type=list)
ldflags += ["-T'" + linker_script + "'" for linker_script in linker_scripts]
cflags += self.conf.get("tools.build:cflags", default=[], check_type=list)
cflags_c = []
cflags_cc = self.conf.get("tools.build:cxxflags", default=[], check_type=list)
cflags_cc += [cppstd_flag(self)]
if cflags_cc == [None]: # Fail to get c++ flags when using emsdk, so set the flags manually here
print("Failed to get C++ build flags, setting flags manually")
cflags_cc = ["-pthread"]
args += f"extra_cflags={json.dumps(cflags)}\n"
args += f"extra_cflags_c={json.dumps(cflags_c)}\n"
args += f"extra_cflags_cc={json.dumps(cflags_cc)}\n"
args += f"extra_ldflags={json.dumps(ldflags)}\n"
args += f"extra_asmflags={json.dumps(asmflags)}\n"
if self.settings.os == "Macos" or self._is_ios_variant():
sdk_path = self.conf.get("tools.apple:sdk_path", default=None)
if not sdk_path:
sdk_path = XCRun(self).sdk_path
if sdk_path:
args += f"xcode_sysroot=\"{sdk_path}\"\n"
if self._is_ios_variant():
args += f"skia_ios_use_signing = false\n"
for key in self._skia_options.keys():
value = self.options.get_safe(key)
if value != None and not key.startswith("use_conan"):
b = self._get_lower_bool_str(value)
k = "use_system_freetype2" if key == "use_system_freetype" else key
args += f"skia_{k}={b}\n"
rmdir(self, "out/conan")
mkdir(self, "out/conan")
save(self, "out/conan/args.gn", args)
if self.settings.os == "Windows":
self.run("bin\gn gen out/conan")
else:
self.run("bin/gn gen out/conan")
self.run("ninja -C out/conan skia svg skresources skcms skunicode skshaper skparagraph skottie bentleyottmann")
def package(self):
source_folder_include = join(self.source_folder, "include")
source_folder_modules = join(self.source_folder, "modules")
package_folder_include = join(self.package_folder, "include")
package_folder_include_modules = join(package_folder_include, "modules")
package_folder_lib = join(self.package_folder, "lib")
package_folder_bin = join(self.package_folder, "bin")
build_folder_out = join(self.build_folder, "out", "conan")
# Skia headers have to be included relative to root of Skia repository (for example, #include <include/core/SkCanvas.h>).
# So we have to create another 'include' folder inside include directory...
# Include the entire skia root folder as an include (only copy includes)
copy(self, "*.h", self.source_folder, package_folder_include)
#copy(self, "*.h", source_folder_include, join(package_folder_include, "include"))
## removed sksg from this list
#for mod in ["skottie", "skresource", "sksg", "skshaper", "skunicode", "svg"]:
# copy(self, "*.h", join(source_folder_modules, mod, "include"), join(package_folder_include_modules, mod, "include"))
## skcms doesn't have include folder for some reason.
#copy(self, "*.h", join(source_folder_modules, "skcms"), join(package_folder_include_modules, "skcms"))
if self.settings.os == "Windows":
if self.options.shared:
copy(self, "*.dll", build_folder_out, package_folder_bin, keep_path=False)
copy(self, "*.dll.lib", build_folder_out, package_folder_lib, keep_path=False)
# rename: *.dll.lib -> *.lib
for filename in os.listdir(package_folder_lib):
if filename.endswith(".dll.lib"):
new_filename = filename.replace(".dll.lib", ".lib")
rename(self, join(package_folder_lib, filename), join(package_folder_lib, new_filename))
else:
copy(self, "*.lib", build_folder_out, package_folder_lib, keep_path=False)
else:
if self.options.shared:
copy(self, "*.so", build_folder_out, package_folder_lib, keep_path=False)
copy(self, "*.dylib", build_folder_out, package_folder_lib, keep_path=False)
else:
copy(self, "*.a", build_folder_out, package_folder_lib, keep_path=False)
#if self.settings.os == "Emscripten" and self.settings.arch == "wasm":
# copy(self, "canvaskit.js", build_folder_out, package_folder_bin)
# copy(self, "canvaskit.wasm", build_folder_out, package_folder_bin)
def package_info(self):
# As of Conan 2.3.1, CMake generators cannot propagate transitive dependencies when you use components.
# So we have to put evetything into root cpp_info...
# https://github.com/conan-io/conan/issues/14888
# component: skia
self.cpp_info.defines += ["SK_CODEC_DEFINES_BMP"]
self.cpp_info.defines += ["SK_CODEC_DEFINES_WBMP"]
self.cpp_info.defines += ["SK_DISABLE_TRACING"] # assuming is_official_build
if self.options.use_gl:
self.cpp_info.defines += ["SK_GL"]
if self.options.use_dawn:
self.cpp_info.defines += ["SK_DAWN"]
if self.options.use_direct3d:
self.cpp_info.defines += ["SK_ENABLE_SPIRV_CROSS"]
self.cpp_info.defines += ["SK_DIRECT3D"]
self.cpp_info.system_libs += ["d3d12", "dxgi", "d3dcompiler"]
if self.options.use_vulkan:
self.cpp_info.defines += ["SK_VULKAN"]
if self.options.use_metal:
self.cpp_info.defines += ["SK_METAL"]
if self.options.shared:
self.cpp_info.defines += ["SKIA_DLL"]
if self.settings.os == "Linux":
self.cpp_info.defines += ["SK_R32_SHIFT=16"]
if self.settings.os == "Android":
self.cpp_info.system_libs += ["log"]
if self.options.enable_optimize_size:
self.cpp_info.defines += ["SK_ENABLE_OPTIMIZE_SIZE"]
if self.options.enable_precompile:
self.cpp_info.defines += ["SK_ENABLE_PRECOMPILE"]
if self.options.enable_ganesh:
self.cpp_info.defines += ["SK_GANESH"]
if self.options.enable_graphite:
self.cpp_info.defines += ["SK_GRAPHITE"]
if self.options.use_perfetto:
self.cpp_info.defines += ["SK_USE_PERFETTO"]
if self.settings.os == "Macos" or self._is_ios_variant():
if self.options.enable_api_available_macro:
self.cpp_info.defines += ["SK_ENABLE_API_AVAILABLE"]
else:
self.cpp_info.cflags += ["-Wno-unguarded-availability"]
if self.options.gl_standard == "gl":
self.cpp_info.defines += ["SKIA_ASSUME_GL=1"]
if self.options.gl_standard == "gles":
self.cpp_info.defines += ["SKIA_ASSUME_GL_ES=1"]
if self.options.gl_standard == "webgl":
self.cpp_info.defines += ["SKIA_ASSUME_WEBGL=1"]
if self.options.enable_pdf:
if self.options.use_zlib and self.options.use_libjpeg_turbo_decode and self.options.use_libjpeg_turbo_encode:
self.cpp_info.defines += ["SK_SUPPORT_PDF"]
if self.options.use_xps:
self.cpp_info.defines += ["SK_SUPPORT_XPS"]
if self.options.use_wuffs and not self.options.shared:
self.cpp_info.defines += ["SK_HAS_WUFFS_LIBRARY"]
self.cpp_info.defines += ["SK_CODEC_DECODES_GIF"]
self.cpp_info.libs += ["wuffs"]
if self.options.use_piex and not self.options.shared:
self.cpp_info.libs += ["piex"]
if self.options.use_dng_sdk and self.options.use_libjpeg_turbo_decode and self.options.use_piex and not self.options.shared:
self.cpp_info.defines += ["qDNGBigEndian=0"]
self.cpp_info.libs += ["dng_sdk"]
if self.options.use_libpng_decode:
self.cpp_info.defines += ["SK_CODEC_DECODES_ICO"]
self.cpp_info.defines += ["SK_CODEC_DECODES_PNG"]
if self.options.use_libpng_decode:
self.cpp_info.defines += ["SK_CODEC_DECODES_WEBP"]
if self.options.use_libavif:
self.cpp_info.defines += ["SK_CODEC_DECODES_AVIF"]
if self.options.use_libjpeg_turbo_decode:
self.cpp_info.defines += ["SK_CODEC_DECODES_JPEG"]
if self.options.use_libjxl_decode:
self.cpp_info.defines += ["SK_CODEC_DECODE_JPEGXL"]
if self.options.use_ndk_images:
self.cpp_info.defines += ["SK_ENABLE_NDK_IMAGES"]
if self.options.use_expat:
self.cpp_info.defines += ["SK_XML"]
if self.options.use_dng_sdk and self.options.use_libjpeg_turbo_decode and self.options.use_piex:
self.cpp_info.defines += ["SK_CODEC_DECODES_RAW"]
if self.options.use_fonthost_mac:
self.cpp_info.defines += ["SK_TYPEFACE_FACTORY_CORETEXT", "SK_FONTMGR_CORETEXT_AVAILABLE"]
if self.settings.os == "Macos":
self.cpp_info.frameworks += ["AppKit", "ApplicationServices"]
elif self._is_ios_variant():
self.cpp_info.frameworks += ["CoreFoundation", "CoreGraphics", "CoreText", "UIKit"]
if self.options.enable_fontmgr_android:
self.cpp_info.defines += ["SK_FONTMGR_ANDROID_AVAILABLE"]
if self.options.enable_fontmgr_custom_directory:
self.cpp_info.defines += ["SK_FONTMGR_FREETYPE_DIRECTORY_AVAILABLE"]
if self.options.enable_fontmgr_custom_embedded:
self.cpp_info.defines += ["SK_FONTMGR_FREETYPE_EMBEDDED_AVAILABLE"]
if self.options.enable_fontmgr_custom_empty:
self.cpp_info.defines += ["SK_FONTMGR_FREETYPE_EMPTY_AVAILABLE"]
if self.options.enable_fontmgr_fontconfig:
self.cpp_info.defines += ["SK_FONTMGR_FONTCONFIG_AVAILABLE"]
if self.options.enable_fontmgr_win:
self.cpp_info.defines += ["SK_TYPEFACE_FACTORY_DIRECTWRITE", "SK_FONTMGR_DIRECTWRITE_AVAILABLE"]
if self.options.enable_fontmgr_win_gdi:
self.cpp_info.defines += ["SK_FONTMGR_GDI_AVAILABLE"]
self.cpp_info.system_libs += ["gdi32"]
# component: pathkit
# not in program's build, so it'll be commented for now
#if not self.options.shared:
# self.cpp_info.libs += ["pathkit"]
# component: skcms
if not self.options.shared:
self.cpp_info.libs += ["skcms"]
# component: sksg
# sksg doesn't exist in the program's build, so it'll be commented for now
# if not self.options.shared:
# self.cpp_info.libs += ["sksg"]
# component: svg
if self.options.enable_svg and self.options.use_expat:
self.cpp_info.defines += ["SK_SVG"]
self.cpp_info.libs += ["svg"]
# component: skresource
if not self.options.shared:
self.cpp_info.libs += ["skresources"]
self.cpp_info.libs += ["skia"] # Placed this after some components due to library order being important on some systems
# component: skunicode
if self.options.enable_skunicode:
self.cpp_info.defines += ["SK_UNICODE_AVAILABLE"]
self.cpp_info.defines += ["SK_UNICODE_ICU_IMPLEMENTATION"]
self.cpp_info.libs += ["skunicode_icu", "skunicode_core"] # Swapped order
# component: skparagraph
if self.options.enable_skparagraph:
if not (self.settings.os == "Windows" and self.options.shared):
self.cpp_info.libs += ["skparagraph"]
self.cpp_info.defines += ["SK_ENABLE_PARAGRAPH"]
# component: skshaper
if self.options.enable_skshaper:
self.cpp_info.libs += ["skshaper"]
self.cpp_info.defines += ["SK_SHAPER_PRIMITIVE_AVAILABLE"]
if self.options.use_fonthost_mac:
self.cpp_info.defines += ["SK_SHAPER_CORETEXT_AVAILABLE"]
if self.options.use_harfbuzz:
self.cpp_info.defines += ["SK_SHAPER_HARFBUZZ_AVAILABLE"]
if self.options.shared:
self.cpp_info.defines += ["SK_SHAPER_UNICODE_AVAILABLE"]
# component: skottie
if self.options.enable_skottie:
self.cpp_info.libs += ["skottie"]
self.cpp_info.defines += ["SK_ENABLE_SKOTTIE", "SK_ENABLE_SKSLEFFECT"]
# component: bentleyottmann
if self.options.enable_bentleyottmann:
if not (self.settings.os == "Windows" and self.options.shared):
self.cpp_info.libs += ["bentleyottmann"]