From e2817ed78b91d8ea92241e7b105fa880cd313595 Mon Sep 17 00:00:00 2001 From: Steve Robinson Date: Mon, 19 Jun 2023 11:11:00 -0700 Subject: [PATCH 1/6] Add iOS, tvOS, and watchOS support --- conan_provider.cmake | 52 ++++++++++++++++++++++++++----- tests/test_smoke.py | 73 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 8 deletions(-) diff --git a/conan_provider.cmake b/conan_provider.cmake index 6c311582..a970b692 100644 --- a/conan_provider.cmake +++ b/conan_provider.cmake @@ -1,14 +1,12 @@ set(CONAN_MINIMUM_VERSION 2.0.5) -function(detect_os OS OS_API_LEVEL OS_VERSION OS_SUBSYSTEM) +function(detect_os OS OS_API_LEVEL OS_SDK OS_SUBSYSTEM OS_VERSION) # it could be cross compilation message(STATUS "CMake-Conan: cmake_system_name=${CMAKE_SYSTEM_NAME}") if(CMAKE_SYSTEM_NAME AND NOT CMAKE_SYSTEM_NAME STREQUAL "Generic") if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") set(${OS} Macos PARENT_SCOPE) - message(STATUS "CMake-Conan: cmake_osx_deployment_target=${CMAKE_OSX_DEPLOYMENT_TARGET}") - set(${OS_VERSION} ${CMAKE_OSX_DEPLOYMENT_TARGET} PARENT_SCOPE) elseif(${CMAKE_SYSTEM_NAME} STREQUAL "QNX") set(${OS} Neutrino PARENT_SCOPE) elseif(${CMAKE_SYSTEM_NAME} STREQUAL "CYGWIN") @@ -25,18 +23,53 @@ function(detect_os OS OS_API_LEVEL OS_VERSION OS_SUBSYSTEM) message(STATUS "CMake-Conan: android_platform=${ANDROID_PLATFORM}") set(${OS_API_LEVEL} ${_OS_API_LEVEL} PARENT_SCOPE) endif() + if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR + ${CMAKE_SYSTEM_NAME} STREQUAL "iOS" OR + ${CMAKE_SYSTEM_NAME} STREQUAL "tvOS" OR + ${CMAKE_SYSTEM_NAME} STREQUAL "watchOS") + if(DEFINED CMAKE_OSX_SYSROOT) + # CMAKE_OSX_SYSROOT contains the full path to the SDK for MakeFile/Ninja + # generators, but just has the original input string for Xcode. Use the + # lowercase form to detect both. + string(TOLOWER ${CMAKE_OSX_SYSROOT} cmake_os_sysroot_lower) + if(cmake_os_sysroot_lower MATCHES appletvos) + set(_OS_SDK appletvos) + elseif(cmake_os_sysroot_lower MATCHES appletvsimulator) + set(_OS_SDK appletvsimulator) + elseif(cmake_os_sysroot_lower MATCHES iphoneos) + set(_OS_SDK iphoneos) + elseif(cmake_os_sysroot_lower MATCHES iphonesimulator) + set(_OS_SDK iphonesimulator) + elseif(cmake_os_sysroot_lower MATCHES watchos) + set(_OS_SDK watchos) + elseif(cmake_os_sysroot_lower MATCHES watchsimulator) + set(_OS_SDK watchsimulator) + endif() + message(STATUS "CMake-Conan: cmake_osx_sysroot=${CMAKE_OSX_SYSROOT}") + set(${OS_SDK} ${_OS_SDK} PARENT_SCOPE) + endif() + if(DEFINED CMAKE_OSX_DEPLOYMENT_TARGET) + message(STATUS "CMake-Conan: cmake_osx_deployment_target=${CMAKE_OSX_DEPLOYMENT_TARGET}") + set(${OS_VERSION} ${CMAKE_OSX_DEPLOYMENT_TARGET} PARENT_SCOPE) + endif() + endif() endif() endfunction() function(detect_arch ARCH) - if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64|arm64") + # CMAKE_OSX_ARCHITECTURES can contain multiple architectures, but Conan only supports one. + # Therefore this code only finds one. If the recipes support mulitple architectures, the + # build will work. Otherwise, there will be a linker error for the missing architecture(s). + if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64|arm64" OR CMAKE_OSX_ARCHITECTURES MATCHES arm64) set(_ARCH armv8) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7-a|armv7l") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7-a|armv7l" OR CMAKE_OSX_ARCHITECTURES MATCHES armv7) set(_ARCH armv7) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686") + elseif(CMAKE_OSX_ARCHITECTURES MATCHES armv7s) + set(_ARCH armv7s) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686" OR CMAKE_OSX_ARCHITECTURES MATCHES i386) set(_ARCH x86) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64|amd64|x86_64") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64|amd64|x86_64" OR CMAKE_OSX_ARCHITECTURES MATCHES x86_64) set(_ARCH x86_64) endif() message(STATUS "CMake-Conan: cmake_system_processor=${_ARCH}") @@ -109,7 +142,7 @@ endfunction() function(detect_host_profile output_file) - detect_os(MYOS MYOS_API_LEVEL MYOS_VERSION MYOS_SUBSYSTEM) + detect_os(MYOS MYOS_API_LEVEL MYOS_SDK MYOS_SUBSYSTEM MYOS_VERSION) detect_arch(MYARCH) detect_compiler(MYCOMPILER MYCOMPILER_VERSION) detect_cxx_standard(MYCXX_STANDARD) @@ -131,6 +164,9 @@ function(detect_host_profile output_file) if(MYOS_VERSION) string(APPEND PROFILE os.version=${MYOS_VERSION} "\n") endif() + if(MYOS_SDK) + string(APPEND PROFILE os.sdk=${MYOS_SDK} "\n") + endif() if(MYOS_SUBSYSTEM) string(APPEND PROFILE os.subsystem=${MYOS_SUBSYSTEM} "\n") endif() diff --git a/tests/test_smoke.py b/tests/test_smoke.py index 2f1b77cb..38b2b329 100644 --- a/tests/test_smoke.py +++ b/tests/test_smoke.py @@ -172,6 +172,7 @@ def test_add_subdirectory(self, capfd, chdir_build): out, _ = capfd.readouterr() assert "subdir/0.1: Hello World Release!" in out + class TestOsVersion: @darwin def test_os_version(self, capfd, chdir_build): @@ -242,3 +243,75 @@ def test_android_x86(self, capfd, chdir_build): assert "os=Android" in out assert "os.api_level=19" in out assert "tools.android:ndk_path=" in out + + +class TestiOS: + @darwin + def test_ios(self, capfd, chdir_build): + run("cmake .. --fresh -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=conan_provider.cmake -DCMAKE_BUILD_TYPE=Release " + "-DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_SYSTEM_NAME=iOS " + "-DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0") + out, _ = capfd.readouterr() + assert "arch=armv8" in out + assert "os=iOS" in out + assert "os.sdk=iphoneos" in out + assert "os.version=11.0" in out + + @darwin + def test_ios_simulator(self, capfd, chdir_build): + run("cmake .. --fresh -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=conan_provider.cmake -G Xcode " + "-DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_SYSTEM_NAME=iOS " + "-DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0") + out, _ = capfd.readouterr() + assert "arch=x86_64" in out + assert "os=iOS" in out + assert "os.sdk=iphonesimulator" in out + assert "os.version=11.0" in out + + +class TestTvOS: + @darwin + def test_tvos(self, capfd, chdir_build): + run("cmake .. --fresh -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=conan_provider.cmake -G Xcode " + "-DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_SYSTEM_NAME=tvOS " + "-DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=15.0") + out, _ = capfd.readouterr() + assert "arch=armv8" in out + assert "os=tvOS" in out + assert "os.sdk=appletvos" in out + assert "os.version=15.0" in out + + @darwin + def test_tvos_simulator(self, capfd, chdir_build): + run("cmake .. --fresh -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=conan_provider.cmake -DCMAKE_BUILD_TYPE=Release " + "-DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_SYSTEM_NAME=tvOS " + "-DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=15.0") + out, _ = capfd.readouterr() + assert "arch=armv8" in out + assert "os=tvOS" in out + assert "os.sdk=appletvsimulator" in out + assert "os.version=15.0" in out + + +class TestWatchOS: + @darwin + def test_watchos(self, capfd, chdir_build): + run("cmake .. --fresh -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=conan_provider.cmake -DCMAKE_BUILD_TYPE=Release -G Ninja " + "-DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_SYSTEM_NAME=watchOS " + "-DCMAKE_OSX_SYSROOT=watchos -DCMAKE_OSX_DEPLOYMENT_TARGET=7.0") + out, _ = capfd.readouterr() + assert "arch=armv8" in out + assert "os=watchOS" in out + assert "os.sdk=watchos" in out + assert "os.version=7.0" in out + + @darwin + def test_watchos_simulator(self, capfd, chdir_build): + run("cmake .. --fresh -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=conan_provider.cmake -G Xcode " + "-DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_SYSTEM_NAME=watchOS " + "-DCMAKE_OSX_SYSROOT=watchsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=7.0") + out, _ = capfd.readouterr() + assert "arch=x86_64" in out + assert "os=watchOS" in out + assert "os.sdk=watchsimulator" in out + assert "os.version=7.0" in out From b1e7f427638b465954284383874d79e01b3c69c4 Mon Sep 17 00:00:00 2001 From: Steve Robinson Date: Tue, 11 Jul 2023 23:35:41 -0700 Subject: [PATCH 2/6] Fix spelling error --- conan_provider.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conan_provider.cmake b/conan_provider.cmake index a970b692..494cc44b 100644 --- a/conan_provider.cmake +++ b/conan_provider.cmake @@ -59,7 +59,7 @@ endfunction() function(detect_arch ARCH) # CMAKE_OSX_ARCHITECTURES can contain multiple architectures, but Conan only supports one. - # Therefore this code only finds one. If the recipes support mulitple architectures, the + # Therefore this code only finds one. If the recipes support multiple architectures, the # build will work. Otherwise, there will be a linker error for the missing architecture(s). if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64|arm64" OR CMAKE_OSX_ARCHITECTURES MATCHES arm64) set(_ARCH armv8) From d04565845bccd365e9d28043bfc795b9178066c4 Mon Sep 17 00:00:00 2001 From: Steve Robinson Date: Tue, 11 Jul 2023 23:38:25 -0700 Subject: [PATCH 3/6] Shorten if statement and omit macOS --- conan_provider.cmake | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/conan_provider.cmake b/conan_provider.cmake index 494cc44b..31543a6c 100644 --- a/conan_provider.cmake +++ b/conan_provider.cmake @@ -23,10 +23,7 @@ function(detect_os OS OS_API_LEVEL OS_SDK OS_SUBSYSTEM OS_VERSION) message(STATUS "CMake-Conan: android_platform=${ANDROID_PLATFORM}") set(${OS_API_LEVEL} ${_OS_API_LEVEL} PARENT_SCOPE) endif() - if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR - ${CMAKE_SYSTEM_NAME} STREQUAL "iOS" OR - ${CMAKE_SYSTEM_NAME} STREQUAL "tvOS" OR - ${CMAKE_SYSTEM_NAME} STREQUAL "watchOS") + if(CMAKE_SYSTEM_NAME MATCHES "iOS|tvOS|watchOS") if(DEFINED CMAKE_OSX_SYSROOT) # CMAKE_OSX_SYSROOT contains the full path to the SDK for MakeFile/Ninja # generators, but just has the original input string for Xcode. Use the From c36a135c4f010deaf2a4758ab0e8b888a463f144 Mon Sep 17 00:00:00 2001 From: Steve Robinson Date: Wed, 12 Jul 2023 00:00:32 -0700 Subject: [PATCH 4/6] Put Darwin back, otherwise, os.version isn't set for macOS --- conan_provider.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conan_provider.cmake b/conan_provider.cmake index 31543a6c..db988866 100644 --- a/conan_provider.cmake +++ b/conan_provider.cmake @@ -23,7 +23,7 @@ function(detect_os OS OS_API_LEVEL OS_SDK OS_SUBSYSTEM OS_VERSION) message(STATUS "CMake-Conan: android_platform=${ANDROID_PLATFORM}") set(${OS_API_LEVEL} ${_OS_API_LEVEL} PARENT_SCOPE) endif() - if(CMAKE_SYSTEM_NAME MATCHES "iOS|tvOS|watchOS") + if(CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|tvOS|watchOS") if(DEFINED CMAKE_OSX_SYSROOT) # CMAKE_OSX_SYSROOT contains the full path to the SDK for MakeFile/Ninja # generators, but just has the original input string for Xcode. Use the From 302b252d565e7f76ae891b9778909a11f709ebb0 Mon Sep 17 00:00:00 2001 From: Steve Robinson Date: Wed, 12 Jul 2023 22:24:59 -0700 Subject: [PATCH 5/6] Refactor OS_SDK setting --- conan_provider.cmake | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/conan_provider.cmake b/conan_provider.cmake index db988866..7d756738 100644 --- a/conan_provider.cmake +++ b/conan_provider.cmake @@ -24,24 +24,25 @@ function(detect_os OS OS_API_LEVEL OS_SDK OS_SUBSYSTEM OS_VERSION) set(${OS_API_LEVEL} ${_OS_API_LEVEL} PARENT_SCOPE) endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|tvOS|watchOS") - if(DEFINED CMAKE_OSX_SYSROOT) - # CMAKE_OSX_SYSROOT contains the full path to the SDK for MakeFile/Ninja - # generators, but just has the original input string for Xcode. Use the - # lowercase form to detect both. - string(TOLOWER ${CMAKE_OSX_SYSROOT} cmake_os_sysroot_lower) - if(cmake_os_sysroot_lower MATCHES appletvos) - set(_OS_SDK appletvos) - elseif(cmake_os_sysroot_lower MATCHES appletvsimulator) - set(_OS_SDK appletvsimulator) - elseif(cmake_os_sysroot_lower MATCHES iphoneos) - set(_OS_SDK iphoneos) - elseif(cmake_os_sysroot_lower MATCHES iphonesimulator) - set(_OS_SDK iphonesimulator) - elseif(cmake_os_sysroot_lower MATCHES watchos) - set(_OS_SDK watchos) - elseif(cmake_os_sysroot_lower MATCHES watchsimulator) - set(_OS_SDK watchsimulator) + # CMAKE_OSX_SYSROOT contains the full path to the SDK for MakeFile/Ninja + # generators, but just has the original input string for Xcode. + if(NOT IS_DIRECTORY ${CMAKE_OSX_SYSROOT}) + set(_OS_SDK ${CMAKE_OSX_SYSROOT}) + else() + if(CMAKE_OSX_SYSROOT MATCHES Simulator) + set(apple_platform_suffix simulator) + else() + set(apple_platform_suffix os) endif() + if(CMAKE_OSX_SYSROOT MATCHES AppleTV) + set(_OS_SDK "appletv${apple_platform_suffix}") + elseif(CMAKE_OSX_SYSROOT MATCHES iPhone) + set(_OS_SDK "iphone${apple_platform_suffix}") + elseif(CMAKE_OSX_SYSROOT MATCHES Watch) + set(_OS_SDK "watch${apple_platform_suffix}") + endif() + endif() + if(DEFINED _OS_SDK) message(STATUS "CMake-Conan: cmake_osx_sysroot=${CMAKE_OSX_SYSROOT}") set(${OS_SDK} ${_OS_SDK} PARENT_SCOPE) endif() From 3f50f15e352725c2ae5f0277507743da3e166d69 Mon Sep 17 00:00:00 2001 From: Steve Robinson Date: Wed, 12 Jul 2023 23:40:28 -0700 Subject: [PATCH 6/6] Add warning about multiple architectures in CMAKE_OSX_ARCHITECTURES --- conan_provider.cmake | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/conan_provider.cmake b/conan_provider.cmake index 7d756738..d804d5f9 100644 --- a/conan_provider.cmake +++ b/conan_provider.cmake @@ -59,6 +59,13 @@ function(detect_arch ARCH) # CMAKE_OSX_ARCHITECTURES can contain multiple architectures, but Conan only supports one. # Therefore this code only finds one. If the recipes support multiple architectures, the # build will work. Otherwise, there will be a linker error for the missing architecture(s). + if(DEFINED CMAKE_OSX_ARCHITECTURES) + string(REPLACE " " ";" apple_arch_list "${CMAKE_OSX_ARCHITECTURES}") + list(LENGTH apple_arch_list apple_arch_count) + if(apple_arch_count GREATER 1) + message(WARNING "CMake-Conan: Multiple architectures detected, this will only work if Conan recipe(s) produce fat binaries.") + endif() + endif() if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64|arm64" OR CMAKE_OSX_ARCHITECTURES MATCHES arm64) set(_ARCH armv8) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7-a|armv7l" OR CMAKE_OSX_ARCHITECTURES MATCHES armv7)