Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new sdk_version setting for Apple OS's and new XcodeBuild, XcodeToolchain tools #10608

Merged
merged 56 commits into from Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
9b70d13
wip
czoido Feb 11, 2022
3a67f7d
wip
czoido Feb 14, 2022
4ba16e0
wip
czoido Feb 14, 2022
026d963
wip
czoido Feb 14, 2022
1944e6f
add conf for verbosity
czoido Feb 14, 2022
d6ffaa4
wip
czoido Feb 14, 2022
c76011b
unit tests
czoido Feb 14, 2022
7211cc2
add sdk version for macos sdk
czoido Feb 15, 2022
b197d52
wip
czoido Feb 15, 2022
4ba12ea
wip
czoido Feb 15, 2022
2adb299
update test
czoido Feb 16, 2022
30493ce
wip
czoido Feb 16, 2022
d6f85f0
minor changes
czoido Feb 16, 2022
5522018
minor changes
czoido Feb 16, 2022
95c60b7
add asterisk
czoido Feb 16, 2022
1baf848
add deployment_target
czoido Feb 16, 2022
5be4767
minor changes
czoido Feb 16, 2022
3640d33
wip
czoido Feb 16, 2022
69dcd1f
wip
czoido Feb 16, 2022
3b6bc26
wip
czoido Feb 16, 2022
d0cab7b
add xcode toolchain
czoido Feb 16, 2022
6e9465f
wip
czoido Feb 16, 2022
260dde0
basic test
czoido Feb 16, 2022
55e04e0
update test
czoido Feb 16, 2022
a08fe22
wip
czoido Feb 17, 2022
e3498e8
wip
czoido Feb 17, 2022
f633d28
wip
czoido Feb 17, 2022
e0c6aa3
wip
czoido Feb 17, 2022
c756076
wip
czoido Feb 17, 2022
f6fe628
handle sdk path in cmake toolchain
czoido Feb 17, 2022
f680c7c
add sdk version
czoido Feb 17, 2022
fc384c6
use sdk path
czoido Feb 17, 2022
7a75ae6
add sdk version
czoido Feb 17, 2022
9bae5aa
remove test
czoido Feb 17, 2022
34ffb1c
wip
czoido Feb 18, 2022
4993c5d
revert change
czoido Feb 18, 2022
192d0cc
update tests
czoido Feb 18, 2022
0646374
minor changes
czoido Feb 18, 2022
7fd98c4
fix test
czoido Feb 18, 2022
24a4c13
minor changes
czoido Feb 18, 2022
4ac2cac
move code
czoido Feb 18, 2022
2c511b1
fix test
czoido Feb 18, 2022
31e830d
fx tests
czoido Feb 18, 2022
aef30c0
remove unused
czoido Feb 18, 2022
356495c
fix
czoido Feb 18, 2022
32f5d31
Merge branch 'develop' into xcode_sdk_version
czoido Feb 23, 2022
e969774
remove unused
czoido Feb 23, 2022
7e2d1a2
Merge branch 'develop' into xcode_sdk_version
czoido Feb 28, 2022
fa4dbe4
review
czoido Feb 28, 2022
aa4fc7d
private
czoido Feb 28, 2022
39b2599
Update conan/tools/apple/xcodebuild.py
memsharded Feb 28, 2022
6b4c37b
Update conan/tools/cmake/toolchain/blocks.py
memsharded Feb 28, 2022
f74087f
Update conan/tools/apple/xcodebuild.py
memsharded Feb 28, 2022
303024c
fix verbosity
czoido Mar 1, 2022
bbcdcdc
Merge branch 'xcode_sdk_version' of github.com:czoido/conan into xcod…
czoido Mar 1, 2022
956e3a5
fix tests
czoido Mar 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions conan/tools/apple/__init__.py
Expand Up @@ -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
3 changes: 2 additions & 1 deletion conan/tools/apple/apple.py
Expand Up @@ -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) if os_sdk else _guess_apple_sdk_name(os_, arch)


def apple_min_version_flag(conanfile):
Expand Down
37 changes: 37 additions & 0 deletions conan/tools/apple/xcodebuild.py
@@ -0,0 +1,37 @@
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 ""

@property
def _verbosity(self):
verbosity = self._conanfile.conf.get("tools.apple.xcodebuild:verbosity", default="", check_type=str)
if verbosity == "quiet" or verbosity == "verbose":
return "-{}".format(verbosity)
elif verbosity:
raise ConanException("Value {} for 'tools.apple.xcodebuild:verbosity' is not valid".format(verbosity))
return ""

@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.get("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)
106 changes: 70 additions & 36 deletions conan/tools/apple/xcodedeps.py
Expand Up @@ -8,22 +8,66 @@
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"
czoido marked this conversation as resolved.
Show resolved Hide resolved


def _xcconfig_settings_filename(settings):
arch = settings.get_safe("arch")
architecture = to_apple_arch(arch) or arch
props = [("configuration", settings.get_safe("build_type")),
("architecture", architecture),
("sdk name", settings.get_safe("os.sdk")),
("sdk version", settings.get_safe("os.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 _xcconfig_conditional(settings):
sdk_condition = "*"
arch = settings.get_safe("arch")
architecture = to_apple_arch(arch) or arch
if settings.get_safe("os.sdk"):
sdk_condition = "{}{}".format(settings.get_safe("os.sdk"), settings.get_safe("os.sdk_version") or "*")

return "[config={}][arch={}][sdk={}]".format(settings.get_safe("build_type"), architecture, sdk_condition)


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 "{}"\n'.format(include)

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("""\
Expand Down Expand Up @@ -70,13 +114,11 @@ 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)

def generate(self):
Expand All @@ -88,24 +130,13 @@ def generate(self):
for generator_file, content in generator_files.items():
save(generator_file, content)

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)
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)
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),
Expand All @@ -120,6 +151,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': _xcconfig_conditional(self._conanfile.settings)
}
formatted_template = Template(self._vars_xconfig).render(**fields)
return formatted_template
Expand All @@ -128,11 +160,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
Expand Down Expand Up @@ -166,10 +193,15 @@ 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()
conf_name = _xcconfig_settings_filename(self._conanfile.settings)

for dep in self._conanfile.dependencies.host.values():
dep_name = dep.ref.name
Expand All @@ -191,6 +223,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
92 changes: 92 additions & 0 deletions conan/tools/apple/xcodetoolchain.py
@@ -0,0 +1,92 @@
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, _xcconfig_settings_filename, _xcconfig_conditional
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)

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 _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(_xcconfig_conditional(self._conanfile.settings),
self.os_version) if self.os_version else ""

@property
def _clang_cxx_library(self):
return 'CLANG_CXX_LIBRARY{}={}'.format(_xcconfig_conditional(self._conanfile.settings),
self.libcxx) if self.libcxx else ""

@property
def _clang_cxx_language_standard(self):
return 'CLANG_CXX_LANGUAGE_STANDARD{}={}'.format(_xcconfig_conditional(self._conanfile.settings),
self._cppstd) if self._cppstd else ""
@property
def _vars_xconfig_filename(self):
return "conantoolchain{}{}".format(_xcconfig_settings_filename(self._conanfile.settings),
self.extension)

@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 _agreggated_xconfig_filename(self):
return self.filename + self.extension
21 changes: 15 additions & 6 deletions conan/tools/cmake/toolchain/blocks.py
Expand Up @@ -349,17 +349,26 @@ 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.get("tools.apple:sdk_path")

if sdk:
return sdk
elif os_ == "Macos": # if the host is Macos it can only be "macosx"
return "{}{}".format("macosx", os_sdk_version)
elif os_sdk:
return "{}{}".format(os_sdk, os_sdk_version)
else:
raise ConanException("Please, specify a suitable value for os.sdk.")

Expand Down
8 changes: 8 additions & 0 deletions conans/client/conf/__init__.py
Expand Up @@ -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
Expand All @@ -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:
Expand Down
5 changes: 4 additions & 1 deletion conans/client/generators/__init__.py
Expand Up @@ -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:
Expand Down Expand Up @@ -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))
Expand Down