Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions conan/tools/apple/apple.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ def resolve_apple_flags(conanfile, is_cross_building=False):
return min_version_flag, apple_arch_flag, apple_isysroot_flag


def xcodebuild_deployment_target_key(os_name):
return {
"Macos": "MACOSX_DEPLOYMENT_TARGET",
"iOS": "IPHONEOS_DEPLOYMENT_TARGET",
"tvOS": "TVOS_DEPLOYMENT_TARGET",
"watchOS": "WATCHOS_DEPLOYMENT_TARGET",
"visionOS": "XROS_DEPLOYMENT_TARGET",
}.get(os_name) if os_name else None


class XCRun:
"""
XCRun is a wrapper for the Apple **xcrun** tool used to get information for building.
Expand Down
13 changes: 10 additions & 3 deletions conan/tools/apple/xcodebuild.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from conan.tools.apple import to_apple_arch
from conan.tools.apple.apple import to_apple_arch, xcodebuild_deployment_target_key


class XcodeBuild(object):
Expand All @@ -8,6 +8,8 @@ def __init__(self, conanfile):
self._arch = to_apple_arch(self._conanfile)
self._sdk = conanfile.settings.get_safe("os.sdk") or ""
self._sdk_version = conanfile.settings.get_safe("os.sdk_version") or ""
self._os = conanfile.settings.get_safe("os")
self._os_version = conanfile.settings.get_safe("os.version")

@property
def _verbosity(self):
Expand Down Expand Up @@ -36,8 +38,13 @@ def build(self, xcodeproj, target=None):
will build all the targets passing the ``-alltargets`` argument instead.
:return: the return code for the launched ``xcodebuild`` command.
"""
target = "-target {}".format(target) if target else "-alltargets"
cmd = "xcodebuild -project {} -configuration {} -arch {} " \
target = "-target '{}'".format(target) if target else "-alltargets"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually quote with double quotes, it is a bit more cross-platform, though I understand this isn't cross-platform at all, so most likely not an issue. Wdyt @czoido?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be fine to use single quotes as this should never run on windows cmd

cmd = "xcodebuild -project '{}' -configuration {} -arch {} " \
"{} {} {}".format(xcodeproj, self._build_type, self._arch, self._sdkroot,
self._verbosity, target)

deployment_target_key = xcodebuild_deployment_target_key(self._os)
if deployment_target_key and self._os_version:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably the main and necessary fix?
I understand that if this is not provided, it will fail to build for iOS, watchOS, etc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's not provided, the setting from the Xcode project will be used, which may be not what the library user desires. Since profile defines OS version, it's natural to use it.

cmd += f" {deployment_target_key}={self._os_version}"

self._conanfile.run(cmd)
12 changes: 3 additions & 9 deletions conan/tools/apple/xcodetoolchain.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import textwrap

from conan.internal import check_duplicated_generator
from conan.tools.apple.apple import to_apple_arch
from conan.tools.apple.apple import to_apple_arch, xcodebuild_deployment_target_key
from conan.tools.apple.xcodedeps import GLOBAL_XCCONFIG_FILENAME, GLOBAL_XCCONFIG_TEMPLATE, \
_add_includes_to_file_or_create, _xcconfig_settings_filename, _xcconfig_conditional
from conan.internal.util.files import save
Expand Down Expand Up @@ -64,16 +64,10 @@ def _cppstd(self):

@property
def _apple_deployment_target(self):
deployment_target_key = {
"Macos": "MACOSX_DEPLOYMENT_TARGET",
"iOS": "IPHONEOS_DEPLOYMENT_TARGET",
"tvOS": "TVOS_DEPLOYMENT_TARGET",
"watchOS": "WATCHOS_DEPLOYMENT_TARGET",
"visionOS": "XROS_DEPLOYMENT_TARGET",
}.get(str(self._conanfile.settings.get_safe("os")))
deployment_target_key = xcodebuild_deployment_target_key(self._conanfile.settings.get_safe("os"))
return '{}{}={}'.format(deployment_target_key,
_xcconfig_conditional(self._conanfile.settings, self.configuration),
self.os_version) if self.os_version else ""
self.os_version) if deployment_target_key and self.os_version else ""

@property
def _clang_cxx_library(self):
Expand Down
5 changes: 3 additions & 2 deletions test/functional/toolchains/apple/test_xcodebuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,12 @@ def package_info(self):
client.run("install . --build=missing")
client.run("install . -s build_type=Debug --build=missing")
client.run_command("xcodegen generate")
client.run("create . --build=missing -c tools.build:verbosity=verbose -c tools.compilation:verbosity=verbose")
client.run("create . --build=missing -s os.version=15.0 -c tools.build:verbosity=verbose -c tools.compilation:verbosity=verbose")
assert "MACOSX_DEPLOYMENT_TARGET=15.0" in client.out
assert "xcodebuild: error: invalid option" not in client.out
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")
client.run("create . -s build_type=Debug -s os.version=15.0 --build=missing")
assert "hello/0.1: Hello World Debug!" in client.out
assert "App Debug!" in client.out

Expand Down
36 changes: 36 additions & 0 deletions test/unittests/client/tools/apple/test_xcodebuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,39 @@ def test_sdk():
xcodebuild = XcodeBuild(conanfile)
xcodebuild.build("app.xcodeproj")
assert "SDKROOT" not in conanfile.command


@pytest.mark.parametrize("os_name, os_version, expected_key", [
("Macos", "14.0", "MACOSX_DEPLOYMENT_TARGET"),
("iOS", "15.1", "IPHONEOS_DEPLOYMENT_TARGET"),
("watchOS", "8.0", "WATCHOS_DEPLOYMENT_TARGET"),
("tvOS", "15.0", "TVOS_DEPLOYMENT_TARGET"),
("visionOS", "1.0", "XROS_DEPLOYMENT_TARGET")
])
def test_deployment_target_and_quoting(os_name, os_version, expected_key):
"""
Checks that the correct deployment target is passed and that paths are quoted.
"""
conanfile = ConanFileMock()
conanfile.settings = MockSettings({"os": os_name, "os.version": os_version})
xcodebuild = XcodeBuild(conanfile)

xcodebuild.build("My Project.xcodeproj", target="My Target")

expected_arg = f" {expected_key}={os_version}"
assert expected_arg in conanfile.command

assert "-project 'My Project.xcodeproj'" in conanfile.command
assert "-target 'My Target'" in conanfile.command


def test_no_deployment_target_if_version_is_missing():
"""
Checks that the deployment target argument is not added if os.version is missing.
"""
conanfile = ConanFileMock()
conanfile.settings = MockSettings({"os": "Macos"})
xcodebuild = XcodeBuild(conanfile)
xcodebuild.build("app.xcodeproj")

assert "MACOSX_DEPLOYMENT_TARGET" not in conanfile.command
Loading