diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0f60c30ac8a60..ab9a73627ae1df 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -383,6 +383,9 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false + - uses: dtolnay/rust-toolchain@1.91.1 + with: + targets: ${{ matrix.arch }}-linux-android - name: Build and test run: ./Android/android.py ci --fast-ci ${{ matrix.arch }}-linux-android @@ -396,7 +399,9 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false - + - uses: dtolnay/rust-toolchain@1.91.1 + with: + targets: aarch64-apple-ios-sim # GitHub recommends explicitly selecting the desired Xcode version: # https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140 # This became a necessity as a result of diff --git a/.github/workflows/reusable-wasi.yml b/.github/workflows/reusable-wasi.yml index 8f412288f530bc..b0462a82ed34a1 100644 --- a/.github/workflows/reusable-wasi.yml +++ b/.github/workflows/reusable-wasi.yml @@ -48,6 +48,9 @@ jobs: uses: actions/setup-python@v5 with: python-version: '3.x' + - uses: dtolnay/rust-toolchain@1.91.1 + with: + targets: wasm32-wasip1 - name: "Runner image version" run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV" - name: "Configure build Python" diff --git a/Cargo.lock b/Cargo.lock index afc3744abd1cb6..132b913b06d5e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,7 @@ version = 4 name = "_base64" version = "0.1.0" dependencies = [ + "cpython-build-helper", "cpython-sys", ] @@ -70,11 +71,26 @@ dependencies = [ "libloading", ] +[[package]] +name = "cpython-build-helper" +version = "0.1.0" +dependencies = [ + "shlex", +] + +[[package]] +name = "cpython-rust-staticlib" +version = "0.1.0" +dependencies = [ + "_base64", +] + [[package]] name = "cpython-sys" version = "0.1.0" dependencies = [ "bindgen", + "shlex", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 8b75182b7a596a..768d289fd77653 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "3" members = [ - "Modules/_base64", + "Modules/_base64", "Modules/cpython-build-helper", "Modules/cpython-rust-staticlib", "Modules/cpython-sys" ] diff --git a/Makefile.pre.in b/Makefile.pre.in index 10f299819cd40f..03c894268fea72 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -62,6 +62,10 @@ CARGO_HOME=@CARGO_HOME@ CARGO_TARGET_DIR=@CARGO_TARGET_DIR@ CARGO_PROFILE=@CARGO_PROFILE@ CARGO_TARGET=@CARGO_TARGET@ +CARGO_TARGET_LINKER_ENV=@CARGO_TARGET_LINKER_ENV@ +CARGO_DYLIB_SUFFIX=@CARGO_DYLIB_SUFFIX@ +LLVM_TARGET=@LLVM_TARGET@ +RUST_STATICLIB_DEP=@RUST_STATICLIB_DEP@ GNULD= @GNULD@ @@ -178,7 +182,8 @@ CONFINCLUDEPY= $(CONFINCLUDEDIR)/python$(LDVERSION) SHLIB_SUFFIX= @SHLIB_SUFFIX@ EXT_SUFFIX= @EXT_SUFFIX@ LDSHARED= @LDSHARED@ $(PY_LDFLAGS) -BLDSHARED= @BLDSHARED@ $(PY_CORE_LDFLAGS) +BLDSHARED_EXE= @BLDSHARED_EXE@ +BLDSHARED_ARGS= @BLDSHARED_ARGS@ $(PY_CORE_LDFLAGS) LDCXXSHARED= @LDCXXSHARED@ $(PY_LDFLAGS) DESTSHARED= $(BINLIBDEST)/lib-dynload @@ -988,7 +993,7 @@ clinic-tests: check-clean-src $(srcdir)/Lib/test/clinic.test.c $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py -f $(srcdir)/Lib/test/clinic.test.c # Build the interpreter -$(BUILDPYTHON): Programs/python.o $(LINK_PYTHON_DEPS) +$(BUILDPYTHON): Programs/python.o $(LINK_PYTHON_DEPS) $(RUST_STATICLIB_DEP) $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) platform: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt @@ -1021,16 +1026,16 @@ $(LIBRARY): $(LIBRARY_OBJS) libpython$(LDVERSION).so: $(LIBRARY_OBJS) $(DTRACE_OBJS) # AIX Linker don't support "-h" option if test "$(MACHDEP)" != "aix"; then \ - $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM); \ + $(BLDSHARED_EXE) $(BLDSHARED_ARGS) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM); \ else \ - $(BLDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM); \ + $(BLDSHARED_EXE) $(BLDSHARED_ARGS) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM); \ fi if test $(INSTSONAME) != $@; then \ $(LN) -f $(INSTSONAME) $@; \ fi libpython3.so: libpython$(LDVERSION).so - $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^ + $(BLDSHARED_EXE) $(BLDSHARED_ARGS) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^ libpython$(LDVERSION).dylib: $(LIBRARY_OBJS) $(CC) -dynamiclib $(PY_CORE_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(DTRACE_OBJS) $(SHLIBS) $(LIBC) $(LIBM); \ @@ -3374,7 +3379,12 @@ Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h # Module dependencies and platform-specific files cpython-sys: Modules/cpython-sys/Cargo.toml Modules/cpython-sys/build.rs Modules/cpython-sys/wrapper.h Modules/cpython-sys/parser.h - CARGO_TARGET_DIR=$(abs_builddir)/target PYTHON_BUILD_DIR=$(abs_builddir) \$(CARGO_HOME)/bin/cargo build --lib --locked --package cpython-sys --profile $(CARGO_PROFILE) $(if $(CARGO_TARGET),--target=$(CARGO_TARGET)) --manifest-path $(srcdir)/Cargo.toml + CARGO_TARGET_DIR=$(abs_builddir)/target PYTHON_BUILD_DIR=$(abs_builddir) PY_CC="$(CC)" PY_CPPFLAGS="$(CPPFLAGS)" PY_CFLAGS="$(CFLAGS)" LLVM_TARGET="$(LLVM_TARGET)" $(CARGO_HOME)/bin/cargo build --lib --locked --package cpython-sys --profile $(CARGO_PROFILE) $(if $(CARGO_TARGET),--target=$(CARGO_TARGET)) --manifest-path $(srcdir)/Cargo.toml + +RUST_STATICLIB_A= target/$(if $(CARGO_TARGET),$(CARGO_TARGET)/$(CARGO_TARGET_DIR),$(CARGO_TARGET_DIR))/libcpython_rust_staticlib.a + +cpython-rust-staticlib: cpython-sys + CARGO_TARGET_DIR=$(abs_builddir)/target PYTHON_BUILD_DIR=$(abs_builddir) $(CARGO_HOME)/bin/cargo build --lib --locked --package cpython-rust-staticlib --profile $(CARGO_PROFILE) $(if $(CARGO_TARGET),--target=$(CARGO_TARGET)) --manifest-path $(srcdir)/Cargo.toml # force rebuild when header file or module build flavor (static/shared) is changed MODULE_DEPS_STATIC=Modules/config.c diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c index f5cd73bdea8333..f6d584189eb4ec 100644 --- a/Misc/platform_triplet.c +++ b/Misc/platform_triplet.c @@ -1,5 +1,12 @@ /* Detect platform triplet from builtin defines * cc -E Misc/platform_triplet.c | grep '^PLATFORM_TRIPLET=' | tr -d ' ' + * + * Also detects the closest Rust target triple for cargo/rustc: + * cc -E Misc/platform_triplet.c | grep '^RUST_TARGET=' | tr -d ' ' + * + * And the LLVM/clang target triple (for bindgen), only when it differs + * from RUST_TARGET: + * cc -E Misc/platform_triplet.c | grep '^LLVM_TARGET=' | tr -d ' ' */ #undef bfin #undef cris @@ -16,12 +23,16 @@ #if defined(__ANDROID__) # if defined(__x86_64__) PLATFORM_TRIPLET=x86_64-linux-android +RUST_TARGET=x86_64-linux-android # elif defined(__i386__) PLATFORM_TRIPLET=i686-linux-android +RUST_TARGET=i686-linux-android # elif defined(__aarch64__) PLATFORM_TRIPLET=aarch64-linux-android +RUST_TARGET=aarch64-linux-android # elif defined(__arm__) PLATFORM_TRIPLET=arm-linux-androideabi +RUST_TARGET=arm-linux-androideabi # else # error unknown Android platform # endif @@ -39,18 +50,25 @@ PLATFORM_TRIPLET=arm-linux-androideabi # elif defined(__GLIBC__) # define LIBC gnu # define LIBC_X32 gnux32 +# define RUST_LIBC gnu +# define RUST_LIBC_X32 gnux32 # if defined(__ARM_PCS_VFP) # define LIBC_ARM gnueabihf +# define RUST_LIBC_ARM gnueabihf # else # define LIBC_ARM gnueabi +# define RUST_LIBC_ARM gnueabi # endif # if defined(__loongarch__) # if defined(__loongarch_soft_float) # define LIBC_LA gnusf +# define RUST_LIBC_LA unknown # elif defined(__loongarch_single_float) # define LIBC_LA gnuf32 +# define RUST_LIBC_LA unknown # elif defined(__loongarch_double_float) # define LIBC_LA gnu +# define RUST_LIBC_LA gnu # else # error unknown loongarch floating-point base abi # endif @@ -59,20 +77,26 @@ PLATFORM_TRIPLET=arm-linux-androideabi # if defined(__mips_hard_float) # if defined(_ABIO32) && _MIPS_SIM == _ABIO32 # define LIBC_MIPS gnu +# define RUST_LIBC_MIPS gnu # elif defined(_ABIN32) && _MIPS_SIM == _ABIN32 # define LIBC_MIPS gnuabin32 +# define RUST_LIBC_MIPS unknown # elif defined(_ABI64) && _MIPS_SIM == _ABI64 # define LIBC_MIPS gnuabi64 +# define RUST_LIBC_MIPS gnuabi64 # else # error unknown mips sim value # endif # else # if defined(_ABIO32) && _MIPS_SIM == _ABIO32 # define LIBC_MIPS gnusf +# define RUST_LIBC_MIPS unknown # elif defined(_ABIN32) && _MIPS_SIM == _ABIN32 # define LIBC_MIPS gnuabin32sf +# define RUST_LIBC_MIPS unknown # elif defined(_ABI64) && _MIPS_SIM == _ABI64 # define LIBC_MIPS gnuabi64sf +# define RUST_LIBC_MIPS unknown # else # error unknown mips sim value # endif @@ -80,8 +104,10 @@ PLATFORM_TRIPLET=arm-linux-androideabi # endif # if defined(__SPE__) # define LIBC_PPC gnuspe +# define RUST_LIBC_PPC gnuspe # else # define LIBC_PPC gnu +# define RUST_LIBC_PPC gnu # endif # else // Heuristic to detect musl libc @@ -89,18 +115,25 @@ PLATFORM_TRIPLET=arm-linux-androideabi # ifdef __DEFINED_va_list # define LIBC musl # define LIBC_X32 muslx32 +# define RUST_LIBC musl +# define RUST_LIBC_X32 unknown # if defined(__ARM_PCS_VFP) # define LIBC_ARM musleabihf +# define RUST_LIBC_ARM musleabihf # else # define LIBC_ARM musleabi +# define RUST_LIBC_ARM musleabi # endif # if defined(__loongarch__) # if defined(__loongarch_soft_float) # define LIBC_LA muslsf +# define RUST_LIBC_LA unknown # elif defined(__loongarch_single_float) # define LIBC_LA muslf32 +# define RUST_LIBC_LA unknown # elif defined(__loongarch_double_float) # define LIBC_LA musl +# define RUST_LIBC_LA musl # else # error unknown loongarch floating-point base abi # endif @@ -109,20 +142,27 @@ PLATFORM_TRIPLET=arm-linux-androideabi # if defined(__mips_hard_float) # if defined(_ABIO32) && _MIPS_SIM == _ABIO32 # define LIBC_MIPS musl +# define RUST_LIBC_MIPS musl # elif defined(_ABIN32) && _MIPS_SIM == _ABIN32 # define LIBC_MIPS musln32 +# define RUST_LIBC_MIPS unknown # elif defined(_ABI64) && _MIPS_SIM == _ABI64 # define LIBC_MIPS musl +# define RUST_LIBC_MIPS muslabi64 +# define LLVM_LIBC_MIPS musl # else # error unknown mips sim value # endif # else # if defined(_ABIO32) && _MIPS_SIM == _ABIO32 # define LIBC_MIPS muslsf +# define RUST_LIBC_MIPS unknown # elif defined(_ABIN32) && _MIPS_SIM == _ABIN32 # define LIBC_MIPS musln32sf +# define RUST_LIBC_MIPS unknown # elif defined(_ABI64) && _MIPS_SIM == _ABI64 # define LIBC_MIPS muslsf +# define RUST_LIBC_MIPS unknown # else # error unknown mips sim value # endif @@ -130,8 +170,10 @@ PLATFORM_TRIPLET=arm-linux-androideabi # endif # if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) # define LIBC_PPC muslsf +# define RUST_LIBC_PPC unknown # else # define LIBC_PPC musl +# define RUST_LIBC_PPC musl # endif # else # error unknown libc @@ -140,85 +182,126 @@ PLATFORM_TRIPLET=arm-linux-androideabi # if defined(__x86_64__) && defined(__LP64__) PLATFORM_TRIPLET=x86_64-linux-LIBC +RUST_TARGET=x86_64-unknown-linux-RUST_LIBC # elif defined(__x86_64__) && defined(__ILP32__) PLATFORM_TRIPLET=x86_64-linux-LIBC_X32 +RUST_TARGET=x86_64-unknown-linux-RUST_LIBC_X32 # elif defined(__i386__) PLATFORM_TRIPLET=i386-linux-LIBC +RUST_TARGET=i686-unknown-linux-RUST_LIBC # elif defined(__aarch64__) && defined(__AARCH64EL__) # if defined(__ILP32__) PLATFORM_TRIPLET=aarch64_ilp32-linux-LIBC +RUST_TARGET=unknown # else PLATFORM_TRIPLET=aarch64-linux-LIBC +RUST_TARGET=aarch64-unknown-linux-RUST_LIBC # endif # elif defined(__aarch64__) && defined(__AARCH64EB__) # if defined(__ILP32__) PLATFORM_TRIPLET=aarch64_be_ilp32-linux-LIBC +RUST_TARGET=unknown # else PLATFORM_TRIPLET=aarch64_be-linux-LIBC +RUST_TARGET=aarch64_be-unknown-linux-RUST_LIBC # endif # elif defined(__alpha__) PLATFORM_TRIPLET=alpha-linux-LIBC +RUST_TARGET=unknown # elif defined(__ARM_EABI__) # if defined(__ARMEL__) PLATFORM_TRIPLET=arm-linux-LIBC_ARM +RUST_TARGET=arm-unknown-linux-RUST_LIBC_ARM # else PLATFORM_TRIPLET=armeb-linux-LIBC_ARM +RUST_TARGET=armeb-unknown-linux-RUST_LIBC_ARM # endif # elif defined(__hppa__) PLATFORM_TRIPLET=hppa-linux-LIBC +RUST_TARGET=unknown # elif defined(__ia64__) PLATFORM_TRIPLET=ia64-linux-LIBC +RUST_TARGET=unknown # elif defined(__loongarch__) && defined(__loongarch_lp64) PLATFORM_TRIPLET=loongarch64-linux-LIBC_LA +RUST_TARGET=loongarch64-unknown-linux-RUST_LIBC_LA # elif defined(__m68k__) && !defined(__mcoldfire__) PLATFORM_TRIPLET=m68k-linux-LIBC +RUST_TARGET=m68k-unknown-linux-RUST_LIBC # elif defined(__mips__) # if defined(__mips_isa_rev) && (__mips_isa_rev >=6) # if defined(_MIPSEL) && defined(__mips64) PLATFORM_TRIPLET=mipsisa64r6el-linux-LIBC_MIPS +RUST_TARGET=mipsisa64r6el-unknown-linux-RUST_LIBC_MIPS # elif defined(_MIPSEL) PLATFORM_TRIPLET=mipsisa32r6el-linux-LIBC_MIPS +RUST_TARGET=mipsisa32r6el-unknown-linux-RUST_LIBC_MIPS # elif defined(__mips64) PLATFORM_TRIPLET=mipsisa64r6-linux-LIBC_MIPS +RUST_TARGET=mipsisa64r6-unknown-linux-RUST_LIBC_MIPS # else PLATFORM_TRIPLET=mipsisa32r6-linux-LIBC_MIPS +RUST_TARGET=mipsisa32r6-unknown-linux-RUST_LIBC_MIPS # endif # else # if defined(_MIPSEL) && defined(__mips64) PLATFORM_TRIPLET=mips64el-linux-LIBC_MIPS +RUST_TARGET=mips64el-unknown-linux-RUST_LIBC_MIPS +# ifdef LLVM_LIBC_MIPS +LLVM_TARGET=mips64el-unknown-linux-LLVM_LIBC_MIPS +# endif # elif defined(_MIPSEL) PLATFORM_TRIPLET=mipsel-linux-LIBC_MIPS +RUST_TARGET=mipsel-unknown-linux-RUST_LIBC_MIPS # elif defined(__mips64) PLATFORM_TRIPLET=mips64-linux-LIBC_MIPS +RUST_TARGET=mips64-unknown-linux-RUST_LIBC_MIPS +# ifdef LLVM_LIBC_MIPS +LLVM_TARGET=mips64-unknown-linux-LLVM_LIBC_MIPS +# endif # else PLATFORM_TRIPLET=mips-linux-LIBC_MIPS +RUST_TARGET=mips-unknown-linux-RUST_LIBC_MIPS # endif # endif # elif defined(__or1k__) PLATFORM_TRIPLET=or1k-linux-LIBC +RUST_TARGET=unknown # elif defined(__powerpc64__) # if defined(__LITTLE_ENDIAN__) PLATFORM_TRIPLET=powerpc64le-linux-LIBC +RUST_TARGET=powerpc64le-unknown-linux-RUST_LIBC # else PLATFORM_TRIPLET=powerpc64-linux-LIBC +RUST_TARGET=powerpc64-unknown-linux-RUST_LIBC # endif # elif defined(__powerpc__) PLATFORM_TRIPLET=powerpc-linux-LIBC_PPC +RUST_TARGET=powerpc-unknown-linux-RUST_LIBC_PPC # elif defined(__s390x__) PLATFORM_TRIPLET=s390x-linux-LIBC +RUST_TARGET=s390x-unknown-linux-RUST_LIBC # elif defined(__s390__) PLATFORM_TRIPLET=s390-linux-LIBC +RUST_TARGET=unknown # elif defined(__sh__) && defined(__LITTLE_ENDIAN__) PLATFORM_TRIPLET=sh4-linux-LIBC +RUST_TARGET=unknown # elif defined(__sparc__) && defined(__arch64__) PLATFORM_TRIPLET=sparc64-linux-LIBC +RUST_TARGET=sparc64-unknown-linux-RUST_LIBC # elif defined(__sparc__) PLATFORM_TRIPLET=sparc-linux-LIBC +RUST_TARGET=sparc-unknown-linux-RUST_LIBC # elif defined(__riscv) # if __riscv_xlen == 32 PLATFORM_TRIPLET=riscv32-linux-LIBC +RUST_TARGET=riscv32gc-unknown-linux-RUST_LIBC +LLVM_TARGET=riscv32-unknown-linux-RUST_LIBC # elif __riscv_xlen == 64 PLATFORM_TRIPLET=riscv64-linux-LIBC +RUST_TARGET=riscv64gc-unknown-linux-RUST_LIBC +LLVM_TARGET=riscv64-unknown-linux-RUST_LIBC # else # error unknown platform triplet # endif @@ -231,16 +314,20 @@ PLATFORM_TRIPLET=riscv64-linux-LIBC #elif defined(__FreeBSD_kernel__) # if defined(__LP64__) PLATFORM_TRIPLET=x86_64-kfreebsd-gnu +RUST_TARGET=unknown # elif defined(__i386__) PLATFORM_TRIPLET=i386-kfreebsd-gnu +RUST_TARGET=unknown # else # error unknown platform triplet # endif #elif defined(__gnu_hurd__) # if defined(__x86_64__) && defined(__LP64__) PLATFORM_TRIPLET=x86_64-gnu +RUST_TARGET=x86_64-unknown-hurd-gnu # elif defined(__i386__) PLATFORM_TRIPLET=i386-gnu +RUST_TARGET=i686-unknown-hurd-gnu # else # error unknown platform triplet # endif @@ -251,28 +338,48 @@ PLATFORM_TRIPLET=i386-gnu # if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR # if __x86_64__ PLATFORM_TRIPLET=x86_64-iphonesimulator +RUST_TARGET=x86_64-apple-ios +LLVM_TARGET=x86_64-apple-ios-simulator # else PLATFORM_TRIPLET=arm64-iphonesimulator +RUST_TARGET=aarch64-apple-ios-sim +LLVM_TARGET=arm64-apple-ios-simulator # endif # else PLATFORM_TRIPLET=arm64-iphoneos +RUST_TARGET=aarch64-apple-ios +LLVM_TARGET=arm64-apple-ios # endif // Older macOS SDKs do not define TARGET_OS_OSX # elif !defined(TARGET_OS_OSX) || TARGET_OS_OSX PLATFORM_TRIPLET=darwin +# if defined(__x86_64__) +RUST_TARGET=x86_64-apple-darwin +LLVM_TARGET=x86_64-apple-macosx +# elif defined(__aarch64__) +RUST_TARGET=aarch64-apple-darwin +LLVM_TARGET=arm64-apple-macosx +# else +RUST_TARGET=unknown +# endif # else # error unknown Apple platform # endif #elif defined(__VXWORKS__) PLATFORM_TRIPLET=vxworks +RUST_TARGET=unknown #elif defined(__wasm32__) # if defined(__EMSCRIPTEN__) PLATFORM_TRIPLET=wasm32-emscripten +RUST_TARGET=wasm32-unknown-emscripten # elif defined(__wasi__) # if defined(_REENTRANT) PLATFORM_TRIPLET=wasm32-wasi-threads +RUST_TARGET=wasm32-wasip1-threads +LLVM_TARGET=wasm32-wasi # else PLATFORM_TRIPLET=wasm32-wasi +RUST_TARGET=wasm32-wasip1 # endif # else # error unknown wasm32 platform @@ -280,8 +387,10 @@ PLATFORM_TRIPLET=wasm32-wasi #elif defined(__wasm64__) # if defined(__EMSCRIPTEN__) PLATFORM_TRIPLET=wasm64-emscripten +RUST_TARGET=unknown # elif defined(__wasi__) PLATFORM_TRIPLET=wasm64-wasi +RUST_TARGET=unknown # else # error unknown wasm64 platform # endif diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 635be3cbe8dbc0..6b56dd858ce585 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -120,7 +120,7 @@ ############################################################################ # Rust modules # -@MODULE__BASE64_TRUE@_base64 _base64/Cargo.toml _base64/src/lib.rs lib_base64.a +@MODULE__BASE64_TRUE@_base64 _base64/Cargo.toml _base64/src/lib.rs ############################################################################ # Modules with some UNIX dependencies diff --git a/Modules/_base64/Cargo.toml b/Modules/_base64/Cargo.toml index 0810b787ab2773..f90350624729d6 100644 --- a/Modules/_base64/Cargo.toml +++ b/Modules/_base64/Cargo.toml @@ -6,6 +6,10 @@ edition = "2024" [dependencies] cpython-sys ={ path = "../cpython-sys" } +[build-dependencies] +cpython-build-helper = { path = "../cpython-build-helper" } + [lib] name = "_base64" -crate-type = ["staticlib"] +# For shared builds, we generate a c dynamic library. Static builds use the rlib +crate-type = ["cdylib", "rlib"] diff --git a/Modules/_base64/build.rs b/Modules/_base64/build.rs new file mode 100644 index 00000000000000..8cca32f8f8c3df --- /dev/null +++ b/Modules/_base64/build.rs @@ -0,0 +1,5 @@ +use cpython_build_helper::print_linker_args; + +fn main() { + print_linker_args(); +} diff --git a/Modules/_base64/src/lib.rs b/Modules/_base64/src/lib.rs index 7e13438ca21c6f..64e4d718789372 100644 --- a/Modules/_base64/src/lib.rs +++ b/Modules/_base64/src/lib.rs @@ -115,7 +115,6 @@ impl Drop for BorrowedBuffer { /// # Safety /// `module` must be a valid pointer of PyObject representing the module. /// `args` must be a valid pointer to an array of valid PyObject pointers with length `nargs`. -#[unsafe(no_mangle)] pub unsafe extern "C" fn standard_b64encode( _module: *mut PyObject, args: *mut *mut PyObject, @@ -193,13 +192,11 @@ fn standard_b64encode_impl(source: &PyObject) -> Result<*mut PyObject, ()> { Ok(result) } -#[unsafe(no_mangle)] pub extern "C" fn _base64_clear(_obj: *mut PyObject) -> c_int { //TODO 0 } -#[unsafe(no_mangle)] pub extern "C" fn _base64_free(_o: *mut c_void) { //TODO } diff --git a/Modules/cpython-build-helper/Cargo.toml b/Modules/cpython-build-helper/Cargo.toml new file mode 100644 index 00000000000000..1369020965012a --- /dev/null +++ b/Modules/cpython-build-helper/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cpython-build-helper" +version = "0.1.0" +edition = "2024" + +[dependencies] +shlex = "1.3" diff --git a/Modules/cpython-build-helper/README.md b/Modules/cpython-build-helper/README.md new file mode 100644 index 00000000000000..f42946cfefc31c --- /dev/null +++ b/Modules/cpython-build-helper/README.md @@ -0,0 +1,4 @@ +# cpython-build-helper + +This crate is used in Rust modules `build.rs` files to help do common tasks such +as passing necessary link arguments. \ No newline at end of file diff --git a/Modules/cpython-build-helper/src/lib.rs b/Modules/cpython-build-helper/src/lib.rs new file mode 100644 index 00000000000000..94883aaf4f8d82 --- /dev/null +++ b/Modules/cpython-build-helper/src/lib.rs @@ -0,0 +1,54 @@ +use std::env; + +/// Print necessary link arguments for the library depending on the build +/// configuration (static or shared) +pub fn print_linker_args() { + let target = env::var("TARGET").unwrap_or_default(); + + // On Apple platforms (macOS, iOS), Cargo's cdylib produces a Mach-O + // dynamiclib (via -dynamiclib), but CPython's C extensions are built as + // bundles (via -bundle). Unlike bundles, dynamiclibs require all symbols + // to be resolved at link time. Pass -undefined dynamic_lookup so that + // Python C API symbols are resolved at load time by the interpreter. + if target.contains("apple") { + println!("cargo:rustc-cdylib-link-arg=-undefined"); + println!("cargo:rustc-cdylib-link-arg=dynamic_lookup"); + } + + // Pass platform-specific shared link arguments (e.g. PY_CORE_LDFLAGS) + // from the CPython build system. + if let Ok(args) = env::var("BLDSHARED_ARGS") { + let args = shlex::split(&args).expect("Invalid BLDSHARED_ARGS"); + let mut iter = args.iter(); + while let Some(arg) = iter.next() { + // -bundle_loader is incompatible with Cargo's cdylib on macOS + // (it only works with -bundle, not -dynamiclib). Skip it and + // its argument. + if arg == "-bundle_loader" { + iter.next(); // skip the path argument + continue; + } + println!("cargo:rustc-cdylib-link-arg={}", arg); + } + } + + // On Android (and Cygwin), extension modules must link against libpython. + // LIBPYTHON is set by the CPython build system on these platforms and + // typically contains "-L. -lpython3.X". The "-L." is relative to the + // make build directory, so resolve it to an absolute path using + // PYTHON_BUILD_DIR. + if let Ok(libpython) = env::var("LIBPYTHON") { + let builddir = env::var("PYTHON_BUILD_DIR").ok(); + for arg in shlex::split(&libpython).expect("Invalid LIBPYTHON") { + if arg == "-L." + && let Some(ref dir) = builddir + { + println!("cargo:rustc-cdylib-link-arg=-L{}", dir); + continue; + } + println!("cargo:rustc-cdylib-link-arg={}", arg); + } + } + + // Static linker configuration is in cpython-rust-staticlib +} diff --git a/Modules/cpython-rust-staticlib/Cargo.toml b/Modules/cpython-rust-staticlib/Cargo.toml new file mode 100644 index 00000000000000..d7f52b0f3e9602 --- /dev/null +++ b/Modules/cpython-rust-staticlib/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "cpython-rust-staticlib" +version = "0.1.0" +edition = "2024" + +[dependencies] +_base64 ={ path = "../_base64" } + +[lib] +name = "cpython_rust_staticlib" +crate-type = ["staticlib"] diff --git a/Modules/cpython-rust-staticlib/src/lib.rs b/Modules/cpython-rust-staticlib/src/lib.rs new file mode 100644 index 00000000000000..a440707833f65d --- /dev/null +++ b/Modules/cpython-rust-staticlib/src/lib.rs @@ -0,0 +1 @@ +pub use _base64::PyInit__base64; diff --git a/Modules/cpython-sys/Cargo.toml b/Modules/cpython-sys/Cargo.toml index de0b88d5d5b723..a12556c6e305a1 100644 --- a/Modules/cpython-sys/Cargo.toml +++ b/Modules/cpython-sys/Cargo.toml @@ -6,4 +6,5 @@ edition = "2024" [dependencies] [build-dependencies] -bindgen = "0.72.1" \ No newline at end of file +bindgen = "0.72.1" +shlex = "1.3" diff --git a/Modules/cpython-sys/build.rs b/Modules/cpython-sys/build.rs index a681e498171675..701a3be550ae0b 100644 --- a/Modules/cpython-sys/build.rs +++ b/Modules/cpython-sys/build.rs @@ -12,11 +12,8 @@ fn main() { if gil_disabled(srcdir, builddir.as_deref()) { println!("cargo:rustc-cfg=py_gil_disabled"); } + println!("cargo::rustc-check-cfg=cfg(py_gil_disabled)"); generate_c_api_bindings(srcdir, builddir.as_deref(), out_path.as_path()); - // TODO(emmatyping): generate bindings to the internal parser API - // The parser includes things slightly differently, so we should generate - // it's bindings independently - //generate_parser_bindings(srcdir, &out_path.as_path()); } fn gil_disabled(srcdir: &Path, builddir: Option<&str>) -> bool { @@ -39,13 +36,95 @@ fn gil_disabled(srcdir: &Path, builddir: Option<&str>) -> bool { fn generate_c_api_bindings(srcdir: &Path, builddir: Option<&str>, out_path: &Path) { let mut builder = bindgen::Builder::default().header("wrapper.h"); - // Always search the source dir and the public headers. - let mut include_dirs = vec![srcdir.to_path_buf(), srcdir.join("Include")]; - // Include the build directory if provided; out-of-tree builds place - // the generated pyconfig.h there. + // Suppress all clang warnings (deprecation warnings, etc.) + builder = builder.clang_arg("-w"); + + // Tell clang the correct target triple for cross-compilation. + // LLVM_TARGET is the clang/LLVM triple which may differ from the Rust + // target (e.g. arm64-apple-macosx vs aarch64-apple-darwin, or + // riscv64-unknown-linux-gnu vs riscv64gc-unknown-linux-gnu). + // Falls back to Cargo's TARGET if LLVM_TARGET is not set. + let target = env::var("LLVM_TARGET") + .or_else(|_| env::var("TARGET")) + .unwrap_or_default(); + if !target.is_empty() { + builder = builder.clang_arg(format!("--target={}", target)); + } + + // Extract cross-compilation flags from the C compiler command (PY_CC), + // preprocessor flags (PY_CPPFLAGS), and compiler flags (PY_CFLAGS). + // These provide the sysroot, include paths, and defines that bindgen's + // clang needs when cross-compiling. + // + // - WASI: sysroot in CC, -D_WASI_EMULATED_SIGNAL in CFLAGS + // - iOS: -isysroot in CPPFLAGS + let mut have_sysroot = false; + for env_name in ["PY_CC", "PY_CPPFLAGS", "PY_CFLAGS"] { + if let Ok(value) = env::var(env_name) + && let Some(flags) = shlex::split(&value) + { + let mut iter = flags.iter().peekable(); + while let Some(flag) = iter.next() { + if flag.starts_with("--sysroot") || flag.starts_with("-isysroot") { + builder = builder.clang_arg(flag); + have_sysroot = true; + // Handle "-isysroot " (space-separated) + if (flag == "-isysroot" || flag == "--sysroot") + && let Some(path) = iter.next() + { + builder = builder.clang_arg(path); + } + } else if flag.starts_with("-I") + || flag.starts_with("-D") + || flag.starts_with("-std=") + || flag.starts_with("-isystem") + { + builder = builder.clang_arg(flag); + } + } + } + } + + // WASI SDK: WASI_SDK_PATH is set by Tools/wasm/wasi/__main__.py. + // The sysroot is at $WASI_SDK_PATH/share/wasi-sysroot. + if !have_sysroot + && target.contains("wasi") + && let Ok(sdk_path) = env::var("WASI_SDK_PATH") + { + let sysroot = PathBuf::from(&sdk_path).join("share").join("wasi-sysroot"); + if sysroot.is_dir() { + builder = builder.clang_arg(format!("--sysroot={}", sysroot.display())); + have_sysroot = true; + } + } + + // Android NDK: ANDROID_HOME is set by the CI/user environment, and + // Android/android-env.sh sets CC to the NDK clang binary at: + // $ANDROID_HOME/ndk//toolchains/llvm/prebuilt//bin/-clang + // The sysroot is a sibling of bin/: + // .../toolchains/llvm/prebuilt//sysroot + if !have_sysroot + && target.contains("android") + && let Ok(cc) = env::var("PY_CC") + && let Some(parts) = shlex::split(&cc) + && let Some(binary) = parts.first() + && let Some(bin_dir) = Path::new(binary).parent() + { + let sysroot = bin_dir.with_file_name("sysroot"); + if sysroot.is_dir() { + builder = builder.clang_arg(format!("--sysroot={}", sysroot.display())); + } + } + + // Include the build directory first so that cross-build pyconfig.h + // takes precedence over any pyconfig.h in the source tree (which may + // be from a native build with different settings like LONG_BIT). + let mut include_dirs = Vec::new(); if let Some(build) = builddir { include_dirs.push(PathBuf::from(build)); } + include_dirs.push(srcdir.to_path_buf()); + include_dirs.push(srcdir.join("Include")); for dir in include_dirs { builder = builder.clang_arg(format!("-I{}", dir.display())); diff --git a/Modules/cpython-sys/src/lib.rs b/Modules/cpython-sys/src/lib.rs index 5180762fbef6bf..17924f0e5fb00a 100644 --- a/Modules/cpython-sys/src/lib.rs +++ b/Modules/cpython-sys/src/lib.rs @@ -55,7 +55,7 @@ pub const _Py_STATIC_FLAG_BITS: Py_ssize_t = pub const _Py_STATIC_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = (_Py_IMMORTAL_INITIAL_REFCNT as Py_ssize_t) | (_Py_STATIC_FLAG_BITS << 48); #[cfg(not(target_pointer_width = "64"))] -pub const _Py_STATIC_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = 7u32 << 28; +pub const _Py_STATIC_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = (7u32 << 28) as Py_ssize_t; #[repr(transparent)] pub struct PyObject(std::cell::UnsafeCell<_object>); @@ -129,7 +129,7 @@ pub const PyObject_HEAD_INIT: PyObject = { PyObject(std::cell::UnsafeCell::new(obj)) }; -#[cfg(not(py_gil_disabled))] +#[cfg(all(not(py_gil_disabled), target_pointer_width = "64"))] pub const PyObject_HEAD_INIT: PyObject = PyObject(std::cell::UnsafeCell::new(_object { __bindgen_anon_1: _object__bindgen_ty_1 { ob_refcnt_full: _Py_STATIC_IMMORTAL_INITIAL_REFCNT as i64, @@ -137,6 +137,15 @@ pub const PyObject_HEAD_INIT: PyObject = PyObject(std::cell::UnsafeCell::new(_ob ob_type: std::ptr::null_mut(), })); +// On 32-bit platforms, the refcount union only has ob_refcnt (no ob_refcnt_split). +#[cfg(all(not(py_gil_disabled), not(target_pointer_width = "64")))] +pub const PyObject_HEAD_INIT: PyObject = PyObject(std::cell::UnsafeCell::new(_object { + __bindgen_anon_1: _object__bindgen_ty_1 { + ob_refcnt: _Py_STATIC_IMMORTAL_INITIAL_REFCNT, + }, + ob_type: std::ptr::null_mut(), +})); + pub const PyModuleDef_HEAD_INIT: PyModuleDef_Base = PyModuleDef_Base { ob_base: PyObject_HEAD_INIT, m_init: None, diff --git a/Modules/makesetup b/Modules/makesetup index bd33c8fb2804c7..4b5085d843f1e7 100755 --- a/Modules/makesetup +++ b/Modules/makesetup @@ -232,7 +232,6 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | yes) continue;; esac objs='' - custom_ldflags='' if test "x$rust" = "x"; then for src in $srcs do @@ -272,6 +271,22 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | esac echo "$rule" >>$rulesf done + case $doconfig in + yes) OBJS="$OBJS $objs";; + esac + for mod in $mods + do + file="$srcdir/$mod\$(EXT_SUFFIX)" + case $doconfig in + no) + SHAREDMODS="$SHAREDMODS $file" + BUILT_SHARED="$BUILT_SHARED $mod" + ;; + esac + rule="$file: $objs \$(MODULE_${mods_upper}_LDEPS)" + rule="$rule; \$(BLDSHARED_EXE) \$(BLDSHARED_ARGS) $objs $libs \$(LIBPYTHON) -o $file" + echo "$rule" >>$rulesf + done else prefixed_srcs= for src in $srcs @@ -279,44 +294,33 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | prefixed_srcs="$prefixed_srcs $srcdir/$src" done objs= - # there's actually only one obj, so just set it to the lib - for lib in $libs - do - objs="target/\$(if \$(CARGO_TARGET),\$(CARGO_TARGET)/\$(CARGO_TARGET_DIR),\$(CARGO_TARGET_DIR))/$lib" - done libs= - # depends on the headers through cpython-sys - rule="$objs: cpython-sys \$(srcdir)/Cargo.toml \$(srcdir)/Cargo.lock \$(srcdir)/$srcdir/$manifest $prefixed_srcs \$(PYTHON_HEADERS)" - rule="$rule; CARGO_TARGET_DIR=\$(abs_builddir)/target PYTHON_BUILD_DIR=\$(abs_builddir) \$(CARGO_HOME)/bin/cargo build --lib --locked --package ${mods} --profile \$(CARGO_PROFILE) \$(if \$(CARGO_TARGET),--target=\$(CARGO_TARGET)) --manifest-path \$(srcdir)/Cargo.toml" - echo "$rule" >>$rulesf - for mod in $mods - do - case $UNAME_SYSTEM in - Darwin*) - custom_ldflags="$custom_ldflags -Wl,-u,_PyInit_$mod" - ;; - *) - custom_ldflags="$custom_ldflags -Wl,--defsym=PyInit_$mod=PyInit_$mod" - ;; - esac - done - fi - case $doconfig in - yes) OBJS="$OBJS $objs";; - esac - for mod in $mods - do - file="$srcdir/$mod\$(EXT_SUFFIX)" + case $doconfig in no) - SHAREDMODS="$SHAREDMODS $file" - BUILT_SHARED="$BUILT_SHARED $mod" + # Shared build: build each Rust module as a cdylib (.so) + for mod in $mods + do + rust_shared="target/\$(if \$(CARGO_TARGET),\$(CARGO_TARGET)/\$(CARGO_TARGET_DIR),\$(CARGO_TARGET_DIR))/lib$mod\$(CARGO_DYLIB_SUFFIX)" + file="$srcdir/$mod\$(EXT_SUFFIX)" + SHAREDMODS="$SHAREDMODS $file" + BUILT_SHARED="$BUILT_SHARED $mod" + # depends on the headers through cpython-sys + rule="$rust_shared: cpython-sys \$(srcdir)/Cargo.toml \$(srcdir)/Cargo.lock \$(srcdir)/$srcdir/$manifest $prefixed_srcs \$(PYTHON_HEADERS) \$(MODULE_${mods_upper}_LDEPS) \$(LIBRARY)" + rule="$rule; CARGO_TARGET_DIR=\$(abs_builddir)/target PYTHON_BUILD_DIR=\$(abs_builddir) BLDSHARED_ARGS=\"\$(BLDSHARED_ARGS)\" LIBPYTHON=\"\$(LIBPYTHON)\" \$(if \$(CARGO_TARGET_LINKER_ENV),\$(CARGO_TARGET_LINKER_ENV)=\$(CC)) \$(CARGO_HOME)/bin/cargo build -vvv --lib --locked --package ${mod} --profile \$(CARGO_PROFILE) \$(if \$(CARGO_TARGET),--target=\$(CARGO_TARGET)) --manifest-path \$(srcdir)/Cargo.toml" + echo "$rule" >>$rulesf + echo "$file: $rust_shared; mv $rust_shared $file" >>$rulesf + done + ;; + yes) + # Static build: Rust modules are built as part of cpython-rust-staticlib. + # The dependency on cpython-rust-staticlib is in Makefile.pre.in + # (via RUST_STATICLIB_DEP on the BUILDPYTHON rule). + rust_staticlib="target/\$(if \$(CARGO_TARGET),\$(CARGO_TARGET)/\$(CARGO_TARGET_DIR),\$(CARGO_TARGET_DIR))/libcpython_rust_staticlib.a" + LIBS="$LIBS $rust_staticlib" ;; esac - rule="$file: $objs \$(MODULE_${mods_upper}_LDEPS)" - rule="$rule; \$(BLDSHARED) $custom_ldflags $objs $libs \$(LIBPYTHON) -o $file" - echo "$rule" >>$rulesf - done + fi done case $SHAREDMODS in diff --git a/Tools/build/generate_stdlib_module_names.py b/Tools/build/generate_stdlib_module_names.py index 646f31b49761c1..f7a4166415a4a5 100644 --- a/Tools/build/generate_stdlib_module_names.py +++ b/Tools/build/generate_stdlib_module_names.py @@ -22,6 +22,10 @@ '__pycache__', 'site-packages', + # Rust build-system support modules + 'cpython-build-helper', + 'cpython-rust-staticlib', + # Test modules and packages '__hello__', '__phello__', diff --git a/configure b/configure index 5b09de36f9a0b8..16db4f9593cd47 100755 --- a/configure +++ b/configure @@ -824,6 +824,7 @@ MODULE_TIME_FALSE MODULE_TIME_TRUE MODULE__IO_FALSE MODULE__IO_TRUE +RUST_STATICLIB_DEP MODULE_BUILDTYPE _PYTHREAD_NAME_MAXLEN TEST_MODULES @@ -887,6 +888,9 @@ TCLTK_LIBS TCLTK_CFLAGS LIBSQLITE3_LIBS LIBSQLITE3_CFLAGS +LLVM_TARGET +CARGO_DYLIB_SUFFIX +CARGO_TARGET_LINKER_ENV CARGO_TARGET CARGO_PROFILE CARGO_TARGET_DIR @@ -908,7 +912,8 @@ SHLIBS CFLAGSFORSHARED LINKFORSHARED CCSHARED -BLDSHARED +BLDSHARED_ARGS +BLDSHARED_EXE LDCXXSHARED LDSHARED SHLIB_SUFFIX @@ -7173,6 +7178,13 @@ printf %s "checking for the platform triplet based on compiler characteristics.. if $CPP $CPPFLAGS $srcdir/Misc/platform_triplet.c >conftest.out 2>/dev/null; then PLATFORM_TRIPLET=`grep '^PLATFORM_TRIPLET=' conftest.out | tr -d ' '` PLATFORM_TRIPLET="${PLATFORM_TRIPLET#PLATFORM_TRIPLET=}" + RUST_TARGET=`grep '^RUST_TARGET=' conftest.out | tr -d ' '` + RUST_TARGET="${RUST_TARGET#RUST_TARGET=}" + LLVM_TARGET=`grep '^LLVM_TARGET=' conftest.out | tr -d ' '` + LLVM_TARGET="${LLVM_TARGET#LLVM_TARGET=}" + if test -z "$LLVM_TARGET"; then + LLVM_TARGET="$RUST_TARGET" + fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PLATFORM_TRIPLET" >&5 printf "%s\n" "$PLATFORM_TRIPLET" >&6; } else @@ -13503,6 +13515,7 @@ fi + # SHLIB_SUFFIX is the extension of shared libraries `(including the dot!) # -- usually .so, .sl on HP-UX, .dll on Cygwin { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the extension of shared libraries" >&5 @@ -13532,7 +13545,8 @@ if test -z "$LDSHARED" then case $ac_sys_system/$ac_sys_release in AIX*) - BLDSHARED="Modules/ld_so_aix \$(CC) -bI:Modules/python.exp" + BLDSHARED_EXE="Modules/ld_so_aix" + BLDSHARED_ARGS="\$(CC) -bI:Modules/python.exp" LDSHARED="\$(LIBPL)/ld_so_aix \$(CC) -bI:\$(LIBPL)/python.exp" ;; SunOS/5*) @@ -13556,7 +13570,8 @@ then LDCXXSHARED='$(CXX) -bundle' if test "$enable_framework" ; then # Link against the framework. All externals should be defined. - BLDSHARED="$LDSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' + BLDSHARED_EXE="$LDSHARED" + BLDSHARED_ARGS='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LDSHARED="$LDSHARED "'$(PYTHONFRAMEWORKPREFIX)/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LDCXXSHARED="$LDCXXSHARED "'$(PYTHONFRAMEWORKPREFIX)/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' else @@ -13567,14 +13582,15 @@ then Darwin/1.4*|Darwin/5.*|Darwin/6.*) LDSHARED='$(CC) -bundle' LDCXXSHARED='$(CXX) -bundle' + BLDSHARED_EXE="$LDSHARED" if test "$enable_framework" ; then # Link against the framework. All externals should be defined. - BLDSHARED="$LDSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' + BLDSHARED_ARGS='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LDSHARED="$LDSHARED "'$(PYTHONFRAMEWORKPREFIX)/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LDCXXSHARED="$LDCXXSHARED "'$(PYTHONFRAMEWORKPREFIX)/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' else # No framework, use the Python app as bundle-loader - BLDSHARED="$LDSHARED "'-bundle_loader $(BUILDPYTHON)' + BLDSHARED_ARGS='-bundle_loader $(BUILDPYTHON)' LDSHARED="$LDSHARED "'-bundle_loader $(BINDIR)/python$(VERSION)$(EXE)' LDCXXSHARED="$LDCXXSHARED "'-bundle_loader $(BINDIR)/python$(VERSION)$(EXE)' fi ;; @@ -13595,13 +13611,15 @@ then # building for OS X 10.3 and later LDSHARED='$(CC) -bundle -undefined dynamic_lookup' LDCXXSHARED='$(CXX) -bundle -undefined dynamic_lookup' - BLDSHARED="$LDSHARED" + BLDSHARED_EXE="$LDSHARED" + BLDSHARED_ARGS="" fi ;; iOS/*) LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - BLDSHARED="$LDSHARED" + BLDSHARED_EXE="$LDSHARED" + BLDSHARED_ARGS="" ;; Emscripten*|WASI*) LDSHARED='$(CC) -shared' @@ -13661,18 +13679,25 @@ fi;; fi if test "$enable_wasm_dynamic_linking" = "yes" -a "$ac_sys_system" = "Emscripten"; then - BLDSHARED='$(CC) -shared -sSIDE_MODULE=1' + BLDSHARED_EXE='$(CC) -shared' + BLDSHARED_ARGS='-sSIDE_MODULE=1' fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LDSHARED" >&5 printf "%s\n" "$LDSHARED" >&6; } LDCXXSHARED=${LDCXXSHARED-$LDSHARED} -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking BLDSHARED flags" >&5 -printf %s "checking BLDSHARED flags... " >&6; } -BLDSHARED=${BLDSHARED-$LDSHARED} -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $BLDSHARED" >&5 -printf "%s\n" "$BLDSHARED" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking BLDSHARED_EXE executable" >&5 +printf %s "checking BLDSHARED_EXE executable... " >&6; } +BLDSHARED_EXE=${BLDSHARED_EXE-$LDSHARED} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $BLDSHARED_EXE" >&5 +printf "%s\n" "$BLDSHARED_EXE" >&6; } + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking BLDSHARED_ARGS flags" >&5 +printf %s "checking BLDSHARED_ARGS flags... " >&6; } +BLDSHARED_ARGS=${BLDSHARED_ARGS-} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $BLDSHARED_ARGS" >&5 +printf "%s\n" "$BLDSHARED_ARGS" >&6; } # CCSHARED are the C *flags* used to create objects to go into a shared # library (module) -- this is only needed for a few systems @@ -16105,28 +16130,28 @@ else CARGO_TARGET_DIR='debug' CARGO_PROFILE='dev' fi - # Set CARGO_TARGET for cross-compilation - case "$host" in - aarch64-apple-ios-simulator) - CARGO_TARGET="aarch64-apple-ios-sim" - ;; - *-apple-darwin*) - cargo_host="$host" - case "$cargo_host" in - arm64-apple-*) - cargo_host="aarch64${cargo_host#arm64}" - ;; - esac - CARGO_TARGET="${cargo_host%%-apple-darwin*}-apple-darwin" - ;; - *-pc-linux-*) - CARGO_TARGET=$(echo "$host" | sed 's/-pc-linux-/-unknown-linux-/') - ;; - *) - CARGO_TARGET="$host" - ;; - esac + # RUST_TARGET is detected from Misc/platform_triplet.c using the + # C preprocessor, giving us the correct Rust target triple for the + # platform being compiled for. + CARGO_TARGET="$RUST_TARGET" + if test -z "$CARGO_TARGET" || test "$CARGO_TARGET" = "unknown"; then + as_fn_error $? "Could not determine a Rust target triple for this platform. + Rust may not support this target. Set CARGO_TARGET manually or + disable Rust support." "$LINENO" 5 + fi fi +if test -n "$CARGO_TARGET"; then + CARGO_TARGET_LINKER_ENV="CARGO_TARGET_$(echo "$CARGO_TARGET" | tr 'a-z-' 'A-Z_')_LINKER" +else + CARGO_TARGET_LINKER_ENV="" +fi +case "$host" in + *-apple-*) CARGO_DYLIB_SUFFIX=".dylib";; + *) CARGO_DYLIB_SUFFIX="$SHLIB_SUFFIX";; +esac + + + @@ -31362,6 +31387,13 @@ case $host_cpu in #( esac +if test "$HAVE_CARGO" != "no" -a "$MODULE_BUILDTYPE" = "static"; then + RUST_STATICLIB_DEP=cpython-rust-staticlib +else + RUST_STATICLIB_DEP= +fi + + MODULE_BLOCK= @@ -36187,3 +36219,4 @@ if test "$ac_cv_header_stdatomic_h" != "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Your compiler or platform does have a working C11 stdatomic.h. A future version of Python may require stdatomic.h." >&5 printf "%s\n" "$as_me: Your compiler or platform does have a working C11 stdatomic.h. A future version of Python may require stdatomic.h." >&6;} fi + diff --git a/configure.ac b/configure.ac index 1561c6f9b2e99f..dd202d193a6da1 100644 --- a/configure.ac +++ b/configure.ac @@ -1154,6 +1154,14 @@ AC_MSG_CHECKING([for the platform triplet based on compiler characteristics]) if $CPP $CPPFLAGS $srcdir/Misc/platform_triplet.c >conftest.out 2>/dev/null; then PLATFORM_TRIPLET=`grep '^PLATFORM_TRIPLET=' conftest.out | tr -d ' '` PLATFORM_TRIPLET="${PLATFORM_TRIPLET@%:@PLATFORM_TRIPLET=}" + RUST_TARGET=`grep '^RUST_TARGET=' conftest.out | tr -d ' '` + RUST_TARGET="${RUST_TARGET@%:@RUST_TARGET=}" + dnl LLVM_TARGET is only emitted when it differs from RUST_TARGET + LLVM_TARGET=`grep '^LLVM_TARGET=' conftest.out | tr -d ' '` + LLVM_TARGET="${LLVM_TARGET@%:@LLVM_TARGET=}" + if test -z "$LLVM_TARGET"; then + LLVM_TARGET="$RUST_TARGET" + fi AC_MSG_RESULT([$PLATFORM_TRIPLET]) else AC_MSG_RESULT([none]) @@ -3379,7 +3387,8 @@ with_tsan="no" AC_SUBST([SHLIB_SUFFIX]) AC_SUBST([LDSHARED]) AC_SUBST([LDCXXSHARED]) -AC_SUBST([BLDSHARED]) +AC_SUBST([BLDSHARED_EXE]) +AC_SUBST([BLDSHARED_ARGS]) AC_SUBST([CCSHARED]) AC_SUBST([LINKFORSHARED]) @@ -3409,7 +3418,8 @@ if test -z "$LDSHARED" then case $ac_sys_system/$ac_sys_release in AIX*) - BLDSHARED="Modules/ld_so_aix \$(CC) -bI:Modules/python.exp" + BLDSHARED_EXE="Modules/ld_so_aix" + BLDSHARED_ARGS="\$(CC) -bI:Modules/python.exp" LDSHARED="\$(LIBPL)/ld_so_aix \$(CC) -bI:\$(LIBPL)/python.exp" ;; SunOS/5*) @@ -3433,7 +3443,8 @@ then LDCXXSHARED='$(CXX) -bundle' if test "$enable_framework" ; then # Link against the framework. All externals should be defined. - BLDSHARED="$LDSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' + BLDSHARED_EXE="$LDSHARED" + BLDSHARED_ARGS='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LDSHARED="$LDSHARED "'$(PYTHONFRAMEWORKPREFIX)/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LDCXXSHARED="$LDCXXSHARED "'$(PYTHONFRAMEWORKPREFIX)/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' else @@ -3444,14 +3455,15 @@ then Darwin/1.4*|Darwin/5.*|Darwin/6.*) LDSHARED='$(CC) -bundle' LDCXXSHARED='$(CXX) -bundle' + BLDSHARED_EXE="$LDSHARED" if test "$enable_framework" ; then # Link against the framework. All externals should be defined. - BLDSHARED="$LDSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' + BLDSHARED_ARGS='$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LDSHARED="$LDSHARED "'$(PYTHONFRAMEWORKPREFIX)/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LDCXXSHARED="$LDCXXSHARED "'$(PYTHONFRAMEWORKPREFIX)/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' else # No framework, use the Python app as bundle-loader - BLDSHARED="$LDSHARED "'-bundle_loader $(BUILDPYTHON)' + BLDSHARED_ARGS='-bundle_loader $(BUILDPYTHON)' LDSHARED="$LDSHARED "'-bundle_loader $(BINDIR)/python$(VERSION)$(EXE)' LDCXXSHARED="$LDCXXSHARED "'-bundle_loader $(BINDIR)/python$(VERSION)$(EXE)' fi ;; @@ -3472,13 +3484,15 @@ then # building for OS X 10.3 and later LDSHARED='$(CC) -bundle -undefined dynamic_lookup' LDCXXSHARED='$(CXX) -bundle -undefined dynamic_lookup' - BLDSHARED="$LDSHARED" + BLDSHARED_EXE="$LDSHARED" + BLDSHARED_ARGS="" fi ;; iOS/*) LDSHARED='$(CC) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' LDCXXSHARED='$(CXX) -dynamiclib -F . -framework $(PYTHONFRAMEWORK)' - BLDSHARED="$LDSHARED" + BLDSHARED_EXE="$LDSHARED" + BLDSHARED_ARGS="" ;; Emscripten*|WASI*) LDSHARED='$(CC) -shared' @@ -3535,18 +3549,24 @@ then esac fi -dnl Emscripten's emconfigure sets LDSHARED. Set BLDSHARED outside the -dnl test -z $LDSHARED block to configure BLDSHARED for side module support. +dnl Emscripten's emconfigure sets LDSHARED. Set BLDSHARED_EXE and BLDSHARED_ARGS +dnl outside the test -z $LDSHARED block to configure BLDSHARED for side module +dnl support. if test "$enable_wasm_dynamic_linking" = "yes" -a "$ac_sys_system" = "Emscripten"; then - BLDSHARED='$(CC) -shared -sSIDE_MODULE=1' + BLDSHARED_EXE='$(CC) -shared' + BLDSHARED_ARGS='-sSIDE_MODULE=1' fi AC_MSG_RESULT([$LDSHARED]) LDCXXSHARED=${LDCXXSHARED-$LDSHARED} -AC_MSG_CHECKING([BLDSHARED flags]) -BLDSHARED=${BLDSHARED-$LDSHARED} -AC_MSG_RESULT([$BLDSHARED]) +AC_MSG_CHECKING([BLDSHARED_EXE executable]) +BLDSHARED_EXE=${BLDSHARED_EXE-$LDSHARED} +AC_MSG_RESULT([$BLDSHARED_EXE]) + +AC_MSG_CHECKING([BLDSHARED_ARGS flags]) +BLDSHARED_ARGS=${BLDSHARED_ARGS-} +AC_MSG_RESULT([$BLDSHARED_ARGS]) # CCSHARED are the C *flags* used to create objects to go into a shared # library (module) -- this is only needed for a few systems @@ -4328,32 +4348,37 @@ else CARGO_TARGET_DIR='debug' CARGO_PROFILE='dev' fi - # Set CARGO_TARGET for cross-compilation - case "$host" in - aarch64-apple-ios-simulator) - CARGO_TARGET="aarch64-apple-ios-sim" - ;; - *-apple-darwin*) - cargo_host="$host" - case "$cargo_host" in - arm64-apple-*) - cargo_host="aarch64${cargo_host#arm64}" - ;; - esac - CARGO_TARGET="${cargo_host%%-apple-darwin*}-apple-darwin" - ;; - *-pc-linux-*) - CARGO_TARGET=$(echo "$host" | sed 's/-pc-linux-/-unknown-linux-/') - ;; - *) - CARGO_TARGET="$host" - ;; - esac + # RUST_TARGET is detected from Misc/platform_triplet.c using the + # C preprocessor, giving us the correct Rust target triple for the + # platform being compiled for. + CARGO_TARGET="$RUST_TARGET" + if test -z "$CARGO_TARGET" || test "$CARGO_TARGET" = "unknown"; then + AC_MSG_ERROR([Could not determine a Rust target triple for this platform. + Rust may not support this target. Set CARGO_TARGET manually or + disable Rust support.]) + fi fi +dnl Compute the CARGO_TARGET__LINKER env var name so we can +dnl tell Cargo which linker to use for the target platform. +if test -n "$CARGO_TARGET"; then + CARGO_TARGET_LINKER_ENV="CARGO_TARGET_$(echo "$CARGO_TARGET" | tr 'a-z-' 'A-Z_')_LINKER" +else + CARGO_TARGET_LINKER_ENV="" +fi +dnl Cargo's cdylib crate type uses the platform's native shared library +dnl extension, which differs from CPython's SHLIB_SUFFIX on macOS/iOS +dnl (CPython uses .so, Cargo uses .dylib). +case "$host" in + *-apple-*) CARGO_DYLIB_SUFFIX=".dylib";; + *) CARGO_DYLIB_SUFFIX="$SHLIB_SUFFIX";; +esac AC_SUBST([CARGO_HOME]) AC_SUBST([CARGO_TARGET_DIR]) AC_SUBST([CARGO_PROFILE]) AC_SUBST([CARGO_TARGET]) +AC_SUBST([CARGO_TARGET_LINKER_ENV]) +AC_SUBST([CARGO_DYLIB_SUFFIX]) +AC_SUBST([LLVM_TARGET]) dnl detect sqlite3 from Emscripten emport @@ -7868,6 +7893,15 @@ AS_CASE([$host_cpu], ) AC_SUBST([MODULE_BUILDTYPE]) +dnl Set RUST_STATICLIB_DEP to cpython-rust-staticlib when building Rust +dnl modules statically so that the python binary depends on it. +if test "$HAVE_CARGO" != "no" -a "$MODULE_BUILDTYPE" = "static"; then + RUST_STATICLIB_DEP=cpython-rust-staticlib +else + RUST_STATICLIB_DEP= +fi +AC_SUBST([RUST_STATICLIB_DEP]) + dnl _MODULE_BLOCK_ADD([VAR], [VALUE]) dnl internal: adds $1=quote($2) to MODULE_BLOCK AC_DEFUN([_MODULE_BLOCK_ADD], [AS_VAR_APPEND([MODULE_BLOCK], ["$1=_AS_QUOTE([$2])$as_nl"])])