Repository: conan-io/conan
Pull request: Add new sdk_version setting for Apple OS's and new XcodeBuild, XcodeToolchain tools
Changelog: Feature: Add `sdk_version` setting for `Macos`, `iOS`, `watchOS` and `tvOS`.
Changelog: Feature: Add new `XcodeBuild` build helper.
Changelog: Feature: Add new `XcodeToolchain` helper.
Docs: https://github.com/conan-io/docs/pull/2431

Closes: https://github.com/conan-io/conan/issues/9608

Superseeds: https://github.com/conan-io/conan/pull/9873


#TAGS: slow

Problem statement:
[feature] SDK Version for apple OSes
This is the second year Apple has made a major change to the SDK within the same major release of Xcode.
With Xcode 12.0 Apple shipped macOS SDK 10.15 and with Xcode 12.1 they changed it to macOS SDK 11.0.
Now it looks the same (probably because iOS 15 came out earlier than macOS 12)
Xcode 13.0 comes with macOS SDK 11.0 and it is sure that one of the next minor updates, probably 13.1, will bring us macOS SDK 12.

Changing an SDK is a big deal as it removes APIs, brings new APIs and can give changes in the behavior of your application. So it's time to have the ability to differentiate Conan packages by SDK version.
The same is true for all other Apple operating systems.

I can add an option myself, or it can become an additional setting under OS

my suggestion would be, these additions in the settings.yml

```
    Macos:
        version: [None, "10.6", "10.7", "10.8", "10.9", "10.10", "10.11", "10.12", "10.13", "10.14", "10.15", "11.0", "12.0"]
        sdk: [None, "macosx"]
        **sdk_version: ANY**    
        subsystem: [None, catalyst]
    iOS:
        version: ["7.0", "7.1", "8.0", "8.1", "8.2", "8.3", "9.0", "9.1", "9.2", "9.3", "10.0", "10.1", "10.2", "10.3", "11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1", "12.2", "12.3", "12.4", "13.0", "13.1", "13.2", "13.3", "13.4",$
        sdk: [None, "iphoneos", "iphonesimulator"]
        **sdk_version: ANY**    
    watchOS:
        version: ["4.0", "4.1", "4.2", "4.3", "5.0", "5.1", "5.2", "5.3", "6.0", "6.1"]
        sdk: [None, "watchos", "watchsimulator"]
        **sdk_version: ANY**    
    tvOS:
        version: ["11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1", "12.2", "12.3", "12.4", "13.0"]
        sdk: [None, "appletvos", "appletvsimulator"]
        **sdk_version: ANY**    
```

A consumer of such a package must have the same or higher sdk_version, otherwise there will be linker warnings.
Within a dependency tree there should be no differences in sdk_version for the same package

Hints from issue discussion:
Thanks for reporting the issue @NoWiseMan 

Let me know more about your use case. Have you faced any problem consuming any package at some point?
Adding it directly to the current Conan settings is not such a simple thing I'm afraid. The settings are part of the final `package_id` so we must be careful adding new ones to the existing recipes because we would need to update all of them. That's talking about a global change in Conan repository but you could make it easier for your personal use case.
It would be enough to use customized settings I guess. Some useful links here:
* https://docs.conan.io/en/latest/extending/custom_settings.html#custom-settings
* https://docs.conan.io/en/latest/howtos/sanitizers.html?#adding-custom-settings
* https://docs.conan.io/en/latest/reference/commands/consumer/config.html#conan-config-install
Thank you for your very fast response.

Yes, custom settings also work. But I see no real difference between custom settings and an option.

But there is a big difference when conan gives an error when the consumer has a lower SDK version than the package.

Apple platforms have, say, this triple of important values.
- Compiler version (due to ABI changes in C++).
- Deployment Target (the minimum version of the operating system required to run the software, which can heavily change the way the dynamic linker works, for example).
- SDK version, this was closely tied to the Xcode version, but this is now no longer certain.
- (Swift version, but we can ignore that for now).

**compiler version** has an equivalent in conan, since it is linked to **settings.compiler.version**.
**development target** has an equivalent in conan, since it is linked to **settings.os.version**
but the SDK version has no equivalent in conan

We have had this problem since last year. Xcode 12.0 came with macOS SDK 10.15, and Xcode 12.1 brought macOS SDK 11.0 (with support for ARM, and some new APIs).
We worked around this problem by adding an SDK_version as an option to our conan packages. A "native" support for the SDK version would be more appealing, and defining only 2 of the 3 dependencies can lead to issues

Oh I forget:

The SDK version, can change the behaviour of the whole application
Thanks for your great explanation.

Yeah, you're right and it could make sense to have it "natively".
Let me have a look into this issue and I'll bring you some news asap.

We might want to generalize any solution here. I've had a similar problem on Linux where I need to support RHEL 6 with has a very old version of `glibc`. So maybe some generic solution would allow a setting for `sdk` version on Mac, `libc` version of Linux, and there is probably something similar on Windows?
@dheater The problem with this fine grained subsettings, like something for ``libc`` is that they force you into an exact version. Settings do not have ranges of values, every ``libc`` will give you a new binary. This might be ok if you want to work with exact libc version all around, but in practice this is not the common thing, but to work with ranges of libc (typical RHEL6 with older libc, modern Debian with modern libc). But the ``libc`` version is not a good solution.

As @NoWiseMan is commenting the Apple SDKs seems to be exact matches, as they add new behavior, but can also remove APIs, and completely break. So consumers might want to make sure they all match an exact SDK, always. So I am not sure this can be generalized to the Linux libc one without causing there more pain than the one it tries to solve.
For Mac development I am specifying the minimum SDK. I can build with a newer SDK and it seems to provide backwards compatibility.  In my profile:
```
[env]
CFLAGS=-mmacosx-version-min=10.15
```

@NoWiseMan could please you confirm the above ``Changing an SDK is a big deal as it removes APIs, ``? Because that means the SDK doesn't provide backwards compatibility.

@dheater Regarding ``CFLAGS=-mmacosx-version-min=10.15``, that is the OS version, not the SDK one, isn't it? (I am no Mac user). Conan toolchains will map the ``os.version`` setting to this compiler flag. The OS might indeed have backwards (mostly runtime) compatibility, while the SDK (mostly buildtime) might not. 
We finally decided to wait a bit, until we release the Xcode toolchain and build helper and have more information about how everything works with the Apple sdk's so I'm moving this 1.43 milestone.
@memsharded Yes, it is possible for an API to be removed, added, or deprecated. There may also be different behavior of the API that is still present. This is more likely in the higher layers of AppKit than in the API for C++ libraries. But yes, there can be big changes.

@dheater
mmacosx-version-min is a different thing, it sets the min os version on which the lib/app runs. This will change the commands used by the dynamic linker for example. 
And as memsharded said this is mapped to os.version, so I see no need to have this in the envoirment

Commit message: remove test

Patch to review:
diff --git a/conan/tools/apple/__init__.py b/conan/tools/apple/__init__.py
index 06c11573a73..b3a7cb5a388 100644
--- a/conan/tools/apple/__init__.py
+++ b/conan/tools/apple/__init__.py
@@ -6,3 +6,5 @@
 # from conan.tools.apple.apple import apple_deployment_target_flag
 # from conan.tools.apple.apple import to_apple_arch
 from conan.tools.apple.xcodedeps import XcodeDeps
+from conan.tools.apple.xcodebuild import XcodeBuild
+from conan.tools.apple.xcodetoolchain import XcodeToolchain
diff --git a/conan/tools/apple/apple.py b/conan/tools/apple/apple.py
index e53a1dbf825..977d44b4207 100644
--- a/conan/tools/apple/apple.py
+++ b/conan/tools/apple/apple.py
@@ -41,7 +41,8 @@ def apple_sdk_name(settings):
     arch = settings.get_safe('arch')
     os_ = settings.get_safe('os')
     os_sdk = settings.get_safe('os.sdk')
-    return os_sdk or _guess_apple_sdk_name(os_, arch)
+    os_sdk_version = settings.get_safe('os.sdk_version') or ""
+    return "{}{}".format(os_sdk, os_sdk_version) or _guess_apple_sdk_name(os_, arch)
 
 
 def apple_min_version_flag(conanfile):
diff --git a/conan/tools/apple/xcodebuild.py b/conan/tools/apple/xcodebuild.py
new file mode 100644
index 00000000000..81f99d09c2c
--- /dev/null
+++ b/conan/tools/apple/xcodebuild.py
@@ -0,0 +1,39 @@
+import os
+
+from conan.tools.apple.apple import to_apple_arch
+from conans.errors import ConanException
+
+
+class XcodeBuild(object):
+    def __init__(self, conanfile):
+        self._conanfile = conanfile
+        self.build_type = conanfile.settings.get_safe("build_type")
+        self.arch = to_apple_arch(conanfile.settings.get_safe("arch"))
+        self.sdk = conanfile.settings.get_safe("os.sdk") or ""
+        self.sdk_version = conanfile.settings.get_safe("os.sdk_version") or ""
+        self.os_version = conanfile.settings.get_safe("os.version") or ""
+
+    @property
+    def verbosity(self):
+        verbosity = self._conanfile.conf["tools.apple.xcodebuild:verbosity"]
+        if not verbosity:
+            return ""
+        elif verbosity == "quiet" or verbosity == "verbose":
+            return "-{}".format(verbosity)
+        else:
+            raise ConanException("Value {} for 'tools.apple.xcodebuild:verbosity' is not valid".format(verbosity))
+
+    @property
+    def sdkroot(self):
+        # User's sdk_path has priority, then if specified try to compose sdk argument
+        # with sdk/sdk_version settings, leave blank otherwise and the sdk will be automatically
+        # chosen by the build system
+        sdk = self._conanfile.conf["tools.apple:sdk_path"]
+        if not sdk and self.sdk:
+            sdk = "{}{}".format(self.sdk, self.sdk_version)
+        return "SDKROOT={}".format(sdk) if sdk else ""
+
+    def build(self, xcodeproj):
+        cmd = "xcodebuild -project {} -configuration {} -arch {} " \
+              "{} {}".format(xcodeproj, self.build_type, self.arch, self.sdkroot, self.verbosity)
+        self._conanfile.run(cmd)
diff --git a/conan/tools/apple/xcodedeps.py b/conan/tools/apple/xcodedeps.py
index 2dd2a887842..e2cb2ff5c52 100644
--- a/conan/tools/apple/xcodedeps.py
+++ b/conan/tools/apple/xcodedeps.py
@@ -8,22 +8,44 @@
 from conans.util.files import load, save
 from conan.tools.apple.apple import to_apple_arch
 
+GLOBAL_XCCONFIG_TEMPLATE = textwrap.dedent("""\
+    // Includes both the toolchain and the dependencies
+    // files if they exist
+
+    """)
+
+GLOBAL_XCCONFIG_FILENAME = "conan_config.xcconfig"
+
+
+def _add_include_to_file_or_create(filename, template, include):
+    if os.path.isfile(filename):
+        content = load(filename)
+    else:
+        content = template
+
+    if include not in content:
+        content = content + '#include "{}"'.format(include) + "\n"
+
+    return content
+
 
 class XcodeDeps(object):
