Last active
March 18, 2019 08:38
-
-
Save Birowsky/352bef7467ca79f7fd868507edcbc1f5 to your computer and use it in GitHub Desktop.
Revise Sentry's iOS patching procedure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as fs from 'fs'; | |
import * as xcode from 'xcode'; | |
export { | |
patchIosProjectIfNotDoneAlready, | |
}; | |
interface PbxProjectUnparsed { | |
parse: (handler: (err: any) => void) => void | |
} | |
interface PbxProjectParsed { | |
addBuildPhase: (a: any[], b: string, c: string, d: null, e: { shellPath: string, shellScript: string }) => void | |
hash: { project: { objects: { PBXShellScriptBuildPhase: { [k: string]: { shellScript?: string } } } } } | |
writeSync: () => string | |
} | |
/////////////////////////////////////////////////////////////////// | |
const patchIosProjectIfNotDoneAlready = (path: string): Promise<void> => | |
parsePbxProject(xcode.project(path)) | |
.then(project => !projectAlreadyPatched(project) && patchAndSaveProject(project, path)) | |
.then(alwaysVoid); | |
const parsePbxProject = (project: PbxProjectUnparsed): Promise<PbxProjectParsed> => | |
new Promise((resolve, reject) => project.parse(err => err ? reject(err) : resolve(project as any))); | |
const projectAlreadyPatched = (project: PbxProjectParsed): boolean => | |
objectValues(project.hash.project.objects.PBXShellScriptBuildPhase) | |
.map(item => item.shellScript) | |
.filter(script => script && script.includes('SENTRY_FRAMEWORK_PATCH')) | |
.length > 2; | |
const patchAndSaveProject = (project: PbxProjectParsed, path: string): void => { | |
addSentryBuildPhaseToProject(project); | |
fs.writeFileSync(path, project.writeSync()); | |
}; | |
const addSentryBuildPhaseToProject = (project: PbxProjectParsed): void => | |
project.addBuildPhase( | |
[], | |
'PBXShellScriptBuildPhase', | |
'Sentry strip unused archs from Framework', | |
null, | |
{ | |
shellPath: '/bin/sh', | |
shellScript: theSentryPatch, | |
}, | |
); | |
const theSentryPatch = ` | |
# SENTRY_FRAMEWORK_PATCH | |
APP_PATH="\${TARGET_BUILD_DIR}/\${WRAPPER_NAME}" | |
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK | |
do | |
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable) | |
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME" | |
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH" | |
EXTRACTED_ARCHS=() | |
for ARCH in $ARCHS | |
do | |
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME" | |
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH" | |
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH") | |
done | |
echo "Merging extracted architectures: \${ARCHS}" | |
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "\${EXTRACTED_ARCHS[@]}" | |
rm "\${EXTRACTED_ARCHS[@]}" | |
echo "Replacing original executable with thinned version" | |
rm "$FRAMEWORK_EXECUTABLE_PATH" | |
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH" | |
done | |
`; | |
// Utilities | |
function alwaysVoid(): void { | |
} | |
function objectValues<T>(obj: { [k: string]: T }): T[] { | |
return Object.keys(obj).map(key => obj[key]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment