From 39ab38920e080473c86a420c68d3f9e540739935 Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Thu, 2 Jan 2025 03:17:55 +0100 Subject: [PATCH] Abstract apple framework creation behind a tool, which will also generate an appropriate Info.plist file. --- test/SConstruct | 38 ++++----- .../Resources/Info.plist | 26 ------ .../Resources/Info.plist | 26 ------ test/project/example.gdextension | 8 +- tools/apple_framework.py | 84 +++++++++++++++++++ 5 files changed, 107 insertions(+), 75 deletions(-) delete mode 100644 test/project/bin/libgdexample.macos.template_debug.framework/Resources/Info.plist delete mode 100644 test/project/bin/libgdexample.macos.template_release.framework/Resources/Info.plist create mode 100644 tools/apple_framework.py diff --git a/test/SConstruct b/test/SConstruct index b949bcacf..41ed021b3 100644 --- a/test/SConstruct +++ b/test/SConstruct @@ -18,29 +18,29 @@ if env["target"] in ["editor", "template_debug"]: doc_data = env.GodotCPPDocData("src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml")) sources.append(doc_data) -if env["platform"] == "macos": - library = env.SharedLibrary( - "project/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format( - env["platform"], env["target"], env["platform"], env["target"] - ), +if env["platform"] == "macos" or env["platform"] == "ios": + # Static libraries (.dylib) are not supported on the iOS app store. + # For consistency, both macOS and iOS will generate .xcframework instead. + framework_tool = Tool("apple_framework", toolpath=["../tools"]) + + framework_name = f"gdexample.{env['platform']}.{env['target']}" + if env["ios_simulator"]: + framework_name += ".simulator" + + library_targets = framework_tool.generate( + f"bin/{framework_name}.xcframework", + env=env, source=sources, + bundle_identifier=f"org.godotengine.{framework_name}" ) -elif env["platform"] == "ios": - if env["ios_simulator"]: - library = env.StaticLibrary( - "project/bin/libgdexample.{}.{}.simulator.a".format(env["platform"], env["target"]), - source=sources, - ) - else: - library = env.StaticLibrary( - "project/bin/libgdexample.{}.{}.a".format(env["platform"], env["target"]), - source=sources, - ) else: - library = env.SharedLibrary( + library_targets = env.SharedLibrary( "project/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]), source=sources, ) -env.NoCache(library) -Default(library) +# Keep the binary intact for as long as possible. +env.Precious(library_targets) + +env.NoCache(library_targets) +Default(library_targets) diff --git a/test/project/bin/libgdexample.macos.template_debug.framework/Resources/Info.plist b/test/project/bin/libgdexample.macos.template_debug.framework/Resources/Info.plist deleted file mode 100644 index fbdbd201f..000000000 --- a/test/project/bin/libgdexample.macos.template_debug.framework/Resources/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleExecutable - libgdexample.template_debug - CFBundleIdentifier - org.godotengine.libgdexample - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - libgdexample.macos.template_debug - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0.0 - CFBundleSupportedPlatforms - - MacOSX - - CFBundleVersion - 1.0.0 - LSMinimumSystemVersion - 10.12 - - diff --git a/test/project/bin/libgdexample.macos.template_release.framework/Resources/Info.plist b/test/project/bin/libgdexample.macos.template_release.framework/Resources/Info.plist deleted file mode 100644 index b3bc3cac8..000000000 --- a/test/project/bin/libgdexample.macos.template_release.framework/Resources/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleExecutable - libgdexample.template_release - CFBundleIdentifier - org.godotengine.libgdexample - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - libgdexample.macos.template_release - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0.0 - CFBundleSupportedPlatforms - - MacOSX - - CFBundleVersion - 1.0.0 - LSMinimumSystemVersion - 10.12 - - diff --git a/test/project/example.gdextension b/test/project/example.gdextension index 8e2f794d1..d60180de8 100644 --- a/test/project/example.gdextension +++ b/test/project/example.gdextension @@ -5,8 +5,8 @@ compatibility_minimum = "4.1" [libraries] -macos.debug = "res://bin/libgdexample.macos.template_debug.framework" -macos.release = "res://bin/libgdexample.macos.template_release.framework" +macos.debug = "res://bin/gdexample.macos.template_debug.xcframework" +macos.release = "res://bin/gdexample.macos.template_release.xcframework" windows.debug.x86_32 = "res://bin/libgdexample.windows.template_debug.x86_32.dll" windows.release.x86_32 = "res://bin/libgdexample.windows.template_release.x86_32.dll" windows.debug.x86_64 = "res://bin/libgdexample.windows.template_debug.x86_64.dll" @@ -29,8 +29,8 @@ android.debug.arm64 = "res://bin/libgdexample.android.template_debug.arm64.so" android.release.arm64 = "res://bin/libgdexample.android.template_release.arm64.so" ios.debug = "res://bin/libgdexample.ios.template_debug.xcframework" ios.release = "res://bin/libgdexample.ios.template_release.xcframework" -web.debug.threads.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm" -web.release.threads.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.wasm" +web.debug.threads.wasm32 = "res://bin/gdexample.web.template_debug.wasm32.wasm" +web.release.threads.wasm32 = "res://bin/gdexample.web.template_release.wasm32.wasm" web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.nothreads.wasm" web.release.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.nothreads.wasm" diff --git a/tools/apple_framework.py b/tools/apple_framework.py new file mode 100644 index 000000000..e0c9fdf94 --- /dev/null +++ b/tools/apple_framework.py @@ -0,0 +1,84 @@ +import pathlib + + +def exists(env): + return True + + +def options(opts): + pass + + +def generate(target, *, env, source, bundle_identifier: str, min_macos_version="10.12", min_ios_version="12.0"): + """ + Generates an Apple .framework folder, containing the binary. + :param target: Folder name of the framework, usually ending in `.framework`. + :param env: The environment. + :param source: A list of sources to pass to SharedLibrary. + :param bundle_identifier: A bundle identifier, like `org.godotengine.gdexample.macos.template_debug`. + :param min_macos_version: The minimum macOS version supported by the framework, if the platform is macos. + :param min_ios_version: The minimum iOS version supported by the framework, if the platform is iOS. + :return: A list of files to be created, the first of which is the binary path. + """ + if env["platform"] == "macos": + dt_platform_name = "macosx" + min_os_part = f""" + LSMinimumSystemVersion + {min_macos_version}\ +""" + plist_subpath = pathlib.Path("Resources/Info.plist") + elif env["platform"] == "ios": + dt_platform_name = "iphoneos" + min_os_part = f""" + MinimumOSVersion + {min_ios_version}\ +""" + plist_subpath = pathlib.Path("Info.plist") + else: + raise ValueError("Unsupported platform.") + + framework_path = pathlib.Path(target) + framework_name = framework_path.name.removesuffix(".framework") + + # This is required because they affect the binary name, which we need to be equal to the framework name. + env["SHLIBPREFIX"] = "" + env["SHLIBSUFFIX"] = "" + + def create_info_plist(target, source, env): + pathlib.Path(target[0].path).write_text(f"""\ + + + + + CFBundleInfoDictionaryVersion + 6.0 + CFBundleDevelopmentRegion + en + CFBundleExecutable + {framework_name} + CFBundleName + NumDot + CFBundleDisplayName + NumDot + CFBundleIdentifier + {bundle_identifier} + NSHumanReadableCopyright + Unlicensed + CFBundleVersion + 1.0.0 + CFBundleShortVersionString + 1.0.0 + CFBundlePackageType + FMWK + CSResourcesFileMapped + + DTPlatformName + {dt_platform_name}{min_os_part} + + +""") + + return [ + env.SharedLibrary(str(framework_path / framework_name), source=source), + env.Command(str(framework_path / plist_subpath), [], action=create_info_plist), + ]