+    general_name = "conandeps.xcconfig"
+
     _vars_xconfig = textwrap.dedent("""\
         // Definition of Conan variables for {{name}}
-        CONAN_{{name}}_BINARY_DIRECTORIES[config={{configuration}}][arch={{architecture}}] = {{bin_dirs}}
-        CONAN_{{name}}_C_COMPILER_FLAGS[config={{configuration}}][arch={{architecture}}] = {{c_compiler_flags}}
-        CONAN_{{name}}_CXX_COMPILER_FLAGS[config={{configuration}}][arch={{architecture}}] = {{cxx_compiler_flags}}
-        CONAN_{{name}}_LINKER_FLAGS[config={{configuration}}][arch={{architecture}}] = {{linker_flags}}
-        CONAN_{{name}}_PREPROCESSOR_DEFINITIONS[config={{configuration}}][arch={{architecture}}] = {{definitions}}
-        CONAN_{{name}}_INCLUDE_DIRECTORIES[config={{configuration}}][arch={{architecture}}] = {{include_dirs}}
-        CONAN_{{name}}_RESOURCE_DIRECTORIES[config={{configuration}}][arch={{architecture}}] = {{res_dirs}}
-        CONAN_{{name}}_LIBRARY_DIRECTORIES[config={{configuration}}][arch={{architecture}}] = {{lib_dirs}}
-        CONAN_{{name}}_LIBRARIES[config={{configuration}}][arch={{architecture}}] = {{libs}}
-        CONAN_{{name}}_SYSTEM_LIBS[config={{configuration}}][arch={{architecture}}] = {{system_libs}}
-        CONAN_{{name}}_FRAMEWORKS_DIRECTORIES[config={{configuration}}][arch={{architecture}}] = {{frameworkdirs}}
-        CONAN_{{name}}_FRAMEWORKS[config={{configuration}}][arch={{architecture}}] = {{frameworks}}
+        CONAN_{{name}}_BINARY_DIRECTORIES{{condition}} = {{bin_dirs}}
+        CONAN_{{name}}_C_COMPILER_FLAGS{{condition}} = {{c_compiler_flags}}
+        CONAN_{{name}}_CXX_COMPILER_FLAGS{{condition}} = {{cxx_compiler_flags}}
+        CONAN_{{name}}_LINKER_FLAGS{{condition}} = {{linker_flags}}
+        CONAN_{{name}}_PREPROCESSOR_DEFINITIONS{{condition}} = {{definitions}}
+        CONAN_{{name}}_INCLUDE_DIRECTORIES{{condition}} = {{include_dirs}}
+        CONAN_{{name}}_RESOURCE_DIRECTORIES{{condition}} = {{res_dirs}}
+        CONAN_{{name}}_LIBRARY_DIRECTORIES{{condition}} = {{lib_dirs}}
+        CONAN_{{name}}_LIBRARIES{{condition}} = {{libs}}
+        CONAN_{{name}}_SYSTEM_LIBS{{condition}} = {{system_libs}}
+        CONAN_{{name}}_FRAMEWORKS_DIRECTORIES{{condition}} = {{frameworkdirs}}
+        CONAN_{{name}}_FRAMEWORKS{{condition}} = {{frameworks}}
         """)
 
     _conf_xconfig = textwrap.dedent("""\
@@ -70,15 +92,20 @@ class XcodeDeps(object):
     def __init__(self, conanfile):
         self._conanfile = conanfile
         self.configuration = conanfile.settings.get_safe("build_type")
-
         arch = conanfile.settings.get_safe("arch")
         self.architecture = to_apple_arch(arch) or arch
-
-        # TODO: check if it makes sense to add a subsetting for sdk version
-        #  related to: https://github.com/conan-io/conan/issues/9608
         self.os_version = conanfile.settings.get_safe("os.version")
+        self.sdk = conanfile.settings.get_safe("os.sdk")
+        self.sdk_version = conanfile.settings.get_safe("os.sdk_version")
         check_using_build_profile(self._conanfile)
 
+    @property
+    def sdk_condition(self):
+        if self.sdk:
+            sdk = "{}{}".format(self.sdk, self.sdk_version or "*")
+            return sdk
+        return "*"
+
     def generate(self):
         if self.configuration is None:
             raise ConanException("XcodeDeps.configuration is None, it should have a value")
@@ -91,21 +118,22 @@ def generate(self):
     def _config_filename(self):
         # Default name
         props = [("configuration", self.configuration),
-                 ("architecture", self.architecture)]
-        name = "".join("_{}".format(v) for _, v in props if v is not None)
+                 ("architecture", self.architecture),
+                 ("sdk name", self.sdk),
+                 ("sdk version", self.sdk_version)]
+        name = "".join("_{}".format(v) for _, v in props if v is not None and v)
+        name = name.replace(".", "_").replace("-", "_")
         return name.lower()
 
     def _vars_xconfig_file(self, dep, name, cpp_info):
         """
-        content for conan_vars_poco_x86_release.xcconfig, containing the variables
+        returns a .xcconfig file with the variables definition for one package for one configuration
         """
-        # returns a .xcconfig file with the variables definition for one package for one configuration
 
-        pkg_placeholder = "$(CONAN_{}_ROOT_FOLDER_{})/".format(name, self.configuration)
+        condition = "[config={}][arch={}][sdk={}]".format(self.configuration, self.architecture,
+                                                          self.sdk_condition)
         fields = {
             'name': name,
-            'configuration': self.configuration,
-            'architecture': self.architecture,
             'root_folder': dep.package_folder,
             'bin_dirs': " ".join('"{}"'.format(os.path.join(dep.package_folder, p)) for p in cpp_info.bindirs),
             'res_dirs': " ".join('"{}"'.format(os.path.join(dep.package_folder, p)) for p in cpp_info.resdirs),
@@ -120,6 +148,7 @@ def _vars_xconfig_file(self, dep, name, cpp_info):
             'cxx_compiler_flags': " ".join(cpp_info.cxxflags),
             'linker_flags': " ".join(cpp_info.sharedlinkflags),
             'exe_flags': " ".join(cpp_info.exelinkflags),
+            'condition': condition
         }
         formatted_template = Template(self._vars_xconfig).render(**fields)
         return formatted_template
@@ -128,11 +157,6 @@ def _conf_xconfig_file(self, dep_name, vars_xconfig_name):
         """
         content for conan_poco_x86_release.xcconfig, containing the activation
         """
-        # TODO: when it's more clear what to do with the sdk, add the condition for it and also
-        #  we are not taking into account the version for the sdk because we probably
-        #  want to model also the sdk version decoupled of the compiler version
-        #  for example XCode 13 is now using sdk=macosx11.3
-        #  related to: https://github.com/conan-io/conan/issues/9608
         template = Template(self._conf_xconfig)
         content_multi = template.render(name=dep_name, vars_filename=vars_xconfig_name)
         return content_multi
@@ -166,9 +190,14 @@ def _all_xconfig_file(self, deps):
             content_multi = content_multi + '\n#include "conan_{}.xcconfig"\n'.format(dep_name)
         return content_multi
 
+    @property
+    def _global_xconfig_content(self):
+        return _add_include_to_file_or_create(GLOBAL_XCCONFIG_FILENAME,
+                                              GLOBAL_XCCONFIG_TEMPLATE,
+                                              self.general_name)
+
     def _content(self):
         result = {}
-        general_name = "conandeps.xcconfig"
         conf_name = self._config_filename()
 
         for dep in self._conanfile.dependencies.host.values():
@@ -191,6 +220,8 @@ def _content(self):
 
         # Include all direct build_requires for host context.
         direct_deps = self._conanfile.dependencies.filter({"direct": True, "build": False})
-        result[general_name] = self._all_xconfig_file(direct_deps)
+        result[self.general_name] = self._all_xconfig_file(direct_deps)
+
+        result[GLOBAL_XCCONFIG_FILENAME] = self._global_xconfig_content
 
         return result
diff --git a/conan/tools/apple/xcodetoolchain.py b/conan/tools/apple/xcodetoolchain.py
new file mode 100644
index 00000000000..c6365259f94
--- /dev/null
+++ b/conan/tools/apple/xcodetoolchain.py
@@ -0,0 +1,111 @@
+import os
+import textwrap
+
+from conan.tools._check_build_profile import check_using_build_profile
+from conan.tools._compilers import cppstd_flag
+from conan.tools.apple.apple import to_apple_arch
+from conan.tools.apple.xcodedeps import GLOBAL_XCCONFIG_FILENAME, GLOBAL_XCCONFIG_TEMPLATE, \
+    _add_include_to_file_or_create
+from conans.util.files import save
+
+
+class XcodeToolchain(object):
+    filename = "conantoolchain"
+    extension = ".xcconfig"
+
+    _vars_xconfig = textwrap.dedent("""\
+        // Definition of toolchain variables
+        {macosx_deployment_target}
+        {clang_cxx_library}
+        {clang_cxx_language_standard}
+        """)
+
+    _agreggated_xconfig = textwrap.dedent("""\
+        // Conan XcodeToolchain generated file
+        // Includes all installed configurations
+
+        """)
+
+    def __init__(self, conanfile):
+        self._conanfile = conanfile
+        arch = conanfile.settings.get_safe("arch")
+        self.architecture = to_apple_arch(arch) or arch
+        self.configuration = conanfile.settings.build_type
+        self.sdk = conanfile.settings.get_safe("os.sdk")
+        self.sdk_version = conanfile.settings.get_safe("os.sdk_version")
+        self.libcxx = conanfile.settings.get_safe("compiler.libcxx")
+        self.os_version = conanfile.settings.get_safe("os.version")
+        check_using_build_profile(self._conanfile)
+
+    @property
+    def cppstd(self):
+        cppstd = cppstd_flag(self._conanfile.settings)
+        if cppstd.startswith("-std="):
+            return cppstd[5:]
+        return cppstd
+
+    @property
+    def macosx_deployment_target(self):
+        return 'MACOSX_DEPLOYMENT_TARGET{}={}'.format(self._var_condition,
+                                                      self.os_version) if self.os_version else ""
+
+    @property
+    def clang_cxx_library(self):
+        return 'CLANG_CXX_LIBRARY{}={}'.format(self._var_condition,
+                                               self.libcxx) if self.libcxx else ""
+
+    @property
+    def clang_cxx_language_standard(self):
+        return 'CLANG_CXX_LANGUAGE_STANDARD{}={}'.format(self._var_condition,
+                                                         self.cppstd) if self.cppstd else ""
+
+    def generate(self):
+        save(GLOBAL_XCCONFIG_FILENAME, self._global_xconfig_content)
+        save(self._agreggated_xconfig_filename, self._agreggated_xconfig_content)
+        save(self._vars_xconfig_filename, self._vars_xconfig_content)
+
+    @property
+    def _vars_xconfig_content(self):
+        ret = self._vars_xconfig.format(macosx_deployment_target=self.macosx_deployment_target,
+                                        clang_cxx_library=self.clang_cxx_library,
+                                        clang_cxx_language_standard=self.clang_cxx_language_standard)
+        return ret
+
+    @property
+    def _agreggated_xconfig_content(self):
+        return _add_include_to_file_or_create(self._agreggated_xconfig_filename,
+                                              self._agreggated_xconfig,
+                                              self._vars_xconfig_filename)
+
+    @property
+    def _global_xconfig_content(self):
+        return _add_include_to_file_or_create(GLOBAL_XCCONFIG_FILENAME,
+                                              GLOBAL_XCCONFIG_TEMPLATE,
+                                              self._agreggated_xconfig_filename)
+
+
+    @property
+    def _sdk_condition(self):
+        if self.sdk:
+            sdk = "{}{}".format(self.sdk, self.sdk_version or "*")
+            return sdk
+        return "*"
+
+    @property
+    def _var_condition(self):
+        return "[config={}][arch={}][sdk={}]".format(self.configuration, self.architecture,
+                                                     self._sdk_condition)
+
+    @property
+    def _vars_xconfig_filename(self):
+        props = [("configuration", self.configuration),
+                 ("architecture", self.architecture),
+                 ("sdk name", self.sdk),
+                 ("sdk version", self.sdk_version)]
+        name = "".join("_{}".format(v) for _, v in props if v is not None and v)
+        name = name.replace(".", "_").replace("-", "_")
+        return self.filename + name.lower() + self.extension
+
+    @property
+    def _agreggated_xconfig_filename(self):
+        return self.filename + self.extension
diff --git a/conan/tools/cmake/toolchain.py b/conan/tools/cmake/toolchain.py
index 9f549c87ce5..c2ac99f9bc7 100644
--- a/conan/tools/cmake/toolchain.py
+++ b/conan/tools/cmake/toolchain.py
@@ -354,17 +354,25 @@ def _get_architecture(self):
 
     def _apple_sdk_name(self):
         """
-        Returns the 'os.sdk' (SDK name) field value. Every user should specify it because
-        there could be several ones depending on the OS architecture.
+        Returns the value for the SDKROOT with this preference:
+        - 1. The full path set in the conf with tools.apple:sdk_path
+        - 2. osd.sdk + os.sdk_version
+        Otherwise None
+        Every user should specify it because there could be several ones depending
+        on the OS architecture.
 
         Note: In case of MacOS it'll be the same for all the architectures.
         """
         os_ = self._conanfile.settings.get_safe('os')
         os_sdk = self._conanfile.settings.get_safe('os.sdk')
-        if os_sdk:
-            return os_sdk
-        elif os_ == "Macos":  # it has only a single value for all the architectures for now
-            return "macosx"
+        os_sdk_version = self._conanfile.settings.get_safe('os.sdk_version') or ""
+        sdk = self._conanfile.conf["tools.apple:sdk_path"]
+
+        if sdk:
+            return sdk
+        elif os_sdk or os_ == "Macos":
+            sdk_name = os_sdk or "macosx"  # if the host is Macos if can only be "macosx"
+            return "{}{}".format(sdk_name, os_sdk_version)
         else:
             raise ConanException("Please, specify a suitable value for os.sdk.")
 
diff --git a/conan/tools/meson/toolchain.py b/conan/tools/meson/toolchain.py
index 58b7f3da465..724f517e5ec 100644
--- a/conan/tools/meson/toolchain.py
+++ b/conan/tools/meson/toolchain.py
@@ -3,7 +3,8 @@
 from jinja2 import Template
 
 from conan.tools._check_build_profile import check_using_build_profile
-from conan.tools.apple.apple import to_apple_arch, is_apple_os, apple_min_version_flag
+from conan.tools.apple.apple import to_apple_arch, is_apple_os, apple_min_version_flag, \
+    apple_sdk_path
 from conan.tools.cross_building import cross_building, get_cross_building_settings
 from conan.tools.env import VirtualBuildEnv
 from conan.tools.meson.helpers import *
@@ -154,7 +155,7 @@ def _add_apple_flags(self):
             return
 
         # SDK path is mandatory for cross-building
-        sdk_path = conanfile.conf["tools.apple:sdk_path"]
+        sdk_path = apple_sdk_path(conanfile)
         if not sdk_path and self.cross_build:
             raise ConanException("You must provide a valid SDK path for cross-compilation.")
 
diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py
index 25da6590094..7b0edb2d9a1 100644
--- a/conans/client/conf/__init__.py
+++ b/conans/client/conf/__init__.py
@@ -37,6 +37,7 @@
         Macos:
             version: [None, "10.6", "10.7", "10.8", "10.9", "10.10", "10.11", "10.12", "10.13", "10.14", "10.15", "11.0", "12.0", "13.0"]
             sdk: [None, "macosx"]
+            sdk_version: [None, "10.13", "10.14", "10.15", "11.0", "11.1", "11.3", "12.0", "12.1"]
             subsystem: [None, catalyst]
         Android:
             api_level: ANY
@@ -46,15 +47,22 @@
                       "13.0", "13.1", "13.2", "13.3", "13.4", "13.5", "13.6", "13.7",
                       "14.0", "14.1", "14.2", "14.3", "14.4", "14.5", "14.6", "14.7", "14.8", "15.0", "15.1"]
             sdk: [None, "iphoneos", "iphonesimulator"]
+            sdk_version: [None, "11.3", "11.4", "12.0", "12.1", "12.2", "12.4",
+                          "13.0", "13.1", "13.2", "13.4", "13.5", "13.6", "13.7",
+                          "14.0", "14.1", "14.2", "14.3", "14.4", "14.5", "15.0", "15.2"]
         watchOS:
             version: ["4.0", "4.1", "4.2", "4.3", "5.0", "5.1", "5.2", "5.3", "6.0", "6.1", "6.2",
                       "7.0", "7.1", "7.2", "7.3", "7.4", "7.5", "7.6", "8.0", "8.1"]
             sdk: [None, "watchos", "watchsimulator"]
+            sdk_version: [None, "4.3", "5.0", "5.1", "5.2", "5.3", "6.0", "6.1", "6.2",
+                          "7.0", "7.1", "7.2", "7.4", "8.0", "8.0.1", "8.3"]
         tvOS:
             version: ["11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1", "12.2", "12.3", "12.4",
                       "13.0", "13.2", "13.3", "13.4", "14.0", "14.2", "14.3", "14.4", "14.5", "14.6", "14.7",
                       "15.0", "15.1"]
             sdk: [None, "appletvos", "appletvsimulator"]
+            sdk_version: [None, "11.3", "11.4", "12.0", "12.1", "12.2", "12.4",
+                          "13.0", "13.1", "13.2", "13.4", "14.0", "14.2", "14.3", "14.5", "15.0", "15.2"]
         FreeBSD:
         SunOS:
         AIX:
diff --git a/conans/client/generators/__init__.py b/conans/client/generators/__init__.py
index 5b2be191b15..46629495587 100644
--- a/conans/client/generators/__init__.py
+++ b/conans/client/generators/__init__.py
@@ -72,7 +72,7 @@ def __init__(self):
                                 "MesonToolchain", "MSBuildDeps", "QbsToolchain", "msbuild",
                                 "VirtualRunEnv", "VirtualBuildEnv", "AutotoolsDeps",
                                 "AutotoolsToolchain", "BazelDeps", "BazelToolchain", "PkgConfigDeps",
-                                "VCVars", "IntelCC", "XcodeDeps", "PremakeDeps"]
+                                "VCVars", "IntelCC", "XcodeDeps", "PremakeDeps", "XcodeToolchain"]
 
     def add(self, name, generator_class, custom=False):
         if name not in self._generators or custom:
@@ -143,6 +143,9 @@ def _new_generator(self, generator_name, output):
         elif generator_name == "PremakeDeps":
             from conan.tools.premake import PremakeDeps
             return PremakeDeps
+        elif generator_name == "XcodeToolchain":
+            from conan.tools.apple import XcodeToolchain
+            return XcodeToolchain
         else:
             raise ConanException("Internal Conan error: Generator '{}' "
                                  "not commplete".format(generator_name))
diff --git a/conans/client/migrations_settings.py b/conans/client/migrations_settings.py
index b8c38c7f075..d075c97f06d 100644
--- a/conans/client/migrations_settings.py
+++ b/conans/client/migrations_settings.py
@@ -3106,4 +3106,147 @@
 cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]  # Deprecated, use compiler.cppstd
 """
 
-settings_1_46_0 = settings_1_45_0
+settings_1_46_0 = """
+# Only for cross building, 'os_build/arch_build' is the system that runs Conan
+os_build: [Windows, WindowsStore, Linux, Macos, FreeBSD, SunOS, AIX, VxWorks]
+arch_build: [x86, x86_64, ppc32be, ppc32, ppc64le, ppc64, armv5el, armv5hf, armv6, armv7, armv7hf, armv7s, armv7k, armv8, armv8_32, armv8.3, sparc, sparcv9, mips, mips64, avr, s390, s390x, sh4le, e2k-v2, e2k-v3, e2k-v4, e2k-v5, e2k-v6, e2k-v7]
+
+# Only for building cross compilation tools, 'os_target/arch_target' is the system for
+# which the tools generate code
+os_target: [Windows, Linux, Macos, Android, iOS, watchOS, tvOS, FreeBSD, SunOS, AIX, Arduino, Neutrino]
+arch_target: [x86, x86_64, ppc32be, ppc32, ppc64le, ppc64, armv5el, armv5hf, armv6, armv7, armv7hf, armv7s, armv7k, armv8, armv8_32, armv8.3, sparc, sparcv9, mips, mips64, avr, s390, s390x, asm.js, wasm, sh4le, e2k-v2, e2k-v3, e2k-v4, e2k-v5, e2k-v6, e2k-v7, xtensalx6, xtensalx106]
+
+# Rest of the settings are "host" settings:
+# - For native building/cross building: Where the library/program will run.
+# - For building cross compilation tools: Where the cross compiler will run.
+os:
+    Windows:
+        subsystem: [None, cygwin, msys, msys2, wsl]
+    WindowsStore:
+        version: ["8.1", "10.0"]
+    WindowsCE:
+        platform: ANY
+        version: ["5.0", "6.0", "7.0", "8.0"]
+    Linux:
+    Macos:
+        version: [None, "10.6", "10.7", "10.8", "10.9", "10.10", "10.11", "10.12", "10.13", "10.14", "10.15", "11.0", "12.0", "13.0"]
+        sdk: [None, "macosx"]
+        sdk_version: [None, "10.13", "10.14", "10.15", "11.0", "11.1", "11.3", "12.0", "12.1"]
+        subsystem: [None, catalyst]
+    Android:
+        api_level: ANY
+    iOS:
+        version: ["7.0", "7.1", "8.0", "8.1", "8.2", "8.3", "9.0", "9.1", "9.2", "9.3", "10.0", "10.1", "10.2", "10.3",
+                  "11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1", "12.2", "12.3", "12.4",
+                  "13.0", "13.1", "13.2", "13.3", "13.4", "13.5", "13.6", "13.7",
+                  "14.0", "14.1", "14.2", "14.3", "14.4", "14.5", "14.6", "14.7", "14.8", "15.0", "15.1"]
+        sdk: [None, "iphoneos", "iphonesimulator"]
+        sdk_version: [None, "11.3", "11.4", "12.0", "12.1", "12.2", "12.4",
+                      "13.0", "13.1", "13.2", "13.4", "13.5", "13.6", "13.7",
+                      "14.0", "14.1", "14.2", "14.3", "14.4", "14.5", "15.0", "15.2"]
+    watchOS:
+        version: ["4.0", "4.1", "4.2", "4.3", "5.0", "5.1", "5.2", "5.3", "6.0", "6.1", "6.2",
+                  "7.0", "7.1", "7.2", "7.3", "7.4", "7.5", "7.6", "8.0", "8.1"]
+        sdk: [None, "watchos", "watchsimulator"]
+        sdk_version: [None, "4.3", "5.0", "5.1", "5.2", "5.3", "6.0", "6.1", "6.2",
+                      "7.0", "7.1", "7.2", "7.4", "8.0", "8.0.1", "8.3"]
+    tvOS:
+        version: ["11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1", "12.2", "12.3", "12.4",
+                  "13.0", "13.2", "13.3", "13.4", "14.0", "14.2", "14.3", "14.4", "14.5", "14.6", "14.7",
+                  "15.0", "15.1"]
+        sdk: [None, "appletvos", "appletvsimulator"]
+        sdk_version: [None, "11.3", "11.4", "12.0", "12.1", "12.2", "12.4",
+                      "13.0", "13.1", "13.2", "13.4", "14.0", "14.2", "14.3", "14.5", "15.0", "15.2"]
+    FreeBSD:
+    SunOS:
+    AIX:
+    Arduino:
+        board: ANY
+    Emscripten:
+    Neutrino:
+        version: ["6.4", "6.5", "6.6", "7.0", "7.1"]
+    baremetal:
+    VxWorks:
+        version: ["7"]
+arch: [x86, x86_64, ppc32be, ppc32, ppc64le, ppc64, armv4, armv4i, armv5el, armv5hf, armv6, armv7, armv7hf, armv7s, armv7k, armv8, armv8_32, armv8.3, sparc, sparcv9, mips, mips64, avr, s390, s390x, asm.js, wasm, sh4le, e2k-v2, e2k-v3, e2k-v4, e2k-v5, e2k-v6, e2k-v7, xtensalx6, xtensalx106]
+compiler:
+    sun-cc:
+        version: ["5.10", "5.11", "5.12", "5.13", "5.14", "5.15"]
+        threads: [None, posix]
+        libcxx: [libCstd, libstdcxx, libstlport, libstdc++]
+    gcc: &gcc
+        version: ["4.1", "4.4", "4.5", "4.6", "4.7", "4.8", "4.9",
+                  "5", "5.1", "5.2", "5.3", "5.4", "5.5",
+                  "6", "6.1", "6.2", "6.3", "6.4", "6.5",
+                  "7", "7.1", "7.2", "7.3", "7.4", "7.5",
+                  "8", "8.1", "8.2", "8.3", "8.4",
+                  "9", "9.1", "9.2", "9.3",
+                  "10", "10.1", "10.2", "10.3",
+                  "11", "11.1", "11.2"]
+        libcxx: [libstdc++, libstdc++11]
+        threads: [None, posix, win32]  # Windows MinGW
+        exception: [None, dwarf2, sjlj, seh]  # Windows MinGW
+        cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]
+    Visual Studio: &visual_studio
+        runtime: [MD, MT, MTd, MDd]
+        version: ["8", "9", "10", "11", "12", "14", "15", "16", "17"]
+        toolset: [None, v90, v100, v110, v110_xp, v120, v120_xp,
+                  v140, v140_xp, v140_clang_c2, LLVM-vs2012, LLVM-vs2012_xp,
+                  LLVM-vs2013, LLVM-vs2013_xp, LLVM-vs2014, LLVM-vs2014_xp,
+                  LLVM-vs2017, LLVM-vs2017_xp, v141, v141_xp, v141_clang_c2, v142,
+                  llvm, ClangCL, v143]
+        cppstd: [None, 14, 17, 20, 23]
+    msvc:
+        version: [190, 191, 192, 193]
+        update: [None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+        runtime: [static, dynamic]
+        runtime_type: [Debug, Release]
+        cppstd: [14, 17, 20, 23]
+    clang:
+        version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0",
+                  "5.0", "6.0", "7.0", "7.1",
+                  "8", "9", "10", "11", "12", "13", "14"]
+        libcxx: [None, libstdc++, libstdc++11, libc++, c++_shared, c++_static]
+        cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]
+        runtime: [None, MD, MT, MTd, MDd]
+    apple-clang: &apple_clang
+        version: ["5.0", "5.1", "6.0", "6.1", "7.0", "7.3", "8.0", "8.1", "9.0", "9.1", "10.0", "11.0", "12.0", "13.0"]
+        libcxx: [libstdc++, libc++]
+        cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20]
+    intel:
+        version: ["11", "12", "13", "14", "15", "16", "17", "18", "19", "19.1"]
+        update: [None, ANY]
+        base:
+            gcc:
+                <<: *gcc
+                threads: [None]
+                exception: [None]
+            Visual Studio:
+                <<: *visual_studio
+            apple-clang:
+                <<: *apple_clang
+    intel-cc:
+        version: ["2021.1", "2021.2", "2021.3"]
+        update: [None, ANY]
+        mode: ["icx", "classic", "dpcpp"]
+        libcxx: [None, libstdc++, libstdc++11, libc++]
+        cppstd: [None, 98, gnu98, 03, gnu03, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]
+        runtime: [None, static, dynamic]
+        runtime_type: [None, Debug, Release]
+    qcc:
+        version: ["4.4", "5.4", "8.3"]
+        libcxx: [cxx, gpp, cpp, cpp-ne, accp, acpp-ne, ecpp, ecpp-ne]
+        cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17]
+    mcst-lcc:
+        version: ["1.19", "1.20", "1.21", "1.22", "1.23", "1.24", "1.25"]
+        base:
+            gcc:
+                <<: *gcc
+                threads: [None]
+                exceptions: [None]
+
+build_type: [None, Debug, Release, RelWithDebInfo, MinSizeRel]
+
+
+cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]  # Deprecated, use compiler.cppstd
+"""
diff --git a/conans/model/conf.py b/conans/model/conf.py
index a54e0c4f3b6..f89a3db0b7e 100644
--- a/conans/model/conf.py
+++ b/conans/model/conf.py
@@ -38,6 +38,7 @@
     "tools.system.package_manager:mode": "Mode for package_manager tools: 'check' or 'install'",
     "tools.system.package_manager:sudo": "Use 'sudo' when invoking the package manager tools in Linux (False by default)",
     "tools.system.package_manager:sudo_askpass": "Use the '-A' argument if using sudo in Linux to invoke the system package manager (False by default)",
+    "tools.apple.xcodebuild:verbosity": "Verbosity level for xcodebuild: 'verbose' or 'quiet"
 }
 
 
