buildboostandroid_windows

#!/bin/bash

# Usage:
# On Windows, run a git bash shell
#     /c/cedanet/repos/ceda-core/android/buildboostandroid_windows 1 69 0 $HOME/AppData/Local/Android/Sdk/ndk-bundle C:/cedanet/boost-android

# Script arguments:
# $1: <major> representing the major boost version number to install
# $2: <minor> representing the minor boost version number to install
# $3: <patch> representing the patch boost version number to install
# $4: <ndk> representing the path to the NDK e.g. $HOME/AppData/Local/Android/Sdk/ndk-bundle
# $5: <prefix> location where to create build/install stuff

# As at Feb 2019, current version of boost is 1.69.0, and Android NDK version is r19
# The Android Native Development Kit (NDK) is a toolset that allows you to use C and C++ code with Android.
# This is installed at location:  $HOME/AppData/Local/Android/Sdk/ndk-bundle
# As of ndk 16 the Android NDK no longer supports gcc, so we will only use clang and libc++

# This script does the following:
#  - creates the folder C:/cedanet/boost-android
#  - downloads the tarball to a file C:/cedanet/boost-android/boost_1_68_0.tar.bz2
#  - uncompresses the tarball to a directory C:/cedanet/boost-android/boost_1_68_0
#  - copies the directory C:/cedanet/boost-android/boost_1_68_0 to C:/cedanet/boost-android/1_68_0
#  - builds the boost libraries for arm64-v8a where:
#    -  the intermediate files are written to C:/cedanet/boost-android/build/arm64-v8a
#    -  the generated headers are written to C:/cedanet/boost-android/install/arm64-v8a/include
#    -  stdout is written to C:/cedanet/boost-android/out.txt
#    -  stderr is written to C:/cedanet/boost-android/err.txt
#    -  the generated libraries (both static .a and shared .so) are written to C:/cedanet/boost-android/install/arm64-v8a/lib

# PREFIX=C:/cedanet/boost-android
# BOOSTDIR1=boost_1_68_0
# BOOSTDIR2=1.68.0
# TARNAME=boost_1_68_0.tar.bz2
# BOOSTDOWNLOAD=http://sourceforge.net/projects/boost/files/boost/1.68.0/boost_1_68_0.tar.bz2/download
# BUILD_DIR=C:/cedanet/boost-android/build/arm64-v8a
# INSTALL_DIR=C:/cedanet/boost-android/install/arm64-v8a
# REL_TOOLCHAIN=android-tool-chain/arm64-v8a
# ABS_TOOLCHAIN=C:/cedanet/boost/android-tool-chain/arm64-v8a

SAVE=`pwd`

# boost major version number, typically 1
MAJOR=$1

# boost minor version number, e.g. 68 
MINOR=$2

# boost patch number, typically a low number, often 0
PATCH=$3

# $NDK is the installation root for the Android NDK
# After Android Studio is installed we assume the Android NDK is located here
# E.g. C:/Users/David/AppData/Local/Android/sdk/ndk-bundle (windows)
#      ~/Android/Sdk/ndk-bundle (linux)
NDK=$4

# Location where to output stuff
# E.g. C:/cedanet/boost-android
PREFIX=$5

# Directory where to unzip the tarball
BOOSTDIR1=boost_${MAJOR}_${MINOR}_${PATCH}

# Directory where to copy from BOOSTDIR1, and having some subsequent changes
BOOSTDIR2=${MAJOR}.${MINOR}.${PATCH}

TARNAME=boost_${MAJOR}_${MINOR}_${PATCH}.tar.bz2
BOOSTDOWNLOAD="http://sourceforge.net/projects/boost/files/boost/${BOOSTDIR2}/${TARNAME}/download"

BUILD_DIR=${PREFIX}/build/arm64-v8a
INSTALL_DIR=${PREFIX}/install/arm64-v8a

# Path to Android toolchain (i.e. android compilers etc), relative to ${PREFIX}
REL_TOOLCHAIN=android-tool-chain/arm64-v8a

ABS_TOOLCHAIN=${PREFIX}/${REL_TOOLCHAIN}

