Skip to content

Commit

Permalink
enable on-device builds
Browse files Browse the repository at this point in the history
Partial compatibility for on-device builds.

There is no guarantee that it will be possible to build all available
packages and built packages will have same reliability that cross-compiled
but should solve "self-hosting" problems as much as possible.
  • Loading branch information
Leonid Plyushch committed Aug 6, 2019
1 parent 5f36563 commit 63441cc
Show file tree
Hide file tree
Showing 15 changed files with 238 additions and 104 deletions.
5 changes: 5 additions & 0 deletions build-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

set -e -u -o pipefail

if [ "$(uname -o)" = "Android" ] || [ -e "/system/bin/app_process" ]; then
echo "On-device execution of this script is not supported."
exit 1
fi

# Read settings from .termuxrc if existing
test -f $HOME/.termuxrc && . $HOME/.termuxrc
: ${TERMUX_TOPDIR:="$HOME/.termux-build"}
Expand Down
48 changes: 36 additions & 12 deletions build-package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@

set -e -o pipefail -u

# Utility function to log an error message and exit with an error code.
source scripts/build/termux_error_exit.sh

if [ "$(uname -o)" = Android ]; then
termux_error_exit "On-device builds are not supported - see README.md"
: "${TMPDIR:=/tmp}"
export TMPDIR

if [ "$(uname -o)" = "Android" ] || [ -e "/system/bin/app_process" ]; then
if [ "$(id -u)" = "0" ]; then
echo "On-device execution of this script as root is disabled."
exit 1
fi
export TERMUX_ON_DEVICE_BUILD=true
else
export TERMUX_ON_DEVICE_BUILD=
fi

# Lock file to prevent parallel running in the same environment.
TERMUX_BUILD_LOCK_FILE="/tmp/.termux-build.lck"
TERMUX_BUILD_LOCK_FILE="${TMPDIR}/.termux-build.lck"
if [ ! -e "$TERMUX_BUILD_LOCK_FILE" ]; then
touch "$TERMUX_BUILD_LOCK_FILE"
fi
Expand All @@ -20,6 +26,9 @@ fi
# lock file.
: "${TERMUX_BUILD_IGNORE_LOCK:=false}"

# Utility function to log an error message and exit with an error code.
source scripts/build/termux_error_exit.sh

# Utility function to download a resource with an expected checksum.
source scripts/build/termux_download.sh

Expand Down Expand Up @@ -151,13 +160,16 @@ source scripts/build/termux_step_finish_build.sh
################################################################################