diff --git a/conans/test/functional/toolchains/apple/test_xcodebuild.py b/conans/test/functional/toolchains/apple/test_xcodebuild.py
new file mode 100644
index 00000000000..c0711d37023
--- /dev/null
+++ b/conans/test/functional/toolchains/apple/test_xcodebuild.py
@@ -0,0 +1,437 @@
+import platform
+import textwrap
+
+import pytest
+
+from conans.test.utils.tools import TestClient
+
+pbxproj = textwrap.dedent("""
+    // !$*UTF8*$!
+    {
+        archiveVersion = 1;
+        classes = {
+        };
+        objectVersion = 55;
+        objects = {
+
+    /* Begin PBXBuildFile section */
+            07879B4027219EE500B6FB51 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07879B3F27219EE500B6FB51 /* main.cpp */; };
+    /* End PBXBuildFile section */
+
+    /* Begin PBXCopyFilesBuildPhase section */
+            07879B3A27219EE500B6FB51 /* CopyFiles */ = {
+                isa = PBXCopyFilesBuildPhase;
+                buildActionMask = 2147483647;
+                dstPath = /usr/share/man/man1/;
+                dstSubfolderSpec = 0;
+                files = (
+                );
+                runOnlyForDeploymentPostprocessing = 1;
+            };
+    /* End PBXCopyFilesBuildPhase section */
+
+    /* Begin PBXFileReference section */
+            07879B3C27219EE500B6FB51 /* app */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = app; sourceTree = BUILT_PRODUCTS_DIR; };
+            07879B3F27219EE500B6FB51 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+            41608B0827BBEB2800527FAA /* conandeps.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = conandeps.xcconfig; path = conandeps.xcconfig; sourceTree = SOURCE_ROOT; };
+            41608B0927BBEB2800527FAA /* conan_hello_vars_release_x86_64.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = conan_hello_vars_release_x86_64.xcconfig; path = conan_hello_vars_release_x86_64.xcconfig; sourceTree = SOURCE_ROOT; };
+            41608B0A27BBEB2900527FAA /* conan_hello_debug_x86_64.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = conan_hello_debug_x86_64.xcconfig; path = conan_hello_debug_x86_64.xcconfig; sourceTree = SOURCE_ROOT; };
+            41608B0B27BBEB2900527FAA /* conan_hello.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = conan_hello.xcconfig; path = conan_hello.xcconfig; sourceTree = SOURCE_ROOT; };
+            41608B0C27BBEB2900527FAA /* conan_hello_vars_debug_x86_64.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = conan_hello_vars_debug_x86_64.xcconfig; path = conan_hello_vars_debug_x86_64.xcconfig; sourceTree = SOURCE_ROOT; };
+            41608B0D27BBEB2900527FAA /* conan_hello_release_x86_64.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = conan_hello_release_x86_64.xcconfig; path = conan_hello_release_x86_64.xcconfig; sourceTree = SOURCE_ROOT; };
+    /* End PBXFileReference section */
+
+    /* Begin PBXFrameworksBuildPhase section */
+            07879B3927219EE500B6FB51 /* Frameworks */ = {
+                isa = PBXFrameworksBuildPhase;
+                buildActionMask = 2147483647;
+                files = (
+                );
+                runOnlyForDeploymentPostprocessing = 0;
+            };
+    /* End PBXFrameworksBuildPhase section */
+
+    /* Begin PBXGroup section */
+            07879B3327219EE500B6FB51 = {
+                isa = PBXGroup;
+                children = (
+                    07879B3E27219EE500B6FB51 /* app */,
+                    07879B3D27219EE500B6FB51 /* Products */,
+                );
+                sourceTree = "<group>";
+            };
+            07879B3D27219EE500B6FB51 /* Products */ = {
+                isa = PBXGroup;
+                children = (
+                    07879B3C27219EE500B6FB51 /* app */,
+                );
+                name = Products;
+                sourceTree = "<group>";
+            };
+            07879B3E27219EE500B6FB51 /* app */ = {
+                isa = PBXGroup;
+                children = (
+                    41608B0A27BBEB2900527FAA /* conan_hello_debug_x86_64.xcconfig */,
+                    41608B0D27BBEB2900527FAA /* conan_hello_release_x86_64.xcconfig */,
+                    41608B0C27BBEB2900527FAA /* conan_hello_vars_debug_x86_64.xcconfig */,
+                    41608B0927BBEB2800527FAA /* conan_hello_vars_release_x86_64.xcconfig */,
+                    41608B0B27BBEB2900527FAA /* conan_hello.xcconfig */,
+                    41608B0827BBEB2800527FAA /* conandeps.xcconfig */,
+                    07879B3F27219EE500B6FB51 /* main.cpp */,
+                );
+                path = app;
+                sourceTree = "<group>";
+            };
+    /* End PBXGroup section */
+
+    /* Begin PBXNativeTarget section */
+            07879B3B27219EE500B6FB51 /* app */ = {
+                isa = PBXNativeTarget;
+                buildConfigurationList = 07879B4327219EE500B6FB51 /* Build configuration list for PBXNativeTarget "app" */;
+                buildPhases = (
+                    07879B3827219EE500B6FB51 /* Sources */,
+                    07879B3927219EE500B6FB51 /* Frameworks */,
+                    07879B3A27219EE500B6FB51 /* CopyFiles */,
+                );
+                buildRules = (
+                );
+                dependencies = (
+                );
+                name = app;
+                productName = app;
+                productReference = 07879B3C27219EE500B6FB51 /* app */;
+                productType = "com.apple.product-type.tool";
+            };
+    /* End PBXNativeTarget section */
+
+    /* Begin PBXProject section */
+            07879B3427219EE500B6FB51 /* Project object */ = {
+                isa = PBXProject;
+                attributes = {
+                    BuildIndependentTargetsInParallel = 1;
+                    LastUpgradeCheck = 1320;
+                    TargetAttributes = {
+                        07879B3B27219EE500B6FB51 = {
+                            CreatedOnToolsVersion = 13.0;
+                        };
+                    };
+                };
+                buildConfigurationList = 07879B3727219EE500B6FB51 /* Build configuration list for PBXProject "app" */;
+                compatibilityVersion = "Xcode 13.0";
+                developmentRegion = en;
+                hasScannedForEncodings = 0;
+                knownRegions = (
+                    en,
+                    Base,
+                );
+                mainGroup = 07879B3327219EE500B6FB51;
+                productRefGroup = 07879B3D27219EE500B6FB51 /* Products */;
+                projectDirPath = "";
+                projectRoot = "";
+                targets = (
+                    07879B3B27219EE500B6FB51 /* app */,
+                );
+            };
+    /* End PBXProject section */
+
+    /* Begin PBXSourcesBuildPhase section */
+            07879B3827219EE500B6FB51 /* Sources */ = {
+                isa = PBXSourcesBuildPhase;
+                buildActionMask = 2147483647;
+                files = (
+                    07879B4027219EE500B6FB51 /* main.cpp in Sources */,
+                );
+                runOnlyForDeploymentPostprocessing = 0;
+            };
+    /* End PBXSourcesBuildPhase section */
+
+    /* Begin XCBuildConfiguration section */
+            07879B4127219EE500B6FB51 /* Debug */ = {
+                isa = XCBuildConfiguration;
+                baseConfigurationReference = 41608B0827BBEB2800527FAA /* conandeps.xcconfig */;
+                buildSettings = {
+                    ALWAYS_SEARCH_USER_PATHS = NO;
+                    CLANG_ANALYZER_NONNULL = YES;
+                    CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                    CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+                    CLANG_CXX_LIBRARY = "libc++";
+                    CLANG_ENABLE_MODULES = YES;
+                    CLANG_ENABLE_OBJC_ARC = YES;
+                    CLANG_ENABLE_OBJC_WEAK = YES;
+                    CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                    CLANG_WARN_BOOL_CONVERSION = YES;
+                    CLANG_WARN_COMMA = YES;
+                    CLANG_WARN_CONSTANT_CONVERSION = YES;
+                    CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                    CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                    CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                    CLANG_WARN_EMPTY_BODY = YES;
+                    CLANG_WARN_ENUM_CONVERSION = YES;
+                    CLANG_WARN_INFINITE_RECURSION = YES;
+                    CLANG_WARN_INT_CONVERSION = YES;
+                    CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                    CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                    CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                    CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                    CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                    CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                    CLANG_WARN_STRICT_PROTOTYPES = YES;
+                    CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                    CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                    CLANG_WARN_UNREACHABLE_CODE = YES;
+                    CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                    COPY_PHASE_STRIP = NO;
+                    DEBUG_INFORMATION_FORMAT = dwarf;
+                    ENABLE_STRICT_OBJC_MSGSEND = YES;
+                    ENABLE_TESTABILITY = YES;
+                    GCC_C_LANGUAGE_STANDARD = gnu11;
+                    GCC_DYNAMIC_NO_PIC = NO;
+                    GCC_NO_COMMON_BLOCKS = YES;
+                    GCC_OPTIMIZATION_LEVEL = 0;
+                    GCC_PREPROCESSOR_DEFINITIONS = (
+                        "DEBUG=1",
+                        "$(inherited)",
+                    );
+                    GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                    GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                    GCC_WARN_UNDECLARED_SELECTOR = YES;
+                    GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                    GCC_WARN_UNUSED_FUNCTION = YES;
+                    GCC_WARN_UNUSED_VARIABLE = YES;
+                    MACOSX_DEPLOYMENT_TARGET = 11.3;
+                    MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+                    MTL_FAST_MATH = YES;
+                    ONLY_ACTIVE_ARCH = YES;
+                    SDKROOT = macosx;
+                };
+                name = Debug;
+            };
+            07879B4227219EE500B6FB51 /* Release */ = {
+                isa = XCBuildConfiguration;
+                baseConfigurationReference = 41608B0827BBEB2800527FAA /* conandeps.xcconfig */;
+                buildSettings = {
+                    ALWAYS_SEARCH_USER_PATHS = NO;
+                    CLANG_ANALYZER_NONNULL = YES;
+                    CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                    CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+                    CLANG_CXX_LIBRARY = "libc++";
+                    CLANG_ENABLE_MODULES = YES;
+                    CLANG_ENABLE_OBJC_ARC = YES;
+                    CLANG_ENABLE_OBJC_WEAK = YES;
+                    CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                    CLANG_WARN_BOOL_CONVERSION = YES;
+                    CLANG_WARN_COMMA = YES;
+                    CLANG_WARN_CONSTANT_CONVERSION = YES;
+                    CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                    CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                    CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                    CLANG_WARN_EMPTY_BODY = YES;
+                    CLANG_WARN_ENUM_CONVERSION = YES;
+                    CLANG_WARN_INFINITE_RECURSION = YES;
+                    CLANG_WARN_INT_CONVERSION = YES;
+                    CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                    CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                    CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                    CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                    CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                    CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                    CLANG_WARN_STRICT_PROTOTYPES = YES;
+                    CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                    CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                    CLANG_WARN_UNREACHABLE_CODE = YES;
+                    CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                    COPY_PHASE_STRIP = NO;
+                    DEBUG_INFORMATION_FORMAT = dwarf;
+                    ENABLE_NS_ASSERTIONS = NO;
+                    ENABLE_STRICT_OBJC_MSGSEND = YES;
+                    GCC_C_LANGUAGE_STANDARD = gnu11;
+                    GCC_NO_COMMON_BLOCKS = YES;
+                    GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                    GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                    GCC_WARN_UNDECLARED_SELECTOR = YES;
+                    GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                    GCC_WARN_UNUSED_FUNCTION = YES;
+                    GCC_WARN_UNUSED_VARIABLE = YES;
+                    MACOSX_DEPLOYMENT_TARGET = 11.3;
+                    MTL_ENABLE_DEBUG_INFO = NO;
+                    MTL_FAST_MATH = YES;
+                    SDKROOT = macosx;
+                };
+                name = Release;
+            };
+            07879B4427219EE500B6FB51 /* Debug */ = {
+                isa = XCBuildConfiguration;
+                baseConfigurationReference = 41608B0827BBEB2800527FAA /* conandeps.xcconfig */;
+                buildSettings = {
+                    CODE_SIGN_IDENTITY = "-";
+                    CODE_SIGN_STYLE = Automatic;
+                    PRODUCT_NAME = "$(TARGET_NAME)";
+                };
+                name = Debug;
+            };
+            07879B4527219EE500B6FB51 /* Release */ = {
+                isa = XCBuildConfiguration;
+                baseConfigurationReference = 41608B0827BBEB2800527FAA /* conandeps.xcconfig */;
+                buildSettings = {
+                    CODE_SIGN_IDENTITY = "-";
+                    CODE_SIGN_STYLE = Automatic;
+                    PRODUCT_NAME = "$(TARGET_NAME)";
+                };
+                name = Release;
+            };
+    /* End XCBuildConfiguration section */
+
+    /* Begin XCConfigurationList section */
+            07879B3727219EE500B6FB51 /* Build configuration list for PBXProject "app" */ = {
+                isa = XCConfigurationList;
+                buildConfigurations = (
+                    07879B4127219EE500B6FB51 /* Debug */,
+                    07879B4227219EE500B6FB51 /* Release */,
+                );
+                defaultConfigurationIsVisible = 0;
+                defaultConfigurationName = Release;
+            };
+            07879B4327219EE500B6FB51 /* Build configuration list for PBXNativeTarget "app" */ = {
+                isa = XCConfigurationList;
+                buildConfigurations = (
+                    07879B4427219EE500B6FB51 /* Debug */,
+                    07879B4527219EE500B6FB51 /* Release */,
+                );
+                defaultConfigurationIsVisible = 0;
+                defaultConfigurationName = Release;
+            };
+    /* End XCConfigurationList section */
+        };
+        rootObject = 07879B3427219EE500B6FB51 /* Project object */;
+    }
+    """)
+
+main = textwrap.dedent("""
+    #include <iostream>
+    #include "hello.h"
+    int main(int argc, char *argv[]) {
+        hello();
+        #ifndef DEBUG
+        std::cout << "App Release!" << std::endl;
+        #else
+        std::cout << "App Debug!" << std::endl;
+        #endif
+    }
+    """)
+
+test = textwrap.dedent("""
+    import os
+    from conans import ConanFile, tools
+    class TestApp(ConanFile):
+        settings = "os", "compiler", "build_type", "arch"
+        generators = "VirtualRunEnv"
+        def test(self):
+            if not tools.cross_building(self):
+                self.run("app", env="conanrun")
+    """)
+
+
+@pytest.fixture(scope="module")
+def client():
+    client = TestClient()
+    client.run("new hello/0.1 -m=cmake_lib")
+    client.run("create . -s build_type=Release")
+    client.run("create . -s build_type=Debug")
+    return client
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
+@pytest.mark.tool_xcodebuild
+def test_project_xcodebuild(client):
+
+    conanfile = textwrap.dedent("""
+        from conans import ConanFile
+        from conan.tools.apple import XcodeBuild
+        class MyApplicationConan(ConanFile):
+            name = "myapplication"
+            version = "1.0"
+            requires = "hello/0.1"
+            settings = "os", "compiler", "build_type", "arch"
+            generators = "XcodeDeps"
+            exports_sources = "app.xcodeproj/*", "app/*"
+            def build(self):
+                xcode = XcodeBuild(self)
+                xcode.build("app.xcodeproj")
+
+            def package(self):
+                self.copy("*/app", dst="bin", src=".", keep_path=False)
+
+            def package_info(self):
+                self.cpp_info.bindirs = ["bin"]
+        """)
+
+    client.save({"conanfile.py": conanfile,
+                 "test_package/conanfile.py": test,
+                 "app/main.cpp": main,
+                 "app.xcodeproj/project.pbxproj": pbxproj}, clean_first=True)
+    client.run("create . --build=missing")
+    assert "hello/0.1: Hello World Release!" in client.out
+    assert "App Release!" in client.out
+    client.run("create . -s build_type=Debug --build=missing")
+    assert "hello/0.1: Hello World Debug!" in client.out
+    assert "App Debug!" in client.out
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
+@pytest.mark.tool_xcodebuild
+@pytest.mark.skip(reason="Different sdks not installed in CI")
+def test_xcodebuild_test_different_sdk(client):
+
+    conanfile = textwrap.dedent("""
+        from conans import ConanFile
+        from conan.tools.apple import XcodeBuild
+        class MyApplicationConan(ConanFile):
+            name = "myapplication"
+            version = "1.0"
+            requires = "hello/0.1"
+            settings = "os", "compiler", "build_type", "arch"
+            generators = "XcodeDeps"
+            exports_sources = "app.xcodeproj/*", "app/*"
+            def build(self):
+                xcode = XcodeBuild(self)
+                xcode.build("app.xcodeproj")
+                self.run("otool -l build/Release/app")
+        """)
+
+    client.save({"conanfile.py": conanfile,
+                 "app/main.cpp": main,
+                 "app.xcodeproj/project.pbxproj": pbxproj}, clean_first=True)
+    client.run("create . --build=missing -s os.sdk=macosx -s os.sdk_version=10.15 "
+               "-c tools.apple:sdk_path='/Applications/Xcode11.7.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk'")
+    assert "sdk 10.15.6" in client.out
+    client.run("create . --build=missing -s os.sdk=macosx -s os.sdk_version=11.3 "
+               "-c tools.apple:sdk_path='/Applications/Xcode12.5.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk'")
+    assert "sdk 11.3" in client.out
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
+@pytest.mark.tool_xcodebuild
+def test_missing_sdk(client):
+
+    conanfile = textwrap.dedent("""
+        from conans import ConanFile
+        from conan.tools.apple import XcodeBuild
+        class MyApplicationConan(ConanFile):
+            name = "myapplication"
+            version = "1.0"
+            requires = "hello/0.1"
+            settings = "os", "compiler", "build_type", "arch"
+            generators = "XcodeDeps"
+            exports_sources = "app.xcodeproj/*", "app/*"
+            def build(self):
+                xcode = XcodeBuild(self)
+                xcode.build("app.xcodeproj")
+        """)
+
+    client.save({"conanfile.py": conanfile,
+                 "app/main.cpp": main,
+                 "app.xcodeproj/project.pbxproj": pbxproj}, clean_first=True)
+    client.run("create . --build=missing -s os.sdk=macosx -s os.sdk_version=11.3 "
+               "-c tools.apple:sdk_path='notexistingsdk'", assert_error=True)
+    assert "unable to find sdk 'notexistingsdk'" in client.out
+
diff --git a/conans/test/functional/toolchains/apple/test_xcodedeps_build_configs.py b/conans/test/functional/toolchains/apple/test_xcodedeps_build_configs.py
index ca40fab3004..818a5cfd5a6 100644
--- a/conans/test/functional/toolchains/apple/test_xcodedeps_build_configs.py
+++ b/conans/test/functional/toolchains/apple/test_xcodedeps_build_configs.py
@@ -231,7 +231,7 @@ def create_xcode_project(client, project_name, source):
                         CLANG_WARN_UNREACHABLE_CODE = YES;
                         CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
                         COPY_PHASE_STRIP = NO;
