Skip to content

Commit 001b626

Browse files
Eclips4Kirill Podoprigora
authored andcommitted
initial approach
1 parent 363f9ac commit 001b626

4 files changed

Lines changed: 94 additions & 12 deletions

File tree

Makefile.pre.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3375,7 +3375,7 @@ Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h
33753375
# Module dependencies and platform-specific files
33763376

33773377
cpython-sys: Modules/cpython-sys/Cargo.toml Modules/cpython-sys/build.rs Modules/cpython-sys/wrapper.h Modules/cpython-sys/parser.h
3378-
CARGO_TARGET_DIR=$(abs_builddir)/target PYTHON_BUILD_DIR=$(abs_builddir) RUST_SHARED_BUILD=\$(PY_ENABLE_SHARED) \$(CARGO_HOME)/bin/cargo build --lib --locked --package cpython-sys --profile $(CARGO_PROFILE) $(if $(CARGO_TARGET),--target=$(CARGO_TARGET)) --manifest-path $(srcdir)/Cargo.toml
3378+
CARGO_TARGET_DIR=$(abs_builddir)/target PYTHON_BUILD_DIR=$(abs_builddir) RUST_SHARED_BUILD=$(PY_ENABLE_SHARED) IPHONEOS_DEPLOYMENT_TARGET=$(IPHONEOS_DEPLOYMENT_TARGET) BLDSHARED_EXE='$(BLDSHARED_EXE)' BLDSHARED_ARGS='$(BLDSHARED_ARGS)' RUSTC=$(CARGO_HOME)/bin/rustc $(CARGO_HOME)/bin/cargo build --lib --locked --package cpython-sys --profile $(CARGO_PROFILE) $(if $(CARGO_TARGET),--target=$(CARGO_TARGET)) --manifest-path $(srcdir)/Cargo.toml
33793379

33803380
# force rebuild when header file or module build flavor (static/shared) is changed
33813381
MODULE_DEPS_STATIC=Modules/config.c

