Repository: conan-io/conan
Pull request: [feature] Mandatory `os.sdk` for CMakeToolchain (only `AppleSystemBlock` block)
Changelog: Feature: `os.sdk` field is mandatory for CMakeToolchain and OS in `('Macos', 'iOS', 'watchOS', 'tvOS')`.
Docs: omit

Closes: https://github.com/conan-io/conan/issues/10275

- [x] Refer to the issue that supports this Pull Request.
- [x] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
- [x] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).
- [x] I've followed the PEP8 style guides for Python code.
- [ ] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one. 

<sup>**Note:** By default this PR will skip the slower tests and will use a limited set of python versions. Check [here](https://github.com/conan-io/conan/blob/develop/.github/PR_INCREASE_TESTING.md) how to increase the testing level by writing some tags in the current PR body text.</sup>


Problem statement:
[bug][2.0] CMakeToolchain does not respect os.sdk when targeting armv8 iOS simulator
Hello,

I'm trying to cross-build some iOS recipes, and I think there's a bug in CMakeToolchain. I use this profile:

```ini
[settings]
os=iOS
os.version=9.0
os.sdk=iphonesimulator
build_type=Release
arch=armv8
compiler=apple-clang
compiler.version=13.0
compiler.libcxx=libc++
compiler.cppstd=17
```

The `test_package` step fails with the following error:

```
ld: in /Users/theo/.conan2/p/f92ba1e43ba51502/p/lib/libsodium.a(libsodium_la-core.o), building for iOS, but linking in object file built for iOS Simulator, for architecture arm64
```

The generated `conan_toolchain.cmake` contains the following line:

>set(CMAKE_OSX_SYSROOT iphoneos CACHE STRING "" FORCE)

This does not happen when setting `arch=x86_64`, `CMAKE_OSX_SYSROOT` being correctly set to `iphonesimulator` in this case.

Hints from issue discussion:
Thanks for reporting, indeed it seems a bug. I think that it should be reproducible in 1.X, so I am targeting this for 1.45 (and it will be automatically merged to 2.0)

Commit message: Solved bug if os.sdk is passed

Patch to review:
diff --git a/conan/tools/cmake/toolchain.py b/conan/tools/cmake/toolchain.py
index 28dc058030a..9472a980938 100644
--- a/conan/tools/cmake/toolchain.py
+++ b/conan/tools/cmake/toolchain.py
@@ -356,7 +356,10 @@ def _apple_sdk_name(self):
         we're building for (considering simulators)"""
         arch = self._conanfile.settings.get_safe('arch')
         os_ = self._conanfile.settings.get_safe('os')
-        if arch.startswith('x86'):
+        os_sdk = self._conanfile.settings.get_safe('os.sdk')
+        if os_sdk:
+            return os_sdk
+        elif arch.startswith('x86'):
             return {'Macos': 'macosx',
                     'iOS': 'iphonesimulator',
                     'watchOS': 'watchsimulator',
diff --git a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
index 13f5c0905b0..95de7612611 100644
--- a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
+++ b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
@@ -351,3 +351,36 @@ def test_libcxx_abi_flag():
     toolchain = CMakeToolchain(c)
     content = toolchain.content
     assert '-D_GLIBCXX_USE_CXX11_ABI=1' in content
+
+
+@pytest.mark.parametrize("os,os_sdk,arch,expected_sdk", [
+    ("iOS", None, "x86_64", "iphonesimulator"),
+    ("iOS", None, "armv8", "iphoneos"),
+    ("iOS", "iphonesimulator", "armv8", "iphonesimulator"),
+    ("watchOS", None, "armv8", "watchos"),
+    ("watchOS", "watchsimulator", "armv8", "watchsimulator")
+])
+def test_apple_cmake_osx_sysroot(os, os_sdk, arch, expected_sdk):
+    """
+    Testing if CMAKE_OSX_SYSROOT is correctly set.
+    Issue related: https://github.com/conan-io/conan/issues/10275
+    """
+    c = ConanFile(Mock(), None)
+    c.settings = "os", "compiler", "build_type", "arch"
+    c.initialize(Settings.loads(get_default_settings_yml()), EnvValues())
+    c.settings.os = os
+    c.settings.os.sdk = os_sdk
+    c.settings.build_type = "Release"
+    c.settings.arch = arch
+    c.settings.compiler = "apple-clang"
+    c.settings.compiler.version = "13.0"
+    c.settings.compiler.libcxx = "libc++"
+    c.settings.compiler.cppstd = "17"
+    c.conf = Conf()
+    c.folders.set_base_generators(".")
+    c._conan_node = Mock()
+    c._conan_node.dependencies = []
+
+    toolchain = CMakeToolchain(c)
+    content = toolchain.content
+    assert 'set(CMAKE_OSX_SYSROOT %s CACHE STRING "" FORCE)' % expected_sdk in content


Code review comments:
diff_hunk: @@ -356,7 +356,10 @@ def _apple_sdk_name(self):
         we're building for (considering simulators)"""
         arch = self._conanfile.settings.get_safe('arch')
         os_ = self._conanfile.settings.get_safe('os')
-        if arch.startswith('x86'):
+        os_sdk = self._conanfile.settings.get_safe('os.sdk')
+        if os_sdk:
+            return os_sdk
+        elif arch.startswith('x86'):
path: conan/tools/cmake/toolchain.py
text: @user1:
Better force the definition of ``os.sdk``?

The thing is that we don't want to auto-deduce it is a simulator. The binary is different, it should have a different package_id, and for that it should have the setting properly defined. It might not be robust relying on the architecture to deduce this. 

It might be necessary to implement the logic of ``Macos`` => ``macosx`` as there is no other sdk for it, but for iOS, watchOS, tvOS, it should be mandatory to be defined in settings.

@author:
Yeah, you're right but it sounds like a breaking change, doesn't it? Should we make that change in another PR?


@author:
Or could we even introduce that change for Conan 2.x?

@user1:
This is ``CMakeToolchain``, which is experimental. It might be fine to make it only work with the 2.0-ready behavior, and fail otherwise, even if it is "breaking" (I don't think it is a huge issue, as it boils down to add the sdk in your profiles or command line, not needing to modify recipes, and it is not that CMakeToolchain for iOS is that extended yet either.

@author:
Definitely, yes, let's do that for all the cases 1.x and 2.x.