-                        DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                        DEBUG_INFORMATION_FORMAT = dwarf;
                         ENABLE_NS_ASSERTIONS = NO;
                         ENABLE_STRICT_OBJC_MSGSEND = YES;
                         GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -300,7 +300,8 @@ def create_xcode_project(client, project_name, source):
 
 
 @pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
-@pytest.mark.tool_cmake()
+@pytest.mark.tool_cmake
+@pytest.mark.tool_xcodebuild
 def test_xcodedeps_build_configurations():
     client = TestClient(path_with_spaces=False)
 
@@ -342,7 +343,8 @@ def test_xcodedeps_build_configurations():
 
 
 @pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
-@pytest.mark.tool_cmake()
+@pytest.mark.tool_cmake
+@pytest.mark.tool_xcodebuild
 def test_frameworks():
     client = TestClient(path_with_spaces=False)
 
@@ -372,6 +374,7 @@ def test_frameworks():
 
 
 @pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
+@pytest.mark.tool_xcodebuild
 def test_xcodedeps_dashes_names_and_arch():
     # https://github.com/conan-io/conan/issues/9949
     client = TestClient(path_with_spaces=False)
diff --git a/conans/test/functional/toolchains/apple/test_xcodetoolchain.py b/conans/test/functional/toolchains/apple/test_xcodetoolchain.py
new file mode 100644
index 00000000000..292bdce1b88
--- /dev/null
+++ b/conans/test/functional/toolchains/apple/test_xcodetoolchain.py
@@ -0,0 +1,381 @@
+import platform
+import textwrap
+
+import pytest
+
+from conans.test.assets.sources import gen_function_cpp
+from conans.test.utils.tools import TestClient
+
+pbxproj = textwrap.dedent("""
+    // !$*UTF8*$!
+    {
+        archiveVersion = 1;
+        classes = {
+        };
+        objectVersion = 55;
+        objects = {
+
+    /* Begin PBXBuildFile section */
+            07879B4027219EE500B6FB51 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07879B3F27219EE500B6FB51 /* main.cpp */; };
+    /* End PBXBuildFile section */
+
+    /* Begin PBXCopyFilesBuildPhase section */
+            07879B3A27219EE500B6FB51 /* CopyFiles */ = {
+                isa = PBXCopyFilesBuildPhase;
+                buildActionMask = 2147483647;
+                dstPath = /usr/share/man/man1/;
+                dstSubfolderSpec = 0;
+                files = (
+                );
+                runOnlyForDeploymentPostprocessing = 1;
+            };
+    /* End PBXCopyFilesBuildPhase section */
+
+    /* Begin PBXFileReference section */
+            07879B3C27219EE500B6FB51 /* app */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = app; sourceTree = BUILT_PRODUCTS_DIR; };
+            07879B3F27219EE500B6FB51 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+            4130DB5F27BE8D0300BDEE84 /* conan_hello_release_x86_64_macosx_12_1.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conan_hello_release_x86_64_macosx_12_1.xcconfig; sourceTree = "<group>"; };
+            4130DB6027BE8D0300BDEE84 /* conan_hello_vars_debug_x86_64_macosx_12_1.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conan_hello_vars_debug_x86_64_macosx_12_1.xcconfig; sourceTree = "<group>"; };
+            4130DB6127BE8D0300BDEE84 /* conantoolchain_debug_x86_64_macosx_12_1.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conantoolchain_debug_x86_64_macosx_12_1.xcconfig; sourceTree = "<group>"; };
+            4130DB6227BE8D0300BDEE84 /* conantoolchain_release_x86_64_macosx_12_1.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conantoolchain_release_x86_64_macosx_12_1.xcconfig; sourceTree = "<group>"; };
+            4130DB6327BE8D0300BDEE84 /* conan_hello.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conan_hello.xcconfig; sourceTree = "<group>"; };
+            4130DB6427BE8D0300BDEE84 /* conan_hello_vars_release_x86_64_macosx_12_1.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conan_hello_vars_release_x86_64_macosx_12_1.xcconfig; sourceTree = "<group>"; };
+            4130DB6527BE8D0300BDEE84 /* conan_hello_debug_x86_64_macosx_12_1.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conan_hello_debug_x86_64_macosx_12_1.xcconfig; sourceTree = "<group>"; };
+            4130DB6627BE8D0300BDEE84 /* conan_config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conan_config.xcconfig; sourceTree = "<group>"; };
+            4130DB6727BE8D0300BDEE84 /* conantoolchain.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conantoolchain.xcconfig; sourceTree = "<group>"; };
+            4130DB6827BE8D0300BDEE84 /* conandeps.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = conandeps.xcconfig; sourceTree = "<group>"; };
+    /* End PBXFileReference section */
+
+    /* Begin PBXFrameworksBuildPhase section */
+            07879B3927219EE500B6FB51 /* Frameworks */ = {
+                isa = PBXFrameworksBuildPhase;
+                buildActionMask = 2147483647;
+                files = (
+                );
+                runOnlyForDeploymentPostprocessing = 0;
+            };
+    /* End PBXFrameworksBuildPhase section */
+
+    /* Begin PBXGroup section */
+            07879B3327219EE500B6FB51 = {
+                isa = PBXGroup;
+                children = (
+                    4130DB6927BE8D0D00BDEE84 /* conan */,
+                    07879B3E27219EE500B6FB51 /* app */,
+                    07879B3D27219EE500B6FB51 /* Products */,
+                );
+                sourceTree = "<group>";
+            };
+            07879B3D27219EE500B6FB51 /* Products */ = {
+                isa = PBXGroup;
+                children = (
+                    07879B3C27219EE500B6FB51 /* app */,
+                );
+                name = Products;
+                sourceTree = "<group>";
+            };
+            07879B3E27219EE500B6FB51 /* app */ = {
+                isa = PBXGroup;
+                children = (
+                    07879B3F27219EE500B6FB51 /* main.cpp */,
+                );
+                path = app;
+                sourceTree = "<group>";
+            };
+            4130DB6927BE8D0D00BDEE84 /* conan */ = {
+                isa = PBXGroup;
+                children = (
+                    4130DB6627BE8D0300BDEE84 /* conan_config.xcconfig */,
+                    4130DB6527BE8D0300BDEE84 /* conan_hello_debug_x86_64_macosx_12_1.xcconfig */,
+                    4130DB5F27BE8D0300BDEE84 /* conan_hello_release_x86_64_macosx_12_1.xcconfig */,
+                    4130DB6027BE8D0300BDEE84 /* conan_hello_vars_debug_x86_64_macosx_12_1.xcconfig */,
+                    4130DB6427BE8D0300BDEE84 /* conan_hello_vars_release_x86_64_macosx_12_1.xcconfig */,
+                    4130DB6327BE8D0300BDEE84 /* conan_hello.xcconfig */,
+                    4130DB6827BE8D0300BDEE84 /* conandeps.xcconfig */,
+                    4130DB6127BE8D0300BDEE84 /* conantoolchain_debug_x86_64_macosx_12_1.xcconfig */,
+                    4130DB6227BE8D0300BDEE84 /* conantoolchain_release_x86_64_macosx_12_1.xcconfig */,
+                    4130DB6727BE8D0300BDEE84 /* conantoolchain.xcconfig */,
+                );
+                name = conan;
+                sourceTree = "<group>";
+            };
+    /* End PBXGroup section */
+
+    /* Begin PBXNativeTarget section */
+            07879B3B27219EE500B6FB51 /* app */ = {
+                isa = PBXNativeTarget;
+                buildConfigurationList = 07879B4327219EE500B6FB51 /* Build configuration list for PBXNativeTarget "app" */;
+                buildPhases = (
+                    07879B3827219EE500B6FB51 /* Sources */,
+                    07879B3927219EE500B6FB51 /* Frameworks */,
+                    07879B3A27219EE500B6FB51 /* CopyFiles */,
+                );
+                buildRules = (
+                );
+                dependencies = (
+                );
+                name = app;
+                productName = app;
+                productReference = 07879B3C27219EE500B6FB51 /* app */;
+                productType = "com.apple.product-type.tool";
+            };
+    /* End PBXNativeTarget section */
+
+    /* Begin PBXProject section */
+            07879B3427219EE500B6FB51 /* Project object */ = {
+                isa = PBXProject;
+                attributes = {
+                    BuildIndependentTargetsInParallel = 1;
+                    LastUpgradeCheck = 1320;
+                    TargetAttributes = {
+                        07879B3B27219EE500B6FB51 = {
+                            CreatedOnToolsVersion = 13.0;
+                        };
+                    };
+                };
+                buildConfigurationList = 07879B3727219EE500B6FB51 /* Build configuration list for PBXProject "app" */;
+                compatibilityVersion = "Xcode 13.0";
+                developmentRegion = en;
+                hasScannedForEncodings = 0;
+                knownRegions = (
+                    en,
+                    Base,
+                );
+                mainGroup = 07879B3327219EE500B6FB51;
+                productRefGroup = 07879B3D27219EE500B6FB51 /* Products */;
+                projectDirPath = "";
+                projectRoot = "";
+                targets = (
+                    07879B3B27219EE500B6FB51 /* app */,
+                );
+            };
+    /* End PBXProject section */
+
+    /* Begin PBXSourcesBuildPhase section */
+            07879B3827219EE500B6FB51 /* Sources */ = {
+                isa = PBXSourcesBuildPhase;
+                buildActionMask = 2147483647;
+                files = (
+                    07879B4027219EE500B6FB51 /* main.cpp in Sources */,
+                );
+                runOnlyForDeploymentPostprocessing = 0;
+            };
+    /* End PBXSourcesBuildPhase section */
+
+    /* Begin XCBuildConfiguration section */
+            07879B4127219EE500B6FB51 /* Debug */ = {
+                isa = XCBuildConfiguration;
+                baseConfigurationReference = 4130DB6627BE8D0300BDEE84 /* conan_config.xcconfig */;
+                buildSettings = {
+                    ALWAYS_SEARCH_USER_PATHS = NO;
+                    ARCHS = x86_64;
+                    CLANG_ANALYZER_NONNULL = YES;
+                    CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                    CLANG_ENABLE_MODULES = YES;
+                    CLANG_ENABLE_OBJC_ARC = YES;
+                    CLANG_ENABLE_OBJC_WEAK = YES;
+                    CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                    CLANG_WARN_BOOL_CONVERSION = YES;
+                    CLANG_WARN_COMMA = YES;
+                    CLANG_WARN_CONSTANT_CONVERSION = YES;
+                    CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                    CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                    CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                    CLANG_WARN_EMPTY_BODY = YES;
+                    CLANG_WARN_ENUM_CONVERSION = YES;
+                    CLANG_WARN_INFINITE_RECURSION = YES;
+                    CLANG_WARN_INT_CONVERSION = YES;
+                    CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                    CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                    CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                    CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                    CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                    CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                    CLANG_WARN_STRICT_PROTOTYPES = YES;
+                    CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                    CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                    CLANG_WARN_UNREACHABLE_CODE = YES;
+                    CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                    COPY_PHASE_STRIP = NO;
+                    DEBUG_INFORMATION_FORMAT = dwarf;
+                    ENABLE_STRICT_OBJC_MSGSEND = YES;
+                    ENABLE_TESTABILITY = YES;
+                    GCC_C_LANGUAGE_STANDARD = gnu11;
+                    GCC_DYNAMIC_NO_PIC = NO;
+                    GCC_NO_COMMON_BLOCKS = YES;
+                    GCC_OPTIMIZATION_LEVEL = 0;
+                    GCC_PREPROCESSOR_DEFINITIONS = (
+                        "DEBUG=1",
+                        "$(inherited)",
+                    );
+                    GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                    GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                    GCC_WARN_UNDECLARED_SELECTOR = YES;
+                    GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                    GCC_WARN_UNUSED_FUNCTION = YES;
+                    GCC_WARN_UNUSED_VARIABLE = YES;
+                    MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+                    MTL_FAST_MATH = YES;
+                    ONLY_ACTIVE_ARCH = YES;
+                    SDKROOT = macosx12.1;
+                };
+                name = Debug;
+            };
+            07879B4227219EE500B6FB51 /* Release */ = {
+                isa = XCBuildConfiguration;
+                baseConfigurationReference = 4130DB6627BE8D0300BDEE84 /* conan_config.xcconfig */;
+                buildSettings = {
+                    ALWAYS_SEARCH_USER_PATHS = NO;
+                    ARCHS = x86_64;
+                    CLANG_ANALYZER_NONNULL = YES;
+                    CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                    CLANG_ENABLE_MODULES = YES;
+                    CLANG_ENABLE_OBJC_ARC = YES;
+                    CLANG_ENABLE_OBJC_WEAK = YES;
+                    CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                    CLANG_WARN_BOOL_CONVERSION = YES;
+                    CLANG_WARN_COMMA = YES;
+                    CLANG_WARN_CONSTANT_CONVERSION = YES;
+                    CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                    CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                    CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                    CLANG_WARN_EMPTY_BODY = YES;
+                    CLANG_WARN_ENUM_CONVERSION = YES;
+                    CLANG_WARN_INFINITE_RECURSION = YES;
+                    CLANG_WARN_INT_CONVERSION = YES;
+                    CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                    CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                    CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                    CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                    CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                    CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                    CLANG_WARN_STRICT_PROTOTYPES = YES;
+                    CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                    CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                    CLANG_WARN_UNREACHABLE_CODE = YES;
+                    CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                    COPY_PHASE_STRIP = NO;
+                    DEBUG_INFORMATION_FORMAT = dwarf;
+                    ENABLE_NS_ASSERTIONS = NO;
+                    ENABLE_STRICT_OBJC_MSGSEND = YES;
+                    GCC_C_LANGUAGE_STANDARD = gnu11;
+                    GCC_NO_COMMON_BLOCKS = YES;
+                    GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                    GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                    GCC_WARN_UNDECLARED_SELECTOR = YES;
+                    GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                    GCC_WARN_UNUSED_FUNCTION = YES;
+                    GCC_WARN_UNUSED_VARIABLE = YES;
+                    MTL_ENABLE_DEBUG_INFO = NO;
+                    MTL_FAST_MATH = YES;
+                    ONLY_ACTIVE_ARCH = YES;
+                    SDKROOT = macosx12.1;
+                };
+                name = Release;
+            };
+            07879B4427219EE500B6FB51 /* Debug */ = {
+                isa = XCBuildConfiguration;
+                buildSettings = {
+                    CODE_SIGN_IDENTITY = "-";
+                    CODE_SIGN_STYLE = Automatic;
+                    PRODUCT_NAME = "$(TARGET_NAME)";
+                };
+                name = Debug;
+            };
+            07879B4527219EE500B6FB51 /* Release */ = {
+                isa = XCBuildConfiguration;
+                buildSettings = {
+                    CODE_SIGN_IDENTITY = "-";
+                    CODE_SIGN_STYLE = Automatic;
+                    PRODUCT_NAME = "$(TARGET_NAME)";
+                };
+                name = Release;
+            };
+    /* End XCBuildConfiguration section */
+
+    /* Begin XCConfigurationList section */
+            07879B3727219EE500B6FB51 /* Build configuration list for PBXProject "app" */ = {
+                isa = XCConfigurationList;
+                buildConfigurations = (
+                    07879B4127219EE500B6FB51 /* Debug */,
+                    07879B4227219EE500B6FB51 /* Release */,
+                );
+                defaultConfigurationIsVisible = 0;
+                defaultConfigurationName = Release;
+            };
+            07879B4327219EE500B6FB51 /* Build configuration list for PBXNativeTarget "app" */ = {
+                isa = XCConfigurationList;
+                buildConfigurations = (
+                    07879B4427219EE500B6FB51 /* Debug */,
+                    07879B4527219EE500B6FB51 /* Release */,
+                );
+                defaultConfigurationIsVisible = 0;
+                defaultConfigurationName = Release;
+            };
+    /* End XCConfigurationList section */
+        };
+        rootObject = 07879B3427219EE500B6FB51 /* Project object */;
+    }
+    """)
+
+test = textwrap.dedent("""
+    import os
+    from conans import ConanFile, tools
+    class TestApp(ConanFile):
+        settings = "os", "compiler", "build_type", "arch"
+        generators = "VirtualRunEnv"
+        def test(self):
+            if not tools.cross_building(self):
+                self.run("app", env="conanrun")
+    """)
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
+@pytest.mark.tool_xcodebuild
+@pytest.mark.parametrize("cppstd, cppstd_output, min_version", [
+    ("gnu14", "__cplusplus201402", "12.0"),
+    ("gnu17", "__cplusplus201703", "12.0"),
+    ("gnu17", "__cplusplus201703", "11.0")
+])
+def test_project_xcodetoolchain(cppstd, cppstd_output, min_version):
+
+    client = TestClient()
+    client.run("new hello/0.1 -m=cmake_lib")
+    client.run("export .")
+
+    conanfile = textwrap.dedent("""
+        from conans import ConanFile
+        from conan.tools.apple import XcodeBuild
+        class MyApplicationConan(ConanFile):
+            name = "myapplication"
+            version = "1.0"
+            requires = "hello/0.1"
+            settings = "os", "compiler", "build_type", "arch"
+            generators = "XcodeDeps", "XcodeToolchain"
+            exports_sources = "app.xcodeproj/*", "app/*"
+            def build(self):
+                xcode = XcodeBuild(self)
+                xcode.build("app.xcodeproj")
+                self.run("otool -l build/{}/app".format(self.settings.build_type))
+
+            def package(self):
+                self.copy("*/app", dst="bin", src=".", keep_path=False)
+
+            def package_info(self):
+                self.cpp_info.bindirs = ["bin"]
+        """)
+
+    client.save({"conanfile.py": conanfile,
+                 "test_package/conanfile.py": test,
+                 "app/main.cpp": gen_function_cpp(name="main", includes=["hello"], calls=["hello"]),
+                 "app.xcodeproj/project.pbxproj": pbxproj}, clean_first=True)
+
+    settings = "-s arch=x86_64 -s os.sdk=macosx -s os.sdk_version=12.1 -s compiler.cppstd={} " \
+               "-s compiler.libcxx=libc++ -s os.version={} ".format(cppstd, min_version)
+
+    client.run("create . -s build_type=Release {} --build=missing".format(settings))
+    assert "main __x86_64__ defined" in client.out
+    assert "main {}".format(cppstd_output) in client.out
+    assert "minos {}".format(min_version) in client.out
+    assert "sdk 12.1" in client.out
+    assert "libc++" in client.out
diff --git a/conans/test/integration/toolchains/apple/test_xcodedeps.py b/conans/test/integration/toolchains/apple/test_xcodedeps.py
index 009717bedd8..dfa51264871 100644
--- a/conans/test/integration/toolchains/apple/test_xcodedeps.py
+++ b/conans/test/integration/toolchains/apple/test_xcodedeps.py
@@ -4,6 +4,7 @@
 import pytest
 
 from conans.test.assets.genconanfile import GenConanfile
