diff --git a/recipes/ios-cmake/all/cmake-wrapper b/recipes/ios-cmake/all/cmake-wrapper index 5cdfc4e7a0558..4003296b4f619 100644 --- a/recipes/ios-cmake/all/cmake-wrapper +++ b/recipes/ios-cmake/all/cmake-wrapper @@ -1,4 +1,5 @@ #!/usr/bin/env bash +set -eu ALL_ARGS=$@ @@ -17,7 +18,7 @@ done if [ $BUILD == "yes" ]; then cmake "$@" else - # TODO check if, based on log level, some configurable outbut of these values could be nice to have + # TODO check if, based on log level, some configurable output of these values could be nice to have fix_cmake_flags="-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=BOTH -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=NEVER" cmake "$@" ${CONAN_USER_CMAKE_FLAGS} ${fix_cmake_flags} fi diff --git a/recipes/ios-cmake/all/conandata.yml b/recipes/ios-cmake/all/conandata.yml index 23c78241a7799..f155810b41509 100644 --- a/recipes/ios-cmake/all/conandata.yml +++ b/recipes/ios-cmake/all/conandata.yml @@ -11,3 +11,6 @@ sources: "4.2.0": url: "https://github.com/leetal/ios-cmake/archive/4.2.0.zip" sha256: "abcae0619751dd46d825f0f341d9a5c1a13bbe8fa84f9a62f09652087f64f87f" + "4.4.1": + url: "https://github.com/leetal/ios-cmake/archive/4.4.1.zip" + sha256: "9edfe43e96f1a08dd29d86c81f7ad7d65069fb6f681bbf002df85bb91c421b27" diff --git a/recipes/ios-cmake/all/conanfile.py b/recipes/ios-cmake/all/conanfile.py index e082576dcdc11..5acfe372e49e6 100644 --- a/recipes/ios-cmake/all/conanfile.py +++ b/recipes/ios-cmake/all/conanfile.py @@ -1,26 +1,49 @@ -from conans import ConanFile, tools -from conans.errors import ConanInvalidConfiguration - import os +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.apple import is_apple_os +from conan.tools.files import copy, get +from conan.tools.layout import basic_layout + +required_conan_version = ">=1.52.0" + class IosCMakeConan(ConanFile): name = "ios-cmake" + description = "iOS CMake toolchain to (cross) compile macOS/iOS/watchOS/tvOS" license = "BSD-3-Clause" - settings = "os" , "arch" url = "https://github.com/conan-io/conan-center-index" homepage = "https://github.com/leetal/ios-cmake" + topics = ("apple", "ios", "cmake", "toolchain", "ios", "tvos", "watchos", "header-only") + + package_type = "build-scripts" + settings = "os", "arch", "compiler", "build_type" + # Note: you need to use `-o:b ...` to set these options due to package_type options = { "enable_bitcode": [True, False], "enable_arc": [True, False], "enable_visibility": [True, False], "enable_strict_try_compile": [True, False], - "toolchain_target": ["auto", "OS", "OS64", "OS64COMBINED", - "SIMULATOR", "SIMULATOR64", "SIMULATORARM64", - "TVOS", "TVOSCOMBINED", - "SIMULATOR_TVOS", "WATCHOS", - "WATCHOSCOMBINED", "SIMULATOR_WATCHOS", - "MAC", "MAC_ARM64", "MAC_CATALYST", "MAC_CATALYST_ARM64"] + "toolchain_target": [ + "auto", + "OS", + "OS64", + "OS64COMBINED", + "SIMULATOR", + "SIMULATOR64", + "SIMULATORARM64", + "TVOS", + "TVOSCOMBINED", + "SIMULATOR_TVOS", + "WATCHOS", + "WATCHOSCOMBINED", + "SIMULATOR_WATCHOS", + "MAC", + "MAC_ARM64", + "MAC_CATALYST", + "MAC_CATALYST_ARM64", + ], } default_options = { "enable_bitcode": True, @@ -29,121 +52,135 @@ class IosCMakeConan(ConanFile): "enable_strict_try_compile": False, "toolchain_target": "auto", } - description = "ios Cmake toolchain to (cross) compile macOS/iOS/watchOS/tvOS" - topics = "conan", "apple", "ios", "cmake", "toolchain", "ios", "tvos", "watchos" - exports_sources = "cmake-wrapper" - @property - def _source_subfolder(self): - return os.path.join(self.source_folder, "source_subfolder") - - @staticmethod - def _chmod_plus_x(filename): - if os.name == 'posix': - os.chmod(filename, os.stat(filename).st_mode | 0o111) + def config_options(self): + if os.getenv("CONAN_CENTER_BUILD_SERVICE") is not None: + # To not simply skip the build in C3I due to a missing toolchain_target value + self.options.toolchain_target = "OS64" - def configure(self): - if not tools.is_apple_os(self.settings.os): - raise ConanInvalidConfiguration("This package only supports Apple operating systems") - - def _guess_toolchain_target(self, os, arch): - if os == "iOS": - if arch in ["armv8", "armv8.3"]: + @property + def _default_toolchain_target(self): + if self.settings.os == "iOS": + if self.settings.arch in ["armv8", "armv8.3"]: return "OS64" - if arch == "x86_64": + if self.settings.arch == "x86_64": return "SIMULATOR64" # 32bit is dead, don't care - elif os == "watchOS": - if arch == "x86_64": + elif self.settings.os == "watchOS": + if self.settings.arch == "x86_64": return "SIMULATOR_WATCHOS" else: return "WATCHOS" - elif os == "tvOS": - if arch == "x86_64": + elif self.settings.os == "tvOS": + if self.settings.arch == "x86_64": return "TVOS" else: return "SIMULATOR_TVOS" - raise ConanInvalidConfiguration("Can not guess toolchain_target. Please set the option explicit (or check our os settings)") + return None + + @property + def _toolchain_target(self): + if self.options.toolchain_target == "auto": + return self._default_toolchain_target + return self.options.toolchain_target + + def export_sources(self): + copy(self, "cmake-wrapper", self.recipe_folder, self.export_sources_folder) + + def layout(self): + basic_layout(self, src_folder="src") + def validate(self): + if not is_apple_os(self): + raise ConanInvalidConfiguration("This package only supports Apple operating systems") + if self._toolchain_target is None: + raise ConanInvalidConfiguration( + "Cannot guess toolchain target type. " + f"Please set the option explicitly with '-o:b {self.name}/*:toolchain_target=...'." + ) + + def package_id(self): + self.info.clear() def source(self): - tools.get(**self.conan_data["sources"][self.version]) - os.rename("ios-cmake-{}".format(self.version), self._source_subfolder) + get(self, **self.conan_data["sources"][self.version], strip_root=True) def build(self): - pass # there is nothing to build + pass # there is nothing to build + + @staticmethod + def _chmod_plus_x(filename): + if os.name == "posix": + os.chmod(filename, os.stat(filename).st_mode | 0o111) def package(self): - self.copy("cmake-wrapper", dst="bin") - self.copy("ios.toolchain.cmake", - src=self._source_subfolder, - dst=os.path.join("lib", "cmake", "ios-cmake"), - keep_path=False) + copy(self, "cmake-wrapper", + src=self.export_sources_folder, + dst=os.path.join(self.package_folder, "bin")) + copy(self, "ios.toolchain.cmake", + src=self.source_folder, + dst=os.path.join(self.package_folder, "lib", "cmake", "ios-cmake"), + keep_path=False) self._chmod_plus_x(os.path.join(self.package_folder, "bin", "cmake-wrapper")) - self.copy("LICENSE.md", dst="licenses", src=self._source_subfolder, keep_path=False) - # satisfy KB-H014 (header_only recipes require headers) - tools.save(os.path.join(self.package_folder, "include", "dummy_header.h"), "\n") + copy(self, "LICENSE.md", + dst=os.path.join(self.package_folder, "licenses"), + src=self.source_folder, + keep_path=False) def package_info(self): - if self.settings.os == "Macos": - if not getattr(self, "settings_target", None): - # not a build_require , but can be fine since its build as a ppr:b, but nothing to do - return - # this is where I want to be, expecting this as a build_require for a host - target_os = str(self.settings_target.os) - arch_flag = self.settings_target.arch - target_version= self.settings_target.os.version - elif self.settings.os == "iOS": # old style 1 profile, don't use - target_os = str(self.settings.os) - arch_flag = self.settings.arch - target_version = self.settings.os.version - else: - #hackingtosh ? hu - raise ConanInvalidConfiguration("Building for iOS on a non Mac platform? Please tell me how!") - - if self.options.toolchain_target == "auto": - toolchain_target = self._guess_toolchain_target(target_os, arch_flag) - else: - toolchain_target = self.options.toolchain_target + settings = getattr(self, "settings_target", self.settings) + if not settings.os: + return + arch_flag = str(settings.arch) if arch_flag == "armv8": arch_flag = "arm64" elif arch_flag == "armv8.3": arch_flag = "arm64e" - cmake_options = "-DENABLE_BITCODE={} -DENABLE_ARC={} -DENABLE_VISIBILITY={} -DENABLE_STRICT_TRY_COMPILE={}".format( - self.options.enable_bitcode, - self.options.enable_arc, - self.options.enable_visibility, - self.options.enable_strict_try_compile - ) + cmake_options = " ".join([ + f"-DENABLE_BITCODE={self.options.enable_bitcode}", + f"-DENABLE_ARC={self.options.enable_arc}", + f"-DENABLE_VISIBILITY={self.options.enable_visibility}", + f"-DENABLE_STRICT_TRY_COMPILE={self.options.enable_strict_try_compile}" + ]) # Note that this, as long as we specify (overwrite) the ARCHS, PLATFORM has just limited effect, # but PLATFORM need to be set in the profile so it makes sense, see ios-cmake docs for more info - cmake_flags = "-DPLATFORM={} -DDEPLOYMENT_TARGET={} -DARCHS={} {}".format( - toolchain_target, target_version, arch_flag, cmake_options - ) + cmake_flags = " ".join([ + f"-DPLATFORM={self._toolchain_target}", + f"-DDEPLOYMENT_TARGET={str(settings.os.version)}", + f"-DARCHS={arch_flag}", + f"{cmake_options}", + ]) + self.output.info(f"Setting toolchain options to: {cmake_flags}") + cmake_wrapper = os.path.join(self.package_folder, "bin", "cmake-wrapper") + self.output.info(f"Setting cmake-wrapper path to: {cmake_wrapper}") + toolchain = os.path.join(self.package_folder, "lib", "cmake", "ios-cmake", "ios.toolchain.cmake") + + self.conf_info.define_path("user.ios-cmake:cmake_program", cmake_wrapper) + self.conf_info.define_path("user.ios-cmake:cmake_toolchain_file", toolchain) + self.conf_info.define("user.ios-cmake:cmake_flags", cmake_flags) + self.conf_info.define("user.ios-cmake:enable_bitcode", bool(self.options.enable_bitcode)) + self.conf_info.define("user.ios-cmake:enable_arc", bool(self.options.enable_arc)) + self.conf_info.define("user.ios-cmake:enable_visibility", bool(self.options.enable_visibility)) + + self.buildenv_info.define("CONAN_CMAKE_PROGRAM", cmake_wrapper) + self.buildenv_info.define("CONAN_CMAKE_TOOLCHAIN_FILE", toolchain) + self.buildenv_info.define("CONAN_USER_CMAKE_FLAGS", cmake_flags) + # add some more env_info, for the case users generate a toolchain file via conan and want to access that info + self.buildenv_info.define("CONAN_ENABLE_BITCODE_FLAG", str(self.options.enable_bitcode)) + self.buildenv_info.define("CONAN_ENABLE_ARC_FLAG", str(self.options.enable_arc)) + self.buildenv_info.define("CONAN_ENABLE_VISIBILITY_FLAG", str(self.options.enable_visibility)) + self.buildenv_info.define("CONAN_ENABLE_STRICT_TRY_COMPILE_FLAG", str(self.options.enable_strict_try_compile)) + # the rest should be exported from profile info anyway + # TODO: Legacy, remove in Conan 2.0 self.env_info.CONAN_USER_CMAKE_FLAGS = cmake_flags - self.output.info("Setting toolchain options to: {}".format(cmake_flags)) - cmake_wrapper = os.path.join(self.package_folder, "bin", "cmake-wrapper") - self.output.info("Setting CONAN_CMAKE_PROGRAM to: {}".format(cmake_wrapper)) self.env_info.CONAN_CMAKE_PROGRAM = cmake_wrapper - tool_chain = os.path.join(self.package_folder, - "lib", - "cmake", - "ios-cmake", - "ios.toolchain.cmake") - self.env_info.CONAN_CMAKE_TOOLCHAIN_FILE = tool_chain - # add some more env_info, for the case users generate a toolchain file via conan and want to access that info + self.env_info.CONAN_CMAKE_TOOLCHAIN_FILE = toolchain self.env_info.CONAN_ENABLE_BITCODE_FLAG = str(self.options.enable_bitcode) self.env_info.CONAN_ENABLE_ARC_FLAG = str(self.options.enable_arc) self.env_info.CONAN_ENABLE_VISIBILITY_FLAG = str(self.options.enable_visibility) self.env_info.CONAN_ENABLE_STRICT_TRY_COMPILE_FLAG = str(self.options.enable_strict_try_compile) - # the rest should be exported from profile info anyway - - def package_id(self): - self.info.header_only() - # TODO , since we have 2 profiles I am not sure that this is still required - # since this will always be / has to be a build profile diff --git a/recipes/ios-cmake/all/test_package/CMakeLists.txt b/recipes/ios-cmake/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000000..5ee4c717c4a64 --- /dev/null +++ b/recipes/ios-cmake/all/test_package/CMakeLists.txt @@ -0,0 +1,2 @@ +cmake_minimum_required(VERSION 3.15) +project(empty) diff --git a/recipes/ios-cmake/all/test_package/conanfile.py b/recipes/ios-cmake/all/test_package/conanfile.py index d17672988e89a..d8a8bb70cd3c9 100644 --- a/recipes/ios-cmake/all/test_package/conanfile.py +++ b/recipes/ios-cmake/all/test_package/conanfile.py @@ -1,14 +1,31 @@ - import os -from conans import ConanFile + +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import cmake_layout class TestPackageConan(ConanFile): - settings = "os" + settings = "os", "arch", "compiler", "build_type" + generators = "VirtualBuildEnv" + test_type = "explicit" + + def layout(self): + cmake_layout(self) + + def build_requirements(self): + self.tool_requires(self.tested_reference_str) + + def generate(self): + info = self.dependencies.build["ios-cmake"].conf_info + cmake_prog = info.get("user.ios-cmake:cmake_program", check_type=str) + toolchain = info.get("user.ios-cmake:cmake_toolchain_file", check_type=str) + assert os.path.basename(cmake_prog) == "cmake-wrapper" + assert os.path.isfile(cmake_prog) + assert os.path.basename(toolchain) == "ios.toolchain.cmake" + assert os.path.isfile(toolchain) def test(self): - if self.settings.os == "iOS": - cmake_prog = os.environ.get("CONAN_CMAKE_PROGRAM") - toolchain = os.environ.get("CONAN_CMAKE_TOOLCHAIN_FILE") - assert (os.path.basename(cmake_prog) == "cmake-wrapper") - assert (os.path.basename(toolchain) == "ios.toolchain.cmake") + if can_run(self): + self.run(f"cmake-wrapper {self.source_folder}") + self.run("cmake-wrapper --build .") diff --git a/recipes/ios-cmake/config.yml b/recipes/ios-cmake/config.yml index ff109c746b106..7d57778c3b33e 100644 --- a/recipes/ios-cmake/config.yml +++ b/recipes/ios-cmake/config.yml @@ -7,3 +7,5 @@ versions: folder: all "4.2.0": folder: all + "4.4.1": + folder: all