diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a1adcd56fe7b977..a0f737c6c7fe6ec 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -260,12 +260,17 @@ jobs: os: ubuntu-26.04-arm build-macos-relocatable: - name: 'macOS (relocatable)' + name: 'macOS (relocatable ${{ matrix.framework }})' needs: build-context if: needs.build-context.outputs.run-macos == 'true' + strategy: + fail-fast: false + matrix: + framework: ['', 'Python', 'RelocatablePython'] uses: ./.github/workflows/reusable-relocatable.yml with: os: macos-26 + framework: ${{ matrix.framework }} build-ubuntu-ssltests: name: 'Ubuntu SSL tests' diff --git a/.github/workflows/reusable-relocatable.yml b/.github/workflows/reusable-relocatable.yml index d031715a3a07ca1..6b33e7cd1a56b60 100644 --- a/.github/workflows/reusable-relocatable.yml +++ b/.github/workflows/reusable-relocatable.yml @@ -6,6 +6,9 @@ on: os: type: string required: true + framework: + type: string + default: '' permissions: contents: read @@ -22,6 +25,7 @@ jobs: run: shell: bash env: + FRAMEWORK: ${{ inputs.framework }} PYTHONSTRICTEXTENSIONBUILD: 1 HOMEBREW_NO_ANALYTICS: 1 HOMEBREW_NO_AUTO_UPDATE: 1 @@ -46,24 +50,16 @@ jobs: echo "GDBM_CFLAGS=-I$(brew --prefix gdbm)/include" >> "$GITHUB_ENV" echo "GDBM_LIBS=-L$(brew --prefix gdbm)/lib -lgdbm" >> "$GITHUB_ENV" echo "OPENSSL_DIR=$(brew --prefix openssl@3.5)" >> "$GITHUB_ENV" - - name: Reject unsupported framework relocation - if: runner.os == 'macOS' - run: | - mkdir "$RUNNER_TEMP/framework-configure" - cd "$RUNNER_TEMP/framework-configure" - if "$GITHUB_WORKSPACE/configure" \ - --enable-framework="$RUNNER_TEMP/framework-install" \ - --enable-relocatable --with-openssl="$OPENSSL_DIR" > configure.log 2>&1; then - cat configure.log - exit 1 - fi - cat configure.log - grep -F 'does not support framework builds yet' configure.log - name: Configure CPython run: | mkdir "$BUILD_DIR" cd "$BUILD_DIR" - configure_args=(--prefix="$INSTALL_DIR" --enable-shared --enable-relocatable) + configure_args=(--prefix="$INSTALL_DIR" --enable-relocatable) + if [ -n "$FRAMEWORK" ]; then + configure_args+=(--enable-framework="$INSTALL_DIR/Library/Frameworks" --with-framework-name="$FRAMEWORK") + else + configure_args+=(--enable-shared) + fi if [ -n "${OPENSSL_DIR:-}" ]; then configure_args+=(--with-openssl="$OPENSSL_DIR") fi @@ -100,7 +96,15 @@ jobs: run: | unset LD_LIBRARY_PATH LD_PRELOAD unset DYLD_LIBRARY_PATH DYLD_FALLBACK_LIBRARY_PATH DYLD_INSERT_LIBRARIES - installed_python="$INSTALL_DIR/bin/python3" + unset DYLD_FRAMEWORK_PATH DYLD_FALLBACK_FRAMEWORK_PATH + export PYTHON_PREFIX="$INSTALL_DIR" + if [ -n "$FRAMEWORK" ]; then + framework_dir="$INSTALL_DIR/Library/Frameworks/$FRAMEWORK.framework" + framework_version=$(readlink "$framework_dir/Versions/Current") + export PYTHON_PREFIX="$framework_dir/Versions/$framework_version" + "$PYTHON_PREFIX/Resources/Python.app/Contents/MacOS/$FRAMEWORK" -I -c 'import ssl, ctypes; print("Direct app launch succeeded")' + fi + installed_python="$PYTHON_PREFIX/bin/python3" "$installed_python" -I - <<'PY' import os import subprocess @@ -109,7 +113,7 @@ jobs: import tempfile import venv - prefix = os.path.realpath(os.environ['INSTALL_DIR']) + prefix = os.path.realpath(os.environ['PYTHON_PREFIX']) assert os.path.realpath(sys.prefix) == prefix, sys.prefix assert sys.exec_prefix == sys.prefix, sys.exec_prefix assert sysconfig.get_config_var('RELOCATABLE') == 'yes' diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 203b04e3b0e1943..824865fb100b8f1 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -1081,18 +1081,23 @@ Linker options This feature is under active development. Do not use it in production. - Currently, this sets relative runtime library paths on Linux and for - non-framework macOS builds. Framework relocation is not implemented yet. - Combining this option with :option:`--enable-framework` is an error. + Currently, this sets relative runtime library paths on Linux and macOS, + including macOS framework builds. Move the installation as a unit. It must use the default ``bin`` and ``lib`` directories under a common prefix. :option:`--with-platlibdir` may select a different directory name for the standard library, but not a nested path. On Linux, these paths use ``DT_RPATH``. - Copied virtual environments from non-framework shared builds require - directory symlinks to the base installation's libraries. Virtual environments - depend on their base installation and must be recreated if it moves. + When :mod:`venv` copies an interpreter from a shared or framework build, + it creates a symlink to the base library directory or the directory + containing the framework. This requires filesystem support for symlinks + even with ``--copies``. Virtual environments depend on their base + installation and must be recreated if it moves. + + A macOS framework can be moved as a unit, including its internal + ``Resources/Python.app``. External command symlinks and application launchers + are not rewritten; update any that point to the original location. Dependencies stored in other directories, such as ``lib/tcltk``, may need additional loader search paths. diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index a434b2206c9313f..b54c52783d62d41 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -1079,7 +1079,15 @@ def test_zippath_from_non_installed_posix(self): bindir = os.path.join(non_installed_dir, self.bindir) os.mkdir(bindir) python_exe = os.path.basename(sys.executable) - shutil.copy2(sys.executable, os.path.join(bindir, python_exe)) + framework = sysconfig.get_config_var("PYTHONFRAMEWORK") + source_executable = sys.executable + if framework and not sysconfig.is_python_build(): + # The framework launcher looks for the app relative to the loaded runtime. + # This fixture lacks that app bundle, so copy its interpreter directly. + source_executable = os.path.join( + sys.base_exec_prefix, 'Resources', 'Python.app', 'Contents', + 'MacOS', framework) + shutil.copy2(source_executable, os.path.join(bindir, python_exe)) if sys.platform == 'cygwin': # Copy libpython DLL exe_path = os.path.dirname(sys.executable) @@ -1132,27 +1140,34 @@ def test_zippath_from_non_installed_posix(self): # venv module correctly. pythonpath = os.pathsep.join( additional_pythonpath_for_non_installed) - # For python built with shared enabled. We need to set - # LD_LIBRARY_PATH so the non-installed python can find and link - # libpython.so - ld_library_path = sysconfig.get_config_var("LIBDIR") - if (sysconfig.get_config_var("RELOCATABLE") == "yes" - and not sysconfig.get_config_var("PYTHONFRAMEWORK")): - ld_library_path = os.path.join(sys.base_exec_prefix, "lib") + # Set the library search path so the non-installed interpreter can + # load its shared library or framework. + if framework: + ld_library_path = sysconfig.get_config_var("PYTHONFRAMEWORKPREFIX") + else: + ld_library_path = sysconfig.get_config_var("LIBDIR") + if sysconfig.get_config_var("RELOCATABLE") == "yes": + if framework: + ld_library_path = os.path.abspath(os.path.join( + sys.base_exec_prefix, '..', '..', '..')) + else: + ld_library_path = os.path.join(sys.base_exec_prefix, "lib") if not ld_library_path or sysconfig.is_python_build(): ld_library_path = os.path.abspath(os.path.dirname(sys.executable)) - if (sysconfig.get_config_var('Py_ENABLE_SHARED') + if ((sysconfig.get_config_var('Py_ENABLE_SHARED') or framework) and sys.platform != 'cygwin'): - # Startup can search relative to libpython before the executable. + # Startup can search relative to the runtime library before the executable. # Load a copy from the temporary installation to select its # standard library. shared_libdir = os.path.join(non_installed_dir, 'lib') - os.makedirs(shared_libdir, exist_ok=True) instsoname = sysconfig.get_config_var('INSTSONAME') - shutil.copy2(os.path.join(ld_library_path, instsoname), - os.path.join(shared_libdir, instsoname)) + copied_library = os.path.join(shared_libdir, instsoname) + os.makedirs(os.path.dirname(copied_library), exist_ok=True) + shutil.copy2(os.path.join(ld_library_path, instsoname), copied_library) ld_library_path = os.pathsep.join((shared_libdir, ld_library_path)) - if sys.platform == 'darwin': + if framework: + ld_library_path_env = "DYLD_FRAMEWORK_PATH" + elif sys.platform == 'darwin': ld_library_path_env = "DYLD_LIBRARY_PATH" else: ld_library_path_env = "LD_LIBRARY_PATH" diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index b4f1cbd6e1e55e8..ca82539fa1ae81d 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -311,12 +311,16 @@ def setup_python(self, context): if not os.path.islink(path): os.chmod(path, 0o755) if (sysconfig.get_config_var('RELOCATABLE') == 'yes' - and sysconfig.get_config_var('Py_ENABLE_SHARED') - and not sysconfig.get_config_var('PYTHONFRAMEWORK')): + and (sysconfig.get_config_var('Py_ENABLE_SHARED') + or sysconfig.get_config_var('PYTHONFRAMEWORK'))): # The copied executable searches relative to this environment. # Link the base library directory so it can find libpython. if sysconfig.is_python_build(): library_dir = context.python_dir + elif sysconfig.get_config_var('PYTHONFRAMEWORK'): + # The install name includes the framework directory. + library_dir = os.path.abspath(os.path.join( + sys.base_exec_prefix, '..', '..', '..')) else: library_dir = os.path.join(sys.base_exec_prefix, 'lib') library_link = os.path.join( diff --git a/Mac/Makefile.in b/Mac/Makefile.in index 32e3a0f55c5d717..a9534f603ad19ed 100644 --- a/Mac/Makefile.in +++ b/Mac/Makefile.in @@ -14,6 +14,13 @@ LIBDEST=$(prefix)/lib/python$(VERSION) RUNSHARED=@RUNSHARED@ BUILDEXE=@BUILDEXEEXT@ BUILDPYTHON=$(builddir)/python$(BUILDEXE) +RELOCATABLE=@RELOCATABLE@ +RELOCATABLE_DIR=$(builddir)/build/relocatable +RELOCATABLE_PYTHONW_LDFLAGS=@RELOCATABLE_PYTHONW_LDFLAGS@ +INSTALL_PYTHON=$(BUILDPYTHON) +ifeq ($(RELOCATABLE),yes) +INSTALL_PYTHON=$(RELOCATABLE_DIR)/python$(BUILDEXE) +endif DESTDIR= LDFLAGS=@LDFLAGS@ FRAMEWORKUNIXTOOLSPREFIX=@FRAMEWORKUNIXTOOLSPREFIX@ @@ -177,6 +184,11 @@ pythonw: $(srcdir)/Tools/pythonw.c Makefile $(srcdir)/Tools/pythonw.c -I.. -I$(srcdir)/../Include \ ../$(PYTHONFRAMEWORK).framework/Versions/$(VERSION)/$(PYTHONFRAMEWORK) +pythonw-relocatable: $(srcdir)/Tools/pythonw.c Makefile $(RELOCATABLE_DIR)/$(PYTHONFRAMEWORK).framework/Versions/$(VERSION)/$(PYTHONFRAMEWORK) + $(CC) $(LDFLAGS) $(RELOCATABLE_PYTHONW_LDFLAGS) -DPYTHONFRAMEWORK='"$(PYTHONFRAMEWORK)"' -o $@ \ + $(srcdir)/Tools/pythonw.c -I.. -I$(srcdir)/../Include \ + $(RELOCATABLE_DIR)/$(PYTHONFRAMEWORK).framework/Versions/$(VERSION)/$(PYTHONFRAMEWORK) + install_PythonLauncher: cd PythonLauncher && make install DESTDIR=$(DESTDIR) @@ -223,7 +235,7 @@ install_Python: esac; \ done; \ done - $(INSTALL_PROGRAM) $(STRIPFLAG) $(BUILDPYTHON) "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)" + $(INSTALL_PROGRAM) $(STRIPFLAG) $(INSTALL_PYTHON) "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)" sed -e "s!%bundleid%!$(PYTHONFRAMEWORKIDENTIFIER)!g" \ -e "s!%version%!`$(RUNSHARED) $(BUILDPYTHON) \ -c 'import platform; print(platform.python_version())'`!g" \ diff --git a/Makefile.pre.in b/Makefile.pre.in index 86752f28bf6b944..add061029e57f76 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -321,16 +321,21 @@ BUILDPYTHON= python$(BUILDEXE) # runtime paths relative to their installed locations. RELOCATABLE_DIR=build/relocatable INSTALL_PYTHON=$(BUILDPYTHON) +INSTALL_PYTHONW=Mac/pythonw INSTALL_LDLIBRARY=$(LDLIBRARY) INSTALL_PY3LIBRARY=$(PY3LIBRARY) INSTALL_SHAREDMODS=$(SHAREDMODS) ifeq ($(RELOCATABLE),yes) INSTALL_PYTHON=$(RELOCATABLE_DIR)/$(BUILDPYTHON) +INSTALL_PYTHONW=Mac/pythonw-relocatable INSTALL_SHAREDMODS=$(addprefix $(RELOCATABLE_DIR)/,$(SHAREDMODS)) ifeq ($(PY_ENABLE_SHARED),1) INSTALL_LDLIBRARY=$(RELOCATABLE_DIR)/$(LDLIBRARY) INSTALL_PY3LIBRARY=$(addprefix $(RELOCATABLE_DIR)/,$(PY3LIBRARY)) endif +ifneq ($(PYTHONFRAMEWORK),) +INSTALL_LDLIBRARY=$(RELOCATABLE_DIR)/$(LDLIBRARY) +endif endif HOSTRUNNER= @HOSTRUNNER@ @@ -1009,7 +1014,7 @@ $(BUILDPYTHON): Programs/python.o $(LINK_PYTHON_DEPS) $(RELOCATABLE_DIR)/$(BUILDPYTHON): Programs/python.o $(LINK_PYTHON_DEPS) $(INSTALL_LDLIBRARY) @mkdir -p $(@D) - $(LINKCC) $(PY_CORE_EXE_LDFLAGS) $(LINKFORSHARED) $(RELOCATABLE_PYTHON_LDFLAGS) -L$(RELOCATABLE_DIR) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) + $(LINKCC) $(PY_CORE_EXE_LDFLAGS) $(subst $(LDLIBRARY),$(INSTALL_LDLIBRARY),$(LINKFORSHARED)) $(RELOCATABLE_PYTHON_LDFLAGS) -L$(RELOCATABLE_DIR) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) platform: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt $(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform @@ -1108,6 +1113,14 @@ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK): \ $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK) $(LN) -fsn Versions/Current/Resources $(PYTHONFRAMEWORKDIR)/Resources +$(RELOCATABLE_DIR)/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK): $(LIBRARY) + @mkdir -p $(@D) + $(CC) -o $@ $(PY_CORE_LDFLAGS) $(RELOCATABLE_LIBPYTHON_LDFLAGS) -dynamiclib \ + -all_load $(LIBRARY) \ + -install_name $(RELOCATABLE_LIBPYTHON_INSTALL_NAME) \ + -compatibility_version $(VERSION) -current_version $(VERSION) \ + -framework CoreFoundation $(LIBS) + # This rule is for iOS, which requires an annoyingly just slightly different # format for frameworks to macOS. It *doesn't* use a versioned framework, and # the Info.plist must be in the root of the framework. @@ -2473,7 +2486,7 @@ endif if test "$(PYTHONFRAMEWORKDIR)" = "no-framework" ; then \ $(INSTALL_PROGRAM) $(INSTALL_PYTHON) $(DESTDIR)$(BINDIR)/python$(LDVERSION)$(EXE); \ else \ - $(INSTALL_PROGRAM) $(STRIPFLAG) Mac/pythonw $(DESTDIR)$(BINDIR)/python$(LDVERSION)$(EXE); \ + $(INSTALL_PROGRAM) $(STRIPFLAG) $(INSTALL_PYTHONW) $(DESTDIR)$(BINDIR)/python$(LDVERSION)$(EXE); \ fi -if test "$(VERSION)" != "$(LDVERSION)"; then \ if test -f $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE) -o -h $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE); \ @@ -3075,7 +3088,7 @@ frameworkinstallframework: @FRAMEWORKINSTALLFIRST@ install frameworkinstallmacli # macOS uses a versioned frameworks structure that includes a full install .PHONY: frameworkinstallversionedstructure -frameworkinstallversionedstructure: $(LDLIBRARY) +frameworkinstallversionedstructure: all @if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \ echo Not configured with --enable-framework; \ exit 1; \ @@ -3094,7 +3107,7 @@ frameworkinstallversionedstructure: $(LDLIBRARY) $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/$(PYTHONFRAMEWORK) $(LN) -fsn Versions/Current/Headers $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers $(LN) -fsn Versions/Current/Resources $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Resources - $(INSTALL_SHARED) $(LDLIBRARY) $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/$(LDLIBRARY) + $(INSTALL_SHARED) $(INSTALL_LDLIBRARY) $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/$(LDLIBRARY) # iOS/tvOS/watchOS uses a non-versioned framework with Info.plist in the # framework root, no .lproj data, and only stub compilation assistance binaries @@ -3141,8 +3154,8 @@ frameworkinstallapps: # an app bundle within the framework. This allows the interpreter to # run OS X GUI APIs. .PHONY: frameworkpythonw -frameworkpythonw: - cd Mac && $(MAKE) pythonw +frameworkpythonw: $(INSTALL_LDLIBRARY) + cd Mac && $(MAKE) $(notdir $(INSTALL_PYTHONW)) # This installs the python* and other bin symlinks in $prefix/bin or in # a bin directory relative to the framework root @@ -3336,7 +3349,7 @@ clean-retain-profile: pycremoval -rm -f pybuilddir.txt -rm -f _bootstrap_python -rm -rf web_example python.mjs python.wasm python*.symbols python*.map - -rm -f Programs/_testembed Programs/_freeze_module + -rm -f Programs/_testembed Programs/_freeze_module Mac/pythonw-relocatable -rm -rf Python/deepfreeze -rm -f Python/frozen_modules/*.h -rm -f Python/frozen_modules/MANIFEST diff --git a/Misc/NEWS.d/next/Build/2026-10-22-19-00-00.gh-issue-119696.f8Rame.rst b/Misc/NEWS.d/next/Build/2026-10-22-19-00-00.gh-issue-119696.f8Rame.rst new file mode 100644 index 000000000000000..5477db22280bdb1 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-10-22-19-00-00.gh-issue-119696.f8Rame.rst @@ -0,0 +1,3 @@ +Support :option:`--enable-relocatable` for macOS framework builds. Use relative +framework library paths for installed interpreters and extensions, and link +copied virtual environments to the base framework. diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index f629b8e528faca7..7d2b923dfeace53 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -261,25 +261,14 @@ static const char * classify_address(uintptr_t addr, int jit_enabled, PyInterpreterState *interp) { Dl_info info; - if (dladdr((void *)addr, &info) != 0 - && info.dli_fname != NULL - && info.dli_fname[0] != '\0') { - const char *base = strrchr(info.dli_fname, '/'); - base = base ? base + 1 : info.dli_fname; - if (strncmp(base, "python", 6) == 0) { + Dl_info python_info; + if (dladdr((void *)addr, &info) != 0) { + // Framework library names need not start with `python` or `libpython`. + // Identify Python by the image containing `Py_Initialize`. + if (dladdr(&Py_Initialize, &python_info) != 0 + && info.dli_fbase == python_info.dli_fbase) { return "python"; } -#ifdef __CYGWIN__ - // Match Cygwin "cygpython3.16.dll" - if (strncmp(base, "cygpython", 9) == 0) { - return "python"; - } -#else - // Match "libpython3.15.so.1.0" - if (strncmp(base, "libpython", 9) == 0) { - return "python"; - } -#endif return "other"; } #ifdef _Py_JIT diff --git a/configure b/configure index e21f637fbfa2e68..7a7cdce47ca9b1b 100755 --- a/configure +++ b/configure @@ -849,6 +849,7 @@ WHEEL_PKG_DIR LIBPL PY_ENABLE_SHARED RELOCATABLE_LIBPYTHON_INSTALL_NAME +RELOCATABLE_PYTHONW_LDFLAGS RELOCATABLE_EXTENSION_LDFLAGS RELOCATABLE_LIBPYTHON_LDFLAGS RELOCATABLE_PYTHON_LDFLAGS @@ -28796,14 +28797,9 @@ BINLIBDEST='${exec_prefix}/${PLATLIBDIR}/python$(VERSION)$(ABI_THREAD)' RELOCATABLE_PYTHON_LDFLAGS= RELOCATABLE_LIBPYTHON_LDFLAGS= RELOCATABLE_EXTENSION_LDFLAGS= +RELOCATABLE_PYTHONW_LDFLAGS= RELOCATABLE_LIBPYTHON_INSTALL_NAME= -if test "$enable_relocatable" = yes && test -n "$enable_framework" -then : - - as_fn_error $? "--enable-relocatable does not support framework builds yet" "$LINENO" 5 - -fi -if test "$enable_relocatable" = yes && test -z "$enable_framework" +if test "x$enable_relocatable" = xyes then : case $ac_sys_system in #( @@ -28875,6 +28871,18 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ RELOCATABLE_PYTHON_LDFLAGS='-Wl,-rpath,@executable_path/../lib -Wl,-rpath,@executable_path/../lib/python-base' RELOCATABLE_LIBPYTHON_LDFLAGS='-Wl,-rpath,@loader_path' RELOCATABLE_EXTENSION_LDFLAGS='-Wl,-rpath,@loader_path/../../../lib' + if test -n "$enable_framework" +then : + + RELOCATABLE_LIBPYTHON_INSTALL_NAME='@rpath/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' + # The installed interpreter is inside Resources/Python.app; pythonw + # is the wrapper in the framework version's bin directory. + RELOCATABLE_PYTHON_LDFLAGS='-Wl,-rpath,@executable_path/../../../../../../.. -Wl,-rpath,@executable_path/../lib/python-base' + RELOCATABLE_PYTHONW_LDFLAGS='-Wl,-rpath,@executable_path/../../../.. -Wl,-rpath,@executable_path/../lib/python-base' + RELOCATABLE_LIBPYTHON_LDFLAGS='-Wl,-rpath,@loader_path/lib -Wl,-rpath,@loader_path/../../..' + as_fn_append RELOCATABLE_EXTENSION_LDFLAGS ' -Wl,-rpath,@loader_path/../../../../../..' + +fi ;; #( *) : ;; @@ -28887,6 +28895,7 @@ fi + if test x$PLATFORM_TRIPLET = x; then LIBPL='$(LIBDEST)'"/config-${LDVERSION}" else diff --git a/configure.ac b/configure.ac index 47741e6e003ec2f..2088a6b01c80abe 100644 --- a/configure.ac +++ b/configure.ac @@ -6879,11 +6879,9 @@ BINLIBDEST='${exec_prefix}/${PLATLIBDIR}/python$(VERSION)$(ABI_THREAD)' RELOCATABLE_PYTHON_LDFLAGS= RELOCATABLE_LIBPYTHON_LDFLAGS= RELOCATABLE_EXTENSION_LDFLAGS= +RELOCATABLE_PYTHONW_LDFLAGS= RELOCATABLE_LIBPYTHON_INSTALL_NAME= -AS_IF([test "$enable_relocatable" = yes && test -n "$enable_framework"], [ - AC_MSG_ERROR([--enable-relocatable does not support framework builds yet]) -]) -AS_IF([test "$enable_relocatable" = yes && test -z "$enable_framework"], [ +AS_VAR_IF([enable_relocatable], [yes], [ AS_CASE([$ac_sys_system], [Linux|Darwin], [], [AC_MSG_ERROR([relocatable builds are not implemented on $ac_sys_system yet])]) @@ -6915,11 +6913,21 @@ AS_IF([test "$enable_relocatable" = yes && test -z "$enable_framework"], [ RELOCATABLE_PYTHON_LDFLAGS='-Wl,-rpath,@executable_path/../lib -Wl,-rpath,@executable_path/../lib/python-base' RELOCATABLE_LIBPYTHON_LDFLAGS='-Wl,-rpath,@loader_path' RELOCATABLE_EXTENSION_LDFLAGS='-Wl,-rpath,@loader_path/../../../lib' + AS_IF([test -n "$enable_framework"], [ + RELOCATABLE_LIBPYTHON_INSTALL_NAME='@rpath/$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' + # The installed interpreter is inside Resources/Python.app; pythonw + # is the wrapper in the framework version's bin directory. + RELOCATABLE_PYTHON_LDFLAGS='-Wl,-rpath,@executable_path/../../../../../../.. -Wl,-rpath,@executable_path/../lib/python-base' + RELOCATABLE_PYTHONW_LDFLAGS='-Wl,-rpath,@executable_path/../../../.. -Wl,-rpath,@executable_path/../lib/python-base' + RELOCATABLE_LIBPYTHON_LDFLAGS='-Wl,-rpath,@loader_path/lib -Wl,-rpath,@loader_path/../../..' + AS_VAR_APPEND([RELOCATABLE_EXTENSION_LDFLAGS], [' -Wl,-rpath,@loader_path/../../../../../..']) + ]) ]) ]) AC_SUBST([RELOCATABLE_PYTHON_LDFLAGS]) AC_SUBST([RELOCATABLE_LIBPYTHON_LDFLAGS]) AC_SUBST([RELOCATABLE_EXTENSION_LDFLAGS]) +AC_SUBST([RELOCATABLE_PYTHONW_LDFLAGS]) AC_SUBST([RELOCATABLE_LIBPYTHON_INSTALL_NAME]) dnl define LIBPL after ABIFLAGS and LDVERSION is defined.