diff --git a/Fixtures/TestProject/GeneratedProject.xcodeproj/project.pbxproj b/Fixtures/TestProject/GeneratedProject.xcodeproj/project.pbxproj index 356951782..b5eb094be 100644 --- a/Fixtures/TestProject/GeneratedProject.xcodeproj/project.pbxproj +++ b/Fixtures/TestProject/GeneratedProject.xcodeproj/project.pbxproj @@ -196,7 +196,7 @@ SBP299349701 /* Sources */, RBP299349701 /* Resources */, HBP299349701 /* Headers */, - SSBP30211001 /* Run Script */, + SSBP35382101 /* Run Script */, ); buildRules = ( ); @@ -215,7 +215,8 @@ HBP652326301 /* Headers */, FBP652326301 /* Frameworks */, CFBP50493301 /* Copy Files */, - SSBP46803701 /* Run Script */, + SSBP24648001 /* Run Script */, + SSBP19207501 /* Run Script */, ); buildRules = ( ); @@ -277,7 +278,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - SSBP30211001 /* Run Script */ = { + SSBP19207501 /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -291,7 +292,21 @@ shellPath = /bin/sh; shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; - SSBP46803701 /* Run Script */ = { + SSBP24648001 /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Strip Unused Architectures from Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "################################################################################\n#\n# Copyright 2015 Realm Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n################################################################################\n\n# This script strips all non-valid architectures from dynamic libraries in\n# the application's `Frameworks` directory.\n#\n# The following environment variables are required:\n#\n# BUILT_PRODUCTS_DIR\n# FRAMEWORKS_FOLDER_PATH\n# VALID_ARCHS\n# EXPANDED_CODE_SIGN_IDENTITY\n\n\n# Signs a framework with the provided identity\ncode_sign() {\n # Use the current code_sign_identitiy\n echo \"Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}\"\n echo \"/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements $1\"\n /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"\n}\n\n# Set working directory to product’s embedded frameworks\ncd \"${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}\"\n\nif [ \"$ACTION\" = \"install\" ]; then\n echo \"Copy .bcsymbolmap files to .xcarchive\"\n find . -name '*.bcsymbolmap' -type f -exec mv {} \"${CONFIGURATION_BUILD_DIR}\" \;\nelse\n # Delete *.bcsymbolmap files from framework bundle unless archiving\n find . -name '*.bcsymbolmap' -type f -exec rm -rf \"{}\" +\;\nfi\n\necho \"Stripping frameworks\"\n\nfor file in $(find . -type f -perm +111); do\n # Skip non-dynamic libraries\n if ! [[ \"$(file \"$file\")\" == *\"dynamically linked shared library\"* ]]; then\n continue\n fi\n # Get architectures for current file\n archs=\"$(lipo -info \"${file}\" | rev | cut -d ':' -f1 | rev)\"\n stripped=\"\"\n for arch in $archs; do\n if ! [[ \"${VALID_ARCHS}\" == *\"$arch\"* ]]; then\n # Strip non-valid architectures in-place\n lipo -remove \"$arch\" -output \"$file\" \"$file\" || exit 1\n stripped=\"$stripped $arch\"\n fi\n done\n if [[ \"$stripped\" != \"\" ]]; then\n echo \"Stripped $file of architectures:$stripped\"\n if [ \"${CODE_SIGNING_REQUIRED}\" == \"YES\" ]; then\n code_sign \"${file}\"\n fi\n fi\ndone\n"; + }; + SSBP35382101 /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( diff --git a/Fixtures/TestProject/scripts/strip-frameworks.sh b/Fixtures/TestProject/scripts/strip-frameworks.sh new file mode 100644 index 000000000..c25991a1a --- /dev/null +++ b/Fixtures/TestProject/scripts/strip-frameworks.sh @@ -0,0 +1,72 @@ +################################################################################ +# +# Copyright 2015 Realm Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ + +# This script strips all non-valid architectures from dynamic libraries in +# the application's `Frameworks` directory. +# +# The following environment variables are required: +# +# BUILT_PRODUCTS_DIR +# FRAMEWORKS_FOLDER_PATH +# VALID_ARCHS +# EXPANDED_CODE_SIGN_IDENTITY + + +# Signs a framework with the provided identity +code_sign() { + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements $1" + /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" +} + +# Set working directory to product’s embedded frameworks +cd "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +if [ "$ACTION" = "install" ]; then + echo "Copy .bcsymbolmap files to .xcarchive" + find . -name '*.bcsymbolmap' -type f -exec mv {} "${CONFIGURATION_BUILD_DIR}" \; +else + # Delete *.bcsymbolmap files from framework bundle unless archiving + find . -name '*.bcsymbolmap' -type f -exec rm -rf "{}" +\; +fi + +echo "Stripping frameworks" + +for file in $(find . -type f -perm +111); do + # Skip non-dynamic libraries + if ! [[ "$(file "$file")" == *"dynamically linked shared library"* ]]; then + continue + fi + # Get architectures for current file + archs="$(lipo -info "${file}" | rev | cut -d ':' -f1 | rev)" + stripped="" + for arch in $archs; do + if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$file" "$file" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" != "" ]]; then + echo "Stripped $file of architectures:$stripped" + if [ "${CODE_SIGNING_REQUIRED}" == "YES" ]; then + code_sign "${file}" + fi + fi +done diff --git a/Fixtures/TestProject/spec.yml b/Fixtures/TestProject/spec.yml index 0b75848df..4f07755a5 100644 --- a/Fixtures/TestProject/spec.yml +++ b/Fixtures/TestProject/spec.yml @@ -13,6 +13,9 @@ targets: testTargets: - TestProjectTests postbuildScripts: + - path: scripts/strip-frameworks.sh + name: Strip Unused Architectures from Frameworks + runOnlyWhenInstalling: true - name: Swiftlint script: | if which swiftlint >/dev/null; then diff --git a/Sources/XcodeGenKit/PBXProjGenerator.swift b/Sources/XcodeGenKit/PBXProjGenerator.swift index 33aa136aa..a8fe74297 100644 --- a/Sources/XcodeGenKit/PBXProjGenerator.swift +++ b/Sources/XcodeGenKit/PBXProjGenerator.swift @@ -293,13 +293,14 @@ public class PBXProjGenerator { func getBuildScript(buildScript: BuildScript) throws -> PBXShellScriptBuildPhase { - let shellScript: String + var shellScript: String switch buildScript.script { case let .path(path): shellScript = try (basePath + path).read() case let .script(script): shellScript = script } + shellScript = shellScript.replacingOccurrences(of: "\"", with: "\\\"") // TODO: remove when xcodeproj escaped values let shellScriptPhase = PBXShellScriptBuildPhase( reference: generateUUID(PBXShellScriptBuildPhase.self, String(describing: buildScript.name) + shellScript + target.name), files: [],