+from conans.test.integration.toolchains.apple.test_xcodetoolchain import _get_filename
 from conans.test.utils.tools import TestClient
 
 _expected_dep_xconfig = [
@@ -17,18 +18,18 @@
 ]
 
 _expected_vars_xconfig = [
-    "CONAN_{name}_BINARY_DIRECTORIES[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_C_COMPILER_FLAGS[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_CXX_COMPILER_FLAGS[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_LINKER_FLAGS[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_PREPROCESSOR_DEFINITIONS[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_INCLUDE_DIRECTORIES[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_RESOURCE_DIRECTORIES[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_LIBRARY_DIRECTORIES[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_LIBRARIES[config={configuration}][arch={architecture}] = -l{name}",
-    "CONAN_{name}_SYSTEM_LIBS[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_FRAMEWORKS_DIRECTORIES[config={configuration}][arch={architecture}] =",
-    "CONAN_{name}_FRAMEWORKS[config={configuration}][arch={architecture}] = -framework framework_{name}"
+    "CONAN_{name}_BINARY_DIRECTORIES[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_C_COMPILER_FLAGS[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_CXX_COMPILER_FLAGS[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_LINKER_FLAGS[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_PREPROCESSOR_DEFINITIONS[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_INCLUDE_DIRECTORIES[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_RESOURCE_DIRECTORIES[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_LIBRARY_DIRECTORIES[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_LIBRARIES[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] = -l{name}",
+    "CONAN_{name}_SYSTEM_LIBS[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_FRAMEWORKS_DIRECTORIES[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] =",
+    "CONAN_{name}_FRAMEWORKS[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] = -framework framework_{name}"
 ]
 
 _expected_conf_xconfig = [
@@ -43,16 +44,9 @@
 ]
 
 
