diff --git a/.gitignore b/.gitignore index 5ff5cdba..cc476db1 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ test.*.log /swift-client-api/Makefile /swift-client-api/build/ /swift-client-api/swift-client-util +/ios/Makefile +/ios/build/ +/ios/frameworks/ diff --git a/Android.mk b/Android.mk index ea11d746..28d585bb 100644 --- a/Android.mk +++ b/Android.mk @@ -3,9 +3,10 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -SQLITE3_AMALGAMATION = sqlite-amalgamation-3140200 +include $(LOCAL_PATH)/headerfiles.mk # for SQLITE3_AMALGAMATION include $(LOCAL_PATH)/sourcefiles.mk + SERVALD_SRC_FILES = \ $(SQLITE3_SOURCES) \ $(SERVAL_CLIENT_SOURCES) \ diff --git a/INSTALL.md b/INSTALL.md index db267d3f..af519e5e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -10,17 +10,24 @@ These instructions will build [Serval DNA][] successfully for the following plat * Debian Linux, ix86 and x86\_64, kernel versions 2.6 to 4.12, using [gcc 4.4][] and later, [gcc 5][] and [gcc 6][] * Mac OS-X x86\_64, releases 10.7 “Lion” to 10.11 “El Capitan”, using - [Xcode][] versions 3.2 to 8, and GNU tools available from [homebrew][] + [Xcode][] versions 3.2 to 8, supplemented by [homebrew][] * Oracle SunOs 5.10 (Solaris), Sparc, using [gcc 4.4][] and GNU tools installed -[Serval DNA][] also runs on the following platforms, to which these build -instructions do not apply: +[Serval DNA][] also builds and runs on the following platforms, for which there +are separate build instructions: - * [Android 2.2 “Froyo”][], Arm, Linux kernels 2.6.x and 3.x, using [gcc 4.4][] - supplied as part of [Android NDK][] Revision 7b - * [OpenWRT][] (as used by the [Serval Mesh Extender][], the [Mesh Potato][], - and the [Commotion Wireless][] project) + * [Serval Mesh app for Android][batphone] includes instructions for building + Serval DNA as part of an app for [Android 2.2 “Froyo”][] and later versions; + Linux kernels 2.6.x and 3.x, Arm architecture, using [gcc 4.4][] supplied as + part of [Android NDK][] Revision 7b + + * [Serval DNA on iOS][iOS] gives instructions for [Apple iOS][] using + [Xcode][] versions 8, supplemented by [homebrew][] + + * [Serval DNA on OpenWRT][OpenWRT] gives instructions for the embedded router + Linux distribution, as used by the [Serval Mesh Extender][], the [Mesh + Potato][], and the [Commotion Wireless][] project Download -------- @@ -53,7 +60,7 @@ Mandatory dependencies: Optional: - * Java compiler and SDK 1.6.0 or later + * [Java][] compiler and SDK 1.6.0 or later * [Swift][] 3 or 4 compiler * ALSA sound library and headers (present on Linux, not on Android) @@ -64,7 +71,7 @@ Test dependencies: * jq 1.3 or later * curl -**Bash** and **curl** are both provided by the [XCode][] package for Mac OS X. +**Bash** and **curl** are both provided by the [Xcode][] package for Mac OS X. **GNU grep**, **GNU sed**, **GNU awk** and **jq** can all be installed on Mac OS-X using the [homebrew][] package manager. The [Notes for Developers][] give more details. @@ -214,11 +221,13 @@ The [native build](#native-build) process produces the following artifacts: functions. An executable (such as *servald*) can be built with any desired subset of Serval functions by linking in only the required parts of this library using the *features* mechanism described in [feature.h](./feature.h). + The Serval DNA [Swift][] API, which is used by the Serval Chat app for iOS, + uses this static library. * **libservaldaemon.so** is a dynamic library containing the complete executable code of the Serval DNA daemon, including [JNI][] entry points, SQLite and libsodium cryptographic functions. The *servaldwrap* executable and the - Serval DNA Java API, which is used by [batphone][], both use this dynamic + Serval DNA [Java][] API, which is used by [batphone][], both use this dynamic library. * **directory_service** is the executable for the [Serval Infrastructure][] @@ -339,6 +348,8 @@ This document is available under the [Creative Commons Attribution 4.0 Internati [Swift Client API module]: ./doc/Development.md#swift-client-api [OpenWRT]: ./doc/OpenWRT.md [Serval Infrastructure]: ./doc/Serval-Infrastructure.md +[iOS]: ./doc/Apple-iOS.md +[Apple iOS]: https://en.wikipedia.org/wiki/IOS [Serval Mesh Extender]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:meshextender: [contact the Serval Project]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:contact [RFD900]: http://rfdesign.com.au/index.php/rfd900 @@ -348,6 +359,7 @@ This document is available under the [Creative Commons Attribution 4.0 Internati [MDP API]: ./doc/Mesh-Datagram-Protocol.md#mdp-api [CLI API]: ./doc/CLI-API.md [JNI]: http://en.wikipedia.org/wiki/Java_Native_Interface +[Java]: https://en.wikipedia.org/wiki/Java_(programming_language) [Swift]: https://en.wikipedia.org/wiki/Swift_(programming_language) [dlopen(3)]: http://man7.org/linux/man-pages/man3/dlopen.3.html [Bash]: http://en.wikipedia.org/wiki/Bash_(Unix_shell) @@ -355,6 +367,6 @@ This document is available under the [Creative Commons Attribution 4.0 Internati [Git]: http://git-scm.com/ [Subversion]: http://subversion.apache.org/ [Bourne shell]: http://en.wikipedia.org/wiki/Bourne_shell -[XCode]: https://developer.apple.com/xcode/ +[Xcode]: https://developer.apple.com/xcode/ [homebrew]: http://brew.sh/ [CC BY 4.0]: ./LICENSE-DOCUMENTATION.md diff --git a/Makefile.in b/Makefile.in index bca816b8..f5ab0b23 100644 --- a/Makefile.in +++ b/Makefile.in @@ -31,10 +31,8 @@ INSTALL= install INSTALL_PROGRAM= $(INSTALL) INSTALL_DATA= $(INSTALL) -m 644 -SQLITE3_AMALGAMATION = sqlite-amalgamation-3140200 - -include $(srcdir)/sourcefiles.mk -include $(srcdir)/headerfiles.mk +include $(srcdir)/headerfiles.mk # sets SQLITE3_AMALGAMATION +include $(srcdir)/sourcefiles.mk # depends on SQLITE3_AMALGAMATION LIBSODIUM_SUBDIR = libsodium/ LIBSODIUM_DEV = libsodium-dev @@ -82,7 +80,7 @@ MONITOR_CLIENT_OBJS = \ SIMULATOR_OBJS = \ $(addprefix $(OBJSDIR_TOOLS)/, $(SIMULATOR_SOURCES:.c=.o)) -PREFIXED_HEADERS = $(addprefix $(srcdir)/, $(HDRS)) +PREFIXED_HEADERS = $(addprefix $(srcdir)/, $(ALL_HDRS)) PREFIXED_SOURCES = $(addprefix $(srcdir)/, $(ALL_SOURCES)) LDFLAGS=@LDFLAGS@ @LIBS@ @@ -97,13 +95,12 @@ CFLAGS+=-DSQLITE_THREADSAFE=0 \ -DSQLITE_OMIT_VIRTUALTABLE \ -DSQLITE_OMIT_AUTHORIZATION CFLAGS+=-fPIC -DSERVAL_ENABLE_DEBUG=1 -Wall -Werror -Wextra -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -CFLAGS+=@CFLAGS_TARGET@ # Solaris magic CFLAGS+=-DSHA2_USE_INTTYPES_H -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D__EXTENSIONS__=1 # OSX magic to compensate for the Solaris magic CFLAGS+=-D_DARWIN_C_SOURCE -CFLAGS_SQLITE= @CFLAGS_SQLITE@ +CFLAGS_SQLITE=@CFLAGS_SQLITE@ -include $(srcdir)/Makefile.dbg @@ -145,7 +142,6 @@ uninstall: $(RM) $(DESTDIR)$(sbindir)/servald clean: - cd $(LIBSODIUM_SUBDIR) && $(MAKE) clean $(RM) -r $(LIBSODIUM_DEV) \ $(OBJSDIRS:%=%/*) \ servald \ @@ -154,6 +150,11 @@ clean: libmonitorclient.so libmonitorclient.a \ tfw_createfile directory_service fakeradio simulator serval-tests \ tags + cd $(LIBSODIUM_SUBDIR) && $(MAKE) clean + +distclean: clean + $(RM) config.h config.status config.log testconfig.sh + cd $(LIBSODIUM_SUBDIR) && $(MAKE) distclean # Only provide Java targets if the Java compiler is available. ifneq ($(JAVAC),) @@ -214,7 +215,9 @@ endif # $(SWIFTC) CFLAGS+= -isystem $(LIBSODIUM_DEV)/include -$(LIBSODIUM_HEADERS) $(LIBSODIUM_A): $(LIBSODIUM_DEV)/.installed +.PHONY: libsodium-dev + +libsodium-dev $(LIBSODIUM_HEADERS) $(LIBSODIUM_A): $(LIBSODIUM_DEV)/.installed # The libsodium package uses libtool, so by default its static libraries get # compiled without the -fPIC option. This prevents the libsodium static @@ -229,8 +232,7 @@ $(LIBSODIUM_DEV)/.installed: @$(RM) $@ @touch $@.in-progress @cd $(LIBSODIUM_SUBDIR) && $(MAKE) \ - CFLAGS+="-prefer-pic @CFLAGS_TARGET@" \ - CCASFLAGS+="@CFLAGS_TARGET@" \ + CFLAGS+="-prefer-pic" \ prefix=$(abspath $(LIBSODIUM_DEV)) \ install @mv -f $@.in-progress $@ diff --git a/README.md b/README.md index d410c287..2e8a16c9 100644 --- a/README.md +++ b/README.md @@ -55,18 +55,20 @@ What is in this repository? This repository contains: -* the [GNU C][] source code for the **servald** executable, -* the [Java][] source code for the Serval API, -* some [technical documentation](./doc/), +* the [GNU C][] source code for the **servald** executable +* the [Java][] source code for the Serval API +* the [Swift][] source code for the Serval API +* [technical documentation](./doc/) * a [test framework](./testframework.sh) and [test scripts](./tests/) written - in [Bash][], + in [Bash][] * various support files for installation and configuration on various - platforms. + platforms The **servald** executable is a multi-purpose program that can be invoked directly from the command line, run as a daemon process, or invoked via [JNI][] -from within a Java program. The **servald** executable is really many commands -built into one; the command-line arguments select which *command* to run. Some +from within a [Java][] program or via the [Swift module][] from within a +[Swift][] program. The **servald** executable is really many commands built +into one; the command-line arguments select which *command* to run. Some commands are stand-alone utilities, some start and stop the servald daemon process, some communicate with the servald daemon as an MDP client, and others via a two-way [pipe][] called the *monitor interface*. @@ -182,6 +184,7 @@ This document is available under the [Creative Commons Attribution 4.0 Internati [issue #28]: https://github.com/servalproject/serval-dna/issues/28 [GNU C]: http://gcc.gnu.org/ [Java]: https://en.wikipedia.org/wiki/Java_(programming_language) +[Swift]: https://en.wikipedia.org/wiki/Swift_(programming_language) [daemon]: http://en.wikipedia.org/wiki/Daemon_(computing) [free software]: http://www.gnu.org/philosophy/free-sw.html [contributors]: /servalproject/serval-dna/blob/development/CONTRIBUTORS.md diff --git a/configure.ac b/configure.ac index 061fd2b6..4d1ad39b 100644 --- a/configure.ac +++ b/configure.ac @@ -4,10 +4,17 @@ AC_INIT(servald, 0.9) AC_CONFIG_SRCDIR([serval_types.h]) AC_CONFIG_MACRO_DIR([m4]) +dnl Specify cross compilation using Xcode. +dnl Sets $enable_xcode_sdk to ARG if the --enable-xcode-sdk=ARG option is given. +dnl The --host flag must specify a compilation target that 'apple' as the vendor. +dnl See below for more details. +AC_ARG_ENABLE([xcode-sdk], [cross compile using Xcode]) + +dnl Specify toolchain programs. AC_ARG_VAR([AR], [Library archiver]) AC_ARG_VAR([RANLIB], [Archive indexer]) -dnl Specify Swift compiler +dnl Specify the Swift compiler AC_ARG_VAR([SWIFTC], [Swift compiler]) AC_ARG_VAR([SWIFTCFLAGS], [Swift compiler flags]) @@ -48,24 +55,105 @@ dnl Set $host, $host_cpu, $host_vendor, $host_os, either from --host option dnl (cross compilation), or falling back to $build (native compilation). AC_CANONICAL_HOST -dnl $CFLAGS_TARGET is used in the Serval DNA Makefile and also passed in CFLAGS to all -dnl sub-Makefiles, such as libsodium. -CFLAGS_TARGET='' +dnl On Apple platforms, the development toolchain is provided by Xcode, which has a +dnl set of "cross compilation" SDKs for the different Apple operating systems such as +dnl Mac OSX, iPhoneOS (aka iOS), WatchOS, etc. In addition, each Mac OSX development +dnl system provides its own "native" SDK (libraries + headers) which is not one of +dnl Xcode's listed SDKs and may be completely different from Xcode's MacOSX SDK. +dnl +dnl To enable cross-compilation on Apple systems, pass the following options to the +dnl configure script: +dnl +dnl ./configure --host=-apple-darwin --enable-xcode-sdk= +dnl +dnl where is case insensitive and may or may not contain a version number +dnl suffix, eg: +dnl ./configure --host=armv7-xcode-darwin --enable-xcode-sdk=iPhoneOS +dnl ./configure --host=x86_64-xcode-darwin --enable-xcode-sdk=macosx10.12 +dnl +dnl Note that if no --host option is given, AC_CANONICAL_HOST will set the 'cpu' part +dnl of $host to the native build CPU. +dnl +dnl Note that passing --enable-xcode-sdk=macosx without a --host option will result +dnl in a build for Mac OSX that will only execute natively if the MacOSX SDK in Xcode +dnl exactly matches the version of OSX that is running natively. Otherwise, the +dnl executables will probably fail to dynamically link with the native libraries at +dnl run time, with errors like: +dnl dyld: Symbol not found: _OBJC_CLASS_$_OS_dispatch_semaphore +dnl +dnl The configure script invokes the xcodebuild utility to resolve the 'os' part +dnl to the full name of the SDK supported by Xcode, with version suffix, and sets +dnl $host to -apple-. If the SDK named in --host is not +dnl available in Xcode, then the configure script fails with an error. +dnl +xcrun='' +xcode_sdk='' +arch_flag='' +min_version_flag='' +AS_IF([test "x$enable_xcode_sdk" != x], [ dnl + AS_IF([test "x$host_vendor" != xapple], [ dnl + AC_MSG_ERROR(["--with-xcode-sdk is incompatible with --host $host; vendor must be 'apple'"]) + ]) -dnl Check for C99 compiler, preprocessor and assembler. -AC_PROG_CC_C99 -AC_PROG_CPP + dnl Query Xcode for an SDK that matches the one specified by the --enable-xcode-sdk flag. + XCODE_SDK_lower=`echo "$enable_xcode_sdk" | tr A-Z a-z` + AC_MSG_CHECKING([Xcode SDK for cross compilation]) + for sdk in [`xcodebuild -showsdks | sed -n -e 's/^.*-sdk \([^ ][^ ]*\)$/\1/p'`]; do + AS_CASE([$sdk], + [["$XCODE_SDK_lower"|"$XCODE_SDK_lower"[0-9]*]], [ dnl + xcode_sdk="$sdk" + break + ] + ) + done + AC_MSG_RESULT([$xcode_sdk]) + AS_IF([test "x$xcode_sdk" = x], [AC_MSG_ERROR([Unsupported Xcode SDK: $enable_xcode_sdk])]) + xcode_sdk_os=[`echo "$xcode_sdk" | sed -n -e 's/^\(.*[^0-9]\)[0-9][0-9]*\.[0-9][0-9]*$/\1/p'`] + xcode_sdk_version=[`echo "$xcode_sdk" | sed -n -e 's/^.*[^0-9]\([0-9][0-9]*\.[0-9][0-9]*\)$/\1/p'`] + xcrun="xcrun --sdk $xcode_sdk " + CC="${xcrun}clang" + CPP="$CC -E" + LD="${xcrun}ld" + AR="${xcrun}ar" + RANLIB="${xcrun}ranlib" + + dnl Map the CPU name from the one used by config.sub to the one used by Xcode. + AS_CASE([$host_cpu], [aarch64], [host_arch=arm64], [host_arch=$host_cpu]) + arch_flag="-arch $host_arch" + cross_compiling=yes + + dnl If building for Mac OS-X or iPhoneOS, then make sure all C source files are + dnl compiled with a consistent target, to avoid warnings about inconsistent + dnl versions at link time, such as: + dnl + dnl ld: warning: object file (libservaldaemon.a(libsodium_la-crypto_sign.o)) was + dnl built for newer OSX version (10.12) than being linked (10.10) + dnl + AC_MSG_CHECKING([Clang Xcode target options]) + AS_CASE([$xcode_sdk_os], + [[macosx]], [min_version_flag="-mmacosx-version-min=$xcode_sdk_version"], + [[iphoneos]], [min_version_flag="-miphoneos-version-min=$xcode_sdk_version"] + [[iphonesimulator]], [min_version_flag="-mios-simulator-version-min=$xcode_sdk_version"] + ) + AC_MSG_RESULT([${min_version_flag:-(none)}]) +], [ dnl + dnl Check for C99 compiler and preprocessor. + AC_PROG_CC_C99 + AC_PROG_CPP + + dnl Check for library creation tools. + AC_CHECK_TOOL([AR], [ar], [:]) + AS_IF([test "x$AR" = x:], [AC_MSG_ERROR([Library archiver not found: ar])]) + AC_CHECK_TOOL([RANLIB], [ranlib], [:]) + AS_IF([test "x$RANLIB" = x:], [AC_MSG_ERROR([Archive indexer not found: ranlib])]) + + dnl C preprocessor option to support cross-compiling. + AX_APPEND_COMPILE_FLAGS(["-arch $host_cpu"], [CPPFLAGS]) +]) + +dnl Check for C assembler. AM_PROG_AS -dnl Check for library creation tools. -AC_CHECK_TOOL([AR], [ar], [:]) -AS_IF([test "x$AR" = x:], [AC_MSG_ERROR([Library archiver not found: ar])]) -AC_CHECK_TOOL([RANLIB], [ranlib], [:]) -AS_IF([test "x$RANLIB" = x:], [AC_MSG_ERROR([Archive indexer not found: ranlib])]) - -dnl C preprocessor option to support cross-compiling. -AX_APPEND_COMPILE_FLAGS(["-arch $host_cpu"], [CPPFLAGS]) - dnl Check for a Swift 3 or 4 compiler; set SWIFTC if found. AC_PROG_SWIFTC @@ -77,8 +165,14 @@ AS_IF([test "x$SWIFTC" != x], [ dnl dnl Swift SDK names differ a little from Xcode names: iPhoneOS and iPhoneSimulator dnl are both represented as ios. - swiftc_target=`$SWIFTC $SWIFTCFLAGS -version 2>&1 | sed -n -e 's/^Target: *//p'` - AS_IF([test "x$swiftc_target" = x], [AC_MSG_ERROR([Swift compiler does not report its target: $SWIFTC $SWIFTCFLAGS -version])]) + swift_target_option='' + AS_CASE([$xcode_sdk_os], + [''], [], + [iphoneos|iphonesimulator], [swift_target_option="-target $host_arch-apple-ios$xcode_sdk_version"], + [*], [swift_target_option="-target $host_arch-apple-$xcode_sdk"] + ) + swiftc_target=`$SWIFTC $swift_target_option $SWIFTCFLAGS -version 2>&1 | sed -n -e 's/^Target: *//p'` + AS_IF([test "x$swiftc_target" = x], [AC_MSG_ERROR([Swift compiler does not report its target: $SWIFTC $swift_target_option $SWIFTCFLAGS -version])]) dnl In a build for Mac OSX (native or cross), ensure that the Swift target is high dnl enough to create a Swift package, which were not supported before Mac OSX 10.10. @@ -87,7 +181,7 @@ AS_IF([test "x$SWIFTC" != x], [ dnl [[*-apple-macosx*]], [ dnl swiftc_target_version=[`echo "$swiftc_target" | sed -n -e 's/^.*-macosx//p'`] AS_VERSION_COMPARE([$swiftc_target_version], [$macosx_min_version], [ dnl - CFLAGS_TARGET="-mmacosx-version-min=$macosx_min_version" + min_version_flag="-mmacosx-version-min=$macosx_min_version" swiftc_target=[`echo "$swiftc_target" | sed -n -e 's/-macosx.*$//p'`-macosx$macosx_min_version] ]) ] @@ -106,8 +200,10 @@ AS_IF([test "x$SWIFTC" != x], [ dnl ]) ]) - dnl Add the -target option to SWIFTCFLAGS (if the user has already supplied a -target option in - dnl SWIFTCFLAGS, then this prepended one will take precedence). + dnl Set up the Swift compiler for cross compilation; invoke it using the Xcode xcrun wrapper + dnl utility and add the -target option to SWIFTCFLAGS (if the user has already supplied a + dnl -target option in SWIFTCFLAGS, then this prepended one will take precedence). + SWIFTC="${xcrun}$SWIFTC" SWIFTCFLAGS="-target $swiftc_target $SWIFTCFLAGS" ]) @@ -116,21 +212,22 @@ AS_IF([test "x$SWIFTC" != x && test "x$SWIFT_BUILD" = x], [ AC_PROG_SWIFT_PACKAGE_MANAGER ]) -dnl The C compilation flags used in all Serval-DNA Makefiles. -CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" -CFLAGS_TARGET="$CFLAGS_TARGET" -CFLAGS="$CFLAGS_TARGET $CFLAGS" - -export CPPFLAGS -export CFLAGS - -AC_SUBST([WRAPPER]) -AC_SUBST([CFLAGS_TARGET]) +dnl Swift definitions that get expanded in Makefiles. AC_SUBST([SWIFTC]) AC_SUBST([SWIFTCFLAGS]) AC_SUBST([SWIFT_VERSION]) AC_SUBST([SWIFT_BUILD]) +dnl The C compilation and linking flags used in all Makefiles and all the following +dnl configuration tests. +CPPFLAGS="$arch_flag $CPPFLAGS -D_GNU_SOURCE" +CFLAGS="$arch_flag $min_version_flag $CFLAGS" +LDFLAGS="$arch_flag $LDFLAGS" + +dnl Extra toolchain definitions that get expanded in Makefiles (CC, CCAS, etc. are already +dnl expanded by default). +AC_SUBST([AR]) + dnl Various GCC function and variable attributes AX_GCC_FUNC_ATTRIBUTE(aligned) AX_GCC_FUNC_ATTRIBUTE(alloc_size) @@ -350,12 +447,19 @@ AC_CONFIG_HEADERS([config.h]) AC_SUBST([CONFIG_H], [config.h]) dnl The entire libsodium source is in a subdirectory, and has its own configure -dnl script. - +dnl script. Invoke the configure script with the compilers and their flags. +export CPP +export CPPFLAGS +export CC +export CCAS +export CFLAGS +export LD +export LDFLAGS +export AR +export RANLIB AC_CONFIG_SUBDIRS([libsodium]) -ac_configure_args="$ac_configure_args CC='$CC' CCAS='$CCAS' LD='$LD'" - +dnl Generate files. AC_OUTPUT([ Makefile testconfig.sh diff --git a/doc/Apple-iOS.md b/doc/Apple-iOS.md new file mode 100644 index 00000000..70842f32 --- /dev/null +++ b/doc/Apple-iOS.md @@ -0,0 +1,299 @@ +Serval DNA on iOS +================= +[Serval Project][], November 2017 + +These instructions describe how to embed [Serval DNA][] into an [Apple iOS][] +app. + +This work was funded by a grant from the [NLnet Foundation][]. + +Introduction +------------ + +Please see the [build instructions][build] and [Notes for Developers][develop] +for an introduction to the [Serval DNA][] native build and development +environment. (To summarise: the [Serval DNA][] build and development toolchain +is completely oriented around the [Bash shell][] command-line on [Unix][] +platforms such as [GNU][]/[Linux][] and [Darwin][], and uses [GNU autoconf][] +achieve portability between different platforms.) + +The only platform available for developing iOS apps is the [Xcode][] integrated +development environment from Apple. Xcode is only available on Mac OS-X, so +[Serval DNA][]'s iOS development toolchain is based entirely on the +[Darwin][]/[Xcode][] environment and is not complicated by portability issues. +Xcode builds iOS apps by [cross compiling][] to the selected target. + +The [ios](../ios) subdirectory contains scripts for building Serval DNA into a +multi-target [Framework Bundle][] that can be imported into any Xcode project. +The framework provides access to all public C functions in the Serval DNA +source code, and to all entry points of the Serval DNA Swift API. + +Supported targets +----------------- + +The supported operating systems are: + + * [iOS 10][] or later (iPhoneOS and iPhoneSimulator) + +running on any of the following devices: + + * [iPhone 5][] and [iPhone 5C][] (ARMv7s 32-bit dual-core CPU) + * [iPhone 5S][] (ARMv8 64-bit dual-core CPU) + * [iPhone 6 and 6 Plus][] (ARMv8 64-bit dual-core CPU) + * [iPhone 6S and 6S Plus][] (ARMv8-A 64-bit dual-core CPU) + * [iPhone SE][] (ARMv8-A 64-bit dual-core CPU) + * [iPhone 7 and 7 Plus][] (ARM 64-bit quad-core CPU) + * [iPhone 8 and 8 Plus][] (ARM 64-bit hexa-core CPU) + * [iPhone X][] (ARM 64-bit hexa-core CPU) + * iPhone Simulator (Intel 32-bit CPU) + * iPhone Simulator (Intel 64-bit CPU) + +In Apple terminology, a CPU architecture is called a *slice*. + +In this document, *target* means an operating system and a slice, so, based on +the above list, the supported targets are: + + * iPhoneOS ARMv7s (32-bit) + * iPhoneOS ARMv8 (64-bit) + * iPhoneSimulator i386 (32-bit) + * iPhoneSimulator x86\_64 (64-bit) + +Dependencies +------------ + +Building [Serval DNA][] for iOS requires [Xcode version 8][Xcode 8] or later, +because the [Swift 3][] programming language was first introduced in [Xcode +version 8][Xcode 8], and Serval DNA exposes its API in iOS using Swift 3. + +[Xcode 8][] provides the following command-line utilities: + + * [Bash shell][] version 3.2 + * [GNU make][] version 3.81 + * [Clang][] compiler for [C11][] based on LLVM version 8 + * [Swift 3][] compiler based on LLVM version 8 + * standard BSD utilities such as [sed][], [tr][], and [mkdir][] + +These are adequate for cross-compiling for iOS as described below, but may not +be enough for native development; see [Notes for Developers][develop]. + +Build the Serval DNA Framework Bundle +------------------------------------- + +In a [working copy of the Serval DNA source code](../INSTALL.md#download), use +the following commands: + + $ cd serval-dna + $ autoreconf -f -i -I m4 + $ cd ios + $ ./configure + $ make + $ + +See below for a description of the [built artifacts](#built-artifacts). + +Once the `ios/configure` script has been run once, it only needs to be run +again if the main configure script [configure.ac](../configure.ac) has been +changed (and `autoreconf` has been re-run) or if [Makefile.in](../Makefile.in) +or any other `.in` files have been changed. + +After any change to Serval DNA source or header file, to re-compile and re-link +the framework bundle, simply run `make` again: + + $ cd ios + $ make + $ + +Built artifacts +--------------- + +The `make` command above produces the following files: + + * `ios/frameworks/ServalDNA.framework/` contains a static iOS [Framework + Bundle][] that consists of the following pieces: + + * `Resources/` (symbolic link) contains all “resource” files that accompany + the shared library: + + * `Info.plist` is the bundle's property list in XML format; this allows + Xcode to recognise the bundle and import it correctly + + * `ServalDNA` (symbolic link) is a multi-slice static library for all + [supported targets](#supported-targets) + + * `Headers/` (symbolic link) contains all the Serval DNA C header files, and + subdirectories for all [supported targets](#supported-targets): + + * `iphoneos-armv7` contains the C header files specific to the iPhone + ARMv7 target + + * `iphoneos-arm64` contains the C header files for the iPhone ARMv8 target + + * `iphonesimulator-i386` contains the C header files for the 32-bit + simulator target + + * `iphonesimulator-x86_64` contains the C header files for the 64-bit + simulator target + + * `module.modulemap` (symbolic link) is a file that defines the [Clang module][] + for the bundle; this is what gives Swift code access to the Serval DNA + headers and entry points + + * `ios/frameworks/ServalDNA.xcconfig` is an Xcode configuration file that + contains all the settings needed to use the `ServalDNA.framework` bundle in + an Xcode project + +Import ServalDNA.framework into Xcode +------------------------------------- + +To use the Serval DNA iOS [Framework Bundle][] in an Xcode iOS project: + +1. Open the Xcode application + +2. Create a new iOS project or open an existing one, called “Sample App” for + example + +1. Add the bundle's config file to the Xcode project: + + * menu **File** → **Add Files to “Sample App”...** + * a file chooser dialog window pops up + * navigate to the Xcode config file, eg: *Home* → **src** → **serval-dna** → + **ios** → **frameworks** → **ServalDNA.xcconfig** + * press the **Add** button at the lower right of the dialog window + * the file chooser dialog window closes + * the **ServalDNA.xcconfig file** should now appear in the “Project + navigator” pane on the left side of the Xcode main window + +2. Include the bundle's config file in the project's settings: + + * in the “Project navigator” pane, click on the topmost row, which should be + labelled with the project name, eg: **Sample App** + * in the second row of the centre pane, click on **Info** + * in the left column of the centre pane, click on the row immediately + beneath the **PROJECT** line, which should be labelled with the project + name, eg: **Sample App** + * in the main area of the centre pane, under the **Configurations** heading, + for each of the “Debug” and “Release” sub-headings: + * click on the triangle to expand the sub-heading + * on the line immediately beneath the sub-heading, which should be + labelled with the project name, eg: **Sample App**, click on the widget + in the “Based on Configuration File” column + * a selection box should pop up, containing the options “None” and “ServalDNA” + * choose **ServalDNA** + +3. Write some simple code that invokes a Serval DNA function: + + * TODO + +4. Run the simulator to test that the bundle links correctly: + + * menu **Product** → **Run** + * the message “Build succeeded” should pop up, and the Simulator window + should appear shortly afterwards + +How it works +------------ + +The `ios/configure` script takes advantage of [GNU autoconf][]'s support for +out-of-tree builds: if an autoconf-generated `configure` script (such as the +one used by Serval DNA's [build][]) is invoked from within a different working +directory than the source directory that contains the `configure` script +itself, then it places all resulting configuration files such as `config.h`, +`config.state` and `Makefile` under the working directory, not the source +directory. Invoking the `make` command in that working directory will then +place all built artifacts under the same working directory, without altering +the source directory; ie, the build is completely contained within the working +directory. Because of this, many differently-configured builds can be +preformed from a single copy of the source code, without interfering with each +other. + +The `ios/configure` script creates one working directory per target, under the +`ios/build` directory, and invokes the main Serval DNA `configure` script in +each target subdirectory, with appropriate options to produce the respective +cross-compilation, eg: + + cd build/armv7-iphoneos + ../../../configure --host="armv7-apple-darwin" --enable-xcode-sdk=iphoneos + cd - + cd build/arm64-iphoneos + ../../../configure --host="aarch64-apple-darwin" --enable-xcode-sdk=iphoneos + cd - + cd build/i386-iphonesimulator + ../../../configure --host="i386-apple-darwin" --enable-xcode-sdk=iphonesimulator + cd - + cd build/x86_64-iphonesimulator + ../../../configure --host="x86_64-apple-darwin" --enable-xcode-sdk=iphonesimulator + cd - + +The `ios/configure` script then creates `ios/Makefile`, which, when invoked +by the `make` command: + + * for each target, runs `cd build/TARGET; make libservaldaemon.a` + + * creates the `ios/frameworks/ServalDNA.framework` destination directory + + * combines the all the built static libraries into a single, multi-slice + static library in the framework directory using the [lipo(1)][] utility + + * copies all the Serval DNA C header files into the framework's `Headers` + subdirectory + + * for each target, copies all the target-specific C header files (config.h and + libsodium headers) into the framework's `Headers/TARGET` subdirectory + + * creates the framework's `Resources/Info.plist` file + + * creates the framework's `modules.modulemap` file + + * creates all framework's internal symbolic links + + * creates the `ServalDNA.xcconfig` file to accompany the framework + +If any Serval DNA source (or header) file is subsequently modified, it is only +necessary to re-run the `make` command to recompile for all the targets and +update the framework. Just like in normal development, only the affected +object files will be re-compiled as determined by each target's Makefile +dependency rules. This makes it possible to carry out development of the +Serval DNA source code itself and test it using an Xcode iOS project, with a +relatively quick turn-around. + +----- +**Copyright 2017 Flinders University** +![CC-BY-4.0](./cc-by-4.0.png) +This document is available under the [Creative Commons Attribution 4.0 International licence][CC BY 4.0]. + + +[Serval Project]: http://www.servalproject.org/ +[Serval DNA]: ../README.md +[Apple iOS]: https://en.wikipedia.org/wiki/IOS +[NLnet Foundation]: https://nlnet.nl/ +[Bash shell]: http://en.wikipedia.org/wiki/Bash_(Unix_shell) +[Unix]: https://en.wikipedia.org/wiki/Unix +[GNU]: https://en.wikipedia.org/wiki/GNU +[Linux]: https://en.wikipedia.org/wiki/Linux +[Darwin]: https://en.wikipedia.org/wiki/Darwin_(operating_system) +[GNU autoconf]: http://www.gnu.org/software/autoconf/autoconf.html +[GNU make]: https://www.gnu.org/software/make/ +[Clang]: https://en.wikipedia.org/wiki/Clang +[build]: ../INSTALL.md +[develop]: ./Development.md +[Xcode]: https://en.wikipedia.org/wiki/Xcode +[Xcode 8]: https://developer.apple.com/swift/blog/?id=36 +[C11]: https://en.wikipedia.org/wiki/C11_(C_standard_revision) +[Swift 3]: https://swift.org/blog/swift-3-0-released/ +[cross compiling]: https://en.wikipedia.org/wiki/Cross_compiler +[iOS 10]: https://en.wikipedia.org/wiki/IOS_10 +[iPhone 5]: https://en.wikipedia.org/wiki/IPhone_5 +[iPhone 5C]: https://en.wikipedia.org/wiki/IPhone_5C +[iPhone 5S]: https://en.wikipedia.org/wiki/IPhone_5S +[iPhone 6 and 6 Plus]: https://en.wikipedia.org/wiki/IPhone_6 +[iPhone 6S and 6S Plus]: https://en.wikipedia.org/wiki/IPhone_6S +[iPhone SE]: https://en.wikipedia.org/wiki/IPhone_SE +[iPhone 7 and 7 Plus]: https://en.wikipedia.org/wiki/IPhone_7 +[iPhone 8 and 8 Plus]: https://en.wikipedia.org/wiki/IPhone_8 +[iPhone X]: https://en.wikipedia.org/wiki/IPhone_X +[sed]: https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/sed.1.html +[tr]: https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/tr.1.html +[mkdir]: https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/mkdir.1.html +[Framework Bundle]: https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPFrameworks/Frameworks.html +[Clang module]: https://clang.llvm.org/docs/Modules.html +[lipo(1)]: http://www.manpages.info/macosx/lipo.1.html diff --git a/doc/Development.md b/doc/Development.md index 9cb39b01..2d5fa371 100644 --- a/doc/Development.md +++ b/doc/Development.md @@ -2,27 +2,40 @@ Notes for Serval DNA Developers =============================== [Serval Project][], December 2017 +This document is intended for all developers of [Serval DNA][], and also for +non-developers who are experiencing errors in the [build][] process. + Introduction ------------ -This document is intended for all developers of [Serval DNA][], and also for -non-developers who are experiencing errors in the [build][] process. +The [Serval DNA][] development and [build][] toolchain is completely oriented +around the [Bash shell][] command-line on [Unix][] platforms such as +[GNU][]/[Linux][] and [Darwin][], and uses [GNU autoconf][] achieve portability +between different platforms. + +To date, the [Serval Project][] has not dedicated effort to integrating with +GUI development environments such as [Android Studio][] or supporting non-Unix +platforms such as [Microsoft Windows][], because the ongoing effort of +maintaining compatibility with so many platforms would detract from the +development of core features. Anybody is welcome to contribute support for +more platforms, but at this stage, the Serval Project cannot commit to +maintaining any contributed integrations. Autotools --------- -The [configure.ac][] file is an [autoconf][] script that contains instructions -for adapting the build of Serval DNA to different platforms and CPU -architectures. This script makes use of many [GNU M4][] macros, each of which -tests an aspect of the build environment, such as the make and version of the C -compiler (eg, [GCC][], [Clang][]), the availability of headers, functions and -system calls in the standard library, and so forth. +The [configure.ac][] file is a [GNU autoconf][] script that contains +instructions for adapting the build of Serval DNA to different platforms and +CPU architectures. This script makes use of many [GNU M4][] macros, each of +which tests an aspect of the build environment, such as the make and version of +the C compiler (eg, [GCC][], [Clang][]), the availability of headers, functions +and system calls in the standard library, and so forth. -Most of these M4 macros are standard, either supplied with [autoconf][] or from -the [autoconf macro archive][]. Some macros are specific to Serval DNA, either -to improve on a standard macro or perform a test for which no standard macro -exists. These extra macros are locally defined in files within the [m4](../m4) -sub-directory. +Most of these M4 macros are standard, either supplied with [GNU autoconf][] or +from the [autoconf macro archive][]. Some macros are specific to Serval DNA, +either to improve on a standard macro or perform a test for which no standard +macro exists. These extra macros are locally defined in files within the +[m4](../m4) sub-directory. The [autoreconf][] command used in the [build][] instructions generates an `aclocal.m4` file that includes all the necessary files from the [m4](../m4) @@ -153,7 +166,7 @@ dependencies before building on [Debian][] and [Ubuntu][] systems: Processing triggers for man-db (2.7.5-1) ... $ -Apple Mac OS X +Apple Mac OS-X -------------- ### Test utilities @@ -350,7 +363,12 @@ Available under the [Creative Commons Attribution 4.0 International licence][CC [CliContext]: ../swift-daemon-api/Sources/CliContext.swift [CliContextFile]: ../swift-daemon-api/Sources/CliContextFile.swift [serval\_commandline\_main]: ../swift-daemon-api/Sources/commandline.swift -[autoconf]: http://www.gnu.org/software/autoconf/autoconf.html +[GNU autoconf]: http://www.gnu.org/software/autoconf/autoconf.html +[Bash shell]: http://en.wikipedia.org/wiki/Bash_(Unix_shell) +[Unix]: https://en.wikipedia.org/wiki/Unix +[GNU]: https://en.wikipedia.org/wiki/GNU +[Linux]: https://en.wikipedia.org/wiki/Linux +[Darwin]: https://en.wikipedia.org/wiki/Darwin_(operating_system) [autoconf macro archive]: http://www.gnu.org/software/autoconf-archive/ [GNU M4]: http://www.gnu.org/software/m4/m4.html [GCC]: https://gcc.gnu.org/ diff --git a/headerfiles.mk b/headerfiles.mk index dfd8d89f..fb4e65ad 100644 --- a/headerfiles.mk +++ b/headerfiles.mk @@ -1,56 +1,81 @@ -HDRS= fifo.h \ +SQLITE3_AMALGAMATION = sqlite-amalgamation-3140200 + +SQLITE3_HDRS = $(SQLITE3_AMALGAMATION)/sqlite3.h + +# These library headers are designed for re-use, and do not depend on any +# SERVAL_HDRS. +LIB_HDRS= \ + lang.h \ + feature.h \ + section.h \ + trigger.h \ + uri.h \ + base64.h \ + xprintf.h \ + whence.h \ + str.h \ + strbuf.h \ + serval_uuid.h \ + numeric_str.h \ + socket.h \ + net.h \ + mem.h \ + os.h \ + strbuf_helpers.h \ + log.h \ + log_output.h \ + debug.h \ + rotbuf.h \ + fifo.h \ + cli.h \ + fdqueue.h \ + http_server.h \ + nibble_tree.h + +# These headers are specific to Serval DNA, and also depend on LIB_HDRS. They +# are exposed by the iOS framework module, so they are accessible to Swift code +# in Xcode projects. +PUBLIC_HDRS= \ + constants.h \ + serval_types.h \ + rhizome_types.h \ + dataformats.h \ + instance.h \ + sighandlers.h \ + commandline.h \ + crypto.h \ + server.h \ + servald_main.h \ + sync_keys.h \ + keyring.h \ + route_link.h \ + limit.h \ overlay_buffer.h \ overlay_address.h \ overlay_packet.h \ overlay_interface.h \ - section.h \ - trigger.h \ - commandline.h \ - limit.h \ - rhizome_types.h \ rhizome.h \ - sync_keys.h \ - httpd.h \ - instance.h \ meshms.h \ meshmb.h \ message_ply.h \ - nibble_tree.h \ - serval_types.h \ - serval.h \ - server.h \ - route_link.h \ - keyring.h \ - socket.h \ - cli.h \ - str.h \ - numeric_str.h \ - base64.h \ - uri.h \ - rotbuf.h \ - mem.h \ - os.h \ - serval_uuid.h \ - sighandlers.h \ - strbuf.h \ - strbuf_helpers.h \ - conf.h \ - conf_schema.h \ - crypto.h \ - dataformats.h \ - log.h \ - log_output.h \ - debug.h \ - net.h \ - fdqueue.h \ - http_server.h \ - xprintf.h \ - lang.h \ - constants.h \ - monitor-client.h \ mdp_client.h \ msp_client.h \ - msp_common.h \ msp_server.h \ radio_link.h \ - $(SQLITE3_AMALGAMATION)/sqlite3.h + monitor-client.h \ + serval.h + +# These headers are specific to Serval DNA, and also depend on LIB_HDRS. They are +# not exposed by the iOS framework module, so are inaccessible to Swift code in +# Xcode projects. +PRIVATE_HDRS= \ + conf.h \ + httpd.h \ + msp_common.h \ + +# These headers cannot be included stand-alone, but some PRIVATE_HDRS depend on them. +SERVAL_META_HDRS = \ + conf_schema.h + +# All header files, useful for writing dependency rules with total coverage. +ALL_HDRS = $(LIB_HDRS) $(PUBLIC_HDRS) $(PRIVATE_HDRS) $(SQLITE3_HDRS) $(SERVAL_META_HDRS) diff --git a/ios/README.md b/ios/README.md new file mode 100644 index 00000000..0186f295 --- /dev/null +++ b/ios/README.md @@ -0,0 +1,18 @@ +Serval DNA on iOS +================= +[Serval Project][], September 2016 + +The files in this directory are used for building [Serval DNA][] for [Apple iOS][]. + +See [Serval DNA on iOS][] for instructions. + +----- +**Copyright 2016 Flinders University** +![CC-BY-4.0](./cc-by-4.0.png) +This document is available under the [Creative Commons Attribution 4.0 International licence][CC BY 4.0]. + + +[Serval Project]: http://www.servalproject.org/ +[Serval DNA]: ../README.md +[Serval DNA on iOS]: ../doc/Apple-iOS.md +[Apple iOS]: https://en.wikipedia.org/wiki/IOS diff --git a/ios/configure b/ios/configure new file mode 100755 index 00000000..91d190eb --- /dev/null +++ b/ios/configure @@ -0,0 +1,403 @@ +#!/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" <\$@ + +\$(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 "$@" diff --git a/ios/info-plist.sh b/ios/info-plist.sh new file mode 100755 index 00000000..980f1669 --- /dev/null +++ b/ios/info-plist.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Utility to output an Apple framework Info.plist file for Serval DNA. +# Copyright 2017 Flinders University + +set -e + +case "$0" in +*/*) SERVAL_DNA_DIR="${0%/*}/..";; +*) SERVAL_DNA_DIR="..";; +esac + +bundle_name="${1?}" +bundle_id="${2?}" +bundle_version="${3?}" + +escape() { + echo -n "$(printf '%s\n' "$*" | sed -e 's/&/&/g' -e 's//>/g')" +} + +comment() { + echo '/-- >/g' + done + echo '-->' +} + +property() { + echo -n ' ' + escape "$1" + echo -n '' + escape "$2" + echo '' +} + +echo '' +echo '' +comment "Info.plist for the $bundle_name framework iOS bundle." \ + "Copyright 2007 Flinders University" +echo '' +echo '' +property CFBundleIdentifier "$bundle_id" +property CFBundleName "$bundle_name" +property CFBundleVersion "$bundle_version" +property CFBundleShortVersionString "$bundle_version" +property CFBundleExecutable "$bundle_name" +property CFBundleDevelopmentRegion English +property CFBundleInfoDictionaryVersion 6.0 +property CFBundlePackageType FMWK +property NSHumanReadableCopyright "$(cat $SERVAL_DNA_DIR/COPYRIGHT.txt)" +echo '' +echo ''