Build libsodium as a CMake external project

master
Johan Ouwerkerk 2020-05-07 22:08:47 +02:00
parent 3018d1f3b8
commit db41697dbf
6 changed files with 303 additions and 2 deletions

View File

@ -27,7 +27,7 @@ include(FeatureSummary)
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
include(KDEInstallDirs)
include(KDECMakeSettings)
@ -42,10 +42,16 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
################# Find dependencies #################
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Gui Svg QuickControls2)
find_package(sodium ${SODIUM_MIN_VERSION} REQUIRED)
find_package(KF5Kirigami2 ${KF5_MIN_VERSION} REQUIRED)
find_package(KF5I18n ${KF5_MIN_VERSION} REQUIRED)
if(NOT BUILD_EXTERNAL AND (NOT ANDROID OR DEFINED BUILD_EXTERNAL))
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
message(STATUS "Will build against system version of: libsodium")
find_package(sodium ${SODIUM_MIN_VERSION} REQUIRED)
endif()
################ Find testing dependencies ##########
if (BUILD_TESTING)
@ -55,6 +61,10 @@ endif()
################# build and install #################
add_subdirectory(src)
if (ANDROID)
add_subdirectory(android)
endif()
if (BUILD_TESTING)
add_subdirectory(autotests)
endif()

12
android/CMakeLists.txt Normal file
View File

@ -0,0 +1,12 @@
#
# SPDX-License-Identifier: BSD-2-Clause
# SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
#
configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/android-export.in.sh" "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android-export.sh" @ONLY ESCAPE_QUOTES)
file (
COPY "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android-export.sh"
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}"
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)

View File

@ -0,0 +1,134 @@
#!/bin/sh
#
# SPDX-License-Identifier: BSD-2-Clause
# SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
#
set -e
cat << INTRO
Running android-export.sh wrapper script: $0
Build info
== target:
- api : @CMAKE_ANDROID_API@
- arch : @CMAKE_ANDROID_ARCH@
- abi : @CMAKE_ANDROID_ARCH_ABI@
- stl : @CMAKE_ANDROID_STL_TYPE@
== build host:
- host: @CMAKE_HOST_SYSTEM_NAME@
- arch: @CMAKE_HOST_SYSTEM_PROCESSOR@
== ndk:
- path : @CMAKE_ANDROID_NDK@
INTRO
tool_prefix ()
{
local binutils="$1"
# see: https://developer.android.com/ndk/guides/other_build_systems
case "@CMAKE_ANDROID_ARCH@" in
arm)
if [ -n "$binutils" ]
then
echo -n "arm-linux-androideabi"
else
echo -n "armv7a-linux-androideabi"
fi
;;
arm64)
echo -n "aarch64-linux-android"
;;
x86)
echo -n "i686-linux-android"
;;
x86-64|x86_64) # not sure which will be passed, accept both
echo -n "x86_64-linux-android"
;;
*)
echo "Unable to continue: unknown/undefined/unsupported Android architecture: '@CMAKE_ANDROID_ARCH@'" >&2
exit 254
;;
esac
}
clang_toolname_prefix ()
{
echo -n "$(tool_prefix)@CMAKE_ANDROID_API@"
}
toolchain_host ()
{
echo -n "@CMAKE_HOST_SYSTEM_NAME@-@CMAKE_HOST_SYSTEM_PROCESSOR@" | tr [:upper:] [:lower:]
}
toolchain_path ()
{
echo -n "@CMAKE_ANDROID_NDK@/toolchains/llvm/prebuilt/$(toolchain_host)"
}
get_stl ()
{
case "@CMAKE_ANDROID_STL_TYPE@" in
c++_shared)
echo -n "libc++"
;;
*)
echo "Unable to continue: unknown/undefined/unsupported STL: '@CMAKE_ANDROID_STL_TYPE@'" >&2
exit 254
;;
esac
}
get_cxx_flags ()
{
case "$CXXFLAGS" in
*"--stl"*)
echo -n "$CXXFLAGS"
;;
*)
echo -n "$CXXFLAGS --stl=$(get_stl)"
;;
esac
}
# see: https://developer.android.com/ndk/guides/other_build_systems
BINUTILS_PREFIX="$(tool_prefix "true")"
CLANG_PREFIX="$(clang_toolname_prefix)"
TOOLCHAIN_BINDIR="$(toolchain_path)/bin"
CXXFLAGS="$(get_cxx_flags)"
AR="$TOOLCHAIN_BINDIR/$BINUTILS_PREFIX-ar"
AS="$TOOLCHAIN_BINDIR/$BINUTILS_PREFIX-as"
CC="$TOOLCHAIN_BINDIR/$CLANG_PREFIX-clang"
LD="$TOOLCHAIN_BINDIR/$BINUTILS_PREFIX-ld"
CXX="$TOOLCHAIN_BINDIR/$CLANG_PREFIX-clang++"
STRIP="$TOOLCHAIN_BINDIR/$BINUTILS_PREFIX-strip"
RANLIB="$TOOLCHAIN_BINDIR/$BINUTILS_PREFIX-ranlib"
if [ ! -d "$TOOLCHAIN_BINDIR" ]
then
echo "Unable to continue: tools directory not found: $TOOLCHAIN_BINDIR" >&2
echo "Android NDK root directory is supposed to be: @CMAKE_ANDROID_NDK@" >&2
exit 1
fi
set -x
export PATH="$TOOLCHAIN_BINDIR:$PATH" \
CXXFLAGS="$CXXFLAGS" \
AR="$AR" \
AS="$AS" \
CC="$CC" \
LD="$LD" \
CXX="$CXX" \
STRIP="$STRIP" \
RANLIB="$RANLIB"
$@

