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
36 changes: 36 additions & 0 deletions cpython-unix/build-cpython.sh
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ fi
# that a) it works on as many machines as possible b) doesn't leak details
# about the build environment, which is non-portable.
cat > ${ROOT}/hack_sysconfig.py << EOF
import json
import os
import sys
import sysconfig
Expand Down Expand Up @@ -628,6 +629,41 @@ def replace_in_all(search, replace):
replace_in_file(SYSCONFIGDATA, search, replace)


def format_sysconfigdata():
"""Reformat the sysconfigdata file to avoid implicit string concatenations.

In some Python versions, the sysconfigdata file contains implicit string
concatenations that extend over multiple lines, which make string replacement
much harder. This function reformats the file to avoid this issue.

See: https://github.com/python/cpython/blob/a03efb533a58fd13fb0cc7f4a5c02c8406a407bd/Mac/BuildScript/build-installer.py#L1360C1-L1385C15.
"""
with open(SYSCONFIGDATA, "rb") as fh:
data = fh.read()

globals_dict = {}
locals_dict = {}
exec(data, globals_dict, locals_dict)
build_time_vars = locals_dict['build_time_vars']
Copy link
Member

Choose a reason for hiding this comment

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

Should we assert there aren't other variables so this doesn't break something in the future?


with open(SYSCONFIGDATA, "wb") as fh:
fh.write(b'# system configuration generated and used by the sysconfig module\n')
fh.write(('build_time_vars = %s' % json.dumps(build_time_vars, indent=4)).encode("utf-8"))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this need a sort_keys=True to make the output deterministic? If there are any dicts, it does.

fh.close()


# Format sysconfig to ensure that string replacements take effect.
format_sysconfigdata()
Copy link
Member Author

Choose a reason for hiding this comment

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

If we don't reformat the sysconfig data file, then -isysroot and the path that follows it appear on separate lines, as separate strings within an implicit concatenation -- and replacing them becomes much harder. It looks like this file is already formatted on 3.13, but not on prior versions, so this seems fine IMO.


# Remove the Xcode path from the compiler flags.
#
# CPython itself will drop this from `sysconfig.get_config_var("CFLAGS")` and
# similar calls, but _not_ if `CFLAGS` is set in the environment (regardless of
# the `CFLAGS` value). It will almost always be wrong, so we drop it unconditionally.
xcode_path = os.getenv("APPLE_SDK_PATH")
if xcode_path:
replace_in_all("-isysroot %s" % xcode_path, "")

# -fdebug-default-version is Clang only. Strip so compiling works on GCC.
replace_in_all("-fdebug-default-version=4", "")

Expand Down
2 changes: 2 additions & 0 deletions cpython-unix/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ def add_target_env(env, build_platform, target_triple, build_env):
if not os.path.exists(sdk_path):
raise Exception("macOS SDK path %s does not exist" % sdk_path)

env["APPLE_SDK_PATH"] = sdk_path

# Grab the version from the SDK so we can put it in PYTHON.json.
sdk_settings_path = pathlib.Path(sdk_path) / "SDKSettings.json"
with sdk_settings_path.open("rb") as fh:
Expand Down
Loading