echo "NDK=$NDK"
echo "PREFIX=$PREFIX"
echo "BOOSTDIR1=$BOOSTDIR1"
echo "BOOSTDIR2=$BOOSTDIR2"
echo "TARNAME=$TARNAME"
echo "BOOSTDOWNLOAD=$BOOSTDOWNLOAD"
echo "BUILD_DIR=$BUILD_DIR"
echo "INSTALL_DIR=$INSTALL_DIR"
echo "REL_TOOLCHAIN=$REL_TOOLCHAIN"
echo "ABS_TOOLCHAIN=$ABS_TOOLCHAIN"

mkdir -p ${PREFIX}
cd ${PREFIX}

if [ -d ${BUILD_DIR} ]; then
    echo folder ${BUILD_DIR} already exists, if you want a clean build delete this folder and run the script again
fi

if [ -d ${INSTALL_DIR} ]; then
    echo folder ${INSTALL_DIR} already exists, if you want a clean build delete this folder and run the script again
fi

if [ -e ${TARNAME} ]; then
    echo ${TARNAME} already exists, no need to download from ${BOOSTDOWNLOAD}
else
    echo Downloading ${TARNAME}
    #wget -c "$BOOSTDOWNLOAD" -O ${TARNAME}
    curl -L -o ${TARNAME} "$BOOSTDOWNLOAD"
fi

if [ -d ${BOOSTDIR1} ]; then
    echo folder ${BOOSTDIR1} already exists, no need to uncompress tarball ${TARNAME}
else
    echo uncompressing tarball
    tar --bzip2 -xf ${TARNAME}
fi

if [ -d ${BOOSTDIR2} ]; then
    echo folder ${BOOSTDIR2} already exists, no need to copy from ${BOOSTDIR1}
else
    echo copying ${BOOSTDIR1} to ${BOOSTDIR2}
    cp -R ${BOOSTDIR1} ${BOOSTDIR2}
fi

# Creating the toolchain
# See: https://developer.android.com/ndk/guides/standalone_toolchain
# The NDK provides the make_standalone_toolchain.py script to allow you to perform a customized toolchain installation 
# from the command line.
# On Linux we have used the prebuilt toolchain, but on Windows it inexplicably gives errors saying it can't recognise the invocation of 
# aarch64-linux-android-clang++ as a program, when running this bash script from git bash.
# Creating a standalone toolchain avoids the issue.
if [ -d ${ABS_TOOLCHAIN} ]; then
    echo folder ${ABS_TOOLCHAIN} already exists, no need to use make_standalone_toolchain.py to create standalone toolchain.
else
    # Create a standalone toolchain for arm64-v8a as described in https://developer.android.com/ndk/guides/standalone_toolchain.html
    # arm64 implies arm64-v8a.
    # The install dir is relative to the current directory - i.e. so it is ${PREFIX}/android-tool-chain/arm64-v8a, these folders are created automatically
    echo creating toolchain ${ABS_TOOLCHAIN}
    $NDK/build/tools/make_standalone_toolchain.py --arch arm64 --install-dir=$REL_TOOLCHAIN
fi

# Add the standalone toolchain to the search path.
export PATH=${ABS_TOOLCHAIN}/bin:$PATH
echo "PATH=$PATH"
echo

cd ${BOOSTDIR2}

# This is what was done in the "Boost for Android" project on GitHub. https://github.com/dec1/Boost-for-Android
# However that appears to be causing problems here (not how we exclude building the graph_parallel and mpi libraries)
echo "" > user-config.jam
#echo "using mpi ;" > user-config.jam

# Compilers:
#    arm64v8a    : aarch64-linux-android21-clang++
#    armeabiv7a  : armv7a-linux-androideabi16-clang++
#    x86         : i686-linux-android16-clang++
#    x8664       : x86_64-linux-android21-clang++

