enable on-device builds

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.
This commit is contained in:
Leonid Plyushch 2019-08-06 15:39:42 +03:00
parent 5b7f6f41ad
commit aecf4675e3
No known key found for this signature in database
GPG Key ID: 45F2964132545795
21 changed files with 384 additions and 147 deletions

View File

@ -6,8 +6,8 @@
[![Join the chat at https://gitter.im/termux/termux](https://badges.gitter.im/termux/termux.svg)](https://gitter.im/termux/termux)
This project contains scripts and patches to build packages for the
[Termux](https://termux.com/) Android application. Note that packages are
cross-compiled and on-device builds are not currently supported.
[Termux](https://termux.com/) Android application. Note that on-device
package building is supported only partially for now.
More information can be found in the [docs](docs/) directory.

View File

@ -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"}

View File

@ -3,15 +3,26 @@
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
: "${TMPDIR:=/tmp}"
export TMPDIR
if [ "$(uname -o)" = Android ]; then
termux_error_exit "On-device builds are not supported - see README.md"
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_ARCH=$(dpkg --print-architecture)
# This variable tells all parts of build system that build
# is performed on device.
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
@ -20,6 +31,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
@ -151,13 +165,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."
@ -167,12 +184,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
export 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;;
@ -197,11 +226,11 @@ 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} \
${TERMUX_DEBDIR+-o $TERMUX_DEBDIR} "$1"
env TERMUX_ARCH="$arch" TERMUX_BUILD_IGNORE_LOCK=true ./build-package.sh \
${TERMUX_FORCE_BUILD+-f} ${TERMUX_INSTALL_DEPS+-i} ${TERMUX_IS_DISABLED+-D} \
${TERMUX_DEBUG+-d} ${TERMUX_DEBDIR+-o $TERMUX_DEBDIR} "$1"
done
exit
fi

View File

@ -2,13 +2,28 @@
# 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
TERMUX_ON_DEVICE_BUILD=true
else
TERMUX_ON_DEVICE_BUILD=
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
@ -20,7 +35,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"

View File

@ -32,12 +32,14 @@ termux_step_configure_autotools() {
QUIET_BUILD="--enable-silent-rules --silent --quiet"
fi
# Some packages provides a $PKG-config script which some configure scripts pickup instead of pkg-config:
mkdir "$TERMUX_PKG_TMPDIR/config-scripts"
for f in $TERMUX_PREFIX/bin/*config; do
test -f "$f" && cp "$f" "$TERMUX_PKG_TMPDIR/config-scripts"
done
export PATH=$TERMUX_PKG_TMPDIR/config-scripts:$PATH
if [ -z "$TERMUX_ON_DEVICE_BUILD" ]; then
# Some packages provides a $PKG-config script which some configure scripts pickup instead of pkg-config:
mkdir "$TERMUX_PKG_TMPDIR/config-scripts"
for f in $TERMUX_PREFIX/bin/*config; do
test -f "$f" && cp "$f" "$TERMUX_PKG_TMPDIR/config-scripts"
done
export PATH=$TERMUX_PKG_TMPDIR/config-scripts:$PATH
fi
# Avoid gnulib wrapping of functions when cross compiling. See
# http://wiki.osdev.org/Cross-Porting_Software#Gnulib

View File

@ -1,7 +1,6 @@
termux_step_configure_cmake() {
termux_setup_cmake
local TOOLCHAIN_ARGS="-DCMAKE_ANDROID_STANDALONE_TOOLCHAIN=$TERMUX_STANDALONE_TOOLCHAIN"
local BUILD_TYPE=MinSizeRel
test -n "$TERMUX_DEBUG" && BUILD_TYPE=Debug
@ -14,33 +13,45 @@ 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")
CMAKE_ADDITIONAL_ARGS+=("-DCMAKE_ANDROID_STANDALONE_TOOLCHAIN=$TERMUX_STANDALONE_TOOLCHAIN")
else
CMAKE_ADDITIONAL_ARGS+=("-DCMAKE_LINKER=$(which $LD) $LDFLAGS")
fi
# XXX: CMAKE_{AR,RANLIB} needed for at least jsoncpp build to not
# pick up cross compiled binutils tool in $PREFIX/bin:
# pick up cross compiled binutils tool in $TERMUX_PREFIX/bin:
cmake -G "$TERMUX_CMAKE_BUILD" "$TERMUX_PKG_SRCDIR" \
-DCMAKE_AR="$(which $AR)" \
-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 \
$TERMUX_PKG_EXTRA_CONFIGURE_ARGS $TOOLCHAIN_ARGS
"${CMAKE_ADDITIONAL_ARGS[@]}" \
$TERMUX_PKG_EXTRA_CONFIGURE_ARGS
}

View File

@ -5,15 +5,33 @@ 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
if [ "$(dpkg-query -W -f '${db:Status-Status}\n' cmake 2>/dev/null)" != "installed" ]; then
echo "Package 'cmake' is not installed."
echo "You can install it with"
echo
echo " pkg install cmake"
echo
echo "or build it from source with"
echo
echo " ./build-package.sh cmake"
echo
exit 1
fi
fi
export PATH=$TERMUX_CMAKE_FOLDER/bin:$PATH
export CMAKE_INSTALL_ALWAYS=1
}

View File

@ -19,20 +19,35 @@ 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
if [ "$(dpkg-query -W -f '${db:Status-Status}\n' golang 2>/dev/null)" != "installed" ]; then
echo "Package 'golang' is not installed."
echo "You can install it with"
echo
echo " pkg install golang"
echo
echo "or build it from source with"
echo
echo " ./build-package.sh golang"
echo
exit 1
fi
fi
}

View File

@ -1,14 +1,30 @@
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
if [ "$(dpkg-query -W -f '${db:Status-Status}\n' ninja 2>/dev/null)" != "installed" ]; then
echo "Package 'ninja' is not installed."
echo "You can install it with"
echo
echo " pkg install ninja"
echo
echo "or build it from source with"
echo
echo " ./build-package.sh ninja"
echo
exit 1
fi
fi
export PATH=$NINJA_FOLDER:$PATH
}

View File

@ -3,17 +3,32 @@ termux_setup_protobuf() {
local _PROTOBUF_ZIP=protoc-$_PROTOBUF_VERSION-linux-x86_64.zip
local _PROTOBUF_FOLDER=$TERMUX_COMMON_CACHEDIR/protobuf-$_PROTOBUF_VERSION
if [ ! -d "$_PROTOBUF_FOLDER" ]; then
termux_download \
if [ -z "$TERMUX_ON_DEVICE_BUILD" ]; then
if [ ! -d "$_PROTOBUF_FOLDER" ]; then
termux_download \
https://github.com/protocolbuffers/protobuf/releases/download/v$_PROTOBUF_VERSION/$_PROTOBUF_ZIP \
$TERMUX_PKG_TMPDIR/$_PROTOBUF_ZIP \
15e395b648a1a6dda8fd66868824a396e9d3e89bc2c8648e3b9ab9801bea5d55
rm -Rf "$TERMUX_PKG_TMPDIR/protoc-$_PROTOBUF_VERSION-linux-x86_64"
unzip $TERMUX_PKG_TMPDIR/$_PROTOBUF_ZIP -d $TERMUX_PKG_TMPDIR/protobuf-$_PROTOBUF_VERSION
mv "$TERMUX_PKG_TMPDIR/protobuf-$_PROTOBUF_VERSION" \
$_PROTOBUF_FOLDER
fi
rm -Rf "$TERMUX_PKG_TMPDIR/protoc-$_PROTOBUF_VERSION-linux-x86_64"
unzip $TERMUX_PKG_TMPDIR/$_PROTOBUF_ZIP -d $TERMUX_PKG_TMPDIR/protobuf-$_PROTOBUF_VERSION
mv "$TERMUX_PKG_TMPDIR/protobuf-$_PROTOBUF_VERSION" \
$_PROTOBUF_FOLDER
fi
export PATH=$_PROTOBUF_FOLDER/bin/:$PATH
export PATH=$_PROTOBUF_FOLDER/bin/:$PATH
else
if [ "$(dpkg-query -W -f '${db:Status-Status}\n' protobuf 2>/dev/null)" != "installed" ]; then
echo "Package 'protobuf' is not installed."
echo "You can install it with"
echo
echo " pkg install protobuf"
echo
echo "or build it from source with"
echo
echo " ./build-package.sh libprotobuf"
echo
exit 1
fi
fi
}

View File

@ -5,6 +5,25 @@ termux_setup_rust() {
CARGO_TARGET_NAME=$TERMUX_ARCH-linux-android
fi
export RUSTFLAGS="-C link-arg=-Wl,-rpath=$TERMUX_PREFIX/lib -C link-arg=-Wl,--enable-new-dtags"
if [ -n "$TERMUX_ON_DEVICE_BUILD" ]; then
if [ "$(dpkg-query -W -f '${db:Status-Status}\n' rust 2>/dev/null)" != "installed" ]; then
echo "Package 'rust' is not installed."
echo "You can install it with"
echo
echo " pkg install rust"
echo
echo "or build it from source with"
echo
echo " ./build-package.sh rust"
echo
echo "Note that package 'rust' is known to be problematic for building on device."
exit 1
fi
return
fi
local ENV_NAME=CARGO_TARGET_${CARGO_TARGET_NAME^^}_LINKER
ENV_NAME=${ENV_NAME//-/_}
export $ENV_NAME=$CC

View File

@ -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"
@ -17,6 +24,7 @@ termux_download_deb() {
fi
fi
done
if [ "$PKG_HASH" = "" ]; then
return 1
else

View File

@ -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" \
@ -10,11 +13,12 @@ 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:
rm -rf $TERMUX_PREFIX
rm -f /data/data/.built-packages/*
rm -f $TERMUX_BUILT_PACKAGES_DIRECTORY/*
fi
for idx in $(seq ${#TERMUX_REPO_URL[@]}); do

View File

@ -1,7 +1,9 @@
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"
mkdir -p "$TERMUX_BUILT_PACKAGES_DIRECTORY"
echo "$TERMUX_PKG_FULLVERSION" > "$TERMUX_BUILT_PACKAGES_DIRECTORY/$TERMUX_PKG_NAME"
exit 0
}

View File

@ -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

View File

@ -4,37 +4,34 @@ termux_step_massage() {
# Remove lib/charset.alias which is installed by gettext-using packages:
rm -f lib/charset.alias
# Remove non-english man pages:
test -d share/man && (cd share/man; for f in $(ls | grep -v man); do rm -Rf $f; done )
# Remove locale files we're not interested in::
rm -Rf share/locale
# Remove old kept libraries (readline):
find . -name '*.old' -delete
find . -name '*.old' -print0 | xargs -0 -r rm -f
# Move over sbin to bin:
for file in sbin/*; do if test -f "$file"; then mv "$file" bin/; fi; done
# Remove world permissions and add write permissions.
# The -f flag is used to suppress warnings about dangling symlinks (such
# as ones to /system/... which may not exist on the build machine):
find . -exec chmod -f u+w,g-rwx,o-rwx \{\} \;
# Remove world permissions and make sure that user still have read-write permissions.
chmod -Rf u+rw,g-rwx,o-rwx . || true
if [ "$TERMUX_DEBUG" = "" ]; then
# Strip binaries. file(1) may fail for certain unusual files, so disable pipefail.
set +e +o pipefail
find . -type f | xargs -r file | grep -E "(executable|shared object)" | grep ELF | cut -f 1 -d : | \
find bin lib libexec -type f | xargs -r file | grep -E "ELF .+ (executable|shared object)" | cut -f 1 -d : | \
xargs -r "$STRIP" --strip-unneeded --preserve-dates
set -e -o pipefail
fi
# Remove DT_ entries which the android 5.1 linker warns about:
find . -type f -print0 | xargs -r -0 "$TERMUX_ELF_CLEANER"
# Remove entries unsupported by Android's linker:
find bin lib libexec -type f -print0 | xargs -r -0 "$TERMUX_ELF_CLEANER"
# Fix shebang paths:
while IFS= read -r -d '' file
do
head -c 100 "$file" | grep -E "^#\!.*\\/bin\\/.*" | grep -q -E -v "^#\! ?\\/system" && sed --follow-symlinks -i -E "1 s@^#\!(.*)/bin/(.*)@#\!$TERMUX_PREFIX/bin/\2@" "$file"
head -c 100 "$file" | grep -E "^#\!.*\\/bin\\/.*" | grep -q -E -v "^#\! ?\\/system" && \
sed --follow-symlinks -i -E "1 s@^#\!(.*)/bin/(.*)@#\!$TERMUX_PREFIX/bin/\2@" "$file"
done < <(find -L . -type f -print0)
test ! -z "$TERMUX_PKG_RM_AFTER_INSTALL" && rm -Rf $TERMUX_PKG_RM_AFTER_INSTALL
@ -42,6 +39,9 @@ termux_step_massage() {
find . -type d -empty -delete # Remove empty directories
if [ -d share/man ]; then
# Remove non-english man pages:
find share/man -mindepth 1 -maxdepth 1 -type d ! -name man\* | xargs -r rm -rf
# Compress man pages with gzip:
find share/man -type f ! -iname \*.gz -print0 | xargs -r -0 gzip
@ -59,6 +59,4 @@ termux_step_massage() {
# .. remove empty directories (NOTE: keep this last):
find . -type d -empty -delete
# Make sure user can read and write all files (problem with dpkg otherwise):
chmod -R u+rw .
}

View File

@ -1,32 +1,32 @@
termux_step_setup_toolchain() {
export PATH=$TERMUX_STANDALONE_TOOLCHAIN/bin:$PATH
export CFLAGS=""
export LDFLAGS="-L${TERMUX_PREFIX}/lib"
export AS=${TERMUX_HOST_PLATFORM}-clang
export AS=$TERMUX_HOST_PLATFORM-clang
export CC=$TERMUX_HOST_PLATFORM-clang
export CXX=$TERMUX_HOST_PLATFORM-clang++
export CCTERMUX_HOST_PLATFORM=$TERMUX_HOST_PLATFORM$TERMUX_PKG_API_LEVEL
if [ $TERMUX_ARCH = arm ]; then
CCTERMUX_HOST_PLATFORM=armv7a-linux-androideabi$TERMUX_PKG_API_LEVEL
fi
export AR=$TERMUX_HOST_PLATFORM-ar
export CPP=${TERMUX_HOST_PLATFORM}-cpp
export CC_FOR_BUILD=gcc
export CPP=$TERMUX_HOST_PLATFORM-cpp
export LD=$TERMUX_HOST_PLATFORM-ld
export OBJCOPY=$TERMUX_HOST_PLATFORM-objcopy
export OBJDUMP=$TERMUX_HOST_PLATFORM-objdump
# Setup pkg-config for cross-compiling:
export PKG_CONFIG=$TERMUX_STANDALONE_TOOLCHAIN/bin/${TERMUX_HOST_PLATFORM}-pkg-config
export RANLIB=$TERMUX_HOST_PLATFORM-ranlib
export READELF=$TERMUX_HOST_PLATFORM-readelf
export STRIP=$TERMUX_HOST_PLATFORM-strip
# Android 7 started to support DT_RUNPATH (but not DT_RPATH), so we may want
# LDFLAGS+="-Wl,-rpath=$TERMUX_PREFIX/lib -Wl,--enable-new-dtags"
# and no longer remove DT_RUNPATH in termux-elf-cleaner.
if [ -z "$TERMUX_ON_DEVICE_BUILD" ]; then
export PATH=$TERMUX_STANDALONE_TOOLCHAIN/bin:$PATH
export CC_FOR_BUILD=gcc
export PKG_CONFIG=$TERMUX_STANDALONE_TOOLCHAIN/bin/${TERMUX_HOST_PLATFORM}-pkg-config
export CCTERMUX_HOST_PLATFORM=$TERMUX_HOST_PLATFORM$TERMUX_PKG_API_LEVEL
if [ $TERMUX_ARCH = arm ]; then
CCTERMUX_HOST_PLATFORM=armv7a-linux-androideabi$TERMUX_PKG_API_LEVEL
fi
else
# Some build scripts use environment variable 'PKG_CONFIG', so
# using this for on-device builds too.
export PKG_CONFIG=pkg-config
fi
if [ "$TERMUX_ARCH" = "arm" ]; then
# https://developer.android.com/ndk/guides/standalone_toolchain.html#abi_compatibility:
@ -51,6 +51,10 @@ termux_step_setup_toolchain() {
CFLAGS+=" -Oz"
fi
# Android 7 started to support DT_RUNPATH (but not DT_RPATH), so we may want
# LDFLAGS+="-Wl,-rpath=$TERMUX_PREFIX/lib -Wl,--enable-new-dtags"
# and no longer remove DT_RUNPATH in termux-elf-cleaner.
# Basic hardening.
CFLAGS+=" -fstack-protector-strong"
LDFLAGS+=" -Wl,-z,relro,-z,now"
@ -69,7 +73,7 @@ termux_step_setup_toolchain() {
export ac_cv_func_sigsetmask=no
export ac_cv_c_bigendian=no
if [ ! -d $TERMUX_STANDALONE_TOOLCHAIN ]; then
if [ -z "$TERMUX_ON_DEVICE_BUILD" ] && [ ! -d $TERMUX_STANDALONE_TOOLCHAIN ]; then
# Do not put toolchain in place until we are done with setup, to avoid having a half setup
# toolchain left in place if something goes wrong (or process is just aborted):
local _TERMUX_TOOLCHAIN_TMPDIR=${TERMUX_STANDALONE_TOOLCHAIN}-tmp
@ -158,16 +162,19 @@ termux_step_setup_toolchain() {
fi
export PKG_CONFIG_LIBDIR="$TERMUX_PKG_CONFIG_LIBDIR"
# Create a pkg-config wrapper. We use path to host pkg-config to
# avoid picking up a cross-compiled pkg-config later on.
local _HOST_PKGCONFIG
_HOST_PKGCONFIG=$(which pkg-config)
mkdir -p $TERMUX_STANDALONE_TOOLCHAIN/bin "$PKG_CONFIG_LIBDIR"
cat > "$PKG_CONFIG" <<-HERE
#!/bin/sh
export PKG_CONFIG_DIR=
export PKG_CONFIG_LIBDIR=$PKG_CONFIG_LIBDIR
exec $_HOST_PKGCONFIG "\$@"
HERE
chmod +x "$PKG_CONFIG"
if [ -z "$TERMUX_ON_DEVICE_BUILD" ]; then
# Create a pkg-config wrapper. We use path to host pkg-config to
# avoid picking up a cross-compiled pkg-config later on.
local _HOST_PKGCONFIG
_HOST_PKGCONFIG=$(which pkg-config)
mkdir -p $TERMUX_STANDALONE_TOOLCHAIN/bin "$PKG_CONFIG_LIBDIR"
cat > "$PKG_CONFIG" <<-HERE
#!/bin/sh
export PKG_CONFIG_DIR=
export PKG_CONFIG_LIBDIR=$PKG_CONFIG_LIBDIR
exec $_HOST_PKGCONFIG "\$@"
HERE
chmod +x "$PKG_CONFIG"
fi
}

View File

@ -16,6 +16,14 @@ termux_step_setup_variables() {
: "${TERMUX_PKG_MAINTAINER:="Fredrik Fornwall @fornwall"}"
: "${TERMUX_PACKAGES_DIRECTORIES:="packages"}"
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.
TERMUX_BUILT_PACKAGES_DIRECTORY="$TERMUX_TOPDIR/.built-packages"
else
TERMUX_BUILT_PACKAGES_DIRECTORY="/data/data/.built-packages"
fi
TERMUX_REPO_URL=(
https://termux.net
https://dl.bintray.com/grimler/game-packages-21
@ -52,10 +60,11 @@ termux_step_setup_variables() {
TERMUX_HOST_PLATFORM="${TERMUX_ARCH}-linux-android"
if [ "$TERMUX_ARCH" = "arm" ]; then TERMUX_HOST_PLATFORM="${TERMUX_HOST_PLATFORM}eabi"; fi
if [ ! -d "$NDK" ]; then
if [ -z "$TERMUX_ON_DEVICE_BUILD" ] && [ ! -d "$NDK" ]; then
termux_error_exit 'NDK not pointing at a directory!'
fi
if ! grep -s -q "Pkg.Revision = $TERMUX_NDK_VERSION_NUM" "$NDK/source.properties"; then
if [ -z "$TERMUX_ON_DEVICE_BUILD" ] && ! grep -s -q "Pkg.Revision = $TERMUX_NDK_VERSION_NUM" "$NDK/source.properties"; then
termux_error_exit "Wrong NDK version - we need $TERMUX_NDK_VERSION"
fi
@ -95,7 +104,7 @@ termux_step_setup_variables() {
TERMUX_PKG_BUILD_DEPENDS=""
TERMUX_PKG_HOMEPAGE=""
TERMUX_PKG_DESCRIPTION="FIXME:Add description"
TERMUX_PKG_LICENSE_FILE="" # Relative path from $TERMUX_PKG_SRCDIR to LICENSE file. It is installed to $PREFIX/share/$TERMUX_PKG_NAME.
TERMUX_PKG_LICENSE_FILE="" # Relative path from $TERMUX_PKG_SRCDIR to LICENSE file. It is installed to $TERMUX_PREFIX/share/$TERMUX_PKG_NAME.
TERMUX_PKG_ESSENTIAL=""
TERMUX_PKG_CONFLICTS="" # https://www.debian.org/doc/debian-policy/ch-relationships.html#s-conflicts
TERMUX_PKG_RECOMMENDS="" # https://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps

View File

@ -30,11 +30,14 @@ termux_step_start_build() {
DEBUG=""
fi
if [ -z "$TERMUX_DEBUG" ] &&
[ -z "${TERMUX_FORCE_BUILD+x}" ] &&
[ -e "/data/data/.built-packages/$TERMUX_PKG_NAME" ]; then
if [ "$(cat "/data/data/.built-packages/$TERMUX_PKG_NAME")" = "$TERMUX_PKG_FULLVERSION" ]; then
echo "$TERMUX_PKG_NAME@$TERMUX_PKG_FULLVERSION built - skipping (rm /data/data/.built-packages/$TERMUX_PKG_NAME to force rebuild)"
if [ -z "$TERMUX_DEBUG" ] && [ -z "${TERMUX_FORCE_BUILD+x}" ]; then
if [ -e "$TERMUX_BUILT_PACKAGES_DIRECTORY/$TERMUX_PKG_NAME" ] &&
[ "$(cat "$TERMUX_BUILT_PACKAGES_DIRECTORY/$TERMUX_PKG_NAME")" = "$TERMUX_PKG_FULLVERSION" ]; then
echo "$TERMUX_PKG_NAME@$TERMUX_PKG_FULLVERSION built - skipping (rm $TERMUX_BUILT_PACKAGES_DIRECTORY/$TERMUX_PKG_NAME to force rebuild)"
exit 0
elif [ -n "$TERMUX_ON_DEVICE_BUILD" ] &&
[ "$(dpkg-query -W -f '${db:Status-Status} ${Version}\n' "$TERMUX_PKG_NAME" 2>/dev/null)" = "installed $TERMUX_PKG_FULLVERSION" ]; then
echo "$TERMUX_PKG_NAME@$TERMUX_PKG_FULLVERSION installed - skipping"
exit 0
fi
fi
@ -42,6 +45,10 @@ termux_step_start_build() {
if [ "$TERMUX_SKIP_DEPCHECK" = false ] && [ "$TERMUX_INSTALL_DEPS" = true ]; then
# Download repo files
termux_get_repo_files
# When doing build on device, ensure that apt lists are up-to-date.
[ -n "$TERMUX_ON_DEVICE_BUILD" ] && apt update
# Download dependencies
while read PKG PKG_DIR; do
if [ -z $PKG ]; then
@ -57,27 +64,29 @@ termux_step_start_build() {
echo "Downloading dependency $PKG@$DEP_VERSION if necessary..."
fi
if [ -e "/data/data/.built-packages/$PKG" ]; then
if [ "$(cat "/data/data/.built-packages/$PKG")" = "$DEP_VERSION" ]; then
if [ -e "$TERMUX_BUILT_PACKAGES_DIRECTORY/$PKG" ]; then
if [ "$(cat "$TERMUX_BUILT_PACKAGES_DIRECTORY/$PKG")" = "$DEP_VERSION" ]; then
continue
fi
fi
if ! termux_download_deb $PKG $DEP_ARCH $DEP_VERSION; then
echo "Download of $PKG@$DEP_VERSION from $TERMUX_REPO_URL failed, building instead"
TERMUX_BUILD_IGNORE_LOCK=true ./build-package.sh -a $TERMUX_ARCH -I "${PKG_DIR}"
TERMUX_BUILD_IGNORE_LOCK=true ./build-package.sh -I "${PKG_DIR}"
continue
else
if [ ! "$TERMUX_QUIET_BUILD" = true ]; then echo "extracting $PKG..."; fi
(
cd $TERMUX_COMMON_CACHEDIR-$DEP_ARCH
ar x ${PKG}_${DEP_VERSION}_${DEP_ARCH}.deb data.tar.xz
tar -xf data.tar.xz --no-overwrite-dir -C /
)
if [ -z "$TERMUX_ON_DEVICE_BUILD" ]; then
if [ ! "$TERMUX_QUIET_BUILD" = true ]; then echo "extracting $PKG..."; fi
(
cd $TERMUX_COMMON_CACHEDIR-$DEP_ARCH
ar x ${PKG}_${DEP_VERSION}_${DEP_ARCH}.deb data.tar.xz
tar -xf data.tar.xz --no-overwrite-dir -C /
)
fi
fi
mkdir -p /data/data/.built-packages
echo "$DEP_VERSION" > "/data/data/.built-packages/$PKG"
mkdir -p $TERMUX_BUILT_PACKAGES_DIRECTORY
echo "$DEP_VERSION" > "$TERMUX_BUILT_PACKAGES_DIRECTORY/$PKG"
done<<<$(./scripts/buildorder.py -i "$TERMUX_PKG_BUILDER_DIR" $TERMUX_PACKAGES_DIRECTORIES || echo "ERROR")
elif [ "$TERMUX_SKIP_DEPCHECK" = false ] && [ "$TERMUX_INSTALL_DEPS" = false ]; then
# Build dependencies
@ -89,12 +98,12 @@ termux_step_start_build() {
fi
echo "Building dependency $PKG if necessary..."
# Built dependencies are put in the default TERMUX_DEBDIR instead of the specified one
TERMUX_BUILD_IGNORE_LOCK=true ./build-package.sh -a $TERMUX_ARCH -s "${PKG_DIR}"
TERMUX_BUILD_IGNORE_LOCK=true ./build-package.sh -s "${PKG_DIR}"
done<<<$(./scripts/buildorder.py "$TERMUX_PKG_BUILDER_DIR" $TERMUX_PACKAGES_DIRECTORIES || echo "ERROR")
fi
# Following directories may contain objects with RO-only permissions which
# makes them undeletable. We need fix that.
# Following directories may contain files with read-only permissions which
# makes them undeletable. We need to fix that.
[ -d "$TERMUX_PKG_BUILDDIR" ] && chmod +w -R "$TERMUX_PKG_BUILDDIR"
[ -d "$TERMUX_PKG_SRCDIR" ] && chmod +w -R "$TERMUX_PKG_SRCDIR"
@ -117,7 +126,7 @@ termux_step_start_build() {
# Make $TERMUX_PREFIX/bin/sh executable on the builder, so that build
# scripts can assume that it works on both builder and host later on:
ln -f -s /bin/sh "$TERMUX_PREFIX/bin/sh"
[ -z "$TERMUX_ON_DEVICE_BUILD" ] && ln -sf /bin/sh "$TERMUX_PREFIX/bin/sh"
local TERMUX_ELF_CLEANER_SRC=$TERMUX_COMMON_CACHEDIR/termux-elf-cleaner.cpp
local TERMUX_ELF_CLEANER_VERSION

View File

@ -62,10 +62,12 @@ class TermuxPackage(object):
raise Exception("build.sh not found for package '" + self.name + "'")
self.deps = parse_build_file_dependencies(build_sh_path)
always_deps = ['libc++']
for dependency_name in always_deps:
if dependency_name not in self.deps and self.name not in always_deps:
self.deps.add(dependency_name)
if os.getenv('TERMUX_ON_DEVICE_BUILD') is None:
always_deps = ['libc++']
for dependency_name in always_deps:
if dependency_name not in self.deps and self.name not in always_deps:
self.deps.add(dependency_name)
# search subpackages
self.subpkgs = []

45
scripts/setup-termux.sh Executable file
View File

@ -0,0 +1,45 @@
#!/data/data/com.termux/files/usr/bin/sh
PACKAGES="autoconf"
PACKAGES+=" automake"
PACKAGES+=" bc"
PACKAGES+=" bison"
PACKAGES+=" bzip2"
PACKAGES+=" clang"
PACKAGES+=" cmake"
PACKAGES+=" coreutils"
PACKAGES+=" curl"
PACKAGES+=" diffutils"
PACKAGES+=" ed"
PACKAGES+=" file"
PACKAGES+=" findutils"
PACKAGES+=" flex"
PACKAGES+=" gawk"
PACKAGES+=" gettext"
PACKAGES+=" git"
PACKAGES+=" golang"
PACKAGES+=" gperf"
PACKAGES+=" grep"
PACKAGES+=" gzip"
PACKAGES+=" libtool"
PACKAGES+=" lzip"
PACKAGES+=" lzop"
PACKAGES+=" m4"
PACKAGES+=" make"
PACKAGES+=" ninja"
PACKAGES+=" patch"
PACKAGES+=" perl"
PACKAGES+=" pkg-config"
PACKAGES+=" protobuf"
PACKAGES+=" python"
PACKAGES+=" python2"
PACKAGES+=" rust"
PACKAGES+=" sed"
PACKAGES+=" tar"
PACKAGES+=" texinfo"
PACKAGES+=" unzip"
PACKAGES+=" xz-utils"
apt update
apt dist-upgrade -y
apt install -y $PACKAGES