_show_usage() {
echo "Usage: ./build-package.sh [-a ARCH] [-d] [-D] [-f] [-i] [-I] [-q] [-s] [-o DIR] PACKAGE_1 PACKAGE_2 ..."
echo "Usage: ./build-package.sh [options] PACKAGE_1 PACKAGE_2 ..."
echo
echo "Build a package by creating a .deb file in the debs/ folder."
echo " -a The architecture to build for: aarch64(default), arm, i686, x86_64 or all."
echo
echo "Available options:"
[ -z "$TERMUX_ON_DEVICE_BUILD" ] && echo " -a The architecture to build for: aarch64(default), arm, i686, x86_64 or all."
echo " -d Build with debug symbols."
echo " -D Build a disabled package in disabled-packages/."
echo " -f Force build even if package has already been built."
echo " -i Download and extract dependencies instead of building them."
[ -z "$TERMUX_ON_DEVICE_BUILD" ] && echo " -i Download and extract dependencies instead of building them."
echo " -I Download and extract dependencies instead of building them, keep existing /data/data/com.termux files."
echo " -q Quiet build."
echo " -s Skip dependency check."
Expand All @@ -167,12 +179,24 @@ _show_usage() {

while getopts :a:hdDfiIqso: option; do
case "$option" in
a) TERMUX_ARCH="$OPTARG";;
a)
if [ -n "$TERMUX_ON_DEVICE_BUILD" ]; then
termux_error_exit "./build-package.sh: option '-a' is not available for on-device builds"
else
TERMUX_ARCH="$OPTARG"
fi
;;
h) _show_usage;;
d) export TERMUX_DEBUG=true;;
D) local TERMUX_IS_DISABLED=true;;
f) TERMUX_FORCE_BUILD=true;;
i) export TERMUX_INSTALL_DEPS=true;;
i)
if [ -n "$TERMUX_ON_DEVICE_BUILD" ]; then
termux_error_exit "./build-package.sh: option '-i' is not available for on-device builds"
else
export TERMUX_INSTALL_DEPS=true
fi
;;
I) export TERMUX_INSTALL_DEPS=true && export TERMUX_NO_CLEAN=true;;
q) export TERMUX_QUIET_BUILD=true;;
s) export TERMUX_SKIP_DEPCHECK=true;;
Expand All @@ -197,7 +221,7 @@ while (($# > 0)); do
fi

# Handle 'all' arch:
if [ -n "${TERMUX_ARCH+x}" ] && [ "${TERMUX_ARCH}" = 'all' ]; then
if [ -z "$TERMUX_ON_DEVICE_BUILD" ] && [ -n "${TERMUX_ARCH+x}" ] && [ "${TERMUX_ARCH}" = 'all' ]; then
for arch in 'aarch64' 'arm' 'i686' 'x86_64'; do
TERMUX_BUILD_IGNORE_LOCK=true ./build-package.sh ${TERMUX_FORCE_BUILD+-f} \
-a $arch ${TERMUX_INSTALL_DEPS+-i} ${TERMUX_IS_DISABLED+-D} ${TERMUX_DEBUG+-d} \
Expand Down
31 changes: 25 additions & 6 deletions clean.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,26 @@
# clean.sh - clean everything.
set -e -u

# Read settings from .termuxrc if existing
test -f $HOME/.termuxrc && . $HOME/.termuxrc
: ${TERMUX_TOPDIR:="$HOME/.termux-build"}
# Checking if script is running on Android with 2 different methods.
# Needed for safety to prevent execution of potentially dangerous
# operations such as 'rm -rf /data/*' on Android device.
if [ "$(uname -o)" = "Android" ] || [ -e "/system/bin/app_process" ]; then
export TERMUX_ON_DEVICE_BUILD=true
fi

if [ "$(id -u)" = "0" ] && [ -n "$TERMUX_ON_DEVICE_BUILD" ]; then
echo "On-device execution of this script as root is disabled."
exit 1
fi

# Read settings from .termuxrc if existing
test -f "$HOME/.termuxrc" && . "$HOME/.termuxrc"
: "${TERMUX_TOPDIR:="$HOME/.termux-build"}"
: "${TMPDIR:=/tmp}"
export TMPDIR

# Lock file. Same as used in build-package.sh.
TERMUX_BUILD_LOCK_FILE="/tmp/.termux-build.lck"
TERMUX_BUILD_LOCK_FILE="${TMPDIR}/.termux-build.lck"
if [ ! -e "$TERMUX_BUILD_LOCK_FILE" ]; then
touch "$TERMUX_BUILD_LOCK_FILE"
fi
Expand All @@ -20,7 +33,13 @@ fi
fi

if [ -d "$TERMUX_TOPDIR" ]; then
chmod +w -R $TERMUX_TOPDIR
chmod +w -R "$TERMUX_TOPDIR"
fi

if [ -n "$TERMUX_ON_DEVICE_BUILD" ]; then
# For on-device build cleanup /data shouldn't be erased.
rm -Rf "$TERMUX_TOPDIR"
else
rm -Rf /data/* "$TERMUX_TOPDIR"
fi
rm -Rf /data/* $TERMUX_TOPDIR
} 5< "$TERMUX_BUILD_LOCK_FILE"
28 changes: 20 additions & 8 deletions scripts/build/configure/termux_step_configure_cmake.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,25 @@ termux_step_configure_cmake() {
else
MAKE_PROGRAM_PATH=$(which make)
fi
CFLAGS+=" --target=$CCTERMUX_HOST_PLATFORM -fno-addrsig"
CXXFLAGS+=" --target=$CCTERMUX_HOST_PLATFORM -fno-addrsig"
LDFLAGS+=" --target=$CCTERMUX_HOST_PLATFORM"

CXXFLAGS+=" -fno-addrsig"
CFLAGS+=" -fno-addrsig"

local CMAKE_ADDITIONAL_ARGS=()
if [ -z "$TERMUX_ON_DEVICE_BUILD" ]; then
CXXFLAGS+=" --target=$CCTERMUX_HOST_PLATFORM"
CFLAGS+=" --target=$CCTERMUX_HOST_PLATFORM"
LDFLAGS+=" --target=$CCTERMUX_HOST_PLATFORM"

CMAKE_ADDITIONAL_ARGS+=("-DCMAKE_CROSSCOMPILING=True")
CMAKE_ADDITIONAL_ARGS+=("-DCMAKE_LINKER=$TERMUX_STANDALONE_TOOLCHAIN/bin/$LD $LDFLAGS")
CMAKE_ADDITIONAL_ARGS+=("-DCMAKE_SYSTEM_NAME=Android")
CMAKE_ADDITIONAL_ARGS+=("-DCMAKE_SYSTEM_VERSION=$TERMUX_PKG_API_LEVEL")
CMAKE_ADDITIONAL_ARGS+=("-DCMAKE_SYSTEM_PROCESSOR=$CMAKE_PROC")
else
CMAKE_ADDITIONAL_ARGS+=("-DCMAKE_LINKER=$(which $LD) $LDFLAGS")
TOOLCHAIN_ARGS=""
fi

# XXX: CMAKE_{AR,RANLIB} needed for at least jsoncpp build to not
# pick up cross compiled binutils tool in $PREFIX/bin:
Expand All @@ -25,22 +41,18 @@ termux_step_configure_cmake() {
-DCMAKE_UNAME="$(which uname)" \
-DCMAKE_RANLIB="$(which $RANLIB)" \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_CROSSCOMPILING=True \
-DCMAKE_C_FLAGS="$CFLAGS $CPPFLAGS" \
-DCMAKE_CXX_FLAGS="$CXXFLAGS $CPPFLAGS" \
-DCMAKE_LINKER="$TERMUX_STANDALONE_TOOLCHAIN/bin/$LD $LDFLAGS" \
-DCMAKE_FIND_ROOT_PATH=$TERMUX_PREFIX \
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
-DCMAKE_INSTALL_PREFIX=$TERMUX_PREFIX \
-DCMAKE_MAKE_PROGRAM=$MAKE_PROGRAM_PATH \
-DCMAKE_SYSTEM_PROCESSOR=$CMAKE_PROC \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=$TERMUX_PKG_API_LEVEL \
-DCMAKE_SKIP_INSTALL_RPATH=ON \
-DCMAKE_USE_SYSTEM_LIBRARIES=True \
-DDOXYGEN_EXECUTABLE= \
-DBUILD_TESTING=OFF \
"${CMAKE_ADDITIONAL_ARGS[@]}" \
$TERMUX_PKG_EXTRA_CONFIGURE_ARGS $TOOLCHAIN_ARGS
}
23 changes: 16 additions & 7 deletions scripts/build/setup/termux_setup_cmake.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,24 @@ termux_setup_cmake() {
local TERMUX_CMAKE_TARNAME=cmake-${TERMUX_CMAKE_VERSION}-Linux-x86_64.tar.gz
local TERMUX_CMAKE_TARFILE=$TERMUX_PKG_TMPDIR/$TERMUX_CMAKE_TARNAME
local TERMUX_CMAKE_FOLDER=$TERMUX_COMMON_CACHEDIR/cmake-$TERMUX_CMAKE_VERSION
if [ ! -d "$TERMUX_CMAKE_FOLDER" ]; then
termux_download https://cmake.org/files/v$TERMUX_CMAKE_MAJORVESION/$TERMUX_CMAKE_TARNAME \

if [ -z "$TERMUX_ON_DEVICE_BUILD" ]; then
if [ ! -d "$TERMUX_CMAKE_FOLDER" ]; then
termux_download https://cmake.org/files/v$TERMUX_CMAKE_MAJORVESION/$TERMUX_CMAKE_TARNAME \
"$TERMUX_CMAKE_TARFILE" \
757e7ddd29d11422334a60d7cd9c19b7af20349a03cb15aa3c879f1b54193c95
rm -Rf "$TERMUX_PKG_TMPDIR/cmake-${TERMUX_CMAKE_VERSION}-Linux-x86_64"
tar xf "$TERMUX_CMAKE_TARFILE" -C "$TERMUX_PKG_TMPDIR"
mv "$TERMUX_PKG_TMPDIR/cmake-${TERMUX_CMAKE_VERSION}-Linux-x86_64" \
"$TERMUX_CMAKE_FOLDER"
rm -Rf "$TERMUX_PKG_TMPDIR/cmake-${TERMUX_CMAKE_VERSION}-Linux-x86_64"
tar xf "$TERMUX_CMAKE_TARFILE" -C "$TERMUX_PKG_TMPDIR"
mv "$TERMUX_PKG_TMPDIR/cmake-${TERMUX_CMAKE_VERSION}-Linux-x86_64" \
"$TERMUX_CMAKE_FOLDER"
fi

export PATH=$TERMUX_CMAKE_FOLDER/bin:$PATH
else
# For on-device builds don't care about which version of cmake is installed.
# In most cases it should be suitable.
apt install -yq cmake
fi
export PATH=$TERMUX_CMAKE_FOLDER/bin:$PATH

export CMAKE_INSTALL_ALWAYS=1
}
30 changes: 18 additions & 12 deletions scripts/build/setup/termux_setup_golang.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,26 @@ termux_setup_golang() {
termux_error_exit "Unsupported arch: $TERMUX_ARCH"
fi

local TERMUX_GO_VERSION=go1.12.7
local TERMUX_GO_PLATFORM=linux-amd64
if [ -z "$TERMUX_ON_DEVICE_BUILD" ]; then
local TERMUX_GO_VERSION=go1.12.7
local TERMUX_GO_PLATFORM=linux-amd64

local TERMUX_BUILDGO_FOLDER=$TERMUX_COMMON_CACHEDIR/${TERMUX_GO_VERSION}
export GOROOT=$TERMUX_BUILDGO_FOLDER
export PATH=$GOROOT/bin:$PATH
local TERMUX_BUILDGO_FOLDER=$TERMUX_COMMON_CACHEDIR/${TERMUX_GO_VERSION}
export GOROOT=$TERMUX_BUILDGO_FOLDER
export PATH=$GOROOT/bin:$PATH

if [ -d "$TERMUX_BUILDGO_FOLDER" ]; then return; fi
if [ -d "$TERMUX_BUILDGO_FOLDER" ]; then return; fi

local TERMUX_BUILDGO_TAR=$TERMUX_COMMON_CACHEDIR/${TERMUX_GO_VERSION}.${TERMUX_GO_PLATFORM}.tar.gz
rm -Rf "$TERMUX_COMMON_CACHEDIR/go" "$TERMUX_BUILDGO_FOLDER"
termux_download https://storage.googleapis.com/golang/${TERMUX_GO_VERSION}.${TERMUX_GO_PLATFORM}.tar.gz \
"$TERMUX_BUILDGO_TAR" \
66d83bfb5a9ede000e33c6579a91a29e6b101829ad41fffb5c5bb6c900e109d9
local TERMUX_BUILDGO_TAR=$TERMUX_COMMON_CACHEDIR/${TERMUX_GO_VERSION}.${TERMUX_GO_PLATFORM}.tar.gz
rm -Rf "$TERMUX_COMMON_CACHEDIR/go" "$TERMUX_BUILDGO_FOLDER"
termux_download https://storage.googleapis.com/golang/${TERMUX_GO_VERSION}.${TERMUX_GO_PLATFORM}.tar.gz \
"$TERMUX_BUILDGO_TAR" \
66d83bfb5a9ede000e33c6579a91a29e6b101829ad41fffb5c5bb6c900e109d9

( cd "$TERMUX_COMMON_CACHEDIR"; tar xf "$TERMUX_BUILDGO_TAR"; mv go "$TERMUX_BUILDGO_FOLDER"; rm "$TERMUX_BUILDGO_TAR" )
( cd "$TERMUX_COMMON_CACHEDIR"; tar xf "$TERMUX_BUILDGO_TAR"; mv go "$TERMUX_BUILDGO_FOLDER"; rm "$TERMUX_BUILDGO_TAR" )
else
# For on-device builds don't care about which version of cmake is installed.
# In most cases it should be suitable.
apt install -yq golang
fi
}
25 changes: 16 additions & 9 deletions scripts/build/setup/termux_setup_ninja.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
termux_setup_ninja() {
local NINJA_VERSION=1.9.0
local NINJA_FOLDER=$TERMUX_COMMON_CACHEDIR/ninja-$NINJA_VERSION
if [ ! -x "$NINJA_FOLDER/ninja" ]; then
mkdir -p "$NINJA_FOLDER"
local NINJA_ZIP_FILE=$TERMUX_PKG_TMPDIR/ninja-$NINJA_VERSION.zip
termux_download https://github.com/ninja-build/ninja/releases/download/v$NINJA_VERSION/ninja-linux.zip \
"$NINJA_ZIP_FILE" \
1b1235f2b0b4df55ac6d80bbe681ea3639c9d2c505c7ff2159a3daf63d196305
unzip "$NINJA_ZIP_FILE" -d "$NINJA_FOLDER"
chmod 755 $NINJA_FOLDER/ninja

if [ -z "$TERMUX_ON_DEVICE_BUILD" ]; then
if [ ! -x "$NINJA_FOLDER/ninja" ]; then
mkdir -p "$NINJA_FOLDER"
local NINJA_ZIP_FILE=$TERMUX_PKG_TMPDIR/ninja-$NINJA_VERSION.zip
termux_download https://github.com/ninja-build/ninja/releases/download/v$NINJA_VERSION/ninja-linux.zip \
"$NINJA_ZIP_FILE" \
1b1235f2b0b4df55ac6d80bbe681ea3639c9d2c505c7ff2159a3daf63d196305
unzip "$NINJA_ZIP_FILE" -d "$NINJA_FOLDER"
chmod 755 $NINJA_FOLDER/ninja
fi
export PATH=$NINJA_FOLDER:$PATH
else
# For on-device builds don't care about which version of cmake is installed.
# In most cases it should be suitable.
apt install -yq ninja
fi
export PATH=$NINJA_FOLDER:$PATH
}
8 changes: 8 additions & 0 deletions scripts/build/termux_download_deb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@ termux_download_deb() {
local PACKAGE=$1
local PACKAGE_ARCH=$2
local VERSION=$3

if [ -n "$TERMUX_ON_DEVICE_BUILD" ]; then
apt install -y "${PACKAGE}=${VERSION}"
return "$?"
fi

local DEB_FILE=${PACKAGE}_${VERSION}_${PACKAGE_ARCH}.deb
PKG_HASH=""

for idx in $(seq ${#TERMUX_REPO_URL[@]}); do
local TERMUX_REPO_NAME=$(echo ${TERMUX_REPO_URL[$idx-1]} | sed -e 's%https://%%g' -e 's%http://%%g' -e 's%/%-%g')
local PACKAGE_FILE_PATH="${TERMUX_REPO_NAME}-${TERMUX_REPO_DISTRIBUTION[$idx-1]}-${TERMUX_REPO_COMPONENT[$idx-1]}-Packages"
Expand All @@ -17,6 +24,7 @@ termux_download_deb() {
fi
fi
done

if [ "$PKG_HASH" = "" ]; then
return 1
else
Expand Down
4 changes: 4 additions & 0 deletions scripts/build/termux_get_repo_files.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
termux_get_repo_files() {
# Not needed for on-device builds.
[ -n "$TERMUX_ON_DEVICE_BUILD" ] && return

# Ensure folders present (but not $TERMUX_PKG_SRCDIR, it will be created in build)
mkdir -p "$TERMUX_COMMON_CACHEDIR" \
"$TERMUX_COMMON_CACHEDIR-$TERMUX_ARCH" \
Expand All @@ -10,6 +13,7 @@ termux_get_repo_files() {
"$TERMUX_PKG_CACHEDIR" \
"$TERMUX_PKG_MASSAGEDIR" \
$TERMUX_PREFIX/{bin,etc,lib,libexec,share,tmp,include}

if [ "$TERMUX_INSTALL_DEPS" = true ]; then
if [ "$TERMUX_NO_CLEAN" = false ]; then
# Remove all previously extracted/built files from $TERMUX_PREFIX:
Expand Down
13 changes: 11 additions & 2 deletions scripts/build/termux_step_finish_build.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
termux_step_finish_build() {
echo "termux - build of '$TERMUX_PKG_NAME' done"
test -t 1 && printf "\033]0;%s - DONE\007" "$TERMUX_PKG_NAME"
mkdir -p /data/data/.built-packages
echo "$TERMUX_PKG_FULLVERSION" > "/data/data/.built-packages/$TERMUX_PKG_NAME"

if [ -n "$TERMUX_ON_DEVICE_BUILD" ]; then
# For on-device builds cross-compiling is not supported so we can
# store information about built packages under $TERMUX_TOPDIR.
mkdir -p "$TERMUX_TOPDIR/.built-packages"
echo "$TERMUX_PKG_FULLVERSION" > "$TERMUX_TOPDIR/.built-packages/$TERMUX_PKG_NAME"
else
mkdir -p /data/data/.built-packages
echo "$TERMUX_PKG_FULLVERSION" > "/data/data/.built-packages/$TERMUX_PKG_NAME"
fi

exit 0
}
2 changes: 2 additions & 0 deletions scripts/build/termux_step_handle_buildarch.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
termux_step_handle_buildarch() {
[ -n "$TERMUX_ON_DEVICE_BUILD" ] && return

# If $TERMUX_PREFIX already exists, it may have been built for a different arch
local TERMUX_ARCH_FILE=/data/TERMUX_ARCH
if [ -f "${TERMUX_ARCH_FILE}" ]; then
Expand Down
Loading

0 comments on commit 63441cc

Please sign in to comment.