1# Copyright (C) 2010 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# 15 16# Create a standalone toolchain package for Android. 17 18. `dirname $0`/prebuilt-common.sh 19 20PROGRAM_PARAMETERS="" 21PROGRAM_DESCRIPTION=\ 22"Generate a customized Android toolchain installation that includes 23a working sysroot. The result is something that can more easily be 24used as a standalone cross-compiler, e.g. to run configure and 25make scripts." 26 27# For now, this is the only toolchain that works reliably. 28TOOLCHAIN_NAME= 29register_var_option "--toolchain=<name>" TOOLCHAIN_NAME "Specify toolchain name" 30 31LLVM_VERSION= 32register_var_option "--llvm-version=<ver>" LLVM_VERSION "Specify LLVM version" 33 34ARCH= 35register_option "--arch=<name>" do_arch "Specify target architecture" "arm" 36do_arch () { ARCH=$1; } 37 38NDK_DIR=`dirname $0` 39NDK_DIR=`dirname $NDK_DIR` 40NDK_DIR=`dirname $NDK_DIR` 41register_var_option "--ndk-dir=<path>" NDK_DIR "Take source files from NDK at <path>" 42 43# Create 32-bit host toolchain by default 44SYSTEM=$HOST_TAG32 45register_var_option "--system=<name>" SYSTEM "Specify host system" 46 47PACKAGE_DIR=/tmp/ndk-$USER 48register_var_option "--package-dir=<path>" PACKAGE_DIR "Place package file in <path>" 49 50INSTALL_DIR= 51register_var_option "--install-dir=<path>" INSTALL_DIR "Don't create package, install files to <path> instead." 52 53PLATFORM= 54register_option "--platform=<name>" do_platform "Specify target Android platform/API level." "android-3" 55do_platform () { PLATFORM=$1; } 56 57extract_parameters "$@" 58 59# Check NDK_DIR 60if [ ! -d "$NDK_DIR/build/core" ] ; then 61 echo "Invalid source NDK directory: $NDK_DIR" 62 echo "Please use --ndk-dir=<path> to specify the path of an installed NDK." 63 exit 1 64fi 65 66# Check ARCH 67if [ -z "$ARCH" ]; then 68 case $TOOLCHAIN_NAME in 69 arm-*) 70 ARCH=arm 71 ;; 72 x86-*) 73 ARCH=x86 74 ;; 75 mips*) 76 ARCH=mips 77 ;; 78 *) 79 ARCH=arm 80 ;; 81 esac 82 log "Auto-config: --arch=$ARCH" 83fi 84 85# Check toolchain name 86if [ -z "$TOOLCHAIN_NAME" ]; then 87 TOOLCHAIN_NAME=$(get_default_toolchain_name_for_arch $ARCH) 88 echo "Auto-config: --toolchain=$TOOLCHAIN_NAME" 89fi 90 91# Detect LLVM version from toolchain name 92if [ -z "$LLVM_VERSION" ]; then 93 LLVM_VERSION_EXTRACT=$(echo "$TOOLCHAIN_NAME" | grep 'clang[0-9]\.[0-9]$' | sed -e 's/.*-clang//') 94 if [ -n "$LLVM_VERSION_EXTRACT" ]; then 95 TOOLCHAIN_NAME=$(get_default_toolchain_name_for_arch $ARCH) 96 LLVM_VERSION=$LLVM_VERSION_EXTRACT 97 echo "Auto-config: --toolchain=$TOOLCHAIN_NAME, --llvm-version=$LLVM_VERSION" 98 fi 99fi 100 101# Check PLATFORM 102if [ -z "$PLATFORM" ]; then 103 case $ARCH in 104 arm) PLATFORM=android-3 105 ;; 106 x86) 107 PLATFORM=android-9 108 ;; 109 mips) 110 # Set it to android-9 111 PLATFORM=android-9 112 ;; 113 esac 114 log "Auto-config: --platform=$PLATFORM" 115fi 116 117if [ ! -d "$NDK_DIR/platforms/$PLATFORM" ] ; then 118 echo "Invalid platform name: $PLATFORM" 119 echo "Please use --platform=<name> with one of:" `(cd "$NDK_DIR/platforms" && ls)` 120 exit 1 121fi 122 123# Check toolchain name 124TOOLCHAIN_PATH="$NDK_DIR/toolchains/$TOOLCHAIN_NAME" 125if [ ! -d "$TOOLCHAIN_PATH" ] ; then 126 echo "Invalid toolchain name: $TOOLCHAIN_NAME" 127 echo "Please use --toolchain=<name> with the name of a toolchain supported by the source NDK." 128 echo "Try one of: " `(cd "$NDK_DIR/toolchains" && ls)` 129 exit 1 130fi 131 132# Extract architecture from platform name 133parse_toolchain_name $TOOLCHAIN_NAME 134 135# Check that there are any platform files for it! 136(cd $NDK_DIR/platforms && ls -d */arch-${ARCH} >/dev/null 2>&1 ) 137if [ $? != 0 ] ; then 138 echo "Platform $PLATFORM doesn't have any files for this architecture: $ARCH" 139 echo "Either use --platform=<name> or --toolchain=<name> to select a different" 140 echo "platform or arch-dependent toolchain name (respectively)!" 141 exit 1 142fi 143 144# Compute source sysroot 145SRC_SYSROOT="$NDK_DIR/platforms/$PLATFORM/arch-$ARCH" 146if [ ! -d "$SRC_SYSROOT" ] ; then 147 echo "No platform files ($PLATFORM) for this architecture: $ARCH" 148 exit 1 149fi 150 151# Check that we have any prebuilts GCC toolchain here 152if [ ! -d "$TOOLCHAIN_PATH/prebuilt" ] ; then 153 echo "Toolchain is missing prebuilt files: $TOOLCHAIN_NAME" 154 echo "You must point to a valid NDK release package!" 155 exit 1 156fi 157 158if [ ! -d "$TOOLCHAIN_PATH/prebuilt/$SYSTEM" ] ; then 159 echo "Host system '$SYSTEM' is not supported by the source NDK!" 160 echo "Try --system=<name> with one of: " `(cd $TOOLCHAIN_PATH/prebuilt && ls) | grep -v gdbserver` 161 exit 1 162fi 163 164TOOLCHAIN_PATH="$TOOLCHAIN_PATH/prebuilt/$SYSTEM" 165TOOLCHAIN_GCC=$TOOLCHAIN_PATH/bin/$ABI_CONFIGURE_TARGET-gcc 166 167if [ ! -f "$TOOLCHAIN_GCC" ] ; then 168 echo "Toolchain $TOOLCHAIN_GCC is missing!" 169 exit 1 170fi 171 172if [ -n "$LLVM_VERSION" ]; then 173 LLVM_TOOLCHAIN_PATH="$NDK_DIR/toolchains/llvm-$LLVM_VERSION" 174 # Check that we have any prebuilts LLVM toolchain here 175 if [ ! -d "$LLVM_TOOLCHAIN_PATH/prebuilt" ] ; then 176 echo "LLVM Toolchain is missing prebuilt files" 177 echo "You must point to a valid NDK release package!" 178 exit 1 179 fi 180 181 if [ ! -d "$LLVM_TOOLCHAIN_PATH/prebuilt/$SYSTEM" ] ; then 182 echo "Host system '$SYSTEM' is not supported by the source NDK!" 183 echo "Try --system=<name> with one of: " `(cd $LLVM_TOOLCHAIN_PATH/prebuilt && ls)` 184 exit 1 185 fi 186 LLVM_TOOLCHAIN_PATH="$LLVM_TOOLCHAIN_PATH/prebuilt/$SYSTEM" 187fi 188 189# Get GCC_BASE_VERSION. Note that GCC_BASE_VERSION may be slightly different from GCC_VERSION. 190# eg. In gcc4.6 GCC_BASE_VERSION is "4.6.x-google" 191LIBGCC_PATH=`$TOOLCHAIN_GCC -print-libgcc-file-name` 192LIBGCC_BASE_PATH=${LIBGCC_PATH%/*} # base path of libgcc.a 193GCC_BASE_VERSION=${LIBGCC_BASE_PATH##*/} # stuff after the last / 194 195# Create temporary directory 196TMPDIR=$NDK_TMPDIR/standalone/$TOOLCHAIN_NAME 197 198dump "Copying prebuilt binaries..." 199# Now copy the GCC toolchain prebuilt binaries 200run copy_directory "$TOOLCHAIN_PATH" "$TMPDIR" 201 202if [ -n "$LLVM_VERSION" ]; then 203 # Copy the clang/llvm toolchain prebuilt binaries 204 run copy_directory "$LLVM_TOOLCHAIN_PATH" "$TMPDIR" 205 206 # Move clang and clang++ to clang${LLVM_VERSION} and clang${LLVM_VERSION}++, 207 # then create scripts linking them with predefined -target flag. This is to 208 # make clang/++ easier drop-in replacement for gcc/++ in NDK standalone mode. 209 # Note that the file name of "clang" isn't important, and the trailing 210 # "++" tells clang to compile in C++ mode 211 LLVM_TARGET= 212 case "$ARCH" in 213 arm) # NOte: -target may change by clang based on the 214 # presence of subsequent -march=armv7-a and/or -mthumb 215 LLVM_TARGET=armv5te-none-linux-androideabi 216 ;; 217 x86) 218 LLVM_TARGET=i686-none-linux-android 219 ;; 220 mips) 221 LLVM_TARGET=mipsel-none-linux-android 222 ;; 223 *) 224 dump "ERROR: Unsupported NDK architecture!" 225 esac 226 # Need to remove '.' from LLVM_VERSION when constructing new clang name, 227 # otherwise clang3.1++ may still compile *.c code as C, not C++, which 228 # is not consistent with g++ 229 LLVM_VERSION_WITHOUT_DOT=$(echo "$LLVM_VERSION" | sed -e "s!\.!!") 230 mv "$TMPDIR/bin/clang${HOST_EXE}" "$TMPDIR/bin/clang${LLVM_VERSION_WITHOUT_DOT}${HOST_EXE}" 231 if [ -h "$TMPDIR/bin/clang++${HOST_EXE}" ] ; then 232 ## clang++ is a link to clang. Remove it and reconstruct 233 rm "$TMPDIR/bin/clang++${HOST_EXE}" 234 ln -s "clang${LLVM_VERSION_WITHOUT_DOT}${HOST_EXE}" "$TMPDIR/bin/clang${LLVM_VERSION_WITHOUT_DOT}++${HOST_EXE}" 235 else 236 mv "$TMPDIR/bin/clang++${HOST_EXE}" "$TMPDIR/bin/clang$LLVM_VERSION_WITHOUT_DOT++${HOST_EXE}" 237 fi 238 239 cat > "$TMPDIR/bin/clang" <<EOF 240if [ "\$1" != "-cc1" ]; then 241 \`dirname \$0\`/clang$LLVM_VERSION_WITHOUT_DOT -target $LLVM_TARGET "\$@" 242else 243 # target/triple already spelled out. 244 \`dirname \$0\`/clang$LLVM_VERSION_WITHOUT_DOT "\$@" 245fi 246EOF 247 cat > "$TMPDIR/bin/clang++" <<EOF 248if [ "\$1" != "-cc1" ]; then 249 \`dirname \$0\`/clang$LLVM_VERSION_WITHOUT_DOT++ -target $LLVM_TARGET "\$@" 250else 251 # target/triple already spelled out. 252 \`dirname \$0\`/clang$LLVM_VERSION_WITHOUT_DOT++ "\$@" 253fi 254EOF 255 chmod 0755 "$TMPDIR/bin/clang" "$TMPDIR/bin/clang++" 256 257 if [ -n "$HOST_EXE" ] ; then 258 cat > "$TMPDIR/bin/clang.cmd" <<EOF 259@echo off 260if "%1" == "-cc1" goto :L 261%~dp0\\clang${LLVM_VERSION_WITHOUT_DOT}${HOST_EXE} -target $LLVM_TARGET %* 262if ERRORLEVEL 1 exit /b 1 263goto :done 264:L 265rem target/triple already spelled out. 266%~dp0\\clang${LLVM_VERSION_WITHOUT_DOT}${HOST_EXE} %* 267if ERRORLEVEL 1 exit /b 1 268:done 269EOF 270 cat > "$TMPDIR/bin/clang++.cmd" <<EOF 271@echo off 272if "%1" == "-cc1" goto :L 273%~dp0\\clang${LLVM_VERSION_WITHOUT_DOT}++${HOST_EXE} -target $LLVM_TARGET %* 274if ERRORLEVEL 1 exit /b 1 275goto :done 276:L 277rem target/triple already spelled out. 278%~dp0\\clang${LLVM_VERSION_WITHOUT_DOT}++${HOST_EXE} %* 279if ERRORLEVEL 1 exit /b 1 280:done 281EOF 282 fi 283fi 284 285dump "Copying sysroot headers and libraries..." 286# Copy the sysroot under $TMPDIR/sysroot. The toolchain was built to 287# expect the sysroot files to be placed there! 288run copy_directory_nolinks "$SRC_SYSROOT" "$TMPDIR/sysroot" 289 290dump "Copying libstdc++ headers and libraries..." 291 292GNUSTL_DIR=$NDK_DIR/$GNUSTL_SUBDIR/$GCC_VERSION 293GNUSTL_LIBS=$GNUSTL_DIR/libs 294 295ABI_STL="$TMPDIR/$ABI_CONFIGURE_TARGET" 296ABI_STL_INCLUDE="$TMPDIR/include/c++/$GCC_BASE_VERSION" 297 298copy_directory "$GNUSTL_DIR/include" "$ABI_STL_INCLUDE" 299ABI_STL_INCLUDE_TARGET="$ABI_STL_INCLUDE/$ABI_CONFIGURE_TARGET" 300mkdir -p "$ABI_STL_INCLUDE_TARGET" 301fail_panic "Can't create directory: $ABI_STL_INCLUDE_TARGET" 302case "$ARCH" in 303 arm) 304 copy_directory "$GNUSTL_LIBS/armeabi/include/bits" "$ABI_STL_INCLUDE_TARGET/bits" 305 copy_file_list "$GNUSTL_LIBS/armeabi" "$ABI_STL/lib" "libgnustl_shared.so" 306 copy_file_list "$GNUSTL_LIBS/armeabi" "$ABI_STL/lib" "libsupc++.a" 307 cp -p "$GNUSTL_LIBS/armeabi/libgnustl_static.a" "$ABI_STL/lib/libstdc++.a" 308 309 copy_directory "$GNUSTL_LIBS/armeabi/include/bits" "$ABI_STL_INCLUDE_TARGET/thumb/bits" 310 copy_file_list "$GNUSTL_LIBS/armeabi/thumb" "$ABI_STL/lib/thumb" "libgnustl_shared.so" 311 copy_file_list "$GNUSTL_LIBS/armeabi/thumb" "$ABI_STL/lib/thumb" "libsupc++.a" 312 cp -p "$GNUSTL_LIBS/armeabi/thumb/libgnustl_static.a" "$ABI_STL/lib/thumb/libstdc++.a" 313 314 copy_directory "$GNUSTL_LIBS/armeabi-v7a/include/bits" "$ABI_STL_INCLUDE_TARGET/armv7-a/bits" 315 copy_file_list "$GNUSTL_LIBS/armeabi-v7a" "$ABI_STL/lib/armv7-a" "libgnustl_shared.so" 316 copy_file_list "$GNUSTL_LIBS/armeabi-v7a" "$ABI_STL/lib/armv7-a" "libsupc++.a" 317 cp -p "$GNUSTL_LIBS/armeabi-v7a/libgnustl_static.a" "$ABI_STL/lib/armv7-a/libstdc++.a" 318 319 copy_directory "$GNUSTL_LIBS/armeabi-v7a/include/bits" "$ABI_STL_INCLUDE_TARGET/armv7-a/thumb/bits" 320 copy_file_list "$GNUSTL_LIBS/armeabi-v7a/thumb" "$ABI_STL/lib/armv7-a/thumb/" "libgnustl_shared.so" 321 copy_file_list "$GNUSTL_LIBS/armeabi-v7a/thumb" "$ABI_STL/lib/armv7-a/thumb/" "libsupc++.a" 322 cp -p "$GNUSTL_LIBS/armeabi-v7a/thumb/libgnustl_static.a" "$ABI_STL/lib/armv7-a//thumb/libstdc++.a" 323 ;; 324 x86) 325 copy_directory "$GNUSTL_LIBS/x86/include/bits" "$ABI_STL_INCLUDE_TARGET/bits" 326 copy_file_list "$GNUSTL_LIBS/x86" "$ABI_STL/lib" "libgnustl_shared.so" 327 copy_file_list "$GNUSTL_LIBS/x86" "$ABI_STL/lib" "libsupc++.a" 328 cp -p "$GNUSTL_LIBS/x86/libgnustl_static.a" "$ABI_STL/lib/libstdc++.a" 329 ;; 330 mips) 331 copy_directory "$GNUSTL_LIBS/mips/include/bits" "$ABI_STL_INCLUDE_TARGET/bits" 332 copy_file_list "$GNUSTL_LIBS/mips" "$ABI_STL/lib" "libgnustl_shared.so" 333 copy_file_list "$GNUSTL_LIBS/mips" "$ABI_STL/lib" "libsupc++.a" 334 cp -p "$GNUSTL_LIBS/mips/libgnustl_static.a" "$ABI_STL/lib/libstdc++.a" 335 ;; 336 *) 337 dump "ERROR: Unsupported NDK architecture!" 338esac 339 340# Install or Package 341if [ -n "$INSTALL_DIR" ] ; then 342 dump "Copying files to: $INSTALL_DIR" 343 run copy_directory "$TMPDIR" "$INSTALL_DIR" 344else 345 PACKAGE_FILE="$PACKAGE_DIR/$TOOLCHAIN_NAME.tar.bz2" 346 dump "Creating package file: $PACKAGE_FILE" 347 pack_archive "$PACKAGE_FILE" "`dirname $TMPDIR`" "$TOOLCHAIN_NAME" 348 fail_panic "Could not create tarball from $TMPDIR" 349fi 350dump "Cleaning up..." 351run rm -rf $TMPDIR 352 353dump "Done." 354