mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-19 21:27:57 +00:00
404 lines
14 KiB
Plaintext
404 lines
14 KiB
Plaintext
|
#!/bin/bash
|
||
|
#
|
||
|
# Build configuration utility for Serval DNA on Apple iOS.
|
||
|
#
|
||
|
# Copyright 2016-2017 Flinders University
|
||
|
#
|
||
|
# This script runs Serval DNA's main 'configure' script several times, once for
|
||
|
# each different target iOS target, and saves the Makefile that is generated by
|
||
|
# each run. It then creates a top-level Makefile that:
|
||
|
# (1) invokes each of the saved Makefiles in turn to generate one static library
|
||
|
# for each target, then
|
||
|
# (2) combines all these libraries into a single "multi slice" static library
|
||
|
# that can be imported into an Xcode project.
|
||
|
#
|
||
|
# This allows the iOS development cycle to be similarly rapid as for platforms
|
||
|
# such as Linux or native Apple OS-X:
|
||
|
# (1) a single 'configure' step adapts the Makefile(s) to the specific needs of
|
||
|
# the target architecture(s), then
|
||
|
# (2) the edit-make-test cycle can be repeated as often as desired:
|
||
|
# (a) edit; make changes to source file(s)
|
||
|
# (b) make; compile the changed source files into executable form using the
|
||
|
# dependency rules in the Makefile(s), which avoids unnecessary
|
||
|
# re-compilation, then re-build the app in Xcode, which links in the
|
||
|
# new static library
|
||
|
# (c) test; run the re-built app, either in an iOS simulator or by
|
||
|
# side-loading into an iPhone
|
||
|
#
|
||
|
|
||
|
# Exit on error
|
||
|
set -e
|
||
|
|
||
|
usage() {
|
||
|
echo "Usage: ${0##*/} [-f|--force]"
|
||
|
}
|
||
|
|
||
|
# Run the Serval DNA configure script once for each architecture, and save the
|
||
|
# files produced by each run.
|
||
|
|
||
|
main() {
|
||
|
setup
|
||
|
parse_command_line "$@"
|
||
|
check
|
||
|
exec 5>&1
|
||
|
TARGETS=()
|
||
|
configure iphoneos armv7 /Library/Serval
|
||
|
configure iphoneos arm64 /Library/Serval
|
||
|
configure iphonesimulator i386 /tmp/serval-dna
|
||
|
configure iphonesimulator x86_64 /tmp/serval-dna
|
||
|
create_makefile
|
||
|
}
|
||
|
|
||
|
# Trace and diagnostic functions.
|
||
|
|
||
|
run() {
|
||
|
echo + "$@" >&5
|
||
|
"$@"
|
||
|
}
|
||
|
|
||
|
usage_error() {
|
||
|
echo "${0##*/}: $*" >&2
|
||
|
usage >&2
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
fatal() {
|
||
|
echo "${0##*/}: $1" >&2
|
||
|
shift
|
||
|
while [ $# -ne 0 ]; do
|
||
|
echo "$1" >&2
|
||
|
shift
|
||
|
done
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
# Parse command-line options.
|
||
|
|
||
|
parse_command_line() {
|
||
|
library=libservaldaemon.a
|
||
|
swiftmodule=ServalDNA.swiftmodule
|
||
|
opt_force_configure=false
|
||
|
opt_force_config_status=false
|
||
|
log_display_line_count=10
|
||
|
while [ $# -ne 0 ]; do
|
||
|
opt="$1"
|
||
|
shift
|
||
|
case "$opt" in
|
||
|
-h | --help)
|
||
|
usage
|
||
|
exit 0
|
||
|
;;
|
||
|
-f|--force-configure)
|
||
|
opt_force_configure=true
|
||
|
;;
|
||
|
--force-config-status)
|
||
|
opt_force_config_status=true
|
||
|
;;
|
||
|
-*)
|
||
|
usage_error "Unknown option: $opt"
|
||
|
;;
|
||
|
*)
|
||
|
usage_error "Spurious argument: $opt"
|
||
|
;;
|
||
|
esac
|
||
|
done
|
||
|
}
|
||
|
|
||
|
# Work out the path of the directory containing this script relative to the
|
||
|
# current working directory (SCRIPT_DIR), the path of the Serval DNA repository
|
||
|
# root directory relative to the current working directory (SERVAL_DNA_DIR), and
|
||
|
# the path of these two directories relative to each other.
|
||
|
|
||
|
setup() {
|
||
|
case "$0" in
|
||
|
*/?*/*) SCRIPT_DIR="${0%/*}"; SERVAL_DNA_DIR="${0%/?*/*}";;
|
||
|
./*) SCRIPT_DIR="."; SERVAL_DNA_DIR="..";;
|
||
|
*/*) SCRIPT_DIR="${0%/*}"; SERVAL_DNA_DIR=".";;
|
||
|
*) SCRIPT_DIR="."; SERVAL_DNA_DIR="..";;
|
||
|
esac
|
||
|
SCRIPT_DIR_RELATIVE_TO_SERVAL_DNA_DIR="$(cd "$SCRIPT_DIR" >/dev/null && echo "${PWD##*/}")"
|
||
|
SERVAL_DNA_DIR_RELATIVE_TO_SCRIPT_DIR=".."
|
||
|
SERVAL_DNA_CONFIGURE="$SERVAL_DNA_DIR/configure"
|
||
|
}
|
||
|
|
||
|
# Ensure that the Serval DNA 'configure' script exists and is executable.
|
||
|
|
||
|
check() {
|
||
|
if [ ! -e "$SERVAL_DNA_CONFIGURE" ]; then
|
||
|
fatal "missing script: $SERVAL_DNA_CONFIGURE" \
|
||
|
"Run 'autoreconf -f -i -I m4' then run me again."
|
||
|
fi
|
||
|
if [ ! -x "$SERVAL_DNA_CONFIGURE" ]; then
|
||
|
fatal "script is not executable: $SERVAL_DNA_CONFIGURE" \
|
||
|
"Run 'autoreconf -f -i -I m4' then run me again."
|
||
|
fi
|
||
|
case "$("$SERVAL_DNA_CONFIGURE" --version)" in
|
||
|
servald\ configure\ *) ;;
|
||
|
*) fatal "malfunctioning script: $SERVAL_DNA_CONFIGURE" \
|
||
|
"Run 'autoreconf -f -i -I m4' then run me again."
|
||
|
esac
|
||
|
}
|
||
|
|
||
|
configure() {
|
||
|
local platform="${1?}"
|
||
|
local arch="${2?}"
|
||
|
local prefix="${3?}"
|
||
|
|
||
|
# Convert from the Xcode architecture name to the autoconf cpu name, so it
|
||
|
# can be passed in the --host option to the configure script.
|
||
|
local cpu
|
||
|
case "$arch" in
|
||
|
arm64) cpu=aarch64;;
|
||
|
*) cpu="$arch";;
|
||
|
esac
|
||
|
|
||
|
# A "target" is an architecture (aka, "slice" or "architecture", eg, armv7,
|
||
|
# arm64, i386) and an Apple SDK (eg, iphoneos, iphonesimulator, macosx).
|
||
|
local target="$arch-$platform"
|
||
|
|
||
|
TARGETS+=("$arch-$platform")
|
||
|
|
||
|
configure_script="$SERVAL_DNA_DIR_RELATIVE_TO_SCRIPT_DIR/configure"
|
||
|
makefile_in="$SERVAL_DNA_DIR_RELATIVE_TO_SCRIPT_DIR/Makefile.in"
|
||
|
|
||
|
# Path of the directory under which the files this script creates will be placed
|
||
|
# relative to the directory containing this script.
|
||
|
local target_build_dir="$SCRIPT_DIR/build/$target"
|
||
|
target_build_dir="${target_build_dir#./}"
|
||
|
script_dir_relative_to_target_build_dir="../.."
|
||
|
|
||
|
if [ ! -d "$target_build_dir" ]; then
|
||
|
run mkdir -p "$target_build_dir"
|
||
|
fi
|
||
|
|
||
|
# Note: the configure script created by autoconf places its output files in
|
||
|
# the current working directory.
|
||
|
if $opt_force_configure || $opt_force_config_status ||
|
||
|
! [ -e "$target_build_dir/.configured" ] ||
|
||
|
[ "$target_build_dir/config.status" -ot "$configure_script" ] ||
|
||
|
[ "$target_build_dir/Makefile" -ot "$configure_script" ] ||
|
||
|
[ "$target_build_dir/Makefile" -ot "$makefile_in" ] ||
|
||
|
[ "$target_build_dir/Makefile" -ot "$target_build_dir/config.status" ]
|
||
|
then
|
||
|
run pushd "$target_build_dir" >/dev/null
|
||
|
|
||
|
rm -f .configured
|
||
|
|
||
|
configure_script="$script_dir_relative_to_target_build_dir/$configure_script"
|
||
|
makefile_in="$script_dir_relative_to_target_build_dir/$makefile_in"
|
||
|
|
||
|
if $opt_force_configure ||
|
||
|
! [ -e ".configured" ] ||
|
||
|
[ "config.status" -ot "$configure_script" ] ||
|
||
|
[ "Makefile" -ot "$configure_script" ]
|
||
|
then
|
||
|
run rm -f config.status Makefile
|
||
|
if ! run "$configure_script" \
|
||
|
--host="$cpu-apple-darwin" \
|
||
|
--enable-xcode-sdk="$platform" \
|
||
|
--prefix "$prefix" \
|
||
|
&>configure.out
|
||
|
then
|
||
|
fatal "configure failed; see $target_build_dir/configure.out for full log" \
|
||
|
"Last $log_display_line_count lines were:" \
|
||
|
"" \
|
||
|
"$(tail -n $log_display_line_count configure.out)"
|
||
|
fi
|
||
|
if [ ! -r config.status ]; then
|
||
|
fatal "configure for $target did not produce config.status"
|
||
|
fi
|
||
|
if [ ! -r Makefile ]; then
|
||
|
fatal "configure for $target did not produce Makefile"
|
||
|
fi
|
||
|
elif $opt_force_config_status ||
|
||
|
[ "Makefile" -ot "$makefile_in" ] ||
|
||
|
[ "Makefile" -ot "config.status" ]
|
||
|
then
|
||
|
run rm -f Makefile
|
||
|
if ! run ./config.status &>config.status.out
|
||
|
then
|
||
|
fatal "./config.status failed; see $target_build_dir/config.status.out:" \
|
||
|
"$(cat config.status.out)"
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
> .configured
|
||
|
run popd >/dev/null
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# Create a Serval DNA Makefile that creates an Apple framework bundle:
|
||
|
# - generates a modulemap file for the bundle
|
||
|
# - generates a Xcode config file
|
||
|
# - invokes all the per-target iOS makefiles to create one static library for
|
||
|
# each target slice (arch-sdk)
|
||
|
# - merges all the static libraries into a single, multi-slice library
|
||
|
# - generates an Info.plist XML file describing the bundle
|
||
|
# - creates the correct directory structure and symbolic links for the bundle
|
||
|
|
||
|
foreach_target() {
|
||
|
local target
|
||
|
local target_dir
|
||
|
for target in "${TARGETS[@]}"; do
|
||
|
arch="${target%%-*}"
|
||
|
sdk="${target#-*}"
|
||
|
target_dir="build/$target"
|
||
|
target_var=$(echo -n "$target" | tr -C a-zA-z0-9_ _)
|
||
|
eval "$@"
|
||
|
done
|
||
|
}
|
||
|
|
||
|
create_makefile() {
|
||
|
echo "Creating $SCRIPT_DIR/Makefile"
|
||
|
cat >"$SCRIPT_DIR/Makefile" <<EOF
|
||
|
# Makefile for Serval DNA on Apple iOS
|
||
|
# Copyright 2017 Flinders University
|
||
|
# This file was auto-generated by the ./${0##*/} script
|
||
|
# $(date)
|
||
|
|
||
|
srcdir=$SERVAL_DNA_DIR_RELATIVE_TO_SCRIPT_DIR
|
||
|
dstdir=frameworks
|
||
|
targets=${TARGETS[*]}
|
||
|
|
||
|
fw_name=ServalDNA
|
||
|
fw_version=A
|
||
|
fw_bundle_id=org.servalproject.serval-dna
|
||
|
fw_bundle_version=1.0
|
||
|
|
||
|
fw_dir=\$(dstdir)/\$(fw_name).framework
|
||
|
fw_dstdir=\$(fw_dir)/Versions/\$(fw_version)
|
||
|
fw_library=\$(fw_dstdir)/\$(fw_name)
|
||
|
fw_swiftmodule=\$(fw_dstdir)/Modules/\$(fw_name).swiftmodule
|
||
|
fw_info_plist=\$(fw_dstdir)/Resources/Info.plist
|
||
|
fw_config_headers=\$(targets:%=\$(fw_dstdir)/Headers/%/config.h)
|
||
|
fw_serval_headers=\$(addprefix \$(fw_dstdir)/Headers/, \$(LIB_HDRS) \$(PUBLIC_HDRS))
|
||
|
fw_sqlite3_headers=\$(addprefix \$(fw_dstdir)/Headers/, \$(notdir \$(SQLITE3_HDRS)))
|
||
|
fw_modulemap=\$(fw_dstdir)/Modules/module.modulemap
|
||
|
xcconfig=\$(dstdir)/\$(fw_name).xcconfig
|
||
|
|
||
|
include \$(srcdir)/headerfiles.mk
|
||
|
|
||
|
.PHONY: all \\
|
||
|
clean\
|
||
|
$(foreach_target echo '" \\"' \; \
|
||
|
echo '" install_${target_var}_sodium_headers \\"' \; \
|
||
|
echo '" $target_dir/$library \\"' \; \
|
||
|
echo '" $target_dir/$swiftmodule \\"' \; \
|
||
|
echo -n '" clean-$target"')
|
||
|
|
||
|
all: \$(fw_library) \\
|
||
|
\$(fw_info_plist) \\
|
||
|
\$(fw_config_headers) \\
|
||
|
\$(fw_serval_headers) \\
|
||
|
\$(fw_sqlite3_headers) \\
|
||
|
\$(fw_modulemap) \\
|
||
|
\$(xcconfig)$(foreach_target echo '" \\"' \; \
|
||
|
echo -n '" install_${target_var}_sodium_headers"' \; \
|
||
|
echo -n '" \$(fw_swiftmodule)/$arch.swiftmodule"')
|
||
|
cd \$(fw_dstdir)/.. && ln -snf \$(fw_version) Current
|
||
|
cd \$(fw_dstdir)/../.. && ln -snf Versions/Current/* .
|
||
|
|
||
|
\$(fw_info_plist): ./info-plist.sh
|
||
|
mkdir -p \$(dir \$@)
|
||
|
./info-plist.sh \$(fw_name) \$(fw_bundle_id) \$(fw_bundle_version) >\$@
|
||
|
|
||
|
\$(fw_library):$(foreach_target echo '" \\"' \; \
|
||
|
echo -n '" $target_dir/$library"')
|
||
|
mkdir -p \$(dir \$@)
|
||
|
lipo -create -output \$@ \$^
|
||
|
|
||
|
$(foreach_target echo '"\$(fw_swiftmodule)/$arch.swiftmodule: $target_dir/$swiftmodule"' \; \
|
||
|
echo '" mkdir -p \$(dir \$@)"' \; \
|
||
|
echo '" cp \$< \$@"' \; \
|
||
|
echo)
|
||
|
|
||
|
\$(fw_config_headers): \$(fw_dstdir)/Headers/%: build/%
|
||
|
mkdir -p \$(dir \$@)
|
||
|
cp \$< \$@
|
||
|
|
||
|
\$(fw_serval_headers): \$(fw_dstdir)/Headers/%: \$(srcdir)/%
|
||
|
mkdir -p \$(dir \$@)
|
||
|
cp \$< \$@
|
||
|
|
||
|
\$(fw_sqlite3_headers): \$(fw_dstdir)/Headers/%: \$(srcdir)/\$(SQLITE3_AMALGAMATION)/%
|
||
|
mkdir -p \$(dir \$@)
|
||
|
cp \$< \$@
|
||
|
|
||
|
\$(fw_modulemap):$(foreach_target echo '" \\"' \; \
|
||
|
echo -n '" install_${target_var}_sodium_headers"') \\
|
||
|
\$(srcdir)/headerfiles.mk Makefile
|
||
|
mkdir -p \$(dir \$@)
|
||
|
@{ \\
|
||
|
echo '/*' \\
|
||
|
echo 'module.modulemap for Serval DNA on Apple iOS' ;\\
|
||
|
echo 'Copyright 2017 Flinders University' ;\\
|
||
|
echo 'This file was auto-generated by \$(abspath Makefile)' ;\\
|
||
|
echo '\$(shell date)' ;\\
|
||
|
echo '*/' ;\\
|
||
|
echo 'framework module ServalDNA {' ;\\
|
||
|
echo ' requires tls // thread-local storage' ;\\
|
||
|
echo ' explicit module Daemon {' ;\\
|
||
|
echo ' export Sodium' ;\\
|
||
|
$(foreach_target echo '" echo '\'' header \"$target/config.h\"'\'' ;\\"')
|
||
|
for header in \$(LIB_HDRS) \$(PUBLIC_HDRS) \$(notdir \$(SQLITE3_HDRS)); do \\
|
||
|
echo " header \"\$\$header\"" ;\\
|
||
|
done ; \\
|
||
|
echo ' }' ;\\
|
||
|
echo ' explicit module Sodium {' ;\\
|
||
|
$(foreach_target echo '" echo '\'' header \"$target/sodium.h\"'\'' ;\\"' \; \
|
||
|
echo '" (cd $target_dir/libsodium-dev/include/; find . -type f -print | sed -e '\''s|^\./||'\'' -e '\''s|.*| header \"$target/&\"|'\'' ) ;\\"')
|
||
|
echo ' }' ;\\
|
||
|
echo '}' ;\\
|
||
|
echo 'module ifaddrs [system] [extern_c] {' ;\\
|
||
|
echo ' header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/ifaddrs.h"' ;\\
|
||
|
echo ' export *' ;\\
|
||
|
echo '}' ;\\
|
||
|
echo 'module inttypes [system] [extern_c] {' ;\\
|
||
|
echo ' header "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/clang/include/inttypes.h"' ;\\
|
||
|
echo ' export *' ;\\
|
||
|
echo '}' ;\\
|
||
|
} >\$@
|
||
|
|
||
|
\$(xcconfig): Makefile
|
||
|
mkdir -p \$(dir \$@)
|
||
|
@{ \\
|
||
|
echo '// ServalDNA.xcconfig for Serval DNA on Apple iOS' ;\\
|
||
|
echo '// Copyright 2017 Flinders University' ;\\
|
||
|
echo '// This file was auto-generated by \$(abspath Makefile)' ;\\
|
||
|
echo '// \$(shell date)' ;\\
|
||
|
echo 'SERVAL_DNA_FRAMEWORK_DIR = \$(abspath \$(fw_dir))' ;\\
|
||
|
echo 'FRAMEWORK_SEARCH_PATHS = \$\$(inherited) \$(abspath \$(dstdir))' ;\\
|
||
|
echo 'GCC_PREPROCESSOR_DEFINITIONS = \$\$(inherited) HAVE_CONFIG_H=1' ;\\
|
||
|
$(foreach_target echo '" echo '\''HEADER_SEARCH_PATHS[arch=$arch] = \$\$(inherited) \$\$(SERVAL_DNA_FRAMEWORK_DIR)/Headers/$target'\'' ;\\"')
|
||
|
echo 'SWIFT_INCLUDE_PATHS = \$\$(inherited) \$\$(SERVAL_DNA_FRAMEWORK_DIR)/Modules' ;\\
|
||
|
echo 'OTHER_SWIFT_FLAGS = \$\$(inherited) -Xcc -DHAVE_CONFIG_H=1' ;\\
|
||
|
} >\$@
|
||
|
|
||
|
$(foreach_target echo \; \
|
||
|
echo '"install_${target_var}_sodium_headers: $target_dir/$library"' \; \
|
||
|
echo '" cp -R $target_dir/libsodium-dev/include/ \$(fw_dstdir)/Headers/$target/"')
|
||
|
|
||
|
# If the source directory is already configured, then its config.h header
|
||
|
# file would interfere with these sub-makes, so delete it before invoking
|
||
|
# each sub-make.
|
||
|
|
||
|
$(foreach_target echo \; \
|
||
|
echo '"$target_dir/$library:"' \; \
|
||
|
echo '" \$(RM) \$(srcdir)/config.h"' \; \
|
||
|
echo '" \$(MAKE) -C $target_dir $library"')
|
||
|
|
||
|
$(foreach_target echo \; \
|
||
|
echo '"$target_dir/$swiftmodule:"' \; \
|
||
|
echo '" \$(RM) \$(srcdir)/config.h"' \; \
|
||
|
echo '" \$(MAKE) -C $target_dir $swiftmodule"')
|
||
|
|
||
|
clean: $(foreach_target echo -n '" clean-$target"')
|
||
|
\$(RM) -r \$(dstdir)
|
||
|
$(foreach_target echo \; \
|
||
|
echo '"clean-$target:"' \; \
|
||
|
echo '" \$(MAKE) -C $target_dir clean"')
|
||
|
EOF
|
||
|
}
|
||
|
|
||
|
main "$@"
|