Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Build Toolchain
on:
push:
branches:
- main
tags:
- v**
pull_request:
jobs:
build:
name: Build Toolchain
runs-on: ubuntu-22.04
strategy:
matrix:
target_arch: [aarch64, arm, i686, x86_64]
steps:
- name: Checkout Repo
uses: actions/checkout@main
with:
path: ${{ github.workspace }}
- name: Build Toolchain
env:
TOOLCHAIN_ARCH: ${{ matrix.target_arch }}
run: |
bash ./build.sh
- name: Waiting for debugger
if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
- name: Upload Build Archive
uses: actions/upload-artifact@v4
with:
name: newer-toolchain-${{ matrix.target_arch }}-${{ github.sha }}
path: ${{ github.workspace }}/build/
release:
name: Create Github Release
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
needs: build
runs-on: ubuntu-22.04
steps:
- name: Fetch archives
uses: actions/download-artifact@v4
with:
path: ./
- name: Copy archives
run: |
cp newer-toolchain-*-${{ github.sha }}/*.tar.bz2 ./
- name: Get checksums
id: checksums
run: |
checksums=$(printf 'SHA-256:\n```\n%s\n```\n' "$(sha256sum *.tar.bz2)")
checksums="${checksums//'%'/'%25'}"
checksums="${checksums//$'\n'/'%0A'}"
checksums="${checksums//$'\r'/'%0D'}"
echo "::set-output name=checksums::$checksums"
- name: Get tag
id: tag
uses: dawidd6/action-get-tag@v1
- name: Publish GitHub release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: "*.tar.bz2"
file_glob: true
release_name: "Android NDK toolchain version r17c with gcc"
tag: ${{ steps.tag.outputs.tag }}
body: ${{ steps.checksums.outputs.checksums }}
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Cache files
/cache/

# Temp files
/tmp/

# Build files
/build/

# VSCode
/.vscode/
165 changes: 165 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#!/bin/bash
# build.sh - script to build a custom NDK toolchain
#
# Copyright 2022 Chongyun Lee <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

set -e -u -o pipefail

_SCRIPTDIR=$(cd "$(realpath "$(dirname "$0")")"; pwd)
source $_SCRIPTDIR/common-files/setup_toolchain_ndk_r17c.sh
source $_SCRIPTDIR/common-files/termux_download.sh

: ${TOOLCHAIN_ARCH:=aarch64}
: ${_CACHE_DIR:=$_SCRIPTDIR/cache}
: ${_TMP_DIR:=$_SCRIPTDIR/tmp}
: ${_API_LEVEL:=21}
: ${_MAKE_PROCESSES:=$(nproc)}
: ${GCC_VERSION:=15.1.0}
: ${GCC_SHA256:=51b9919ea69c980d7a381db95d4be27edf73b21254eb13d752a08003b4d013b1}
: ${BINUTILS_VERSION:=2.44}
: ${BINUTILS_SHA256:=0cdd76777a0dfd3dd3a63f215f030208ddb91c2361d2bcc02acec0f1c16b6a2e}

export TOOLCHAIN_ARCH

TERMUX_PKG_TMPDIR=$_TMP_DIR
mkdir -p $_CACHE_DIR
rm -rf $_TMP_DIR
mkdir -p $_TMP_DIR

_HOST_PLATFORM="${TOOLCHAIN_ARCH}-linux-android"

_GCC_EXTRA_HOST_BUILD=""
_BINUTILS_EXTRA_HOST_BUILD="--enable-gold"
if [ "$TOOLCHAIN_ARCH" = "arm" ]; then
_HOST_PLATFORM="${_HOST_PLATFORM}eabi"
_GCC_EXTRA_HOST_BUILD="--with-arch=armv7-a --with-float=soft --with-fpu=vfp"
elif [ "$TOOLCHAIN_ARCH" = "aarch64" ]; then
_GCC_EXTRA_HOST_BUILD="--enable-fix-cortex-a53-835769 --enable-fix-cortex-a53-843419"
_BINUTILS_EXTRA_HOST_BUILD+=" $_GCC_EXTRA_HOST_BUILD"
elif [ "$TOOLCHAIN_ARCH" = "i686" ]; then
_GCC_EXTRA_HOST_BUILD="--with-arch=i686 --with-fpmath=sse "
elif [ "$TOOLCHAIN_ARCH" = "x86_64" ]; then
_GCC_EXTRA_HOST_BUILD="--with-arch=x86-64 --with-fpmath=sse"
fi

# Install dependencies
sudo apt update
sudo apt install -y build-essential curl
sudo apt install -y libgmp-dev libmpfr-dev libmpc-dev zlib1g-dev libisl-dev

pushd $_TMP_DIR

# Download source
GCC_SRC_URL=https://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.gz
GCC_SRC_FILE=$_CACHE_DIR/gcc-${GCC_VERSION}.tar.gz
GCC_SRC_DIR=$_TMP_DIR/gcc-${GCC_VERSION}
termux_download $GCC_SRC_URL $GCC_SRC_FILE $GCC_SHA256
BINUTILS_SRC_URL=https://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_VERSION}.tar.gz
BINUTILS_SRC_FILE=$_CACHE_DIR/binutils-${BINUTILS_VERSION}.tar.gz
BINUTILS_SRC_DIR=$_TMP_DIR/binutils-${BINUTILS_VERSION}
termux_download $BINUTILS_SRC_URL $BINUTILS_SRC_FILE $BINUTILS_SHA256

# Setup a standalone toolchain
_setup_standalone_toolchain_ndk_r17c $_TMP_DIR/standalone-toolchain
cp -R $_TMP_DIR/standalone-toolchain/sysroot/usr/include/$_HOST_PLATFORM/* $_TMP_DIR/standalone-toolchain/sysroot/usr/include/

# Extract source
tar -xf $GCC_SRC_FILE -C $_TMP_DIR/
pushd $_TMP_DIR
PATCHES="$(find "$_SCRIPTDIR/patches/" -maxdepth 1 -type f -name *.patch | sort)"
for f in $PATCHES; do
echo "Applying patch: $(basename $f)"
patch -d "$GCC_SRC_DIR/" -p1 < "$f";
done
tar -xf $BINUTILS_SRC_FILE -C $_TMP_DIR/
popd

# Copy sysroot
mkdir -p $_TMP_DIR/newer-toolchain
cp -R $_TMP_DIR/standalone-toolchain/sysroot $_TMP_DIR/newer-toolchain/

# Set CPPFLAGS/CFLAGS/CXXFLAGS
export CPPFLAGS="-O3 -g0"
export CFLAGS="$CPPFLAGS"
export CXXFLAGS="$CPPFLAGS"

# Build binutils
mkdir -p binutils-build
pushd binutils-build
$BINUTILS_SRC_DIR/configure \
--target=$_HOST_PLATFORM \
--prefix=$_TMP_DIR/newer-toolchain \
--with-sysroot=$_TMP_DIR/newer-toolchain/sysroot \
--with-zstd \
ZSTD_LIBS=-l:libzstd.a \
$_BINUTILS_EXTRA_HOST_BUILD
make -j $_MAKE_PROCESSES
make -j $_MAKE_PROCESSES install-strip
popd # binutils-build

export PATH="$_TMP_DIR/newer-toolchain/bin:$PATH"

# Build GCC toolchain
mkdir -p newer-toolchain-build
pushd newer-toolchain-build

export CPPFLAGS+=" -D__ANDROID_API__=$_API_LEVEL"
export CFLAGS+=" -D__ANDROID_API__=$_API_LEVEL"
export CXXFLAGS+=" -D__ANDROID_API__=$_API_LEVEL"

$GCC_SRC_DIR/configure \
--host=x86_64-linux-gnu \
--build=x86_64-linux-gnu \
--target=$_HOST_PLATFORM \
--disable-shared \
--disable-nls \
--enable-default-pie \
--with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' \
--with-gnu-as --with-gnu-ld \
--disable-libstdc__-v3 \
--disable-tls \
--disable-ssp \
--disable-bootstrap \
--enable-initfini-array \
--enable-libatomic-ifuncs=no \
--prefix=$_TMP_DIR/newer-toolchain \
--with-gmp --with-mpfr --with-mpc --with-system-zlib \
--enable-languages=c,c++,fortran \
--enable-plugins --enable-libgomp \
--enable-gnu-indirect-function \
--disable-libcilkrts --disable-libsanitizer \
--enable-gold --enable-threads \
--enable-eh-frame-hdr-for-static \
--enable-graphite=yes --with-isl \
--disable-multilib \
$_GCC_EXTRA_HOST_BUILD \
--with-sysroot=$_TMP_DIR/newer-toolchain/sysroot \
--with-gxx-include-dir=$_TMP_DIR/newer-toolchain/include/c++/$GCC_VERSION

make -j $_MAKE_PROCESSES
make -j $_MAKE_PROCESSES install-strip

popd # newer-toolchain-build

# Make the archive
mv newer-toolchain gcc-$GCC_VERSION-$TOOLCHAIN_ARCH
tar -cjvf gcc-$GCC_VERSION-$TOOLCHAIN_ARCH.tar.bz2 gcc-$GCC_VERSION-$TOOLCHAIN_ARCH

popd # $_TMP_DIR

# Copy the archive
mkdir -p build
cp $_TMP_DIR/gcc-$GCC_VERSION-$TOOLCHAIN_ARCH.tar.bz2 ./build
45 changes: 45 additions & 0 deletions common-files/setup_toolchain_ndk_r17c.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
_download_ndk_r17c() {
if [ ! -f $_CACHE_DIR/.placeholder-android-ndk-r17c ]; then
echo "Start downloading Android NDK toolchain (version r17c)..."
mkdir -p $_CACHE_DIR/
local _NDKARCHIVE_FILE=$_CACHE_DIR/android-ndk-r17c-linux-x86_64.zip
local _NDK_URL=https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip
local _NDK_SHA256=3f541adbd0330a9205ba12697f6d04ec90752c53d6b622101a2a8a856e816589
termux_download $_NDK_URL $_NDKARCHIVE_FILE $_NDK_SHA256
unzip -d $_CACHE_DIR/ $_NDKARCHIVE_FILE > /dev/null 2>&1
touch $_CACHE_DIR/.placeholder-android-ndk-r17c
echo "Downloading completed."
fi
}

_setup_standalone_toolchain_ndk_r17c() {
_download_ndk_r17c

local TOOLCHAIN_DIR="$1"
rm -rf $TOOLCHAIN_DIR

local _NDKARCH
if [ "$TOOLCHAIN_ARCH" == "aarch64" ]; then
_NDKARCH="arm64"
elif [ "$TOOLCHAIN_ARCH" == "arm" ]; then
_NDKARCH="arm"
elif [ "$TOOLCHAIN_ARCH" == "x86_64" ]; then
_NDKARCH="x86_64"
elif [ "$TOOLCHAIN_ARCH" == "i686" ]; then
_NDKARCH="x86"
fi

# Setup a standalone toolchain
python $_CACHE_DIR/android-ndk-r17c/build/tools/make_standalone_toolchain.py \
--arch $_NDKARCH --api $_API_LEVEL --install-dir $TOOLCHAIN_DIR

# Modify sysroot
pushd $TOOLCHAIN_DIR

# See https://github.com/android/ndk/issues/215#issuecomment-524293090
sed -i "s/include_next <stddef.h>/include <stddef.h>/" include/c++/4.9.x/cstddef

sed -i "s/define __ANDROID_API__ __ANDROID_API_FUTURE__/define __ANDROID_API__ $_API_LEVEL/" \
sysroot/usr/include/android/api-level.h
popd
}
60 changes: 60 additions & 0 deletions common-files/termux_download.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/bash
##
## Copyright 2020 Termux
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##

termux_download() {
if [ $# != 3 ]; then
termux_error_exit "termux_download(): Invalid arguments - expected \$URL \$DESTINATION \$CHECKSUM"
fi
local URL="$1"
local DESTINATION="$2"
local CHECKSUM="$3"

if [ -f "$DESTINATION" ] && [ "$CHECKSUM" != "SKIP_CHECKSUM" ]; then
# Keep existing file if checksum matches.
local EXISTING_CHECKSUM
EXISTING_CHECKSUM=$(sha256sum "$DESTINATION" | cut -f 1 -d ' ')
if [ "$EXISTING_CHECKSUM" = "$CHECKSUM" ]; then return; fi
fi

local TMPFILE
TMPFILE=$(mktemp "$TERMUX_PKG_TMPDIR/download.${TERMUX_PKG_NAME-unnamed}.XXXXXXXXX")
echo "Downloading ${URL}"
if curl --fail --retry 20 --retry-connrefused --retry-delay 30 --location --output "$TMPFILE" "$URL"; then
local ACTUAL_CHECKSUM
ACTUAL_CHECKSUM=$(sha256sum "$TMPFILE" | cut -f 1 -d ' ')
if [ "$CHECKSUM" != "SKIP_CHECKSUM" ]; then
if [ "$CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then
>&2 printf "Wrong checksum for %s:\nExpected: %s\nActual: %s\n" \
"$URL" "$CHECKSUM" "$ACTUAL_CHECKSUM"
return 1
fi
elif [ -z "$CHECKSUM" ]; then
printf "WARNING: No checksum check for %s:\nActual: %s\n" \
"$URL" "$ACTUAL_CHECKSUM"
fi
mv "$TMPFILE" "$DESTINATION"
return 0
fi

echo "Failed to download $URL" >&2
return 1
}

# Make script standalone executable as well as sourceable
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
termux_download "$@"
fi
Loading