aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2018-05-30 11:53:44 -0700
committerGarrett D'Amore <garrett@damore.org>2018-05-30 11:53:44 -0700
commitbcbb36cd4fee89ba86dc1028b9f4de928d361abe (patch)
treeb1c45912b99ef7586adbe27a764c582ed3311578
parentf01e2c82f236b405b95adbe517a3cc9b41d17f16 (diff)
downloadnng-bcbb36cd4fee89ba86dc1028b9f4de928d361abe.tar.gz
nng-bcbb36cd4fee89ba86dc1028b9f4de928d361abe.tar.bz2
nng-bcbb36cd4fee89ba86dc1028b9f4de928d361abe.zip
fixes #477 Android NDK build configuration
This enables the software to be built for Android, going back to at least Android SDK r15 (IceCreamSandwich) and at least up to SDK r27 (Oreo). Older versions of Android may work, but we have no way to build them to test. While here we have changed our CMake configuration to disable building tools or tests when we detect a cross-compile situation. Documentation for cross-compilation is updated as well.
-rw-r--r--CMakeLists.txt27
-rw-r--r--docs/BUILD_ANDROID.adoc81
-rw-r--r--docs/BUILD_CROSSCOMPILE.adoc33
-rw-r--r--docs/BUILD_IOS.adoc50
-rw-r--r--src/platform/posix/posix_file.c19
-rw-r--r--src/platform/posix/posix_pollq_epoll.c9
6 files changed, 198 insertions, 21 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 36ba269f..03116540 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -86,12 +86,22 @@ else ()
set (NNG_PACKAGE_VERSION "Unknown")
endif()
+
# User-defined options.
option(BUILD_SHARED_LIBS "Build shared library" ${BUILD_SHARED_LIBS})
-option (NNG_TESTS "Build and run tests" ON)
-option (NNG_TOOLS "Build extra tools" ON)
+if (CMAKE_CROSSCOMPILING)
+ set (NNG_NATIVE_BUILD OFF)
+else()
+ set (NNG_NATIVE_BUILD ON)
+endif()
+
+# We only build command line tools and tests if we are not in a
+# cross-compile situation. Cross-compiling users who still want to
+# build these must enable them explicitly.
+option (NNG_TESTS "Build and run tests" ${NNG_NATIVE_BUILD})
+option (NNG_TOOLS "Build extra tools" ${NNG_NATIVE_BUILD})
option (NNG_ENABLE_NNGCAT "Enable building nngcat utility." ${NNG_TOOLS})
option (NNG_ENABLE_COVERAGE "Enable coverage reporting." OFF)
# Enable access to private APIs for our own use.
@@ -301,6 +311,13 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
endif()
set(NNG_PLATFORM_POSIX ON)
+elseif (CMAKE_SYSTEM_NAME MATCHES "Android")
+ add_definitions (-DNNG_PLATFORM_POSIX)
+ add_definitions (-DNNG_PLATFORM_LINUX)
+ add_definitions (-DNNG_PLATFORM_ANDROID)
+ add_definitions (-DNNG_USE_EVENTFD)
+ set(NNG_PLATFORM_POSIX ON)
+
elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_definitions (-DNNG_PLATFORM_POSIX)
add_definitions (-DNNG_PLATFORM_DARWIN)
@@ -404,6 +421,9 @@ else ()
add_definitions (-D_THREAD_SAFE)
add_definitions (-D_POSIX_PTHREAD_SEMANTICS)
+ nng_check_func (lockf NNG_HAVE_LOCKF)
+ nng_check_func (flock NNG_HAVE_FLOCK)
+
nng_check_lib (rt clock_gettime NNG_HAVE_CLOCK_GETTIME)
nng_check_lib (pthread sem_wait NNG_HAVE_SEMAPHORE_PTHREAD)
nng_check_lib (nsl gethostbyname NNG_HAVE_LIBNSL)
@@ -415,7 +435,8 @@ else ()
nng_check_struct_member(msghdr msg_control sys/socket.h NNG_HAVE_MSG_CONTROL)
nng_check_sym (kqueue sys/event.h NNG_HAVE_KQUEUE)
nng_check_sym (port_create port.h NNG_HAVE_PORT_CREATE)
- nng_check_sym (epoll_wait sys/epoll.h NNG_HAVE_EPOLL)
+ nng_check_sym (epoll_create sys/epoll.h NNG_HAVE_EPOLL)
+ nng_check_sym (epoll_create1 sys/epoll.h NNG_HAVE_EPOLL_CREATE1)
nng_check_sym (getpeereid unistd.h NNG_HAVE_GETPEEREID)
nng_check_sym (SO_PEERCRED sys/socket.h NNG_HAVE_SOPEERCRED)
nng_check_sym (LOCAL_PEERCRED sys/un.h NNG_HAVE_LOCALPEERCRED)
diff --git a/docs/BUILD_ANDROID.adoc b/docs/BUILD_ANDROID.adoc
new file mode 100644
index 00000000..6e210c6d
--- /dev/null
+++ b/docs/BUILD_ANDROID.adoc
@@ -0,0 +1,81 @@
+= Building for Android
+
+NOTE: I am not an Android developer, so this work has received only cursory
+testing. As always, _caveat emptor_.
+
+== Pre-Requisites
+
+Android Studio:::
+
+ There are probably other ways to cross-build for Android, but if you're
+ not using Android Studio, then you probably don't need much help here.
+
+Android NDK::
+
+ A copy of the Android NDK is required to build native code applications.
+ Android Studio has information for downloading it within the app.
+
+== Steps
+
+You need to use the CMake that is included with Android Studio, because
+it knows how to build the Gradle targets. (At least on macOS, the system
+default cmake does not have the right generator support.)
+
+You will also use the Android toolchain file for CMake that is included
+with the NDK.
+
+NOTE: You *must* use the _NDK_ toolchain, not the one that came with the _SDK_.
+The _SDK_ toolchain file is too old and will not work with modern NDKs!
+
+When building for Android, by default we build static libraries, and
+we do not build tools or tests. The tools and tests won't work since
+they assume a shell environment, and you don't want to deal with the
+dependency nightmare that is dynamic libraries anyway. Trust us.
+
+The Android NDK includes documentation for how to run
+CMake including the options that can be set. Details are located
+here: https://developer.android.com/ndk/guides/cmake
+
+TIP: It is *highly* recommended you review the NDK documentation,
+because you will most likely want to change some of the default values
+for the ABI or API level.
+For the sake of clarity, we are assuming only the defaults here.
+
+Set the following environment variables:
+
+`CMAKE`::
+
+ Path to the Android SDK supplied CMake binary. For example, on
+ our macOS install of Android Studio, we have it located in
+ `$HOME/Library/Android/sdk/cmake/3.6.4111459/bin/cmake`.
+
+`NDK`::
+
+ Path to the Android NDK. In the same installation, on our system,
+ it is in `$HOME/Library/Android/sdk/ndk-bundle`
+
+Using the above toolchain file, we can build for Android using
+the CMake standard `CMAKE_TOOLCHAIN_FILE` macro, and using the
+Android supplied CMake:
+
+If you have checked out this repository in `$SRC`, and your copy of the
+Android SDK is located in `$SDK`, the following should work:
+
+[source, sh]
+----
+% cd $SRC
+% mkdir android-build
+% cd android-build
+% ${CMAKE} -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake ..
+----
+
+Then you can build using Xcode, or simply use cmake to drive the build:
+
+[source, sh]
+----
+% ${CMAKE} --build .
+----
+
+Extra effort may be required to enable the use of mbedTLS; you will
+need to review the mbedTLS documentation for configuring that for use
+in Android.
diff --git a/docs/BUILD_CROSSCOMPILE.adoc b/docs/BUILD_CROSSCOMPILE.adoc
new file mode 100644
index 00000000..8b57f812
--- /dev/null
+++ b/docs/BUILD_CROSSCOMPILE.adoc
@@ -0,0 +1,33 @@
+= Building for Cross Compilation
+
+TIP: Cross-compiling is used when the operating system or process architecure
+the software is being built for is different than the system where the software
+is being compiled. If you don't know what this means, this does not apply to
+and you should ignore this file.
+
+When building for cross-compilation, you can use CMake's native support
+`CMAKE_TOOLCHAIN_FILE` to configure the location of the toolchain.
+
+You'll need that toolchain to have your compiler, linker, header files,
+and possibly any other libraries that need to be linked at build time.
+
+This is all relatively standard stuff for CMake.
+
+A lot more detail is located here: https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/CrossCompiling
+
+NOTE: When _NNG_ detects that it is being built in a Cross-Compile
+situation (i.e. when `CMAKE_CROSSCOMPILING` is true), it will default
+to disabling the building of the test suite and tools.
+This is normally preferable, since many embedded environments cannot host
+command line applications or shell environments. +
+ +
+To enable tools or tests to build anyway, the values of either
+`NNG_TOOLS` or `NNG_TESTS` (or both) may be set to `ON`.
+
+== Cross-compiling for Android
+
+More details for Android are located in the <<BUILD_ANDROID.adoc>> file.
+
+== Cross-compiling for iOS
+
+More details for iOS (and tvOS, etc.) are located in the <<BUILD_IOS.adoc>> file.
diff --git a/docs/BUILD_IOS.adoc b/docs/BUILD_IOS.adoc
index 573daf50..eed23714 100644
--- a/docs/BUILD_IOS.adoc
+++ b/docs/BUILD_IOS.adoc
@@ -1,38 +1,54 @@
= Building for iOS (and tvOS, watchOS)
-NOTE: I am not an iOS developer, so this work is not fully tested.
-It seems to work, but YMMV!
+NOTE: I am not an iOS developer, so this work has had only minimal validation.
+As always, _caveat emptor_!
-First, you will need to download a suitable toolchain file.
+== Pre-Requisites
-At the time of this writing (May 28, 2018), the toolchain file
-located at https://github.com/leetal/ios-cmake is appears to work
-reasonably well.
+macOS::
+
+ As far as we know, the only way to build iOS applications is on a
+ macOS host system.
+
+Xcode::
+
+ You will need Xcode. We tested this with Xcode 9.3.
+
+CMake::
+
+ We tested this with CMake 3.9. Other versions may work.
+
+iOS cmake toolchain file::
+
+ At the time of this writing (May 28, 2018), the toolchain file
+ located at https://github.com/leetal/ios-cmake is appears to work
+ reasonably well.
+
+== Steps
When building for iOS and similar targets, only static libraries may be built.
(This is good for avoiding dependency nightmares anyway.)
Using the above toolchain file, we can build for iOS using
the CMake standard CMAKE_TOOLCHAIN_FILE macro, and using
-the IOS_PLATFORM macro to set the target.
-
-We also need to disable tests and tools, since we can't build command line
-executables for that environment. These are controlled by setting
-NNG_TESTS and NNG_TOOLS both to OFF.
+the IOS_PLATFORM macro to set the target. (See the iOS CMake
+toolchain README for valid options; we select "OS" for iOS.)
-You will also need to use the Xcode generator.
+The test suite and command line tools will automatically be removed
+from the build, since they aren't interesting or useful in cross-compile
+environment. (There is no way to run them.)
-So, for example:
+If you have checked out this repository in $SRC, the following should work:
[source, sh]
----
+% cd $SRC
% mkdir ios-build
% cd ios-build
+% git clone https://github.com/leetal/ios-cmake
% cmake -G Xcode \
- -DCMAKE_TOOLCHAIN_FILE=$GITROOT/ios-cmake/ios.toolchain.cmake \
- -DIOS_PLATFORM=OS \
- -DNNG_TESTS=OFF \
- -DNNG_TOOLS=OFF ..
+ -DCMAKE_TOOLCHAIN_FILE=`pwd`/ios-cmake/ios.toolchain.cmake \
+ -DIOS_PLATFORM=OS ..
----
Then you can build using Xcode, or simply use cmake to drive the build:
diff --git a/src/platform/posix/posix_file.c b/src/platform/posix/posix_file.c
index 83d045fa..b1da3cd5 100644
--- a/src/platform/posix/posix_file.c
+++ b/src/platform/posix/posix_file.c
@@ -22,6 +22,11 @@
#include <sys/types.h>
#include <unistd.h>
+// Some systems -- Android -- have BSD flock but not POSIX lockf.
+#if defined(NNG_HAVE_FLOCK) && !defined(NNG_HAVE_LOCKF)
+#include <sys/file.h>
+#endif
+
// File support.
static int
@@ -264,10 +269,22 @@ int
nni_plat_file_lock(const char *path, nni_plat_flock *lk)
{
int fd;
+ int rv;
if ((fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
return (nni_plat_errno(errno));
}
- if (lockf(fd, F_TLOCK, 0) < 0) {
+#ifdef NNG_HAVE_LOCKF
+ rv = lockf(fd, F_TLOCK, 0);
+#elif defined NNG_HAVE_FLOCK
+ rv = flock(fd, LOCK_EX | LOCK_NB);
+#else
+ // We don't have locking support. This means you live dangerously.
+ // For example, ZeroTier cannot be sure that nothing else is using
+ // the same configuration file. If you're here, its probably an
+ // embedded scenario, and we can live with it.
+ rv = 0;
+#endif
+ if (rv < 0) {
int rv = errno;
close(fd);
if (rv == EAGAIN) {
diff --git a/src/platform/posix/posix_pollq_epoll.c b/src/platform/posix/posix_pollq_epoll.c
index 9c1ae682..e4f9ddb6 100644
--- a/src/platform/posix/posix_pollq_epoll.c
+++ b/src/platform/posix/posix_pollq_epoll.c
@@ -348,9 +348,18 @@ nni_posix_pollq_create(nni_posix_pollq *pq)
{
int rv;
+#if NNG_HAVE_EPOLL_CREATE1
if ((pq->epfd = epoll_create1(EPOLL_CLOEXEC)) < 0) {
return (nni_plat_errno(errno));
}
+#else
+ // Old Linux. Size is a "hint" about number of descriptors.
+ // Hopefully not a hard limit, and not used in modern Linux.
+ if ((pq->epfd = epoll_create(16)) < 0) {
+ return (nni_plat_errno(errno));
+ }
+ (void) fcntl(pq->epfd, F_SETFD, FD_CLOEXEC);
+#endif
pq->close = false;