diff --git a/metadata-generator/build-step-metadata-generator.py b/metadata-generator/build-step-metadata-generator.py index 1acd946c9..a35054ec3 100755 --- a/metadata-generator/build-step-metadata-generator.py +++ b/metadata-generator/build-step-metadata-generator.py @@ -3,6 +3,7 @@ import os import shlex import subprocess +import filecmp import sys print("Python version: " + sys.version) @@ -126,7 +127,7 @@ def save_stream_to_file(filename, stream): def generate_metadata(arch): # metadata generator arguments generator_call = ["./objc-metadata-generator", "-verbose", - "-output-bin", "{}/metadata-{}.bin".format(conf_build_dir, arch), + "-output-bin", "{}/metadata-{}.bin.tmp".format(conf_build_dir, arch), "-output-umbrella", "{}/umbrella-{}.h".format(conf_build_dir, arch), "-docset-path", docset_path] @@ -192,6 +193,14 @@ def generate_metadata(arch): print(error_stream_content) sys.exit(1) + # Generated during linking, but also an input of the link (-sectcreate): + # replacing unchanged metadata would make Xcode relink on every build. + output_bin = "{}/metadata-{}.bin".format(conf_build_dir, arch) + if os.path.exists(output_bin) and filecmp.cmp(output_bin + ".tmp", output_bin, shallow=False): + os.remove(output_bin + ".tmp") + else: + os.replace(output_bin + ".tmp", output_bin) + for arch in env("ARCHS").split(): # skip metadata generation for architectures different than the one specified in the command line diff --git a/project-template-ios/internal/nativescript-pre-build b/project-template-ios/internal/nativescript-pre-build index 2216ef798..61556db7d 100755 --- a/project-template-ios/internal/nativescript-pre-build +++ b/project-template-ios/internal/nativescript-pre-build @@ -1,10 +1,30 @@ #!/usr/bin/env bash # Ignore errors while inserting environment variables (some could be readonly) -(echo "set +e"; echo "set +o posix"; export; echo "set -o posix"; echo "set -e";) > ./.build_env_vars.sh +ENV_FILE=./.build_env_vars.sh +(echo "set +e"; echo "set +o posix"; export; echo "set -o posix"; echo "set -e";) > "$ENV_FILE.tmp" +if cmp -s "$ENV_FILE.tmp" "$ENV_FILE"; then + rm "$ENV_FILE.tmp" +else + mv "$ENV_FILE.tmp" "$ENV_FILE" +fi -# create temporary empty metadata files for XCode LD/LDPLUSPLUS flag analysis +# create temporary empty metadata files for XCode LD/LDPLUSPLUS flag analysis. +# Never touch existing ones: the link step reads them, so a newer timestamp +# would make Xcode relink on every build. for arch in $VALID_ARCHS do : - touch "$CONFIGURATION_BUILD_DIR/metadata-$arch.bin" + [ -e "$CONFIGURATION_BUILD_DIR/metadata-$arch.bin" ] || touch "$CONFIGURATION_BUILD_DIR/metadata-$arch.bin" done + +# The metadata generator reads these during linking, which Xcode would skip when +# only they changed. +FILTERS_STAMP="$CONFIGURATION_BUILD_DIR/metadata-filters.stamp" +FILTERS_HASH=$(cd "$SRCROOT" && shasum whitelist.mdg blacklist.mdg 2>/dev/null || true) +if [ ! -e "$FILTERS_STAMP" ] || [ "$FILTERS_HASH" != "$(cat "$FILTERS_STAMP")" ]; then + for arch in $VALID_ARCHS + do : + touch "$CONFIGURATION_BUILD_DIR/metadata-$arch.bin" + done + printf '%s' "$FILTERS_HASH" > "$FILTERS_STAMP" +fi diff --git a/project-template-ios/internal/strip-dynamic-framework-architectures.sh b/project-template-ios/internal/strip-dynamic-framework-architectures.sh index 1679d1a7b..5f411a202 100755 --- a/project-template-ios/internal/strip-dynamic-framework-architectures.sh +++ b/project-template-ios/internal/strip-dynamic-framework-architectures.sh @@ -41,16 +41,21 @@ if [ ! -e "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}" ]; then exit 0 fi -echo "Stripping frameworks" +# Simulator builds never ship, so extra architectures in them are harmless. +if [[ "${PLATFORM_NAME}" == *simulator ]]; then + exit 0 +fi + cd "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}" -for file in $(find . -type f); do - # Skip non-dynamic libraries - if ! [[ "$(file "$file")" == *"dynamically linked shared library"* ]]; then +shopt -s nullglob +for file in *.framework/* *.dylib; do + # Only a framework's main binary (named after it) and loose dylibs are Mach-O + if [[ "$file" == *.framework/* && "$(basename "$file")" != "$(basename "$(dirname "$file")" .framework)" ]]; then continue fi - # Get architectures for current file - archs="$(lipo -info "${file}" | rev | cut -d ':' -f1 | rev)" + + archs="$(lipo -archs "$file" 2>/dev/null)" || continue stripped="" for arch in $archs; do if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then @@ -59,6 +64,7 @@ for file in $(find . -type f); do stripped="$stripped $arch" fi done + if [[ "$stripped" != "" ]]; then echo "Stripped $file of architectures:$stripped" if [ "${CODE_SIGNING_ALLOWED}" == "YES" ]; then diff --git a/project-template-vision/internal/nativescript-pre-build b/project-template-vision/internal/nativescript-pre-build index 2216ef798..61556db7d 100755 --- a/project-template-vision/internal/nativescript-pre-build +++ b/project-template-vision/internal/nativescript-pre-build @@ -1,10 +1,30 @@ #!/usr/bin/env bash # Ignore errors while inserting environment variables (some could be readonly) -(echo "set +e"; echo "set +o posix"; export; echo "set -o posix"; echo "set -e";) > ./.build_env_vars.sh +ENV_FILE=./.build_env_vars.sh +(echo "set +e"; echo "set +o posix"; export; echo "set -o posix"; echo "set -e";) > "$ENV_FILE.tmp" +if cmp -s "$ENV_FILE.tmp" "$ENV_FILE"; then + rm "$ENV_FILE.tmp" +else + mv "$ENV_FILE.tmp" "$ENV_FILE" +fi -# create temporary empty metadata files for XCode LD/LDPLUSPLUS flag analysis +# create temporary empty metadata files for XCode LD/LDPLUSPLUS flag analysis. +# Never touch existing ones: the link step reads them, so a newer timestamp +# would make Xcode relink on every build. for arch in $VALID_ARCHS do : - touch "$CONFIGURATION_BUILD_DIR/metadata-$arch.bin" + [ -e "$CONFIGURATION_BUILD_DIR/metadata-$arch.bin" ] || touch "$CONFIGURATION_BUILD_DIR/metadata-$arch.bin" done + +# The metadata generator reads these during linking, which Xcode would skip when +# only they changed. +FILTERS_STAMP="$CONFIGURATION_BUILD_DIR/metadata-filters.stamp" +FILTERS_HASH=$(cd "$SRCROOT" && shasum whitelist.mdg blacklist.mdg 2>/dev/null || true) +if [ ! -e "$FILTERS_STAMP" ] || [ "$FILTERS_HASH" != "$(cat "$FILTERS_STAMP")" ]; then + for arch in $VALID_ARCHS + do : + touch "$CONFIGURATION_BUILD_DIR/metadata-$arch.bin" + done + printf '%s' "$FILTERS_HASH" > "$FILTERS_STAMP" +fi diff --git a/project-template-vision/internal/strip-dynamic-framework-architectures.sh b/project-template-vision/internal/strip-dynamic-framework-architectures.sh index 1679d1a7b..5f411a202 100755 --- a/project-template-vision/internal/strip-dynamic-framework-architectures.sh +++ b/project-template-vision/internal/strip-dynamic-framework-architectures.sh @@ -41,16 +41,21 @@ if [ ! -e "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}" ]; then exit 0 fi -echo "Stripping frameworks" +# Simulator builds never ship, so extra architectures in them are harmless. +if [[ "${PLATFORM_NAME}" == *simulator ]]; then + exit 0 +fi + cd "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}" -for file in $(find . -type f); do - # Skip non-dynamic libraries - if ! [[ "$(file "$file")" == *"dynamically linked shared library"* ]]; then +shopt -s nullglob +for file in *.framework/* *.dylib; do + # Only a framework's main binary (named after it) and loose dylibs are Mach-O + if [[ "$file" == *.framework/* && "$(basename "$file")" != "$(basename "$(dirname "$file")" .framework)" ]]; then continue fi - # Get architectures for current file - archs="$(lipo -info "${file}" | rev | cut -d ':' -f1 | rev)" + + archs="$(lipo -archs "$file" 2>/dev/null)" || continue stripped="" for arch in $archs; do if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then @@ -59,6 +64,7 @@ for file in $(find . -type f); do stripped="$stripped $arch" fi done + if [[ "$stripped" != "" ]]; then echo "Stripped $file of architectures:$stripped" if [ "${CODE_SIGNING_ALLOWED}" == "YES" ]; then