Skip to content

Commit f0081e1

Browse files
committed
global: add Apple SDK metadata to PYTHON.json
indygreg/PyOxidizer#373 has revealed issues relinking the Python distributions on older Apple SDKs and Clang toolchains. In order to help downstream consumers validate they are using a sufficiently modern SDK and toolchain, this commit adds metadata to the Python distribution to advertise information about the Apple SDK used to build and its targeting settings. As part of this, we teach the Rust validation code to ensure fields are present on Apple triples.
1 parent e24247e commit f0081e1

File tree

5 files changed

+79
-5
lines changed

5 files changed

+79
-5
lines changed

cpython-unix/build.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ def add_target_env(env, build_platform, target_triple, build_env):
120120
raise Exception("could not find minimum Apple SDK version in cflags")
121121

122122
sdk_platform = settings["apple_sdk_platform"]
123+
env["APPLE_SDK_PLATFORM"] = sdk_platform
123124

124125
env["TARGET_TRIPLE"] = target_triple
125126

@@ -148,6 +149,13 @@ def add_target_env(env, build_platform, target_triple, build_env):
148149
if not os.path.exists(sdk_path):
149150
raise Exception("macOS SDK path %s does not exist" % sdk_path)
150151

152+
# Grab the version from the SDK so we can put it in PYTHON.json.
153+
sdk_settings_path = pathlib.Path(sdk_path) / "SDKSettings.json"
154+
with sdk_settings_path.open("rb") as fh:
155+
sdk_settings = json.load(fh)
156+
env["APPLE_SDK_VERSION"] = sdk_settings["Version"]
157+
env["APPLE_SDK_CANONICAL_NAME"] = sdk_settings["CanonicalName"]
158+
151159
extra_target_cflags.extend(["-isysroot", sdk_path])
152160
extra_target_ldflags.extend(["-isysroot", sdk_path])
153161

@@ -854,7 +862,7 @@ def build_cpython(
854862

855863
# Create PYTHON.json file describing this distribution.
856864
python_info = {
857-
"version": "6",
865+
"version": "7",
858866
"target_triple": target_triple,
859867
"optimizations": optimizations,
860868
"python_tag": entry["python_tag"],
@@ -890,6 +898,14 @@ def build_cpython(
890898
"tk8.6",
891899
]
892900

901+
if "-apple" in target_triple:
902+
python_info["apple_sdk_platform"] = env["APPLE_SDK_PLATFORM"]
903+
python_info["apple_sdk_version"] = env["APPLE_SDK_VERSION"]
904+
python_info["apple_sdk_canonical_name"] = env["APPLE_SDK_CANONICAL_NAME"]
905+
python_info["apple_sdk_deployment_target"] = env[
906+
"APPLE_MIN_DEPLOYMENT_TARGET"
907+
]
908+
893909
# Add metadata derived from built distribution.
894910
extra_metadata = build_env.get_file("metadata.json")
895911
python_info.update(json.loads(extra_metadata))

cpython-windows/build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2204,7 +2204,7 @@ def build_cpython(
22042204

22052205
# Create PYTHON.json file describing this distribution.
22062206
python_info = {
2207-
"version": "6",
2207+
"version": "7",
22082208
"target_triple": target_triple,
22092209
"optimizations": optimizations,
22102210
"python_tag": entry["python_tag"],

docs/distributions.rst

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ without having to resort to heuristics.
3232
The file contains a JSON map. This map has the following keys:
3333

3434
version
35-
Version number of the file format. Currently ``6``.
35+
Version number of the file format. Currently ``7``.
3636

3737
target_triple
3838
A target triple defining the platform and architecture of the machine
@@ -279,6 +279,44 @@ python_extension_module_loading
279279

280280
(Version 5 or above only.)
281281

282+
apple_sdk_canonical_name
283+
Optional canonical name of Apple SDK used to build.
284+
285+
Should only be present for target triples with ``apple`` in them.
286+
287+
The canonical name can be used to find a copy of this SDK on another
288+
machine.
289+
290+
(Version 7 or above only.)
291+
292+
apple_sdk_platform
293+
Optional name of the platform of the Apple SDK used to build.
294+
295+
Should only be present for target triples with ``apple`` in them.
296+
297+
e.g. ``macosx``
298+
299+
(Version 7 or above only.)
300+
301+
apple_sdk_version
302+
Optional version of the Apple SDK used to build.
303+
304+
Should only be present for target triples with ``apple`` in them.
305+
306+
If relinking build artifacts, ideally this exact SDK version is used.
307+
Newer versions will likely work. Older versions or Clang toolchains
308+
associated with older versions may not.
309+
310+
(Version 7 or above only.)
311+
312+
apple_sdk_deployment_target
313+
Optional version of the Apple SDK deployment target used to build.
314+
315+
This effectively establishes a minimum version of the target operating
316+
system this binary is purportedly compatible with.
317+
318+
(Version 7 or above only.)
319+
282320
crt_features
283321
Describes C Runtime features/requirements for binaries.
284322

src/json.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ pub struct PythonBuildInfo {
5757
#[derive(Debug, Deserialize)]
5858
#[serde(deny_unknown_fields)]
5959
pub struct PythonJsonMain {
60+
pub apple_sdk_canonical_name: Option<String>,
61+
pub apple_sdk_deployment_target: Option<String>,
62+
pub apple_sdk_platform: Option<String>,
63+
pub apple_sdk_version: Option<String>,
6064
pub build_info: PythonBuildInfo,
6165
pub crt_features: Vec<String>,
6266
pub libpython_link_mode: String,

src/main.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,13 +615,29 @@ fn validate_possible_object_file(
615615
fn validate_json(json: &PythonJsonMain, triple: &str) -> Result<Vec<String>> {
616616
let mut errors = vec![];
617617

618-
if json.version != "6" {
618+
if json.version != "7" {
619619
errors.push(format!(
620-
"expected version 6 in PYTHON.json; got {}",
620+
"expected version 7 in PYTHON.json; got {}",
621621
json.version
622622
));
623623
}
624624

625+
// Distributions built with Apple SDKs should have SDK metadata.
626+
if triple.contains("-apple-") {
627+
if json.apple_sdk_canonical_name.is_none() {
628+
errors.push("JSON missing apple_sdk_canonical_name on Apple triple".to_string());
629+
}
630+
if json.apple_sdk_deployment_target.is_none() {
631+
errors.push("JSON missing apple_sdk_deployment_target on Apple triple".to_string());
632+
}
633+
if json.apple_sdk_platform.is_none() {
634+
errors.push("JSON missing apple_sdk_platform on Apple triple".to_string());
635+
}
636+
if json.apple_sdk_version.is_none() {
637+
errors.push("JSON missing apple_sdk_version on Apple triple".to_string());
638+
}
639+
}
640+
625641
let wanted_platform_tag = PLATFORM_TAG_BY_TRIPLE
626642
.get(triple)
627643
.ok_or_else(|| anyhow!("platform tag not defined for triple {}", triple))?

0 commit comments

Comments
 (0)