-def get_name(configuration, architecture):
-    props = [("configuration", configuration),
-             ("architecture", architecture)]
-    name = "".join("_{}".format(v) for _, v in props if v is not None)
-    return name.lower()
-
-
-def expected_files(current_folder, configuration, architecture):
+def expected_files(current_folder, configuration, architecture, sdk, sdk_version):
     files = []
-    name = get_name(configuration, architecture)
+    name = _get_filename(configuration, architecture, sdk, sdk_version)
     deps = ["hello", "goodbye"]
     files.extend(
         [os.path.join(current_folder, "conan_{}{}.xcconfig".format(dep, name)) for dep in deps])
@@ -62,11 +56,11 @@ def expected_files(current_folder, configuration, architecture):
     return files
 
 
-def check_contents(client, deps, configuration, architecture):
+def check_contents(client, deps, configuration, architecture, sdk, sdk_version):
     for dep_name in deps:
         dep_xconfig = client.load("conan_{}.xcconfig".format(dep_name))
         conf_name = "conan_{}{}.xcconfig".format(dep_name,
-                                                 get_name(configuration, architecture))
+                                                 _get_filename(configuration, architecture, sdk, sdk_version))
 
         assert '#include "{}"'.format(conf_name) in dep_xconfig
         for var in _expected_dep_xconfig:
@@ -74,10 +68,11 @@ def check_contents(client, deps, configuration, architecture):
             assert line in dep_xconfig
 
         vars_name = "conan_{}_vars{}.xcconfig".format(dep_name,
-                                                      get_name(configuration, architecture))
+                                                      _get_filename(configuration, architecture, sdk, sdk_version))
         conan_vars = client.load(vars_name)
         for var in _expected_vars_xconfig:
-            line = var.format(name=dep_name, configuration=configuration, architecture=architecture)
+            line = var.format(name=dep_name, configuration=configuration, architecture=architecture,
+                              sdk=sdk, sdk_version=sdk_version)
             assert line in conan_vars
 
         conan_conf = client.load(conf_name)
@@ -102,13 +97,16 @@ def test_generator_files():
 
     for build_type in ["Release", "Debug"]:
 
-        client.run("install . -g XcodeDeps -s build_type={} -s arch=x86_64 --build missing".format(build_type))
+        client.run("install . -g XcodeDeps -s build_type={} -s arch=x86_64 -s os.sdk=macosx -s os.sdk_version=12.1 --build missing".format(build_type))
 
-        for config_file in expected_files(client.current_folder, build_type, "x86_64"):
+        for config_file in expected_files(client.current_folder, build_type, "x86_64", "macosx", "12.1"):
             assert os.path.isfile(config_file)
 
         conandeps = client.load("conandeps.xcconfig")
         assert '#include "conan_hello.xcconfig"' in conandeps
         assert '#include "conan_goodbye.xcconfig"' in conandeps
 