Modules/cpython-build-helper/src/lib.rs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,54 @@ use std::env;
33
/// Print necessary link arguments for the library depending on the build
44
/// configuration (static or shared)
55
pub fn print_linker_args() {
6-
let shared_build = env::var("RUST_SHARED_BUILD").expect("RUST_SHARED_BUILD not set in Makefile?");
7-
if shared_build == "1" {
8-
let build_shared_args =
9-
env::var("BLDSHARED_ARGS").expect("BLDSHARED_ARGS not set in Makefile?");
10-
// TODO(emmatyping): Ideally, we would not need to split the args here and take shlex
11-
// as a dependency.
12-
for arg in shlex::split(&build_shared_args).expect("Invalid BUILDSHARED_ARGS") {
13-
println!("cargo:rustc-link-arg={}", arg);
6+
println!("cargo:rerun-if-env-changed=RUST_SHARED_BUILD");
7+
println!("cargo:rerun-if-env-changed=BLDSHARED_EXE");
8+
println!("cargo:rerun-if-env-changed=BLDSHARED_ARGS");
9+
println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS");
10+
11+
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
12+
// Apple framework builds for iOS have PY_ENABLE_SHARED=0 but still require
13+
// BLDSHARED-derived framework/link flags for extension modules.
14+
let shared_build = env::var("RUST_SHARED_BUILD").unwrap_or_default() == "1"
15+
|| target_os == "ios";
16+
if shared_build {
17+
if let Ok(build_shared_exe) = env::var("BLDSHARED_EXE") {
18+
// BLDSHARED_EXE starts with the linker executable, so we only pass
19+
// the trailing arguments through to rustc.
20+
print_link_args(&build_shared_exe, true);
21+
}
22+
if let Ok(build_shared_args) = env::var("BLDSHARED_ARGS") {
23+
print_link_args(&build_shared_args, false);
1424
}
25+
return;
26+
}
27+
28+
// Static python builds on macOS still load extension symbols from the
29+
// interpreter at runtime.
30+
if target_os == "macos" {
31+
println!("cargo:rustc-link-arg=-undefined");
32+
println!("cargo:rustc-link-arg=dynamic_lookup");
33+
}
34+
}
35+
36+
fn print_link_args(raw: &str, skip_first: bool) {
37+
let mut args = shlex::split(raw).expect("Invalid linker args");
38+
if skip_first && !args.is_empty() {
39+
args.remove(0);
40+
}
41+
42+
let build_dir = env::var("PYTHON_BUILD_DIR").ok();
43+
let mut i = 0;
44+
while i < args.len() {
45+
if args[i] == "-F"
46+
&& i + 1 < args.len()
47+
&& args[i + 1] == "."
48+
&& let Some(dir) = &build_dir
49+
{
50+
args[i + 1] = dir.clone();
51+
}
52+
53+
println!("cargo:rustc-link-arg={}", args[i]);
54+
i += 1;
1555
}
16-
// Static linker configuration is in cpython-rust-staticlib
1756
}

Modules/cpython-sys/build.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ fn generate_c_api_bindings(srcdir: &Path, builddir: Option<&str>, out_path: &Pat
5353
for dir in include_dirs {
5454
builder = builder.clang_arg(format!("-I{}", dir.display()));
5555
}
56+
builder = add_target_clang_args(builder, builddir);
5657

5758
let bindings = builder
5859
.allowlist_function("_?Py.*")
@@ -69,3 +70,37 @@ fn generate_c_api_bindings(srcdir: &Path, builddir: Option<&str>, out_path: &Pat
6970
.write_to_file(out_path.join("c_api.rs"))
7071
.expect("Couldn't write bindings!");
7172
}
73+
74+
fn add_target_clang_args(mut builder: bindgen::Builder, builddir: Option<&str>) -> bindgen::Builder {
75+
let target = env::var("TARGET").unwrap_or_default();
76+
if !target.contains("apple-ios") {
77+
return builder;
78+
}
79+
80+
// For iOS targets, bindgen may parse headers with an iOS simulator/device
81+
// target but without a deployment minimum, which disables TLS support.
82+
let deployment_target = ios_deployment_target(builddir).unwrap_or_else(|| "13.0".to_string());
83+
builder = builder.clang_arg(format!("-mios-version-min={deployment_target}"));
84+
builder
85+
}
86+
87+
fn ios_deployment_target(builddir: Option<&str>) -> Option<String> {
88+
if let Ok(value) = env::var("IPHONEOS_DEPLOYMENT_TARGET")
89+
&& !value.is_empty()
90+
{
91+
return Some(value);
92+
}
93+
94+
let builddir = builddir?;
95+
let makefile = Path::new(builddir).join("Makefile");
96+
let text = std::fs::read_to_string(makefile).ok()?;
97+
for line in text.lines() {
98+
if let Some(value) = line.strip_prefix("IPHONEOS_DEPLOYMENT_TARGET=") {
99+
let value = value.trim();
100+
if !value.is_empty() {
101+
return Some(value.to_string());
102+
}
103+
}
104+
}
105+
None
106+
}

Modules/makesetup

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,20 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' |
293293
do
294294
prefixed_srcs="$prefixed_srcs $srcdir/$src"
295295
done
296+
case $UNAME_SYSTEM in
297+
Darwin*)
298+
rust_shlib_suffix=".dylib"
299+
;;
300+
*)
301+
rust_shlib_suffix="\$(SHLIB_SUFFIX)"
302+
;;
303+
esac
296304
objs=
297305
libs=
298306

299307
for mod in $mods
300308
do
301-
rust_shared="target/\$(if \$(CARGO_TARGET),\$(CARGO_TARGET)/\$(CARGO_TARGET_DIR),\$(CARGO_TARGET_DIR))/lib$mod\$(SHLIB_SUFFIX)"
309+
rust_shared="target/\$(if \$(CARGO_TARGET),\$(CARGO_TARGET)/\$(CARGO_TARGET_DIR),\$(CARGO_TARGET_DIR))/lib$mod$rust_shlib_suffix"
302310
file="$srcdir/$mod\$(EXT_SUFFIX)"
303311
case $doconfig in
304312
no)
@@ -308,7 +316,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' |
308316
esac
309317
# depends on the headers through cpython-sys
310318
rule="$rust_shared: cpython-sys \$(srcdir)/Cargo.toml \$(srcdir)/Cargo.lock \$(srcdir)/$srcdir/$manifest $prefixed_srcs \$(PYTHON_HEADERS) \$(MODULE_${mods_upper}_LDEPS) \$(LIBRARY)"
311-
rule="$rule; CARGO_TARGET_DIR=\$(abs_builddir)/target PYTHON_BUILD_DIR=\$(abs_builddir) RUST_SHARED_BUILD=\$(PY_ENABLE_SHARED) \$(CARGO_HOME)/bin/cargo build -vvv --lib --locked --package ${mod} --profile \$(CARGO_PROFILE) \$(if \$(CARGO_TARGET),--target=\$(CARGO_TARGET)) --manifest-path \$(srcdir)/Cargo.toml"
319+
rule="$rule; CARGO_TARGET_DIR=\$(abs_builddir)/target PYTHON_BUILD_DIR=\$(abs_builddir) RUST_SHARED_BUILD=\$(PY_ENABLE_SHARED) IPHONEOS_DEPLOYMENT_TARGET=\$(IPHONEOS_DEPLOYMENT_TARGET) BLDSHARED_EXE='\$(BLDSHARED_EXE)' BLDSHARED_ARGS='\$(BLDSHARED_ARGS)' RUSTC=\$(CARGO_HOME)/bin/rustc \$(CARGO_HOME)/bin/cargo build -vvv --lib --locked --package ${mod} --profile \$(CARGO_PROFILE) \$(if \$(CARGO_TARGET),--target=\$(CARGO_TARGET)) --manifest-path \$(srcdir)/Cargo.toml"
312320
echo "$rule" >>$rulesf
313321
echo "$file: $rust_shared; mv $rust_shared $file" >>$rulesf
314322
done

0 commit comments

Comments
 (0)