Abstract apple framework creation behind a tool, which will `lipo` the input binaries together and create an appropriate `Info.plist`.
parent
47f11bc5c7
commit
3bfe5fd1e5
|
@ -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"]
|
||||
),
|
||||
source=sources,
|
||||
)
|
||||
elif env["platform"] == "ios":
|
||||
if env["ios_simulator"]:
|
||||
library = env.StaticLibrary(
|
||||
"project/bin/libgdexample.{}.{}.simulator.a".format(env["platform"], env["target"]),
|
||||
source=sources,
|
||||
library_targets = env.SharedLibrary(
|
||||
"project/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
|
||||
source=sources,
|
||||
)
|
||||
|
||||
if env["platform"] == "macos" or env["platform"] == "ios":
|
||||
# The app store requires signed .framework bundles for dependencies.
|
||||
# We do not sign the test framework bundles, but for consistency
|
||||
# (and testing) we will always generate the .framework anyway.
|
||||
framework_tool = Tool("apple_framework", toolpath=["../tools"])
|
||||
|
||||
framework_name = f"gdexample.{env['platform']}.{env['target']}"
|
||||
library_targets = framework_tool.generate(
|
||||
f"project/bin/{framework_name}.framework",
|
||||
env=env,
|
||||
source=library_targets,
|
||||
plist_entries=dict(
|
||||
CFBundleIdentifier=f"org.godotengine.{framework_name}",
|
||||
)
|
||||
else:
|
||||
library = env.StaticLibrary(
|
||||
"project/bin/libgdexample.{}.{}.a".format(env["platform"], env["target"]),
|
||||
source=sources,
|
||||
)
|
||||
else:
|
||||
library = env.SharedLibrary(
|
||||
"project/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
|
||||
source=sources,
|
||||
)
|
||||
|
||||
env.NoCache(library)
|
||||
Default(library)
|
||||
# Keep the final build intact for as long as possible.
|
||||
env.Precious(library_targets)
|
||||
|
||||
env.NoCache(library_targets)
|
||||
Default(library_targets)
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>libgdexample.template_debug</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.godotengine.libgdexample</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>libgdexample.macos.template_debug</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.12</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>libgdexample.template_release</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.godotengine.libgdexample</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>libgdexample.macos.template_release</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.12</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -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.framework"
|
||||
macos.release = "res://bin/gdexample.macos.template_release.framework"
|
||||
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"
|
||||
|
@ -27,17 +27,17 @@ android.debug.x86_64 = "res://bin/libgdexample.android.template_debug.x86_64.so"
|
|||
android.release.x86_64 = "res://bin/libgdexample.android.template_release.x86_64.so"
|
||||
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"
|
||||
ios.debug = "res://bin/libgdexample.ios.template_debug.framework"
|
||||
ios.release = "res://bin/libgdexample.ios.template_release.framework"
|
||||
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"
|
||||
|
||||
[dependencies]
|
||||
ios.debug = {
|
||||
"res://bin/libgodot-cpp.ios.template_debug.xcframework": ""
|
||||
"res://bin/libgodot-cpp.ios.template_debug.framework": ""
|
||||
}
|
||||
ios.release = {
|
||||
"res://bin/libgodot-cpp.ios.template_release.xcframework": ""
|
||||
"res://bin/libgodot-cpp.ios.template_release.framework": ""
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
import os
|
||||
import pathlib
|
||||
|
||||
|
||||
def exists(env):
|
||||
return True
|
||||
|
||||
|
||||
def options(opts):
|
||||
pass
|
||||
|
||||
|
||||
def generate(
|
||||
target,
|
||||
*,
|
||||
env,
|
||||
source,
|
||||
min_macos_version="10.12",
|
||||
min_ios_version="12.0",
|
||||
plist_entries=None,
|
||||
):
|
||||
"""
|
||||
Generates an Apple .framework folder, containing the binary and metadata.
|
||||
Framework structures are required to be able to sign binaries.
|
||||
Signing binaries is required to avoid the apple gatekeeper, and to be accepted into the App Store.
|
||||
See https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
|
||||
|
||||
:param target: Folder name of the framework, usually ending in `.framework`.
|
||||
:param env: The environment.
|
||||
:param source: A list of binary sources to generate.
|
||||
: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.
|
||||
:param plist_entries: Additional keys to send to the plist generator.
|
||||
:return: Targets for framework creation, where the first item is the binary generator.
|
||||
"""
|
||||
if env["platform"] == "macos":
|
||||
dt_platform_name = "macosx"
|
||||
min_os_part = f"LSMinimumSystemVersion={min_macos_version}"
|
||||
elif env["platform"] == "ios":
|
||||
dt_platform_name = "iphoneos"
|
||||
min_os_part = f"MinimumOSVersion={min_ios_version}"
|
||||
else:
|
||||
raise ValueError("Unsupported platform.")
|
||||
|
||||
framework_path = pathlib.Path(target)
|
||||
assert framework_path.suffix == ".framework"
|
||||
framework_name = framework_path.name.removesuffix(".framework")
|
||||
|
||||
parent_path = pathlib.Path(__file__).parent
|
||||
plist_creation_script_path = (parent_path / "create_apple_framework_plist.sh").relative_to(os.getcwd())
|
||||
plist_command = f"{plist_creation_script_path} $TARGET --entry CFBundleExecutable={framework_name} --entry DTPlatformName={dt_platform_name} --entry {min_os_part}"
|
||||
if plist_entries:
|
||||
for key, value in plist_entries.items():
|
||||
plist_command += f' --entry "{key}={value}"'
|
||||
|
||||
return [
|
||||
# Create the binary itself.
|
||||
env.Command(
|
||||
str(framework_path / framework_name),
|
||||
source,
|
||||
action="lipo -create $SOURCE -output $TARGET",
|
||||
),
|
||||
# Create the Info.plist.
|
||||
env.Command(
|
||||
str(framework_path / "Resources" / "Info.plist"),
|
||||
[str(plist_creation_script_path)],
|
||||
action=plist_command,
|
||||
),
|
||||
]
|
|
@ -0,0 +1,128 @@
|
|||
#!/bin/bash
|
||||
|
||||
USAGE_STRING="Usage: $0 plist_path --entry CFBundleExecutable=executable [--entry key=value]..."
|
||||
|
||||
PLIST_PATH=""
|
||||
PLIST_ENTRIES=()
|
||||
|
||||
# Parse the command line arguments.
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--entry)
|
||||
IFS='=' read -r key value <<< "$2"
|
||||
# Replace if key exists, otherwise add new key-value.
|
||||
found=false
|
||||
for ((i=0; i<${#PLIST_ENTRIES[@]}; i++)); do
|
||||
if [[ "${PLIST_ENTRIES[i]}" =~ ^$key= ]]; then
|
||||
PLIST_ENTRIES[i]="$key=$value"
|
||||
found=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$found" = false ]; then
|
||||
PLIST_ENTRIES+=("$key=$value")
|
||||
fi
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
# Assume positional argument is the plist path.
|
||||
if [ -n "$PLIST_PATH" ]; then
|
||||
# Cannot generate more than one plist; this was likely an error.
|
||||
echo "$USAGE_STRING"
|
||||
exit 1
|
||||
fi
|
||||
PLIST_PATH="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Extract known keys from PLIST_ENTRIES, for defaults and mandatory arguments.
|
||||
for ((i=0; i<${#PLIST_ENTRIES[@]}; i++)); do
|
||||
IFS='=' read -r key value <<< "${PLIST_ENTRIES[$i]}"
|
||||
case $key in
|
||||
CFBundleInfoDictionaryVersion)
|
||||
CFBundleInfoDictionaryVersion="$value"
|
||||
;;
|
||||
CFBundlePackageType)
|
||||
CFBundlePackageType="$value"
|
||||
;;
|
||||
CFBundleName)
|
||||
CFBundleName="$value"
|
||||
;;
|
||||
CFBundleExecutable)
|
||||
CFBundleExecutable="$value"
|
||||
;;
|
||||
CFBundleIdentifier)
|
||||
CFBundleIdentifier="$value"
|
||||
;;
|
||||
CFBundleVersion)
|
||||
CFBundleVersion="$value"
|
||||
;;
|
||||
CFBundleShortVersionString)
|
||||
CFBundleShortVersionString="$value"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check for mandatory arguments.
|
||||
if [ -z "$PLIST_PATH" ] || [ -z "$CFBundleExecutable" ]; then
|
||||
echo "$USAGE_STRING"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add defaults for missing arguments.
|
||||
if [ -z "$CFBundleInfoDictionaryVersion" ]; then
|
||||
CFBundleInfoDictionaryVersion="6.0"
|
||||
PLIST_ENTRIES+=("CFBundleInfoDictionaryVersion=$CFBundleInfoDictionaryVersion")
|
||||
fi
|
||||
if [ -z "$CFBundlePackageType" ]; then
|
||||
CFBundlePackageType="FMWK"
|
||||
PLIST_ENTRIES+=("CFBundlePackageType=$CFBundlePackageType")
|
||||
fi
|
||||
if [ -z "$CFBundleName" ]; then
|
||||
CFBundleName="$CFBundleExecutable"
|
||||
PLIST_ENTRIES+=("CFBundleName=$CFBundleName")
|
||||
fi
|
||||
if [ -z "$CFBundleIdentifier" ]; then
|
||||
CFBundleIdentifier="com.example.$CFBundleName"
|
||||
PLIST_ENTRIES+=("CFBundleIdentifier=$CFBundleIdentifier")
|
||||
fi
|
||||
if [ -z "$CFBundleVersion" ]; then
|
||||
CFBundleVersion="1.0.0"
|
||||
PLIST_ENTRIES+=("CFBundleVersion=$CFBundleVersion")
|
||||
fi
|
||||
if [ -z "$CFBundleShortVersionString" ]; then
|
||||
CFBundleShortVersionString="$CFBundleVersion"
|
||||
PLIST_ENTRIES+=("CFBundleShortVersionString=$CFBundleShortVersionString")
|
||||
fi
|
||||
|
||||
# Ensure the directory exists.
|
||||
mkdir -p "$(dirname "$PLIST_PATH")"
|
||||
|
||||
# Create the Info.plist file.
|
||||
{
|
||||
echo '<?xml version="1.0" encoding="UTF-8"?>'
|
||||
echo '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
|
||||
echo '<plist version="1.0">'
|
||||
echo '<dict>'
|
||||
|
||||
for ((i=0; i<${#PLIST_ENTRIES[@]}; i++)); do
|
||||
IFS='=' read -r key value <<< "${PLIST_ENTRIES[$i]}"
|
||||
if [[ -n "$value" ]]; then
|
||||
echo " <key>$key</key>"
|
||||
echo " <string>$value</string>"
|
||||
fi
|
||||
done
|
||||
|
||||
echo '</dict>'
|
||||
echo '</plist>'
|
||||
} > "$PLIST_PATH"
|
||||
|
||||
# Confirm Info.plist was created.
|
||||
if [ -s "$PLIST_PATH" ]; then
|
||||
echo "$PLIST_PATH"
|
||||
else
|
||||
echo "Failed to create $PLIST_PATH."
|
||||
exit 1
|
||||
fi
|
Loading…
Reference in New Issue