-
-
Save CognitiveDisson/0ac4c8031ee60c0ec16de848e576ff42 to your computer and use it in GitHub Desktop.
#!/bin/sh | |
# Print all the commands in script before their execution | |
# export PS4='+ 6: ' | |
set -x | |
# Force the script to stop if any unhandled error occurs (i.e. an error not handled with `||`) | |
# set -e | |
# Force the script to stop if any uninitialized variable is used | |
set -u | |
# Force the script to bypass error result through all pipes if any pipe fails | |
set -o pipefail | |
# Get path to a folder containing the script | |
SCRIPT_ROOT=`cd "$(dirname "$0")" && pwd` | |
workspaceName="${SCRIPT_ROOT}/DependenciesBuilder.xcworkspace" | |
schemeName="Pods-DependenciesBuilder" | |
configurationName="Release" | |
inputPath="${SCRIPT_ROOT}/DerivedData.ignored" | |
outputPath="${SCRIPT_ROOT}/UniversalOutput.ignored" | |
podspecsPath="${SCRIPT_ROOT}/../" | |
# Navigate to script directory | |
cd "$(dirname "$0")" | |
# Prepare folders | |
rm -rf $inputPath | |
rm -rf $outputPath | |
# Update project pods | |
pod install --project-directory="${SCRIPT_ROOT}" || exit 1 | |
# Build frameworks for all architectures | |
xcodebuild \ | |
-workspace $workspaceName \ | |
-scheme $schemeName \ | |
-configuration $configurationName \ | |
-sdk iphoneos \ | |
-derivedDataPath $inputPath \ | |
build | xcpretty || exit 1 | |
xcodebuild \ | |
-workspace $workspaceName \ | |
-scheme $schemeName \ | |
-configuration $configurationName \ | |
-sdk iphonesimulator \ | |
-derivedDataPath $inputPath \ | |
build | xcpretty || exit 1 | |
frameworksCreated=0 | |
dsymsCreated=0 | |
if [ ! -d "${outputPath}" ]; then | |
echo "Create output folder" | |
mkdir "${outputPath}" | |
fi; | |
devicePath="${inputPath}/Build/Products/${configurationName}-iphoneos" | |
simulatorPath="${inputPath}/Build/Products/${configurationName}-iphonesimulator" | |
writePodspec() { | |
local name="${1:?}" | |
local module_name="${2:?}" | |
local version="${3:?}" | |
local podspecName="${name}.podspec" | |
local podspecPath="${podspecsPath}/${podspecName}" | |
if [ -e "${podspecPath}" ]; then | |
echo "Podspec ${podspecName} already exists" | |
return | |
fi | |
echo "podspecPath: $podspecPath" | |
{ | |
echo "Pod::Spec.new do |s|" | |
echo " s.name = '${name}'" | |
if [[ "${name}" != "${module_name}" ]]; then | |
echo " s.module_name = '${module_name}'" | |
fi | |
echo " s.version = '${version}'" | |
echo " s.summary = 'Prebuilded ${name}'" | |
echo " s.homepage = 'http://.../prebuilded-frameworks/${name}'" | |
echo " s.license = 'MIT'" | |
echo " s.author = { '$(git config --global user.name)' => '$(git config --global user.email)' }" | |
echo " s.source = { :git => 'ssh://.../prebuilded-frameworks.git', :branch => 'master' }" | |
echo " s.platform = :ios, '9.0'" | |
echo " s.ios.deployment_target = '9.0'" | |
echo " s.requires_arc = true" | |
echo " s.vendored_frameworks = '${name}/${module_name}.framework'" | |
echo "end" | |
} > "${podspecPath}" | |
} | |
for deviceFolder in $(find $devicePath -mindepth 1 -maxdepth 1); do | |
frameworkName=$(basename "${deviceFolder}") | |
echo "Process ${frameworkName} == ${schemeName}.framework" | |
tmpName=$(echo $frameworkName | tr '_' '-') | |
if [ "${tmpName}" == "${schemeName}.framework" ]; then | |
continue; | |
fi; | |
simulatorFolder="$simulatorPath/$frameworkName" | |
deviceFrameworkPath=$(find $deviceFolder -mindepth 1 -maxdepth 1 | grep '.*\.framework$') | |
simulatorFrameworkPath=$(find $simulatorFolder -mindepth 1 -maxdepth 1 | grep '.*\.framework$') | |
if [ ! -d "$deviceFrameworkPath" ]; then continue; fi; | |
echo "Process $(tput bold)$frameworkName$(tput sgr0)" | |
if [ ! -d "$simulatorFrameworkPath" ]; then | |
echo " Could not find simulator framework" | |
continue | |
fi; | |
binaryName="$(basename $deviceFrameworkPath)" | |
binaryName="${binaryName%.*}" | |
deviceBinaryPath="$deviceFrameworkPath/$binaryName" | |
simulatorBinaryPath="$simulatorFrameworkPath/$binaryName" | |
if [ ! -f "$deviceBinaryPath" ]; then | |
echo " Could not find binary file for device" | |
continue | |
fi; | |
if [ ! -f "$simulatorBinaryPath" ]; then | |
echo " Could not find binary file for simulator" | |
continue | |
fi; | |
echo " Copy device framework" | |
cp -r "${deviceFrameworkPath}" "${outputPath}" | |
frameworkFileName="$(basename $deviceFrameworkPath)" | |
universalBinaryPath="${outputPath}/$frameworkFileName/$binaryName" | |
similatorSwiftModulesPath="${simulatorFrameworkPath}/Modules/$frameworkName.swiftmodule" | |
universalSwiftModulesPath="${outputPath}/$frameworkFileName/Modules/" | |
if [ -d "$similatorSwiftModulesPath" ]; then | |
echo " Copy simulator swiftModules" | |
cp -r "$similatorSwiftModulesPath" "$universalSwiftModulesPath" | |
fi; | |
echo " Merge framework architectures" | |
lipo -create $deviceBinaryPath $simulatorBinaryPath -o $universalBinaryPath | |
echo "success lipo" | |
let "frameworksCreated++" | |
deviceDsymPath=$(find $deviceFolder -mindepth 1 -maxdepth 1 | grep '.*\.framework.dSYM$') | |
simulatorDsymPath=$(find $simulatorFolder -mindepth 1 -maxdepth 1 | grep '.*\.framework.dSYM$') | |
echo "success find dsym" | |
if [ ! -d "$deviceDsymPath" ]; then | |
echo " Could not find dSYM for device" | |
continue | |
fi; | |
if [ ! -d "$simulatorDsymPath" ]; then | |
echo " Could not find dSYM for simulator" | |
continue | |
fi; | |
echo " Copy device dSYM" | |
cp -r "${deviceDsymPath}" "${outputPath}" | |
deviceDwafrPath="$deviceDsymPath/Contents/Resources/DWARF/$binaryName" | |
simulatorDwafrPath="$simulatorDsymPath/Contents/Resources/DWARF/$binaryName" | |
universalDwarfPath="${outputPath}/$frameworkFileName.dSYM/Contents/Resources/DWARF/$binaryName" | |
echo " Merge dSYM architectures" | |
lipo -create $deviceDwafrPath $simulatorDwafrPath -o $universalDwarfPath | |
let "dsymsCreated++" | |
frameworkModuleName="${frameworkFileName%.*}" | |
frameworkName=$(echo $frameworkModuleName | tr '_' '-') | |
version=$(cat Podfile.lock | grep -e "-[[:space:]]${frameworkName}.*[[:space:]]([0-9]\+" | sed 's#.*(##' | sed 's#).*##' | head -1) | |
frameworkPath="${outputPath}/${frameworkFileName}" | |
dwarfPath="${outputPath}/${frameworkFileName}.dSYM" | |
frameworkDirectory="${podspecsPath}/${frameworkName}" | |
mkdir -p $frameworkDirectory | |
frameworkDestination="${frameworkDirectory}/${frameworkModuleName}.framework" | |
dwarfDestination="${frameworkDirectory}/${frameworkModuleName}.framework.dSYM" | |
rm -rf $frameworkDestination | |
rm -rf $dwarfDestination | |
mv $frameworkPath $frameworkDestination | |
mv $dwarfPath $dwarfDestination | |
writePodspec "${frameworkName}" "${frameworkModuleName}" "${version}" | |
done | |
# Clean folders | |
rm -rf $inputPath | |
rm -rf $outputPath | |
echo "$(tput bold)Done! $frameworksCreated frameworks created with $dsymsCreated dSYMs $(tput sgr0)" |
In 91 line you specify only one vendored framework. What if there are several dependencies for compiled pod?
For example, you are importing RxCocoa which also has two dependencies as RxRelay & RxSwift. There are will be an errorMissing required module RxRelay
, because we didn't addRxRelay
to list of vendored frameworks
There is one solution for it, is to scan Podfile.lock and get needed dependency. I am interesting in your solution for that problem
Hi @daukabase. In this code a vendored framework is the framework that we are trying to pre-build, not dependencies. As you can see from the code, there is nothing about dependencies there. All dependency linking flags will already be set in the binary after the build. You just need to include all dependencies in the final build.
Example: We are trying to pre-build the RxCocoa framework. The podspec file looks like this:
Pod::Spec.new do |spec|
spec.name = 'RxCocoa'
...
spec.dependency 'RxRelay'
spec.dependency 'RxSwift'
end
If we run this script, we will get another podspec for the prebuilded framework.
Pod::Spec.new do |spec|
spec.name = 'RxCocoa'
...
s.vendored_frameworks = 'RxCocoa/RxCocoa.framework'"
end
What we need to do is to make it work eventually, it also runs this script for other dependencies - RxRelay & RxSwift, and integrate them to Podfile.
target 'MyApp' do
pod 'RxCocoa', :path => 'RxCocoa'
pod 'RxRelay', :path => 'RxRelay'
pod 'RxSwift', :path => 'RxSwift'
end
The only problem is that you need to specify all the transitive dependencies for the framework you are trying to pre-build in order to specify the path to them.
In 91 line you specify only one vendored framework. What if there are several dependencies for compiled pod?
For example, you are importing RxCocoa which also has two dependencies as RxRelay & RxSwift. There are will be an error
Missing required module RxRelay
, because we didn't addRxRelay
to list of vendored frameworks