1 #!/bin/sh 2 # 3 # Copyright (C) 2012 The Android Open Source Project 4 # Copyright (C) 2012 Ray Donnelly <mingw.android at gmail.com> 5 # 6 # Licensed under the Apache License, Version 2.0 (the "License"); 7 # you may not use this file except in compliance with the License. 8 # You may obtain a copy of the License at 9 # 10 # http://www.apache.org/licenses/LICENSE-2.0 11 # 12 # Unless required by applicable law or agreed to in writing, software 13 # distributed under the License is distributed on an "AS IS" BASIS, 14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 # See the License for the specific language governing permissions and 16 # limitations under the License. 17 # 18 # Rebuild the host Python binaries from sources. 19 # Also copies any gnu libstdc++ pretty-printers 20 # found in $TOOLCHAIN_SRC_DIR/gcc/gcc-* 21 # and Joachim Reichel's stlport pretty printers 22 # found in sources/host-tools/gdb-pretty-printers/stlport 23 # 24 25 # include common function and variable definitions 26 NDK_BUILDTOOLS_PATH="$(dirname $0)" 27 . "$NDK_BUILDTOOLS_PATH/prebuilt-common.sh" 28 . "$NDK_BUILDTOOLS_PATH/common-build-host-funcs.sh" 29 30 PROGRAM_PARAMETERS="" 31 PROGRAM_DESCRIPTION="\ 32 This program is used to rebuild one or more Python client programs from 33 sources. To use it, you will need a working set of toolchain sources, like 34 those downloaded with download-toolchain-sources.sh, then pass the 35 corresponding directory with the --toolchain-src-dir=<path> option. 36 37 By default, the script rebuilds Python for you host system [$HOST_TAG], 38 but you can use --systems=<tag1>,<tag2>,.. to ask binaries that can run on 39 several distinct systems. Each <tag> value in the list can be one of the 40 following: 41 42 linux-x86 43 linux-x86_64 44 windows 45 windows-x86 (equivalent to 'windows') 46 windows-x86_64 47 darwin-x86 48 darwin-x86_64 49 50 For example, here's how to rebuild Python 2.7.5 on Linux 51 for six different systems: 52 53 $PROGNAME --build-dir=/path/to/toolchain/src \n \ 54 --python-version=2.7.5 \n \ 55 --systems=linux-x86,linux-x86_64,windows,windows-x86_64,darwin-x86,darwin-x86_64" 56 57 TOOLCHAIN_SRC_DIR= 58 register_var_option "--toolchain-src-dir=<path>" TOOLCHAIN_SRC_DIR "Select toolchain source directory" 59 60 PYTHON_VERSION=$DEFAULT_PYTHON_VERSION 61 register_var_option "--python-version=<version>" PYTHON_VERSION "Select Python version." 62 63 NDK_DIR=$ANDROID_NDK_ROOT 64 register_var_option "--ndk-dir=<path>" NDK_DIR "Select NDK install directory." 65 66 PACKAGE_DIR= 67 register_var_option "--package-dir=<path>" PACKAGE_DIR "Package prebuilt tarballs into directory." 68 69 BUILD_DIR= 70 register_var_option "--build-dir=<path>" BUILD_DIR "Build Python into directory" 71 72 bh_register_options 73 register_try64_option 74 register_canadian_option 75 register_jobs_option 76 77 extract_parameters "$@" 78 79 if [ -n "$PARAMETERS" ]; then 80 panic "This script doesn't take parameters, only options. See --help" 81 fi 82 83 if [ -z "$TOOLCHAIN_SRC_DIR" ]; then 84 panic "Please use --toolchain-src-dir=<path> to select toolchain source directory." 85 fi 86 check_toolchain_src_dir "$TOOLCHAIN_SRC_DIR" 87 TOOLCHAIN_SRC_DIR=`cd $TOOLCHAIN_SRC_DIR; pwd` 88 89 BH_HOST_SYSTEMS=$(commas_to_spaces $BH_HOST_SYSTEMS) 90 AUTO_BUILD="no" 91 92 if [ "$MINGW" = "yes" ]; then 93 BH_HOST_SYSTEMS="windows" 94 log "Auto-config: --systems=windows" 95 fi 96 97 if [ "$DARWIN" = "yes" ]; then 98 BH_HOST_SYSTEMS="darwin-x86" 99 log "Auto-config: --systems=darwin-x86" 100 fi 101 102 determine_systems () 103 { 104 local IN_SYSTEMS="$1" 105 local OUT_SYSTEMS 106 107 for SYSTEM in $IN_SYSTEMS; do 108 if [ "$TRY64" = "yes" ]; then 109 case $SYSTEM in 110 darwin-x86|linux-x86|windows-x86) 111 SYSTEM=${SYSTEM%%x86}x86_64 112 ;; 113 windows) 114 SYSTEM=windows-x86_64 115 ;; 116 esac 117 else 118 # 'windows-x86' causes substitution 119 # failure at the packing stage. 120 case $SYSTEM in 121 windows-x86) 122 SYSTEM=windows 123 ;; 124 esac 125 fi 126 OUT_SYSTEMS="$OUT_SYSTEMS $SYSTEM" 127 done 128 echo $OUT_SYSTEMS 129 } 130 131 BH_HOST_SYSTEMS=$(determine_systems "$BH_HOST_SYSTEMS") 132 133 # Build python for build machine automatically 134 if [ "$(bh_list_contains $BH_BUILD_TAG $BH_HOST_SYSTEMS)" = "no" ]; then 135 BH_HOST_SYSTEMS="$BH_BUILD_TAG $BH_HOST_SYSTEMS" 136 AUTO_BUILD="yes" 137 fi 138 139 # Python needs to execute itself during its build process, so must build the build 140 # Python first. It should also be an error if not asked to build for build machine. 141 BH_HOST_SYSTEMS=$(bh_sort_systems_build_first "$BH_HOST_SYSTEMS") 142 143 download_package () 144 { 145 # Assume the packages are already downloaded under $ARCHIVE_DIR 146 local PKG_URL=$1 147 local PKG_NAME=$(basename $PKG_URL) 148 149 case $PKG_NAME in 150 *.tar.bz2) 151 PKG_BASENAME=${PKG_NAME%%.tar.bz2} 152 ;; 153 *.tar.gz) 154 PKG_BASENAME=${PKG_NAME%%.tar.gz} 155 ;; 156 *) 157 panic "Unknown archive type: $PKG_NAME" 158 esac 159 160 if [ ! -f "$ARCHIVE_DIR/$PKG_NAME" ]; then 161 log "Downloading $PKG_URL..." 162 (cd $ARCHIVE_DIR && run curl -L -o "$PKG_NAME" "$PKG_URL") 163 fail_panic "Can't download '$PKG_URL'" 164 fi 165 166 if [ ! -d "$SRC_DIR/$PKG_BASENAME" ]; then 167 log "Uncompressing $PKG_URL into $SRC_DIR" 168 case $PKG_NAME in 169 *.tar.bz2) 170 run tar xjf $ARCHIVE_DIR/$PKG_NAME -C $SRC_DIR 171 ;; 172 *.tar.gz) 173 run tar xzf $ARCHIVE_DIR/$PKG_NAME -C $SRC_DIR 174 ;; 175 *) 176 panic "Unknown archive type: $PKG_NAME" 177 ;; 178 esac 179 fail_panic "Can't uncompress $ARCHIVE_DIR/$PKG_NAME" 180 fi 181 } 182 183 if [ -z "$BUILD_DIR" ] ; then 184 BUILD_DIR=/tmp/ndk-$USER/buildhost 185 fi 186 187 bh_setup_build_dir $BUILD_DIR 188 189 if [ "$BH_BUILD_MODE" = "debug" ] ; then 190 PYDEBUG="-with-pydebug" 191 fi 192 193 # Sanity check that we have the right compilers for all hosts 194 for SYSTEM in $BH_HOST_SYSTEMS; do 195 bh_setup_build_for_host $SYSTEM 196 done 197 198 TEMP_DIR=$BUILD_DIR/tmp 199 # Download and unpack source packages from official sites 200 ARCHIVE_DIR=$TEMP_DIR/archive 201 STAMP_DIR=$TEMP_DIR/timestamps 202 BUILD_DIR=$TEMP_DIR/build-$HOST_TAG 203 204 mkdir -p $BUILD_DIR 205 206 PROGDIR=`dirname $0` 207 PROGDIR=$(cd $PROGDIR && pwd) 208 209 # Sanity check for all Python versions. 210 for VERSION in $(commas_to_spaces $PYTHON_VERSION); do 211 PYTHON_SRCDIR=$TOOLCHAIN_SRC_DIR/python/Python-$VERSION 212 if [ ! -d "$PYTHON_SRCDIR" ]; then 213 panic "Missing source directory: $PYTHON_SRCDIR" 214 fi 215 done 216 217 arch_to_qemu_arch () 218 { 219 case $1 in 220 x86) 221 echo i386 222 ;; 223 *) 224 echo $1 225 ;; 226 esac 227 } 228 229 # $1: host system tag 230 # $2: python version 231 build_host_python () 232 { 233 local SRCDIR=$TOOLCHAIN_SRC_DIR/python/Python-$2 234 local BUILDDIR=$BH_BUILD_DIR/build-python-$1-$2 235 local INSTALLDIR=$(python_build_install_dir $1 $2) 236 local ARGS TEXT 237 238 if [ ! -f "$SRCDIR/configure" ]; then 239 panic "Missing configure script in $SRCDIR" 240 fi 241 242 # Currently, 2.7.5 and 3.3.0 builds generate $SRCDIR/Lib/_sysconfigdata.py, unless it 243 # already exists (in which case it ends up wrong anyway!)... this should really be in 244 # the build directory instead. 245 if [ ! -f "$SRCDIR/Lib/_sysconfigdata.py" ]; then 246 log "Removing old $SRCDIR/Lib/_sysconfigdata.py" 247 rm -f $SRCDIR/Lib/_sysconfigdata.py 248 fi 249 250 ARGS=" --prefix=$INSTALLDIR" 251 252 ARGS=$ARGS" --build=$BH_BUILD_CONFIG" 253 ARGS=$ARGS" --host=$BH_HOST_CONFIG" 254 ARGS=$ARGS" --with-build-sysroot" 255 ARGS=$ARGS" $PYDEBUG" 256 ARGS=$ARGS" --disable-ipv6" 257 258 mkdir -p "$BUILDDIR" && rm -rf "$BUILDDIR"/* 259 cd "$BUILDDIR" && 260 bh_setup_host_env 261 262 CFG_SITE= 263 # Need to add -L$HOST_STATIC_LIBDIR to LDSHARED if need 264 # any static host libs. 265 export LDSHARED="$CC -shared " 266 if [ ! $BH_HOST_TAG = $BH_BUILD_TAG ]; then 267 268 # Cross compiling. 269 CFG_SITE=$BUILDDIR/config.site 270 271 # Ideally would remove all of these configury hacks by 272 # patching the issues. 273 274 if [ $1 = darwin-x86 -o $1 = darwin-x86_64 ]; then 275 echo "ac_cv_file__dev_ptmx=no" > $CFG_SITE 276 echo "ac_cv_file__dev_ptc=no" >> $CFG_SITE 277 echo "ac_cv_have_long_long_format=yes" >> $CFG_SITE 278 if [ $1 = darwin-x86 ] ; then 279 echo "ac_osx_32bit=yes" >> $CFG_SITE 280 elif [ $1 = darwin-x86_64 ] ; then 281 echo "ac_osx_32bit=no" >> $CFG_SITE 282 fi 283 echo "ac_cv_have_sendfile=no" >> $CFG_SITE 284 # I could change AC_MSG_CHECKING(LDSHARED) in configure.ac 285 # to check $host instead of $ac_sys_system/$ac_sys_release 286 # but it handles loads of platforms 287 # and I can only test on three, so instead... 288 export LDSHARED="$CC -bundle -undefined dynamic_lookup" 289 elif [ $1 = windows-x86 -o $1 = windows-x86_64 ]; then 290 echo "ac_cv_file__dev_ptmx=no" > $CFG_SITE 291 echo "ac_cv_file__dev_ptc=no" >> $CFG_SITE 292 CFLAGS=$CFLAGS" -D__USE_MINGW_ANSI_STDIO=1" 293 CXXFLAGS=$CXXFLAGS" -D__USE_MINGW_ANSI_STDIO=1" 294 elif [ $1 = linux-x86 -o $1 = linux-x86_64 ]; then 295 echo "ac_cv_file__dev_ptmx=yes" > $CFG_SITE 296 echo "ac_cv_file__dev_ptc=no" >> $CFG_SITE 297 echo "ac_cv_have_long_long_format=yes" >> $CFG_SITE 298 echo "ac_cv_pthread_system_supported=yes" >> $CFG_SITE 299 echo "ac_cv_working_tzset=yes" >> $CFG_SITE 300 echo "ac_cv_little_endian_double=yes" >> $CFG_SITE 301 fi 302 303 if [ "$BH_HOST_OS" = "$BH_BUILD_OS" ]; then 304 # Only cross compiling from arch perspective. 305 # qemu causes failures as cross-compilation is not detected 306 # if a test executable can be run successfully, so we test 307 # for qemu-${BH_HOST_ARCH} and qemu-${BH_HOST_ARCH}-static 308 # and panic if either are found. 309 QEMU_HOST_ARCH=$(arch_to_qemu_arch $BH_HOST_ARCH) 310 if [ ! -z "$(which qemu-$QEMU_HOST_ARCH 2>/dev/null)" -o \ 311 ! -z "$(which qemu-$QEMU_HOST_ARCH-static 2>/dev/null)" ] ; then 312 panic "Installed qemu(s) ($(which qemu-$QEMU_HOST_ARCH 2>/dev/null) $(which qemu-$QEMU_HOST_ARCH-static 2>/dev/null))" \ 313 "will prevent this build from working." 314 fi 315 fi 316 else 317 if [ $1 = darwin-x86 -o $1 = darwin-x86_64 ]; then 318 export LDSHARED="$CC -bundle -undefined dynamic_lookup" 319 fi 320 fi 321 322 TEXT="$(bh_host_text) python-$BH_HOST_CONFIG-$2:" 323 324 touch $SRCDIR/Include/graminit.h 325 touch $SRCDIR/Python/graminit.c 326 echo "" > $SRCDIR/Parser/pgen.stamp 327 touch $SRCDIR/Parser/Python.asdl 328 touch $SRCDIR/Parser/asdl.py 329 touch $SRCDIR/Parser/asdl_c.py 330 touch $SRCDIR/Include/Python-ast.h 331 touch $SRCDIR/Python/Python-ast.c 332 333 # By default, the Python build will force the following compiler flags 334 # after our own CFLAGS: 335 # -g -fwrap -O3 -Wall -Wstrict-prototypes 336 # 337 # The '-g' is unfortunate because it makes the generated binaries 338 # much larger than necessary, and stripping them after the fact is 339 # a bit delicate when cross-compiling. To avoid this, define a 340 # custom OPT variable here (see Python-2.7.5/configure.ac) when 341 # generating non stripped builds. 342 if [ "$BH_BUILD_MODE" = "release" ]; then 343 OPT="-fwrapv -O3 -Wall -Wstrict-prototypes" 344 export OPT 345 fi 346 347 dump "$TEXT Building" 348 export CONFIG_SITE=$CFG_SITE && 349 run2 "$SRCDIR"/configure $ARGS && 350 # 351 # Note 1: 352 # sharedmods is a phony target, but it's a dependency of both "make all" and also 353 # "make install", this causes it to fail on Windows as it tries to rename pydoc3 354 # to pydoc3.3 twice, and the second time aroud the file exists. So instead, we 355 # just do make install. 356 # 357 # Note 2: 358 # Can't run make install with -j as from the Makefile: 359 # install: altinstall bininstall maninstall 360 # meaning altinstall and bininstall are kicked off at the same time 361 # but actually, bininstall depends on altinstall being run first 362 # due to libainstall: doing 363 # $(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(VERSION)-config 364 # and bininstall: doing 365 # (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)-config python2-config) 366 # Though the real fix is to make bininstall depend on libainstall. 367 run2 make -j$NUM_JOBS && 368 run2 make install 369 370 # Pretty printers. 371 PYPPDIR="$INSTALLDIR/share/pretty-printers/" 372 373 # .. for gnu stdlibc++ 374 GCC_DIRS=$(find $TOOLCHAIN_SRC_DIR/gcc/ -maxdepth 1 -name "gcc-*" -type d) 375 for GCC_DIR in $GCC_DIRS; do 376 ( 377 if [ -d "$GCC_DIR/libstdc++-v3/python" ]; then 378 cd "$GCC_DIR/libstdc++-v3/python" 379 [ -d "$PYPPDIR/libstdcxx/$(basename $GCC_DIR)" ] || mkdir -p "$PYPPDIR/libstdcxx/$(basename $GCC_DIR)" 380 run2 find . -path "*.py" -exec cp {} "$PYPPDIR/libstdcxx/$(basename $GCC_DIR)/" \; 381 fi 382 ) 383 done 384 385 # .. for STLPort 386 run2 cp -rf $NDK_DIR/sources/host-tools/gdb-pretty-printers/stlport/gppfs-0.2 $PYPPDIR/stlport 387 } 388 389 need_build_host_python () 390 { 391 bh_stamps_do host-python-$1-$2 build_host_python $1 $2 392 } 393 394 # Install host Python binaries and support files to the NDK install dir. 395 # $1: host tag 396 # $2: python version 397 install_host_python () 398 { 399 local SRCDIR="$(python_build_install_dir $1 $2)" 400 local DSTDIR="$NDK_DIR/$(python_ndk_install_dir $1 $2)" 401 402 need_build_host_python $1 $2 403 404 if [ $AUTO_BUILD != "yes" -o $1 != $BH_BUILD_TAG ]; then 405 dump "$(bh_host_text) python-$BH_HOST_ARCH-$2: Installing" 406 run copy_directory "$SRCDIR/bin" "$DSTDIR/bin" 407 run copy_directory "$SRCDIR/lib" "$DSTDIR/lib" 408 run copy_directory "$SRCDIR/share" "$DSTDIR/share" 409 run copy_directory "$SRCDIR/include" "$DSTDIR/include" 410 fi 411 } 412 413 need_install_host_python () 414 { 415 local SRCDIR="$(python_build_install_dir $1 $2)" 416 417 bh_stamps_do install-host-python-$1-$2 install_host_python $1 $2 418 419 # make sharedmods (setup.py) needs to use the build machine's Python 420 # for the other hosts to build correctly. 421 if [ $BH_BUILD_TAG = $BH_HOST_TAG ]; then 422 export PATH=$SRCDIR/bin:$PATH 423 fi 424 } 425 426 # Package host Python binaries into a tarball 427 # $1: host tag 428 # $2: python version 429 package_host_python () 430 { 431 local BLDDIR="$(python_build_install_dir $1 $2)" 432 local SRCDIR="$(python_ndk_install_dir $1 $2)" 433 # This is similar to BLDDIR=${BLDDIR%%$SRCDIR} (and requires we use windows and not windows-x86) 434 BLDDIR=$(echo "$BLDDIR" | sed "s/$(echo "$SRCDIR" | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/&/\\\&/g')//g") 435 local PACKAGENAME=ndk-python-$(install_dir_from_host_tag $1).tar.bz2 436 local PACKAGE="$PACKAGE_DIR/$PACKAGENAME" 437 438 need_install_host_python $1 $2 439 440 dump "$(bh_host_text) $PACKAGENAME: Packaging" 441 run pack_archive "$PACKAGE" "$BLDDIR" "$SRCDIR" 442 } 443 444 need_package_host_python () 445 { 446 bh_stamps_do package-host-python-$1-$2 package_host_python $1 $2 447 } 448 449 PYTHON_VERSION=$(commas_to_spaces $PYTHON_VERSION) 450 ARCHS=$(commas_to_spaces $ARCHS) 451 452 # Let's build this 453 for SYSTEM in $BH_HOST_SYSTEMS; do 454 bh_setup_build_for_host $SYSTEM 455 for VERSION in $PYTHON_VERSION; do 456 need_install_host_python $SYSTEM $VERSION 457 done 458 done 459 460 if [ "$PACKAGE_DIR" ]; then 461 for SYSTEM in $BH_HOST_SYSTEMS; do 462 bh_setup_build_for_host $SYSTEM 463 if [ $AUTO_BUILD != "yes" -o $SYSTEM != $BH_BUILD_TAG ]; then 464 for VERSION in $PYTHON_VERSION; do 465 need_package_host_python $SYSTEM $VERSION 466 done 467 fi 468 done 469 fi 470