#!/system/bin/sh # # Script to init the environment for clang in /data/local/tmp/sysroot # # Usage: see below or execute the script with the parameter "--help" # # # History # 25.12.2024 v1.0.0 /bs # initial release # 18.01.2025 v1.1.0 /bs # added the directory /data/local/tmp/sysroot/usr/ndk/r27b/sysroot/usr/include/aarch64-linux-android to the include dirs in CFLAGS # 26.01.2025 v1.1.1 /bs # the script does not change the SELinux policies anymore if running as user root # 02.02.2025 v1.2.0 /bs # added the directory /data/local/tmp/sysroot/usr/lib to the list of directories with libraries in the environment variable LDFLAGS # 30.03.2025 v1.2.1 /bs # added the directory /data/local/tmp/sysroot/usr/include to the list of directories with include files in the environment variable CFLAGS # added the alias nano for /data/local/tmp/sysroot/usr/bin/nano # # 01.04.2025 v1.2.2 /bs # added the alias curl for /data/local/tmp/sysroot/usr/bin/nano # the script now defines the environment variable SSL_CERT_FILE # the script now sets the environment variable PKG_CONFIG_PATH # # 24.04.2025 v1.2.3 /bs # the script now sets the environment variable HOSTNAME to "$( getprop ro.product.device ) $( getprop ro.serialno )" if it's empty # # 19.05.2025 v1.3.0 /bs # the script now uses /system/bin/test to check, if a file or directdory exists (-> the script now also works in bash) # added a "Hello Rorld" program written in Assembler for the arm64 CPU # added support for this syntax: CLANG_SYSROOT=/data/local/tmp/sysroot.test source ${CLANG_SYSROOT}/bin/init_clang19_env # # 04.06.2025 v1.3.1 /bs # if 'uname -m" returns "armv8*" the script sets CPU_TYPE now to aarch64 # the script now prints warning messages if a directory from the NDK is missing # # 06.06.2025 v1.4.0 /bs # the script now uses the executable sysroot/bin/testcpu to check if the current CPU can execute binaries compiled for arm64 CPUs # added the parameter nocpucheck # the value for CPU_TYPE is now hardcoded in the script # the parameter are now processed BEFORE setting the variables # 22.09.2025 v1.4.1 /bs # the script now ignores all parameter following the parameter "--" # # 31.10.2025 v1.5.0 /bs # use sepolicy-inject (via helper script add_missing_selinux_rules.sh) to add missing SELinux policies if Magisk is not installed # # 21.12.2025 v1.5.1 /bs # the script now creates an alias for each file in /system_ext/bin that is also part of the clang19 toolchain # # 23.12.2025 v1.5.2 /bs # the script now exports the environment variable CLANG_SYSROOT # __TRUE=0 __FALSE=1 STANDALONE_SCRIPT=${__FALSE} CONTINUE=${__TRUE} if [ ${CONTINUE} = ${__TRUE} ] ; then # this variable is set to ture if the parameter "examples" is used # PRINT_EXAMPLES=${__FALSE} alias LogDebugMsg='[ "${DEBUG}"x != ""x ] && echo "DEBUG: $*" >&2 ' # the test binary to use # TEST="$( which test )" # this is NOT a supported environment variable -> use this code to avoid adding the variable to the list of supported environment variables in the usage output # [ "${TEST}"x = ""x ] && TEST="test" # set to ${__FALSE} to disable the CPU check # CHECK_CPU="${CHECK_CPU:=${__TRUE}}" THIS_SCRIPT="$0" # check if this script was sourced in # if [[ "${THIS_SCRIPT}" != */init_clang*_env ]] ; then THIS_SCRIPT="/data/local/tmp/sysroot/bin/init_clang19_env" else CLANG_SYSROOT="$( cd "${THIS_SCRIPT%/bin/*}" && pwd )" fi # --------------------------------------------------------------------- # the variable TMPDIR is used by the /sytem/bin/sh to get the default directory for temporary files # TMPDIR="${TMPDIR:=/data/local/tmp}" export TMPDIR fi # --------------------------------------------------------------------- function add_path { while [ $# -ne 0 ] ; do CUR_DIR="$1" shift [[ *:${PATH}:* != *:${CUR_DIR}:* ]] && PATH="${PATH}:${CUR_DIR}" done } function add_library_path { while [ $# -ne 0 ] ; do CUR_DIR="$1" shift [[ *:${LD_LIBRARY_PATH}:* != *:${CUR_DIR}:* ]] && LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${CUR_DIR}" done } # --------------------------------------------------------------------- # main function starts here # if [ ${CONTINUE} = ${__TRUE} ] ; then while [ $# -ne 0 ] ; do CUR_PARAMETER="$1" shift case ${CUR_PARAMETER} in -h | --help | help ) if ${TEST} -r "${THIS_SCRIPT}" ; then SUPPORTED_ENV_VARIABLES="Supported environment variables are: $( grep ":=" ${THIS_SCRIPT} | grep -v SUPPORTED_ENV_VARIABLES ) " else SUPPORTED_ENV_VARIABLES="" fi cat </dev/null 1>/dev/null if [ $? -eq 0 ] ; then ROOT_ACCESS_AVAILABLE=${__TRUE} ROOT_PREFIX="su - -c " fi fi fi # --------------------------------------------------------------------- if [ ${CONTINUE} = ${__TRUE} ] ; then # # 06.06.2025 /bs : CPU_TYPE is hardcoded now; CUR_CPU_TYPE is only used for messages # CPU_TYPE="aarch64" CUR_CPU_TYPE="$( uname -m )" # # check, if the current CPU can execute binaries compiled for arm64 # if [ ${CHECK_CPU}x != ${__FALSE}x ] ; then CHECK_CPU_TEST_PROGRAM="${CLANG_SYSROOT}/bin/testcpu" if [ -x "${CHECK_CPU_TEST_PROGRAM}" ] ; then echo "Checking if the current CPU can execute binaries for arm64 CPUs using the binary \"${CHECK_CPU_TEST_PROGRAM}\" ..." ${CHECK_CPU_TEST_PROGRAM} if [ $? -ne 0 ] ; then echo "ERROR: Looks like the current CPU can NOT execute binaries for arm64 CPUs" echo " Note: To disable this test either use the parameter \"nocpucheck\" or delete or rename the file \"${CHECK_CPU_TEST_PROGRAM}\" " CONTINUE=${__FALSE} fi else echo "The CPU check program \"${CHECK_CPU_TEST_PROGRAM}\" does not exist or is not executable - no CPU check done" fi fi fi # --------------------------------------------------------------------- if [ ${CONTINUE} = ${__TRUE} ] ; then echo "Running as user \"${CUR_USER}\" " if [[ $0 == *init_clang*_env* ]] ; then echo echo "*******************************************************************************************" echo " WARNING: The script $0 must be sourced in " echo "*******************************************************************************************" echo STANDALONE_SCRIPT=${__TRUE} fi # --------------------------------------------------------------------- LIB_DIRS="${CLANG_SYSROOT}/usr/lib" OBJ_DIRS="" INCLUDE_DIRS="${CLANG_SYSROOT}/usr/include ${CLANG_DIR}/include" BIN_DIRS="${CLANG_DIR}/bin" SYSROOT_CONFIGURE_OPTION="" if [ "${NDK_DIR}"x != ""x ] ; then if ${TEST} -d "${NDK_DIR}" ; then INCLUDE_DIRS="${INCLUDE_DIRS} ${NDK_DIR}/include ${NDK_DIR}/sysroot/usr/include/${CPU_TYPE}-linux-android" fi fi if [ "${SYSROOT}"x != ""x ] ; then if ${TEST} -d "${SYSROOT}" ; then SYSROOT_LIB_DIR="${SYSROOT}/usr/lib/${CPU_TYPE}-linux-android" INCLUDE_DIRS="${INCLUDE_DIRS} ${SYSROOT}/usr/include" LIB_DIRS="${LIB_DIRS} ${SYSROOT_LIB_DIR}/${API}" OBJ_DIRS="${OBJ_DIRS} ${SYSROOT_LIB_DIR}/${API}" LIB_DIRS="${LIB_DIRS} ${SYSROOT_LIB_DIR}" ${TEST} -d ${SYSROOT}/usr/bin && BIN_DIRS="${BIN_DIRS} ${SYSROOT}/usr/bin" SYSROOT_CONFIGURE_OPTION="--sysroot ${SYSROOT}" else echo "WARNING: The sysroot directory ${SYSROOT} does not exist" fi fi CLANG="${CLANG_DIR}/bin/clang" add_path "${CLANG_DIR}/bin" # --------------------------------------------------------------------- if ${TEST} ! -x "${CLANG}" ; then echo "ERROR: The binary ${CLANG} does not exist or is not executable" CONTINUE=${__FALSE} fi fi # --------------------------------------------------------------------- if [ ${CONTINUE} = ${__TRUE} ] ; then echo echo "Preparing the clang environment for creating binaries for the CPU type ${CPU_TYPE}" if [ "${CUR_CPU_TYPE}"x != "${CPU_TYPE}"x ] ; then echo "The current CPU type is \"${CUR_CPU_TYPE}\" " fi if [ "${TARGET_ROOT}"x != ""x ] ; then if ${TEST} -d "${TARGET_ROOT}" ; then INCLUDE_DIRS="${INCLUDE_DIRS} ${TARGET_ROOT}/usr/include" BIN_DIRS="${BIN_DIRS} ${TARGET_ROOT}/usr/bin" LIB_DIRS="${LIB_DIRS} ${TARGET_ROOT}/usr/lib" else echo "INFO: The target root directory ${TARGET_ROOT} does not exist" fi fi echo "" printf "%-90s %s\n" "Using clang ${CLANG_VERSION}" printf "\n" if [ "${NDK_DIR}"x != ""x ] ; then printf "%-90s %s\n" "Using the NDK ${NDK_DIR}" "(environment variable NDK_DIR)" fi if [ "${SYSROOT}"x != ""x ] ; then printf "%-90s %s\n" "Using the sysroot directory ${SYSROOT}" "(environment variable SYSROOT)" fi if [ "${TARGET_ROOT}"x != ""x ] ; then printf "%-90s %s\n" "Using the target root directory ${TARGET_ROOT}" "(environment variable TARGET_ROOT)" fi printf "\n" echo "" for CUR_DIR in ${BIN_DIRS} ; do echo ":${PATH}:" | grep ":${CUR_DIR}:" >/dev/null if [ $? -ne 0 ] ; then if ! ${TEST} -d "${CUR_DIR}" ; then echo "WARNING: The directory with binaries \"${CUR_DIR}\" does not exist" fi [[ :${PATH}: != *:${CUR_DIR}: ]] && PATH="${CUR_DIR}:${PATH}" fi done for CUR_DIR in ${INCLUDE_DIRS} ; do if ! ${TEST} -d "${CUR_DIR}" ; then echo "WARNING: The directory with include files \"${CUR_DIR}\" does not exist" fi echo "${CFLAGS} " | grep -- "-I${CUR_DIR} " >/dev/null if [ $? -ne 0 ] ; then echo "${CFLAGS} " | grep -- "-I${CUR_DIR} " >/dev/null CFLAGS="${CFLAGS} -I${CUR_DIR}" fi echo "${CPPFLAGS} " | grep -- "-I${CUR_DIR} " >/dev/null if [ $? -ne 0 ] ; then CPPFLAGS="${CPPFLAGS} -I${CUR_DIR}" fi echo "${CXXFLAGS} " | grep -- "-I${CUR_DIR} " >/dev/null if [ $? -ne 0 ] ; then CXXFLAGS="${CXXFLAGS} -I${CUR_DIR}" fi done for CUR_DIR in ${LIB_DIRS} ; do if ! ${TEST} -d "${CUR_DIR}" ; then echo "WARNING: The directory with libraries \"${CUR_DIR}\" does not exist" fi echo "${LDFLAGS} " | grep -- "-L${CUR_DIR} " >/dev/null if [ $? -ne 0 ] ; then LDFLAGS="${LDFLAGS} -L${CUR_DIR}" fi done for CUR_DIR in ${OBJ_DIRS} ; do if ! ${TEST} -d "${CUR_DIR}" ; then echo "WARNING: The directory with object files \"${CUR_DIR}\" does not exist" fi echo "${LDFLAGS} " | grep -- "-B${CUR_DIR}/ " >/dev/null if [ $? -ne 0 ] ; then LDFLAGS="${LDFLAGS} -B${CUR_DIR}/" fi done if [ "${SYSROOT_CONFIGURE_OPTION}"x != ""x ] ; then echo "$CFLAGS" | grep -- " --sysroot" >/dev/null || CFLAGS="$CFLAGS --sysroot=${SYSROOT}" echo "$CPPFLAGS" | grep -- " --sysroot" >/dev/null || CPPFLAGS="$CPPFLAGS --sysroot=${SYSROOT}" echo "$CXXLAGS" | grep -- " --sysroot " >/dev/null || CXXFLAGS="$CXXFLAGS --sysroot=${SYSROOT}" echo "$LDFLAGS" | grep -- " --sysroot " >/dev/null || LDFLAGS="$LDFLAGS --sysroot=${SYSROOT}" fi echo " $LDFLAGS " | grep -- " -lc " >/dev/null || LDFLAGS="$LDFLAGS -lc " add_library_path "${SYSROOT}/usr/lib/${CPU_TYPE}-linux-android" "${CLANG_DIR}/lib" for CUR_PKG_CONFIG_PATH in /data/local/tmp/sysroot/usr/lib/pkgconfig/ /data/local/tmp/develop/sysroot/usr/lib/pkgconfig/ ; do if [[ " :${PKG_CONFIG_PATH}: " != *:${CUR_PKG_CONFIG_PATH}:* ]] ; then export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${CUR_PKG_CONFIG_PATH}" fi done export CFLAGS CXXFLAGS CPPFLAGS LDFLAGS SYSROOT TARGET_ROOT API NDK SYSROOT PKG_CONFIG_PATH export CC="${CLANG_DIR}/bin/clang" export CXX="${CLANG_DIR}/bin/clang++" export AR="${CLANG_DIR}/bin/llvm-ar" export AS="${CLANG_DIR}/bin/llvm-as" export LD="${CLANG_DIR}/bin/lld" export RANLIB="${CLANG_DIR}/bin/llvm-ranlib" export STRIP="${CLANG_DIR}/bin/llvm-strip" export CPP="${CLANG_DIR}/bin/clang-cpp" export CXXCPP="${CLANG_DIR}/bin/clang-cpp" if [ "${PKG_CONFIG}"x = ""x ] ; then export PKG_CONFIG="${CLANG_DIR}/bin/pkg-config" fi echo "Environment variables used:" CUR_VAR_NAME_FIELD_LENGTH=25 printf "\n" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "PATH is now:" "${PATH}" printf "\n" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "LD_LIBRARY_PATH:" "${LD_LIBRARY_PATH}" printf "\n" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "API is now:" "${API}" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "NDK_DIR is now:" "${NDK_DIR}" printf "\n" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "SYSROOT is now:" "${SYSROOT}" printf "\n" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "CFLAGS are now:" "${CFLAGS}" printf "\n" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "CPPFLAGS are now:" "${CPPFLAGS}" printf "\n" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "CXXFLAGS are now:" "${CXXFLAGS}" printf "\n" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "LDFLAGS are now:" "${LDFLAGS}" printf "\n" for CUR_VAR in CC CXX CPP CXXCPP AR AS LD RANLIB STRIP PKG_CONFIG PKG_CONFIG_PATH ; do eval CUR_VALUE="\$$CUR_VAR" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "${CUR_VAR} is now:" "${CUR_VALUE}" done echo if ! ${TEST} -d /tmp ; then if [ "${TMP}"x = ""x ] ; then if ${TEST} -d /data/local/tmp ; then export TMP="/data/local/tmp" printf "%-${CUR_VAR_NAME_FIELD_LENGTH}s %s\n" "TMP is now:" "${TMP}" else echo "WARNING: The directories /tmp and /data/local/tmp do not exist - please set the variable TMP before using clang" fi fi fi echo "Checking the clang binary ..." echo ${CLANG} --version THISRC=$? echo if [ ${THISRC} != 0 ] ; then echo "WARNING: Executing \"${CLANG} --version\" ended with RC=${THISRC}" fi if [ $API -lt 30 ] ; then echo echo "WARNING: Compling C++ program using API version less then 30 will probably not work" echo fi export CC=${CLANG} export LD=${LLD} # define aliase # echo "Define some aliase ..." NEW_ALIAS="" alias sysroot="cd ${CLANG_SYSROOT}; pwd" alias setlibpath="export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" alias addlib='LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/data/local/tmp/develop/sysroot/usr/lib ' alias cp_crt_libs='cp ${NDK_DIR}/sysroot/usr/lib/${CPU_TYPE}-linux-android/${API}/crt*.o .' NEW_ALIAS="sysroot setlibpath addlib" for i in vi find tar bash sed awk dd nano curl ; do if ${TEST} -x "${CLANG_SYSROOT}/usr/bin/$i" ; then alias $i="${CLANG_SYSROOT}/usr/bin/$i" NEW_ALIAS="${NEW_ALIAS} $i" fi done for i in /system_ext/bin/* ; do f=${i##*/} [[ " ${NEW_ALIAS} " == *\ $f\ * ]] && continue if [ -x "${CLANG_SYSROOT}/usr/bin/$f" ] ; then alias $f="${CLANG_SYSROOT}/usr/bin/$f" NEW_ALIAS="${NEW_ALIAS} $f" fi done for i in ${NEW_ALIAS} ; do alias $i done echo "" if [ ${ROOT_ACCESS_AVAILABLE} = ${__TRUE} ] ; then if [ "${ROOT_PREFIX}"x = ""x ] ; then echo "The user running this script is the user \"root\" " else echo "Root access is enabled on this machine" echo "" if [ "${MAGISKPOLICY}"x != ""x ] ; then echo "Adding missing SELinux policies using \"${MAGISKPOLICY}\" ..." if which tmux 2>/dev/null 1>dev/null ; then echo "Enabling socket access for the user \"shell\" (this is necessary to use tmux)..." ${ROOT_PREFIX} ${MAGISKPOLICY} '--live "allow shell shell_data_file sock_file { create getattr setattr write unlink }" ' ${ROOT_PREFIX} ${MAGISKPOLICY} '--live "allow shell devpts chr_file { read write open }"' fi if which mtr 2>/dev/null 1>dev/null ; then echo "Enabling icmp_socket access for the user \"shell\" (this is necessary to use mtr)..." ${ROOT_PREFIX} ${MAGISKPOLICY} '--live "allow shell port icmp_socket { name_bind }"' fi echo "Enabling hard links for the user \"shell\" ..." ${ROOT_PREFIX} ${MAGISKPOLICY} '--live "allow shell shell_data_file file link" ' echo "Enabling creating and using fifos for the user \"shell\" ..." ${ROOT_PREFIX} ${MAGISKPOLICY} '--live "allow shell shell_data_file fifo_file { create read open write getattr unlink ioctl }" ' elif [ "${SELINUX_HELP_SCRIPT}"x != ""x ] ; then echo "Adding missing SELinux policies using the script \"${SELINUX_HELP_SCRIPT}\" ..." ${ROOT_PREFIX} ${SELINUX_HELP_SCRIPT} else LogDebugMsg "Magisk is not installed on this machine and the SELinux helper script is missing - can not add missing SELinux rules" fi fi echo "" else LogDebugMsg "root access is NOT enabled on this machine" fi if ${TEST} -r ${DEFAULT_SSL_CERT_FILE} ; then echo "Setting the variable \"SSL_CERT_FILE\" to \"${DEFAULT_SSL_CERT_FILE}\" ..." export SSL_CERT_FILE=${DEFAULT_SSL_CERT_FILE} else echo "WARNING: Certificate file \"${DEFAULT_SSL_CERT_FILE}\" not found " fi echo "$PS1" | grep "\[clang19" 2>/dev/null >/dev/null || export PS1="[clang19 toolchain] $PS1" CLANG_ENV_INIT_DONE=${__TRUE} echo "" if [ "${HOSTNAME}"x = ""x ] ; then if [ $( hostname )x != "localhost"x ] ; then export HOSTNAME="$( hostname )" else export HOSTNAME="$( getprop ro.product.device ) $( getprop ro.serialno )" fi fi fi if [ ${PRINT_EXAMPLES} = ${__TRUE} ] ; then cat <