19
cmake/external/configure-autotools.sh vendored Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
#
# SPDX-License-Identifier: BSD-2-Clause
# SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
#
set -ex
#
# Autotools builds are in-source which is messy. In particular, it can
# cause conflicts if builds have to be run with different ./configure
# settings one after another
#
# Impose some sanity by ensuring builds/configure always start from scratch
#
git clean -fdx
./autogen.sh
./configure "$@"

23
cmake/external/make.sh vendored Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh
#
# SPDX-License-Identifier: BSD-2-Clause
# SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
#
set -e
#
# Try to speed up builds by using parallel make. Assume that if MAKEFLAGS
# is set, someone is trying to control make behaviour explicitly and do not
# second-guess that.
#
if [ -z "$MAKEFLAGS" ]
then
cores="$(nproc --all)"
jobs="$(($cores * 5 / 4))"
set -x
make -j "$jobs" "$@"
else
set -x
make "$@"
fi

View File

@ -6,4 +6,107 @@
set(secret_SRCS secrets.cpp)
add_library(secrets_lib STATIC ${secret_SRCS})
if (BUILD_EXTERNAL OR (NOT DEFINED BUILD_EXTERNAL AND ANDROID))
message(STATUS "Will build external project: libsodium")
include(ExternalProject)
#
# FIXME: for now assume that ANDROID means cross-compiling.
# Technically this is not quite true when running on Android itself.
#
# As a work-around, a user may set an empty AUTOTOOLS_HOST to disable this.
#
if (ANDROID AND NOT DEFINED AUTOTOOLS_HOST)
# see: https://developer.android.com/ndk/guides/other_build_systems
set(AUTOTOOLS_HOST "")
if ("${CMAKE_ANDROID_ARCH}" STREQUAL "arm")
# note: this is the binutils name, armv7a-linux-androideabi is the name for clang
set(AUTOTOOLS_HOST "arm-linux-androideabi")
elseif ("${CMAKE_ANDROID_ARCH}" STREQUAL "arm64")
set(AUTOTOOLS_HOST "aarch64-linux-android")
elseif("${CMAKE_ANDROID_ARCH}" STREQUAL "x86")
set(AUTOTOOLS_HOST "i686-linux-android")
# not sure which will be passed, accept both
elseif("${CMAKE_ANDROID_ARCH}" STREQUAL "x86_64" OR "${CMAKE_ANDROID_ARCH}" STREQUAL "x86-64")
set(AUTOTOOLS_HOST "x86_64-linux-android")
else()
message(FATAL_ERROR "Building for Android but got an unknown/undefined/unsupported Android architecture (ANDROID_ARCH): '${ANDROID_ARCH}'")
endif()
endif()
if (AUTOTOOLS_HOST)
set(AUTOTOOLS_HOST_OPTION "--host=${AUTOTOOLS_HOST}")
else()
set(AUTOTOOLS_HOST_OPTION "")
endif()
set(sodium_LIBRARY_PATH "lib/libsodium.so")
set(sodium_INCLUDE_PATH "include")
#
# Use a wrapper script for Android to pre-populate the environment with necessary environment variables.
# This ensures the right toolchain will be picked up by the autotools build system.
#
set(ENV_WRAPPER "")
if (ANDROID)
set(ENV_WRAPPER "${CMAKE_BINARY_DIR}/android/android-export.sh")
endif()
#
# Make gets confused if there is another make process somewhere in the process tree above it. This prevents it from
# doing parallel make with the "jobserver is unavailable" warning instead of assuming it is an actual top-level make
# process as it were.
#
# The work-around is to use $(MAKE), but that doesn't work if the parent process is not itself a make (e.g. ninja).
# So the work-around for that is to use a wrapper script by default that does the right thing, except when CMake is
# configured to use the Unix Makefiles generator in which case $(MAKE) should be used instead.
#
set(MAKE_SH "${CMAKE_SOURCE_DIR}/cmake/external/make.sh")
if ("${CMAKE_GENERATOR}" STREQUAL "Unix Makefiles")
set(MAKE_SH "$(MAKE)")
endif()
set(CONFIGURE_SH "${CMAKE_SOURCE_DIR}/cmake/external/configure-autotools.sh" "${AUTOTOOLS_HOST_OPTION}" "--prefix=<INSTALL_DIR>")
#
# Unfortunately CMake generates a build system (make/ninja) which does not check whether the library already exists.
# This causes the external project to be fully rebuilt always. In turn, that triggers a rebuild of everything from
# the external project upwards as well because the library file has changed.
#
# CHECK_SH is a prefix/wrapper for actual commands that short-circuits the build if the library already exists.
#
set(CHECK_SH test -e "<INSTALL_DIR>/${sodium_LIBRARY_PATH}" ||)
externalProject_add(
ext_libsodium
PREFIX "${CMAKE_BINARY_DIR}/external"
GIT_REPOSITORY https://github.com/jedisct1/libsodium.git
GIT_TAG 1.0.18 # ${sodium_VERSION_STRING}
GIT_SHALLOW ON
GIT_PROGRESS ON
CONFIGURE_COMMAND ${CHECK_SH} ${ENV_WRAPPER} ${CONFIGURE_SH}
BUILD_COMMAND ${CHECK_SH} ${ENV_WRAPPER} ${MAKE_SH}
BUILD_IN_SOURCE ON
BUILD_ALWAYS OFF
INSTALL_COMMAND ${CHECK_SH} ${ENV_WRAPPER} ${MAKE_SH} install
# register the lib manually, otherwise cmake gets very confused about depending on this file
BUILD_BYPRODUCTS <INSTALL_DIR>/${sodium_LIBRARY_PATH}
)
add_library(sodium SHARED IMPORTED)
externalProject_get_property(ext_libsodium INSTALL_DIR)
#
# INTERFACE_INCLUDE_DIRECTORIES cannot take a non-existent directory. However, nearly everything external projects do
# is done *after* cmake configure stage is over, so the directory simply won't be there.
#
# Apply the popular work-around and create it up front.
#
file(MAKE_DIRECTORY "${INSTALL_DIR}/${sodium_INCLUDE_PATH}")
set_target_properties(sodium PROPERTIES IMPORTED_LOCATION "${INSTALL_DIR}/${sodium_LIBRARY_PATH}" INTERFACE_INCLUDE_DIRECTORIES "${INSTALL_DIR}/${sodium_INCLUDE_PATH}")
add_dependencies(secrets_lib ext_libsodium)
endif()
target_link_libraries(secrets_lib Qt5::Core sodium base32_lib)