From 2c76eff5f916d1b7af8f52c8dc595c5d9d62fb83 Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Sat, 26 Oct 2024 14:51:40 +0200 Subject: [PATCH] Default to platform-specific arch on macOS for now, as universal builds do not work anyway. Set the python library name to @rpath/LIBNAME, such that it is linked correctly, rather than patching post-create. --- SConstruct | 13 +++++++------ test/python.gdextension | 2 +- tools/build/build_utils.py | 6 +++--- tools/build/platform/godotcpp.py | 6 +++--- tools/build/platform/ios.py | 7 +++++-- tools/build/platform/macos.py | 6 ++++-- tools/build/prepare_python.py | 15 +++++++++++---- 7 files changed, 34 insertions(+), 21 deletions(-) diff --git a/SConstruct b/SConstruct index c630057..dc8e822 100644 --- a/SConstruct +++ b/SConstruct @@ -351,6 +351,12 @@ elif env['platform'] == 'macos': # For Objective-C++ files env.Append(CCFLAGS = ['-ObjC++']) + # Need to set the rpath for relative loading of libpython to succeed. + # This doesn't work for some reason + # env.Replace(RPATH=['@loader_path']) + env.Append(LINKFLAGS=['-Wl,-rpath,@loader_path']) + + env.Prepend(CPPPATH=['src', os.fspath(generated_path), 'extern/pybind11/include']) env.Append(CPPDEFINES = [f'PYGODOT_PLATFORM=\\"{env["platform"]}\\"']) @@ -370,6 +376,7 @@ def _append_python_config(env, target, **kwargs): env.Append(CPPPATH = _config_vars.include_flags) if env['platform'] != 'windows': + env['python_ldlibrary'] = _config_vars.ldlibrary env.Append(CPPDEFINES = [f'PYTHON_LIBRARY_PATH=\\"{_config_vars.ldlibrary or ""}\\"']) dest = pathlib.Path(target[0].path) @@ -406,12 +413,6 @@ library = env.SharedLibrary( source = sources, ) -if env['platform'] == 'macos': - # Change the expected lib directory of libpython to @loader-path using rpaths. - env.AddPostAction(library, env.Action( - "install_name_tool -add_rpath @loader_path bin/macos-universal/libgodot-python.macos.universal.dylib" - "&& install_name_tool -change /install/lib/libpython3.12.dylib @rpath/libpython3.12.dylib bin/macos-universal/libgodot-python.macos.universal.dylib" - )) Default(library) Return("env") diff --git a/test/python.gdextension b/test/python.gdextension index 558f8ef..052e197 100644 --- a/test/python.gdextension +++ b/test/python.gdextension @@ -5,7 +5,7 @@ entry_symbol = "python_extension_init" [libraries] -macos = "res://bin/macos-universal/libgodot-python.macos.universal.dylib" +macos.x86_64 = "res://bin/macos-x86_64/libgodot-python.macos.x86_64.dylib" windows.x86_32 = "res://bin/windows-x86_32/libgodot-python.windows.x86_32.dll" windows.x86_64 = "res://bin/windows-x86_64/libgodot-python.windows.x86_64.dll" diff --git a/tools/build/build_utils.py b/tools/build/build_utils.py index ef2bb72..058519d 100644 --- a/tools/build/build_utils.py +++ b/tools/build/build_utils.py @@ -124,9 +124,9 @@ def process_arch(env): # No architecture specified. Default to arm64 if building for Android, # universal if building for macOS or iOS, wasm32 if building for web, # otherwise default to the host architecture. - if env["platform"] in ["macos", "ios"]: - env["arch"] = "universal" - elif env["platform"] == "android": + # if env["platform"] in ["macos", "ios"]: + # env["arch"] = "universal" + if env["platform"] == "android": env["arch"] = "arm64" elif env["platform"] == "web": env["arch"] = "wasm32" diff --git a/tools/build/platform/godotcpp.py b/tools/build/platform/godotcpp.py index 9ceac02..3fe91ba 100644 --- a/tools/build/platform/godotcpp.py +++ b/tools/build/platform/godotcpp.py @@ -406,9 +406,9 @@ def generate(env): # No architecture specified. Default to arm64 if building for Android, # universal if building for macOS or iOS, wasm32 if building for web, # otherwise default to the host architecture. - if env["platform"] in ["macos", "ios"]: - env["arch"] = "universal" - elif env["platform"] == "android": + # if env["platform"] in ["macos", "ios"]: + # env["arch"] = "universal" + if env["platform"] == "android": env["arch"] = "arm64" elif env["platform"] == "web": env["arch"] = "wasm32" diff --git a/tools/build/platform/ios.py b/tools/build/platform/ios.py index 9675ab1..d99b789 100644 --- a/tools/build/platform/ios.py +++ b/tools/build/platform/ios.py @@ -30,8 +30,11 @@ def exists(env): def generate(env): - if env["arch"] not in ("universal", "arm64", "x86_64"): - raise ValueError("Only universal, arm64, and x86_64 are supported on iOS. Exiting.") + if env["arch"] == "universal": + print("Universal is currently not supported on iOS. Exiting.") + if env["arch"] not in ("arm64", "x86_64"): + print("Only arm64, and x86_64 are supported on iOS. Exiting.") + env.Exit(1) if env["ios_simulator"]: sdk_name = "iphonesimulator" diff --git a/tools/build/platform/macos.py b/tools/build/platform/macos.py index 7418150..56cc568 100644 --- a/tools/build/platform/macos.py +++ b/tools/build/platform/macos.py @@ -20,8 +20,10 @@ def exists(env): def generate(env): - if env["arch"] not in ("universal", "arm64", "x86_64"): - print("Only universal, arm64, and x86_64 are supported on macOS. Exiting.") + if env["arch"] == "universal": + print("Universal is currently not supported on macOS. Exiting.") + if env["arch"] not in ("arm64", "x86_64"): + print("Only arm64, and x86_64 are supported on macOS. Exiting.") env.Exit(1) if sys.platform == "darwin": diff --git a/tools/build/prepare_python.py b/tools/build/prepare_python.py index 8108249..1a802ea 100644 --- a/tools/build/prepare_python.py +++ b/tools/build/prepare_python.py @@ -61,7 +61,7 @@ def add_platform_config(*args, **kwargs): add_platform_config( platform = 'macos', - arch = 'universal', + arch = 'x86_64', source_url = 'https://github.com/indygreg/python-build-standalone/releases/download/' '20231002/cpython-3.12.0+20231002-x86_64-apple-darwin-install_only.tar.gz', so_suffixes = ['.os'], @@ -93,14 +93,21 @@ def prepare_for_platform(platform: str, arch: str, shutil.unpack_archive(src_dir / pathlib.Path(config.source_url).name, extract_dir = src_dir) src = src_dir / 'python' + src_lib_path = src / config.so_path + lib_filename = pathlib.Path(config.so_path).name + + if platform == 'macos': + # Rename the library id (which we depend on) to be in @rpath. + # (it defaults to /install/lib/) + subprocess.run(['install_name_tool', '-id', f'@rpath/{lib_filename}', src_lib_path], check=True) dest_dir.mkdir(parents=True, exist_ok=True) + shutil.copy2(src_lib_path, dest_dir) - shutil.copy2(src / config.so_path, dest_dir) if platform == 'macos': - subprocess.run(['strip', '-x', str(dest_dir / pathlib.Path(config.so_path).name)], check=True) + subprocess.run(['strip', '-x', dest_dir / lib_filename], check=True) else: - subprocess.run(['strip', '-s', str(dest_dir / pathlib.Path(config.so_path).name)], check=True) + subprocess.run(['strip', '-s', dest_dir / lib_filename], check=True) if (src / config.python_ext_dir).exists(): dest_ext_dir = dest_dir / 'python3.12' / 'lib-dynload'