echo "using clang" >> user-config.jam
echo "    : arm64" >> user-config.jam 
echo "    : ${ABS_TOOLCHAIN}/bin/aarch64-linux-android-clang++" >> user-config.jam 
echo "    : <ranlib>${ABS_TOOLCHAIN}/bin/aarch64-linux-android-ranlib.exe" >> user-config.jam
echo "      <archiver>${ABS_TOOLCHAIN}/bin/llvm-ar.exe" >> user-config.jam 
echo "      <compileflags>-fPIC" >> user-config.jam
echo "      <compileflags>-fexceptions" >> user-config.jam
echo "      <compileflags>-frtti" >> user-config.jam
echo "      <cxxflags>-std=c++17" >> user-config.jam
echo "      ;" >> user-config.jam

#echo "      <cflags>-fPIE" >> user-config.jam
#echo "      <compileflags>-fPIC" >> user-config.jam
#echo "      <compileflags>-ffunction-sections" >> user-config.jam
#echo "      <compileflags>-fdata-sections" >> user-config.jam
#echo "      <compileflags>-funwind-tables" >> user-config.jam
#echo "      <compileflags>-fstack-protector-strong" >> user-config.jam
#echo "      <compileflags>-no-canonical-prefixes" >> user-config.jam
#echo "      <compileflags>-Wno-unused-variable" >> user-config.jam
#echo "      <compileflags>-Wformat" >> user-config.jam
#echo "      <compileflags>-Werror=format-security" >> user-config.jam
#echo "      <compileflags>-frtti" >> user-config.jam
#echo "      <compileflags>-fexceptions" >> user-config.jam
#echo "      <compileflags>-DNDEBUG" >> user-config.jam
#echo "      <compileflags>-g" >> user-config.jam
#echo "      <compileflags>-Oz" >> user-config.jam
#echo "      <cxxflags>-std=c++17" >> user-config.jam
#echo "      <linkflags>-fuse-ld=lld ;" >> user-config.jam

./bootstrap.bat

echo
echo
echo
    
# -d+2   Show commands as they are executed
# -q     Stop at first error
# -j16   Run up to 16 commands concurrently
# -n     Do not execute the commands, only print them.
# -d0    Suppress all informational messages.

# The following libraries cannot be built currently
# --with-graph_parallel \
# --with-mpi \
# --with-python \

# atomic chrono system thread filesystem locale

echo "Building both static and shared boost libraries"
echo "Headers will be installed under ${PREFIX}/install/arm64-v8a/include"
echo "Libraries will be installed under ${PREFIX}/install/arm64-v8a/lib"
echo "Writing stdout to ${PREFIX}/out.txt and stderr to ${PREFIX}/err.txt"
echo "Have patience this takes a long time..."
./b2 -d+2 -q -j16 \
    variant=release \
    link=shared,static \
    runtime-link=shared \
    threading=multi \
    target-os=android \
    toolset=clang-arm64 \
    architecture=arm \
    --user-config=user-config.jam \
    --layout=system \
    --prefix=$INSTALL_DIR \
    --build-dir=$BUILD_DIR \
    --with-atomic \
    --with-chrono \
    --with-system \
    --with-thread \
    --with-filesystem \
    --with-locale \
    install \
    1>${PREFIX}/out.txt 2>${PREFIX}/err.txt

if [ $? -eq 0 ]
then
  echo
  echo "Successfully built boost libraries"
else
  echo
  echo "Error building boost libraries, return code: $?" >&2
fi

cd $SAVE

# Note that in the above call to b2 we only build the release variant:
#       variant=release
# Instead of 
#       variant=debug,release
#
# This is necessary to avoid the following error:
#
#     error: Name clash for '<pC:\cedanet\boost-android\install\arm64-v8a\lib>libboost_atomic.so.1.69.0'
#     error: 
#     error: Tried to build the target twice, with property sets having 
#     error: these incompatible properties:
#     error: 
#     error:     -  <debug-symbols>on <inlining>off <optimization>off <variant>debug
#     error:     -  <debug-symbols>off <define>NDEBUG <inlining>full <optimization>speed <variant>release
#     error: 
#     error: Please make sure to have consistent requirements for these 
#     error: properties everywhere in your project, especially for install
#     error: targets.