mirror of
https://github.com/radareorg/radare2
synced 2026-08-22 20:23:32 -04:00
282 lines
7.1 KiB
Bash
Executable file
282 lines
7.1 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Android SDK builder
|
|
|
|
set -euo pipefail
|
|
|
|
CALLER_DIR=$PWD
|
|
cd "$(dirname "$0")/.."
|
|
ROOT=$PWD
|
|
SCRIPT="$ROOT/sys/android-sdk.sh"
|
|
PREFIX=/usr/local
|
|
DEFAULT_ARCHS="arm+arm64+x86+x86_64"
|
|
ARCHS=$DEFAULT_ARCHS
|
|
ANDROID_API=${ANDROID_API:-28}
|
|
JOBS=${JOBS:-4}
|
|
OUTPUT=""
|
|
PLUGINS_CFG=${R2_PLUGINS_CFG:-dist/plugins-cfg/plugins.android.cfg}
|
|
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
|
SOURCE_DATE_EPOCH=$(git log -1 --format=%ct 2>/dev/null || date +%s)
|
|
fi
|
|
|
|
showHelp() {
|
|
echo "Android SDK builder"
|
|
echo
|
|
echo "Usage: $0 [options]"
|
|
echo
|
|
echo "Options:"
|
|
echo " -a, --archs ARCHS Architectures separated by + or ,"
|
|
echo " (arm, arm64, x86, x86_64; default: $DEFAULT_ARCHS)"
|
|
echo " --api LEVEL Android API level (default: $ANDROID_API)"
|
|
echo " -j, --jobs JOBS Parallel build jobs (default: $JOBS)"
|
|
echo " -o, --output FILE Output zip path"
|
|
echo " -h, --help Show this help"
|
|
echo
|
|
echo "Examples:"
|
|
echo " sys/android-sdk.sh"
|
|
echo " sys/android-sdk.sh -a arm64+x86_64 --api 28"
|
|
}
|
|
|
|
fail() {
|
|
echo "android-sdk: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
buildAbi() {
|
|
local ndk_arch=$1
|
|
local android_abi=$2
|
|
local target=$3
|
|
local install_dst=$4
|
|
local make=make
|
|
|
|
if gmake --help >/dev/null 2>&1; then
|
|
make=gmake
|
|
fi
|
|
|
|
export CFLAGS="-fPIC -Oz -DNDEBUG"
|
|
export LDFLAGS=""
|
|
case "$ndk_arch" in
|
|
aarch64|x86_64)
|
|
export LDFLAGS="-Wl,-z,max-page-size=16384"
|
|
;;
|
|
esac
|
|
export AR=llvm-ar
|
|
export RANLIB=llvm-ranlib
|
|
|
|
echo "Building Android SDK libraries for $android_abi (API $ANDROID_API)"
|
|
if [ -f libr/config.mk ]; then
|
|
"$make" mrproper
|
|
fi
|
|
cp -f "$PLUGINS_CFG" plugins.cfg
|
|
./configure --with-compiler=android --with-ostype=android \
|
|
--target="$target" --prefix="$PREFIX" --with-libr \
|
|
--with-bundle-prefix --without-gpl --without-sqsh \
|
|
--with-checks-level=0
|
|
"$make" -s -j "$JOBS"
|
|
"$make" -s install DESTDIR="$install_dst"
|
|
}
|
|
|
|
if [ "${1:-}" = "--build-abi" ]; then
|
|
[ $# = 5 ] || fail "invalid internal build arguments"
|
|
buildAbi "$2" "$3" "$4" "$5"
|
|
exit 0
|
|
fi
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-a|--archs)
|
|
[ $# -gt 1 ] || fail "$1 requires an argument"
|
|
ARCHS=$2
|
|
shift 2
|
|
;;
|
|
--api)
|
|
[ $# -gt 1 ] || fail "$1 requires an argument"
|
|
ANDROID_API=$2
|
|
shift 2
|
|
;;
|
|
-j|--jobs)
|
|
[ $# -gt 1 ] || fail "$1 requires an argument"
|
|
JOBS=$2
|
|
shift 2
|
|
;;
|
|
-o|--output)
|
|
[ $# -gt 1 ] || fail "$1 requires an argument"
|
|
OUTPUT=$2
|
|
shift 2
|
|
;;
|
|
-h|--help)
|
|
showHelp
|
|
exit 0
|
|
;;
|
|
*)
|
|
fail "unknown option: $1"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
case "$ANDROID_API" in
|
|
""|*[!0-9]*)
|
|
fail "invalid Android API level: $ANDROID_API"
|
|
;;
|
|
esac
|
|
case "$JOBS" in
|
|
""|*[!0-9]*)
|
|
fail "invalid job count: $JOBS"
|
|
;;
|
|
esac
|
|
[ "$JOBS" -gt 0 ] || fail "job count must be greater than zero"
|
|
command -v zip >/dev/null 2>&1 || fail "zip is required"
|
|
|
|
VERSION=$(./configure -qV)
|
|
SDK_NAME="radare2-$VERSION-android-sdk"
|
|
if [ -z "$OUTPUT" ]; then
|
|
OUTPUT="$CALLER_DIR/$SDK_NAME.zip"
|
|
elif [ "${OUTPUT#/}" = "$OUTPUT" ]; then
|
|
OUTPUT="$CALLER_DIR/$OUTPUT"
|
|
fi
|
|
|
|
WORKDIR=$(mktemp -d "${TMPDIR:-/tmp}/r2-android-sdk.XXXXXX")
|
|
SDK_ROOT="$WORKDIR/package/$SDK_NAME"
|
|
mkdir -p "$SDK_ROOT/include" "$SDK_ROOT/lib"
|
|
|
|
cleanup() {
|
|
rm -rf "$WORKDIR"
|
|
}
|
|
trap cleanup EXIT HUP INT TERM
|
|
|
|
copyLibraries() {
|
|
local source_dir=$1
|
|
local dest_dir=$2
|
|
local source_file
|
|
local dest_file
|
|
|
|
mkdir -p "$dest_dir"
|
|
while IFS= read -r source_file; do
|
|
dest_file="$dest_dir/$(basename "$source_file")"
|
|
if [ -f "$dest_file" ] && ! cmp -s "$source_file" "$dest_file"; then
|
|
fail "library name collision: $(basename "$source_file")"
|
|
fi
|
|
cp -Lf "$source_file" "$dest_file"
|
|
done < <(find "$source_dir" \( -type f -o -type l \) \( -name '*.a' -o -name '*.so' \) -print)
|
|
}
|
|
|
|
rewritePkgConfig() {
|
|
local pkg_dir=$1
|
|
local android_abi=$2
|
|
local pc
|
|
|
|
[ -d "$pkg_dir" ] || return 0
|
|
for pc in "$pkg_dir"/*.pc; do
|
|
[ -f "$pc" ] || continue
|
|
sed \
|
|
-e 's|^prefix=.*|prefix=${pcfiledir}/../../..|' \
|
|
-e 's|^exec_prefix=.*|exec_prefix=${prefix}|' \
|
|
-e "s|^libdir=.*|libdir=\${prefix}/lib/$android_abi|" \
|
|
-e 's|^includedir=.*|includedir=${prefix}/include|' \
|
|
"$pc" > "$pc.tmp"
|
|
mv -f "$pc.tmp" "$pc"
|
|
done
|
|
}
|
|
|
|
FIRST_ABI=1
|
|
BUILT_ABIS=""
|
|
NORMALIZED_ARCHS=$(printf '%s' "$ARCHS" | tr ',+' ' ')
|
|
export ANDROID_API JOBS PLUGINS_CFG SOURCE_DATE_EPOCH
|
|
|
|
for arch in $NORMALIZED_ARCHS; do
|
|
case "$arch" in
|
|
arm|armeabi-v7a)
|
|
NDK_ARCH=arm
|
|
ANDROID_ABI=armeabi-v7a
|
|
TARGET=arm-linux-androideabi
|
|
;;
|
|
arm64|aarch64|arm64-v8a)
|
|
NDK_ARCH=aarch64
|
|
ANDROID_ABI=arm64-v8a
|
|
TARGET=aarch64-linux-android
|
|
;;
|
|
x86)
|
|
NDK_ARCH=x86
|
|
ANDROID_ABI=x86
|
|
TARGET=i686-linux-android
|
|
;;
|
|
x64|x86_64)
|
|
NDK_ARCH=x86_64
|
|
ANDROID_ABI=x86_64
|
|
TARGET=x86_64-linux-android
|
|
;;
|
|
*)
|
|
fail "unsupported architecture: $arch"
|
|
;;
|
|
esac
|
|
|
|
case " $BUILT_ABIS " in
|
|
*" $ANDROID_ABI "*)
|
|
continue
|
|
;;
|
|
esac
|
|
BUILT_ABIS="$BUILT_ABIS $ANDROID_ABI"
|
|
INSTALL_DST="$WORKDIR/install-$ANDROID_ABI"
|
|
mkdir -p "$INSTALL_DST"
|
|
sys/android-shell.sh "$NDK_ARCH" "$SCRIPT" --build-abi \
|
|
"$NDK_ARCH" "$ANDROID_ABI" "$TARGET" "$INSTALL_DST"
|
|
INSTALL_PREFIX="$INSTALL_DST$PREFIX"
|
|
[ -d "$INSTALL_PREFIX/include/libr" ] || fail "missing headers for $ANDROID_ABI"
|
|
[ -d "$INSTALL_PREFIX/lib" ] || fail "missing libraries for $ANDROID_ABI"
|
|
|
|
if [ "$FIRST_ABI" = 1 ]; then
|
|
cp -R "$INSTALL_PREFIX/include/." "$SDK_ROOT/include"
|
|
if [ -d "$INSTALL_PREFIX/share/radare2" ]; then
|
|
mkdir -p "$SDK_ROOT/share"
|
|
cp -R "$INSTALL_PREFIX/share/radare2" "$SDK_ROOT/share/radare2"
|
|
fi
|
|
FIRST_ABI=0
|
|
elif ! diff -qr "$SDK_ROOT/include" "$INSTALL_PREFIX/include" >/dev/null; then
|
|
diff -ru "$SDK_ROOT/include" "$INSTALL_PREFIX/include" || true
|
|
fail "installed headers differ for $ANDROID_ABI"
|
|
fi
|
|
|
|
ABI_LIBDIR="$SDK_ROOT/lib/$ANDROID_ABI"
|
|
copyLibraries "$INSTALL_PREFIX/lib" "$ABI_LIBDIR"
|
|
if [ -d "$INSTALL_PREFIX/lib/pkgconfig" ]; then
|
|
mkdir -p "$ABI_LIBDIR/pkgconfig"
|
|
cp -R "$INSTALL_PREFIX/lib/pkgconfig/." "$ABI_LIBDIR/pkgconfig"
|
|
rewritePkgConfig "$ABI_LIBDIR/pkgconfig" "$ANDROID_ABI"
|
|
fi
|
|
find "$ABI_LIBDIR" -maxdepth 1 -name '*.a' -print -quit | grep -q . || \
|
|
fail "no static libraries found for $ANDROID_ABI"
|
|
find "$ABI_LIBDIR" -maxdepth 1 -name '*.so' -print -quit | grep -q . || \
|
|
fail "no shared libraries found for $ANDROID_ABI"
|
|
done
|
|
|
|
[ "$FIRST_ABI" = 0 ] || fail "no architectures selected"
|
|
cp -f COPYING.md "$SDK_ROOT"
|
|
printf '%s\n' \
|
|
"radare2 Android SDK $VERSION" \
|
|
"" \
|
|
"Android API level: $ANDROID_API" \
|
|
"ABIs:$BUILT_ABIS" \
|
|
"" \
|
|
"Layout:" \
|
|
" include/libr/ Public radare2 headers" \
|
|
" lib/<android-abi>/ Static and shared libraries" \
|
|
" lib/<android-abi>/pkgconfig/ Relocatable pkg-config files" \
|
|
" share/ Runtime data files" \
|
|
"" \
|
|
"Use include/libr as an include directory and lib/\${ANDROID_ABI} as" \
|
|
"a library directory. Set PKG_CONFIG_PATH to the matching pkgconfig" \
|
|
"directory when using pkg-config." > "$SDK_ROOT/README.txt"
|
|
printf 'version=%s\napi=%s\nabis=%s\n' \
|
|
"$VERSION" "$ANDROID_API" "${BUILT_ABIS# }" > "$SDK_ROOT/METADATA"
|
|
|
|
mkdir -p "$(dirname "$OUTPUT")"
|
|
ZIP_PATH="$WORKDIR/$SDK_NAME.zip"
|
|
(
|
|
cd "$WORKDIR/package"
|
|
zip -qry "$ZIP_PATH" "$SDK_NAME"
|
|
)
|
|
if command -v unzip >/dev/null 2>&1; then
|
|
unzip -tq "$ZIP_PATH" >/dev/null
|
|
fi
|
|
mv -f "$ZIP_PATH" "$OUTPUT"
|
|
echo "$OUTPUT"
|