-        check_contents(client, ["hello", "goodbye"], build_type, "x86_64")
+        conan_config = client.load("conan_config.xcconfig")
+        assert '#include "conandeps.xcconfig"' in conan_config
+
+        check_contents(client, ["hello", "goodbye"], build_type, "x86_64", "macosx", "12.1")
diff --git a/conans/test/integration/toolchains/apple/test_xcodetoolchain.py b/conans/test/integration/toolchains/apple/test_xcodetoolchain.py
new file mode 100644
index 00000000000..7ed0c9a13e7
--- /dev/null
+++ b/conans/test/integration/toolchains/apple/test_xcodetoolchain.py
@@ -0,0 +1,55 @@
+import platform
+
+import pytest
+
+from conans.test.utils.tools import TestClient
+
+
+def _get_filename(configuration, architecture, sdk, sdk_version):
+    props = [("configuration", configuration),
+             ("architecture", architecture),
+             ("sdk name", sdk),
+             ("sdk version", sdk_version)]
+    name = "".join("_{}".format(v) for _, v in props if v is not None and v)
+    name = name.replace(".", "_").replace("-", "_")
+    return name.lower()
+
+
+def _condition(configuration, architecture, sdk_name, sdk_version):
+    sdk = "{}{}".format(sdk_name, sdk_version or "*")
+    return "[config={}][arch={}][sdk={}]".format(configuration, architecture, sdk)
+
+
+@pytest.mark.skipif(platform.system() != "Darwin", reason="Only for MacOS")
+@pytest.mark.parametrize("configuration, os_version, libcxx, cppstd, arch, sdk_name, sdk_version", [
+    ("Release", "", "", "", "x86_64", "", ""),
+    ("Release", "12.0", "libc++", "20", "x86_64", "", ""),
+    ("Debug", "12.0", "libc++", "20", "x86_64", "", ""),
+    ("Release", "12.0", "libc++", "20", "x86_64", "macosx", "11.3"),
+    ("Release", "12.0", "libc++", "20", "x86_64", "macosx", ""),
+])
+def test_toolchain_files(configuration, os_version, cppstd, libcxx, arch, sdk_name, sdk_version):
+    client = TestClient()
+    client.save({"conanfile.txt": "[generators]\nXcodeToolchain\n"})
+    cmd = "install . -s build_type={}".format(configuration)
+    cmd = cmd + " -s os.version={}".format(os_version) if os_version else cmd
+    cmd = cmd + " -s compiler.cppstd={}".format(cppstd) if cppstd else cmd
+    cmd = cmd + " -s os.sdk={}".format(sdk_name) if sdk_name else cmd
+    cmd = cmd + " -s os.sdk_version={}".format(sdk_version) if sdk_version else cmd
+    client.run(cmd)
+    filename = _get_filename(configuration, arch, sdk_name, sdk_version)
+    condition = _condition(configuration, arch, sdk_name, sdk_version)
+
+    toolchain_all = client.load("conantoolchain.xcconfig")
+    toolchain_vars = client.load("conantoolchain{}.xcconfig".format(filename))
+    conan_config = client.load("conan_config.xcconfig")
+
+    assert '#include "conantoolchain.xcconfig"' in conan_config
+    assert '#include "conantoolchain{}.xcconfig"'.format(filename) in toolchain_all
+
+    if libcxx:
+        assert 'CLANG_CXX_LIBRARY{}={}'.format(condition, libcxx) in toolchain_vars
+    if os_version:
+        assert 'MACOSX_DEPLOYMENT_TARGET{}={}'.format(condition, os_version) in toolchain_vars
+    if cppstd:
+        assert 'CLANG_CXX_LANGUAGE_STANDARD{}={}'.format(condition, cppstd) in toolchain_vars
diff --git a/conans/test/unittests/client/tools/apple/test_xcodebuild.py b/conans/test/unittests/client/tools/apple/test_xcodebuild.py
new file mode 100644
index 00000000000..f5cdbbdabb8
--- /dev/null
+++ b/conans/test/unittests/client/tools/apple/test_xcodebuild.py
@@ -0,0 +1,63 @@
+import pytest
+
+from conan.tools.apple import XcodeBuild
+from conans.errors import ConanException
+from conans.model.conf import ConfDefinition
+from conans.test.utils.mocks import ConanFileMock, MockSettings
+
+
+@pytest.mark.parametrize("mode", ["quiet", "verbose", "invalid"])
+def test_verbosity(mode):
+    conanfile = ConanFileMock()
+    conf = ConfDefinition()
+    conf.loads("tools.apple.xcodebuild:verbosity={}".format(mode))
+    conanfile.conf = conf
+    conanfile.settings = MockSettings({})
+    xcodebuild = XcodeBuild(conanfile)
+    if mode != "invalid":
+        xcodebuild.build("app.xcodeproj")
+        assert "-{}".format(mode) in conanfile.command
+    else:
+        with pytest.raises(ConanException) as excinfo:
+            xcodebuild.build("app.xcodeproj")
+        assert "Value {} for 'tools.apple.xcodebuild:verbosity' is not valid".format(mode) == str(
+            excinfo.value)
+
+
+def test_sdk_path():
+    conanfile = ConanFileMock()
+    conf = ConfDefinition()
+    conf.loads("tools.apple:sdk_path=mypath")
+    conanfile.conf = conf
+    conanfile.settings = MockSettings({})
+    xcodebuild = XcodeBuild(conanfile)
+    xcodebuild.build("app.xcodeproj")
+    assert "SDKROOT=mypath " in conanfile.command
+
+
+def test_sdk():
+    conanfile = ConanFileMock()
+    conf = ConfDefinition()
+    conf.loads("tools.apple:sdk_path=mypath")
+    conanfile.conf = conf
+    conanfile.settings = MockSettings({"os": "Macos",
+                                       "os.sdk": "macosx"})
+    xcodebuild = XcodeBuild(conanfile)
+    xcodebuild.build("app.xcodeproj")
+    # sdk_path takes preference
+    assert "SDKROOT=mypath " in conanfile.command
+    conf = ConfDefinition()
+    conanfile.conf = conf
+    xcodebuild = XcodeBuild(conanfile)
+    xcodebuild.build("app.xcodeproj")
+    assert "SDKROOT=macosx " in conanfile.command
+    conanfile.settings = MockSettings({"os": "Macos",
+                                       "os.sdk": "macosx",
+                                       "os.sdk_version": "12.1"})
+    xcodebuild = XcodeBuild(conanfile)
+    xcodebuild.build("app.xcodeproj")
+    assert "SDKROOT=macosx12.1 " in conanfile.command
+    conanfile.settings = MockSettings({})
+    xcodebuild = XcodeBuild(conanfile)
+    xcodebuild.build("app.xcodeproj")
+    assert "SDKROOT" not in conanfile.command


Code review comments:
diff_hunk: @@ -154,7 +155,7 @@ def _add_apple_flags(self):
             return
 
         # SDK path is mandatory for cross-building
-        sdk_path = conanfile.conf["tools.apple:sdk_path"]
+        sdk_path = apple_sdk_path(conanfile)
path: conan/tools/meson/toolchain.py
text: @author:
I changed this so it takes into account the sdk and sdk_version settings to try to find the path

@author:
reverted, because you can omit the isysroot flag if not cross-building so this is not necessary