mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Reworked the way libSession-util builds to use a static library and be less hacky Updated to the latest version of WebRTC-lib (no longer includes bitcode) Removed the 'skip_web_rtc_re_rsync' patch as it's no longer an issue since the bitcode was removed so the framework is much smaller
261 lines
11 KiB
Bash
Executable file
261 lines
11 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# XCode will error during it's dependency graph construction (which happens before the build
|
|
# stage starts and any target "Run Script" phases are triggered)
|
|
#
|
|
# In order to avoid this error we need to build the framework before actually getting to the
|
|
# build stage so XCode is able to build the dependency graph
|
|
#
|
|
# XCode's Pre-action scripts don't output anything into XCode so the only way to emit a useful
|
|
# error is to **return a success status** and have the project detect and log the error itself
|
|
# then log it, stopping the build at that point
|
|
#
|
|
# The other step to get this to work properly is to ensure the framework in "Link Binary with
|
|
# Libraries" isn't using a relative directory, unfortunately there doesn't seem to be a good
|
|
# way to do this directly so we need to modify the '.pbxproj' file directly, updating the
|
|
# framework entry to have the following (on a single line):
|
|
# {
|
|
# isa = PBXFileReference;
|
|
# explicitFileType = wrapper.xcframework;
|
|
# includeInIndex = 0;
|
|
# path = "{FRAMEWORK NAME GOES HERE}";
|
|
# sourceTree = BUILD_DIR;
|
|
# };
|
|
#
|
|
# Note: We might one day be able to replace this with a local podspec if this GitHub feature
|
|
# request ever gets implemented: https://github.com/CocoaPods/CocoaPods/issues/8464
|
|
|
|
# Need to set the path or we won't find cmake
|
|
PATH=${PATH}:/usr/local/bin:/opt/homebrew/bin:/sbin/md5
|
|
|
|
exec 3>&1 # Save original stdout
|
|
|
|
# Ensure the build directory exists (in case we need it before XCode creates it)
|
|
mkdir -p "${TARGET_BUILD_DIR}/libSessionUtil"
|
|
|
|
# Remove any old build errors
|
|
rm -rf "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_output.log"
|
|
|
|
# Restore stdout and stderr and redirect it to the 'libsession_util_output.log' file
|
|
exec &> "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_output.log"
|
|
|
|
# Define a function to echo a message.
|
|
function echo_message() {
|
|
exec 1>&3 # Restore stdout
|
|
echo "$1"
|
|
exec >> "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_output.log" # Redirect all output to the log file
|
|
}
|
|
|
|
echo_message "info: Validating build requirements"
|
|
|
|
set -x
|
|
|
|
# Ensure the build directory exists (in case we need it before XCode creates it)
|
|
mkdir -p "${TARGET_BUILD_DIR}"
|
|
|
|
if ! which cmake > /dev/null; then
|
|
echo_message "error: cmake is required to build, please install (can install via homebrew with 'brew install cmake')."
|
|
exit 0
|
|
fi
|
|
|
|
# Check if we have the `LibSession-Util` submodule checked out and if not (depending on the 'SHOULD_AUTO_INIT_SUBMODULES' argument) perform the checkout
|
|
if [ ! -d "${SRCROOT}/LibSession-Util" ] || [ ! -d "${SRCROOT}/LibSession-Util/src" ] || [ ! "$(ls -A "${SRCROOT}/LibSession-Util")" ]; then
|
|
echo_message "error: Need to fetch LibSession-Util submodule (git submodule update --init --recursive)."
|
|
exit 0
|
|
else
|
|
are_submodules_valid() {
|
|
local PARENT_PATH=$1
|
|
local RELATIVE_PATH=$2
|
|
|
|
# Change into the path to check for it's submodules
|
|
cd "${PARENT_PATH}"
|
|
local SUB_MODULE_PATHS=($(git config --file .gitmodules --get-regexp path | awk '{ print $2 }'))
|
|
|
|
# If there are no submodules then return success based on whether the folder has any content
|
|
if [ ${#SUB_MODULE_PATHS[@]} -eq 0 ]; then
|
|
if [[ ! -z "$(ls -A "${PARENT_PATH}")" ]]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# Loop through the child submodules and check if they are valid
|
|
for i in "${!SUB_MODULE_PATHS[@]}"; do
|
|
local CHILD_PATH="${SUB_MODULE_PATHS[$i]}"
|
|
|
|
# If the child path doesn't exist then it's invalid
|
|
if [ ! -d "${PARENT_PATH}/${CHILD_PATH}" ]; then
|
|
echo_message "info: Submodule '${RELATIVE_PATH}/${CHILD_PATH}' doesn't exist."
|
|
return 1
|
|
fi
|
|
|
|
are_submodules_valid "${PARENT_PATH}/${CHILD_PATH}" "${RELATIVE_PATH}/${CHILD_PATH}"
|
|
local RESULT=$?
|
|
|
|
if [ "${RESULT}" -eq 1 ]; then
|
|
echo_message "info: Submodule '${RELATIVE_PATH}/${CHILD_PATH}' is in an invalid state."
|
|
return 1
|
|
fi
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
# Validate the state of the submodules
|
|
are_submodules_valid "${SRCROOT}/LibSession-Util" "LibSession-Util"
|
|
|
|
HAS_INVALID_SUBMODULE=$?
|
|
|
|
if [ "${HAS_INVALID_SUBMODULE}" -eq 1 ]; then
|
|
echo_message "error: Submodules are in an invalid state, please delete 'LibSession-Util' and run 'git submodule update --init --recursive'."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Generate a hash of the libSession-util source files and check if they differ from the last hash
|
|
echo "info: Checking for changes to source"
|
|
|
|
NEW_SOURCE_HASH=$(find "${SRCROOT}/LibSession-Util/src" -type f -exec md5 {} + | awk '{print $NF}' | sort | md5 | awk '{print $NF}')
|
|
NEW_HEADER_HASH=$(find "${SRCROOT}/LibSession-Util/include" -type f -exec md5 {} + | awk '{print $NF}' | sort | md5 | awk '{print $NF}')
|
|
|
|
if [ -f "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_source_hash.log" ]; then
|
|
read -r OLD_SOURCE_HASH < "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_source_hash.log"
|
|
fi
|
|
|
|
if [ -f "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_header_hash.log" ]; then
|
|
read -r OLD_HEADER_HASH < "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_header_hash.log"
|
|
fi
|
|
|
|
if [ -f "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_archs.log" ]; then
|
|
read -r OLD_ARCHS < "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_archs.log"
|
|
fi
|
|
|
|
# If all of the hashes match, the archs match and there is a library file then we can just stop here
|
|
if [ "${NEW_SOURCE_HASH}" == "${OLD_SOURCE_HASH}" ] && [ "${NEW_HEADER_HASH}" == "${OLD_HEADER_HASH}" ] && [ "${ARCHS[*]}" == "${OLD_ARCHS}" ] && [ -f "${TARGET_BUILD_DIR}/libSessionUtil/libSessionUtil.a" ]; then
|
|
echo_message "info: Build is up-to-date"
|
|
exit 0
|
|
fi
|
|
|
|
# If any of the above differ then we need to rebuild
|
|
echo_message "info: Build is not up-to-date - creating new build"
|
|
|
|
# Import settings from XCode (defaulting values if not present)
|
|
VALID_SIM_ARCHS=(arm64 x86_64)
|
|
VALID_DEVICE_ARCHS=(arm64)
|
|
VALID_SIM_ARCH_PLATFORMS=(SIMULATORARM64 SIMULATOR64)
|
|
VALID_DEVICE_ARCH_PLATFORMS=(OS64)
|
|
|
|
OUTPUT_DIR="${TARGET_BUILD_DIR}"
|
|
IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET}
|
|
ENABLE_BITCODE=${ENABLE_BITCODE}
|
|
|
|
# Generate the target architectures we want to build for
|
|
TARGET_ARCHS=()
|
|
TARGET_PLATFORMS=()
|
|
TARGET_SIM_ARCHS=()
|
|
TARGET_DEVICE_ARCHS=()
|
|
|
|
if [ -z $PLATFORM_NAME ] || [ $PLATFORM_NAME = "iphonesimulator" ]; then
|
|
for i in "${!VALID_SIM_ARCHS[@]}"; do
|
|
ARCH="${VALID_SIM_ARCHS[$i]}"
|
|
ARCH_PLATFORM="${VALID_SIM_ARCH_PLATFORMS[$i]}"
|
|
|
|
if [[ " ${ARCHS[*]} " =~ " ${ARCH} " ]]; then
|
|
TARGET_ARCHS+=("sim-${ARCH}")
|
|
TARGET_PLATFORMS+=("${ARCH_PLATFORM}")
|
|
TARGET_SIM_ARCHS+=("sim-${ARCH}")
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ -z $PLATFORM_NAME ] || [ $PLATFORM_NAME = "iphoneos" ]; then
|
|
for i in "${!VALID_DEVICE_ARCHS[@]}"; do
|
|
ARCH="${VALID_DEVICE_ARCHS[$i]}"
|
|
ARCH_PLATFORM="${VALID_DEVICE_ARCH_PLATFORMS[$i]}"
|
|
|
|
if [[ " ${ARCHS[*]} " =~ " ${ARCH} " ]]; then
|
|
TARGET_ARCHS+=("ios-${ARCH}")
|
|
TARGET_PLATFORMS+=("${ARCH_PLATFORM}")
|
|
TARGET_DEVICE_ARCHS+=("ios-${ARCH}")
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Build the individual architectures
|
|
for i in "${!TARGET_ARCHS[@]}"; do
|
|
build="${TARGET_BUILD_DIR}/libSessionUtil/${TARGET_ARCHS[$i]}"
|
|
platform="${TARGET_PLATFORMS[$i]}"
|
|
echo_message "Building ${TARGET_ARCHS[$i]} for $platform in $build"
|
|
|
|
cd "${SRCROOT}/LibSession-Util"
|
|
./utils/static-bundle.sh "$build" "" \
|
|
-DCMAKE_TOOLCHAIN_FILE="${SRCROOT}/LibSession-Util/external/ios-cmake/ios.toolchain.cmake" \
|
|
-DPLATFORM=$platform \
|
|
-DDEPLOYMENT_TARGET=$IPHONEOS_DEPLOYMENT_TARGET \
|
|
-DENABLE_BITCODE=$ENABLE_BITCODE
|
|
|
|
if [ $? -ne 0 ]; then
|
|
LAST_OUTPUT=$(tail -n 4 "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_output.log" | head -n 1)
|
|
echo_message "error: $LAST_OUTPUT"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Remove the old static library file
|
|
rm -rf "${TARGET_BUILD_DIR}/libSessionUtil/libSessionUtil.a"
|
|
rm -rf "${TARGET_BUILD_DIR}/libSessionUtil/Headers"
|
|
|
|
# If needed combine simulator builds into a multi-arch lib
|
|
if [ "${#TARGET_SIM_ARCHS[@]}" -eq "1" ]; then
|
|
# Single device build
|
|
cp "${TARGET_BUILD_DIR}/libSessionUtil/${TARGET_SIM_ARCHS[0]}/libsession-util.a" "${TARGET_BUILD_DIR}/libSessionUtil/libSessionUtil.a"
|
|
elif [ "${#TARGET_SIM_ARCHS[@]}" -gt "1" ]; then
|
|
# Combine multiple device builds into a multi-arch lib
|
|
echo_message "info: Built multiple architectures, merging into single static library"
|
|
lipo -create "${TARGET_BUILD_DIR}/libSessionUtil"/sim-*/libsession-util.a -output "${TARGET_BUILD_DIR}/libSessionUtil/libSessionUtil.a"
|
|
fi
|
|
|
|
# If needed combine device builds into a multi-arch lib
|
|
if [ "${#TARGET_DEVICE_ARCHS[@]}" -eq "1" ]; then
|
|
cp "${TARGET_BUILD_DIR}/libSessionUtil/${TARGET_DEVICE_ARCHS[0]}/libsession-util.a" "${TARGET_BUILD_DIR}/libSessionUtil/libSessionUtil.a"
|
|
elif [ "${#TARGET_DEVICE_ARCHS[@]}" -gt "1" ]; then
|
|
# Combine multiple device builds into a multi-arch lib
|
|
echo_message "info: Built multiple architectures, merging into single static library"
|
|
lipo -create "${TARGET_BUILD_DIR}/libSessionUtil"/ios-*/libsession-util.a -output "${TARGET_BUILD_DIR}/libSessionUtil/libSessionUtil.a"
|
|
fi
|
|
|
|
# Save the updated hashes to disk to prevent rebuilds when there were no changes
|
|
echo "${NEW_SOURCE_HASH}" > "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_source_hash.log"
|
|
echo "${NEW_HEADER_HASH}" > "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_header_hash.log"
|
|
echo "${ARCHS[*]}" > "${TARGET_BUILD_DIR}/libSessionUtil/libsession_util_archs.log"
|
|
echo_message "info: Build complete"
|
|
|
|
# Copy the headers across
|
|
echo_message "info: Copy headers and prepare modulemap"
|
|
mkdir -p "${TARGET_BUILD_DIR}/libSessionUtil/Headers"
|
|
cp -r "${SRCROOT}/LibSession-Util/include/session" "${TARGET_BUILD_DIR}/libSessionUtil/Headers"
|
|
|
|
# The 'module.modulemap' is needed for XCode to be able to find the headers
|
|
modmap="${TARGET_BUILD_DIR}/libSessionUtil/Headers/module.modulemap"
|
|
echo "module SessionUtil {" >"$modmap"
|
|
echo " module capi {" >>"$modmap"
|
|
for x in $(cd include && find session -name '*.h'); do
|
|
echo " header \"$x\"" >>"$modmap"
|
|
done
|
|
echo -e " export *\n }" >>"$modmap"
|
|
if false; then
|
|
# If we include the cpp headers like this then Xcode will try to load them as C headers (which
|
|
# of course breaks) and doesn't provide any way to only load the ones you need (because this is
|
|
# Apple land, why would anything useful be available?). So we include the headers in the
|
|
# archive but can't let xcode discover them because it will do it wrong.
|
|
echo -e "\n module cppapi {" >>"$modmap"
|
|
for x in $(cd include && find session -name '*.hpp'); do
|
|
echo " header \"$x\"" >>"$modmap"
|
|
done
|
|
echo -e " export *\n }" >>"$modmap"
|
|
fi
|
|
echo "}" >>"$modmap"
|
|
|
|
# Output to XCode just so the output is good
|
|
echo_message "info: libSessionUtil Ready" |