Skip to content

Commit 06f6f31

Browse files
shs96caignas
andauthored
fix: Correctly resolve macOS SDK paths (#2478)
XCode has facilities for accurately telling us where SDKs are installed. This is important to use, particularly when there may be multiple SDKs or versions of XCode installed. --------- Co-authored-by: Ignas Anikevicius <[email protected]>
1 parent e2d4ac8 commit 06f6f31

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Unreleased changes template.
5959
* 3.11.11
6060
* 3.12.9
6161
* 3.13.2
62+
* (pypi) Use `xcrun xcodebuild --showsdks` to find XCode root.
6263

6364
[20250317]: https://github.com/astral-sh/python-build-standalone/releases/tag/20250317
6465

python/private/pypi/whl_library.bzl

+43-9
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ _CPPFLAGS = "CPPFLAGS"
3030
_COMMAND_LINE_TOOLS_PATH_SLUG = "commandlinetools"
3131
_WHEEL_ENTRY_POINT_PREFIX = "rules_python_wheel_entry_point"
3232

33-
def _get_xcode_location_cflags(rctx):
33+
def _get_xcode_location_cflags(rctx, logger = None):
3434
"""Query the xcode sdk location to update cflags
3535
3636
Figure out if this interpreter target comes from rules_python, and patch the xcode sdk location if so.
@@ -46,6 +46,7 @@ def _get_xcode_location_cflags(rctx):
4646
rctx,
4747
op = "GetXcodeLocation",
4848
arguments = [repo_utils.which_checked(rctx, "xcode-select"), "--print-path"],
49+
logger = logger,
4950
)
5051
if xcode_sdk_location.return_code != 0:
5152
return []
@@ -55,9 +56,37 @@ def _get_xcode_location_cflags(rctx):
5556
# This is a full xcode installation somewhere like /Applications/Xcode13.0.app/Contents/Developer
5657
# so we need to change the path to to the macos specific tools which are in a different relative
5758
# path than xcode installed command line tools.
58-
xcode_root = "{}/Platforms/MacOSX.platform/Developer".format(xcode_root)
59+
xcode_sdks_json = repo_utils.execute_checked(
60+
rctx,
61+
op = "LocateXCodeSDKs",
62+
arguments = [
63+
repo_utils.which_checked(rctx, "xcrun"),
64+
"xcodebuild",
65+
"-showsdks",
66+
"-json",
67+
],
68+
environment = {
69+
"DEVELOPER_DIR": xcode_root,
70+
},
71+
logger = logger,
72+
).stdout
73+
xcode_sdks = json.decode(xcode_sdks_json)
74+
potential_sdks = [
75+
sdk
76+
for sdk in xcode_sdks
77+
if "productName" in sdk and
78+
sdk["productName"] == "macOS" and
79+
"darwinos" not in sdk["canonicalName"]
80+
]
81+
82+
# Now we'll get two entries here (one for internal and another one for public)
83+
# It shouldn't matter which one we pick.
84+
xcode_sdk_path = potential_sdks[0]["sdkPath"]
85+
else:
86+
xcode_sdk_path = "{}/SDKs/MacOSX.sdk".format(xcode_root)
87+
5988
return [
60-
"-isysroot {}/SDKs/MacOSX.sdk".format(xcode_root),
89+
"-isysroot {}".format(xcode_sdk_path),
6190
]
6291

6392
def _get_toolchain_unix_cflags(rctx, python_interpreter, logger = None):
@@ -84,6 +113,7 @@ def _get_toolchain_unix_cflags(rctx, python_interpreter, logger = None):
84113
"import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}', end='')",
85114
],
86115
srcs = [],
116+
logger = logger,
87117
)
88118
_python_version = stdout
89119
include_path = "{}/include/python{}".format(
@@ -176,19 +206,23 @@ def _create_repository_execution_environment(rctx, python_interpreter, logger =
176206
Dictionary of environment variable suitable to pass to rctx.execute.
177207
"""
178208

179-
# Gather any available CPPFLAGS values
180-
cppflags = []
181-
cppflags.extend(_get_xcode_location_cflags(rctx))
182-
cppflags.extend(_get_toolchain_unix_cflags(rctx, python_interpreter, logger = logger))
183-
184209
env = {
185210
"PYTHONPATH": pypi_repo_utils.construct_pythonpath(
186211
rctx,
187212
entries = rctx.attr._python_path_entries,
188213
),
189-
_CPPFLAGS: " ".join(cppflags),
190214
}
191215

216+
# Gather any available CPPFLAGS values
217+
#
218+
# We may want to build in an environment without a cc toolchain.
219+
# In those cases, we're limited to --download-only, but we should respect that here.
220+
is_wheel = rctx.attr.filename and rctx.attr.filename.endswith(".whl")
221+
if not (rctx.attr.download_only or is_wheel):
222+
cppflags = []
223+
cppflags.extend(_get_xcode_location_cflags(rctx, logger = logger))
224+
cppflags.extend(_get_toolchain_unix_cflags(rctx, python_interpreter, logger = logger))
225+
env[_CPPFLAGS] = " ".join(cppflags)
192226
return env
193227

194228
def _whl_library_impl(rctx):

0 commit comments

Comments
 (0)