#!/bin/bash # Copyright (c) 2012 The Native Client Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # #@ PNaCl toolchain build script #@------------------------------------------------------------------- #@ This script builds the ARM and PNaCl untrusted toolchains. #@ It MUST be run from the native_client/ directory. ###################################################################### # Directory Layout Description ###################################################################### # # All directories are relative to BASE which is # On Linux: native_client/toolchain/linux_x86/pnacl_newlib/ # On Mac: native_client/toolchain/mac_x86/pnacl_newlib/ # On Windows: native_client/toolchain/win_x86/pnacl_newlib/ # ###################################################################### set -o nounset set -o errexit PWD_ON_ENTRY="$(pwd)" # The script is located in "native_client/pnacl/". # Set pwd to pnacl/ cd "$(dirname "$0")" if [[ $(basename "$(pwd)") != "pnacl" ]] ; then echo "ERROR: cannot find pnacl/ directory" exit -1 fi source scripts/common-tools.sh readonly PNACL_ROOT="$(pwd)" readonly NACL_ROOT="$(GetAbsolutePath ..)" readonly GCLIENT_ROOT="$(GetAbsolutePath ${NACL_ROOT}/..)" readonly SCONS_OUT="${NACL_ROOT}/scons-out" SetScriptPath "${PNACL_ROOT}/build.sh" SetLogDirectory "${PNACL_ROOT}/build/log" readonly TOOLCHAIN_BUILD="${NACL_ROOT}/toolchain_build/toolchain_build_pnacl.py" # For different levels of make parallelism change this in your env readonly PNACL_CONCURRENCY=${PNACL_CONCURRENCY:-8} # Concurrency for builds using the host's system compiler (which might be goma) readonly PNACL_CONCURRENCY_HOST=${PNACL_CONCURRENCY_HOST:-${PNACL_CONCURRENCY}} PNACL_PRUNE=${PNACL_PRUNE:-false} PNACL_BUILD_ARM=true PNACL_BUILD_MIPS=${PNACL_BUILD_MIPS:-false} if ${BUILD_PLATFORM_MAC} || ${BUILD_PLATFORM_WIN}; then # We don't yet support building ARM tools for mac or windows. PNACL_BUILD_ARM=false PNACL_BUILD_MIPS=false fi # PNaCl builds libc++/libc++abi as well as libstdc++, allowing users to # choose which to use through the -stdlib=XXX command-line argument. # # The following strings are used for banner names as well as file and # folder names. These names are created by the libraries themselves, and # expected by their dependents. Changing them would be ill-advised. readonly LIB_CXX_NAME="libc++" readonly LIB_STDCPP_NAME="libstdc++" # TODO(pdox): Decide what the target should really permanently be readonly CROSS_TARGET_ARM=arm-none-linux-gnueabi readonly BINUTILS_TARGET=arm-pc-nacl readonly REAL_CROSS_TARGET=le32-nacl readonly NACL64_TARGET=x86_64-nacl readonly DRIVER_DIR="${PNACL_ROOT}/driver" readonly ARM_ARCH=armv7-a readonly ARM_FPU=vfp readonly TOOLCHAIN_ROOT="${NACL_ROOT}/toolchain" readonly TOOLCHAIN_BASE="${TOOLCHAIN_ROOT}/${SCONS_BUILD_PLATFORM}_x86" readonly NNACL_NEWLIB_ROOT="${TOOLCHAIN_BASE}/nacl_x86_newlib" readonly NNACL_ARM_NEWLIB_ROOT="${TOOLCHAIN_BASE}/nacl_arm_newlib" readonly PNACL_MAKE_OPTS="${PNACL_MAKE_OPTS:-}" readonly MAKE_OPTS="-j${PNACL_CONCURRENCY} VERBOSE=1 ${PNACL_MAKE_OPTS}" readonly MAKE_OPTS_HOST="-j${PNACL_CONCURRENCY_HOST} VERBOSE=1 ${PNACL_MAKE_OPTS}" readonly NONEXISTENT_PATH="/going/down/the/longest/road/to/nowhere" # For speculative build status output. ( see status function ) # Leave this blank, it will be filled during processing. SPECULATIVE_REBUILD_SET="" readonly PNACL_SUPPORT="${PNACL_ROOT}/support" readonly THIRD_PARTY="${NACL_ROOT}"/../third_party readonly NACL_SRC_THIRD_PARTY="${NACL_ROOT}/src/third_party" # Git sources readonly PNACL_GIT_ROOT="${NACL_ROOT}/toolchain_build/src" readonly TC_SRC_BINUTILS="${PNACL_GIT_ROOT}/binutils" readonly TC_SRC_LLVM="${PNACL_GIT_ROOT}/llvm" readonly TC_SRC_GCC="${PNACL_GIT_ROOT}/pnacl-gcc" readonly TC_SRC_NEWLIB="${PNACL_GIT_ROOT}/pnacl-newlib" readonly TC_SRC_LIBSTDCPP="${TC_SRC_GCC}/${LIB_STDCPP_NAME}-v3" readonly TC_SRC_COMPILER_RT="${PNACL_GIT_ROOT}/compiler-rt" readonly TC_SRC_CLANG="${PNACL_GIT_ROOT}/clang" readonly TC_SRC_LIBCXX="${PNACL_GIT_ROOT}/libcxx" readonly SERVICE_RUNTIME_SRC="${NACL_ROOT}/src/trusted/service_runtime" readonly EXPORT_HEADER_SCRIPT="${SERVICE_RUNTIME_SRC}/export_header.py" readonly NACL_SYS_HEADERS="${SERVICE_RUNTIME_SRC}/include" readonly NEWLIB_INCLUDE_DIR="${TC_SRC_NEWLIB}/newlib/libc/sys/nacl" # The location of each project. These should be absolute paths. readonly TC_BUILD="${PNACL_ROOT}/build" readonly TC_BUILD_LLVM="${TC_BUILD}/llvm_${HOST_ARCH}" readonly TC_BUILD_BINUTILS="${TC_BUILD}/binutils_${HOST_ARCH}" readonly TC_BUILD_BINUTILS_LIBERTY="${TC_BUILD}/binutils-liberty" TC_BUILD_NEWLIB="${TC_BUILD}/newlib" readonly TC_BUILD_COMPILER_RT="${TC_BUILD}/compiler_rt" readonly TC_BUILD_GCC="${TC_BUILD}/gcc" readonly NACL_HEADERS_TS="${TC_BUILD}/nacl.sys.timestamp" readonly TIMESTAMP_FILENAME="make-timestamp" # PNaCl toolchain installation directories (absolute paths) readonly INSTALL_ROOT="${TOOLCHAIN_BASE}/pnacl_newlib" readonly INSTALL_BIN="${INSTALL_ROOT}/bin" # Bitcode lib directories (including static bitcode libs) INSTALL_LIB="${INSTALL_ROOT}/lib" # Native nacl lib directories # The pattern `${INSTALL_LIB_NATIVE}${arch}' is used in many places. readonly INSTALL_LIB_NATIVE="${INSTALL_ROOT}/translator/" readonly INSTALL_LIB_ARM="${INSTALL_LIB_NATIVE}arm/lib" readonly INSTALL_LIB_X8632="${INSTALL_LIB_NATIVE}x86-32/lib" readonly INSTALL_LIB_X8664="${INSTALL_LIB_NATIVE}x86-64/lib" readonly INSTALL_LIB_MIPS32="${INSTALL_LIB_NATIVE}mips32/lib" # PNaCl client-translators (sandboxed) binary locations readonly INSTALL_TRANSLATOR="${TOOLCHAIN_BASE}/pnacl_translator" # The INSTALL_HOST directory has host binaries and libs which # are part of the toolchain (e.g. llvm and binutils). # There are also tools-x86 and tools-arm which have host binaries which # are not part of the toolchain but might be useful in the SDK, e.g. # arm sel_ldr and x86-hosted arm/mips validators. readonly INSTALL_HOST="${INSTALL_ROOT}" # Component installation directories readonly LLVM_INSTALL_DIR="${INSTALL_HOST}" readonly BINUTILS_INSTALL_DIR="${INSTALL_HOST}" readonly BFD_PLUGIN_DIR="${BINUTILS_INSTALL_DIR}/lib/bfd-plugins" readonly FAKE_INSTALL_DIR="${INSTALL_HOST}/fake" NEWLIB_INSTALL_DIR="${INSTALL_ROOT}/usr" # Location of the PNaCl tools defined for configure invocations. readonly PNACL_CC="${INSTALL_BIN}/pnacl-clang" readonly PNACL_CXX="${INSTALL_BIN}/pnacl-clang++" readonly PNACL_LD="${INSTALL_BIN}/pnacl-ld" readonly PNACL_PP="${INSTALL_BIN}/pnacl-clang -E" readonly PNACL_AR="${INSTALL_BIN}/pnacl-ar" readonly PNACL_RANLIB="${INSTALL_BIN}/pnacl-ranlib" readonly PNACL_AS="${INSTALL_BIN}/pnacl-as" readonly PNACL_DIS="${INSTALL_BIN}/pnacl-dis" readonly PNACL_FINALIZE="${INSTALL_BIN}/pnacl-finalize" readonly PNACL_NM="${INSTALL_BIN}/pnacl-nm" readonly PNACL_TRANSLATE="${INSTALL_BIN}/pnacl-translate" readonly PNACL_READELF="${INSTALL_BIN}/pnacl-readelf" readonly PNACL_SIZE="${BINUTILS_INSTALL_DIR}/bin/${REAL_CROSS_TARGET}-size" readonly PNACL_STRIP="${INSTALL_BIN}/pnacl-strip" readonly ILLEGAL_TOOL="${INSTALL_BIN}"/pnacl-illegal # Tools for building the LLVM BuildTools in the translator build readonly HOST_CLANG_PATH="${GCLIENT_ROOT}/third_party/llvm-build/Release+Asserts/bin" readonly HOST_CLANG="${HOST_CLANG_PATH}/clang" # Use toolchain_build's libcxx install directory instead of ${INSTALL_ROOT}/lib # because the latter also has the LLVM shared libs in it, and given how stupid # the LLVM BuildTools build is, who knows what would happen if it found those. readonly HOST_LIBCXX="${NACL_ROOT}/toolchain_build/out/libcxx_x86_64_linux_install" # For a production (release) build, we want the sandboxed # translator to only contain the code needed to handle # its own architecture. For example, the translator shipped with # an X86-32 browser would only be able to translate to X86-32 code. # This is so that the translator binary is as small as possible. # # If SBTC_PRODUCTION is true, then the translators are built # separately, one for each architecture, so that each translator # can only target its own architecture. # # If SBTC_PRODUCTION is false, then we instead use PNaCl to # build a `fat` translator which can target all supported # architectures. This translator is built as a .pexe # which can then be translated to each individual architecture. SBTC_PRODUCTION=${SBTC_PRODUCTION:-true} # Which arches to build for our sandboxed toolchain. SBTC_ARCHES_ALL=${SBTC_ARCHES_ALL:-"armv7 i686 x86_64"} get-sbtc-llvm-arches() { # For LLVM i686 brings in both i686 and x86_64. De-dupe that. echo ${SBTC_ARCHES_ALL} \ | sed 's/x86_64/i686/' | sed 's/i686\(.*\)i686/i686\1/' } SBTC_ARCHES_LLVM=$(get-sbtc-llvm-arches) CC=${CC:-gcc} CXX=${CXX:-g++} AR=${AR:-ar} RANLIB=${RANLIB:-ranlib} if ${HOST_ARCH_X8632}; then # These are simple compiler wrappers to force 32bit builds CC="${PNACL_ROOT}/scripts/mygcc32" CXX="${PNACL_ROOT}/scripts/myg++32" fi # The gold plugin that we use is documented at # http://llvm.org/docs/GoldPlugin.html # Despite its name it is actually used by both gold and bfd. The changes to # this file to enable its use are: # * Build shared # * --enable-gold and --enable-plugin when building binutils # * --with-binutils-include when building binutils # * linking the plugin in bfd-plugins ###################################################################### ###################################################################### # # < USER ACCESSIBLE FUNCTIONS > # ###################################################################### ###################################################################### # Convert a path given on the command-line to an absolute path. # This takes into account the fact that we changed directories at the # beginning of this script. PWD_ON_ENTRY is used to remember the # initial working directory. ArgumentToAbsolutePath() { local relpath="$1" local savepwd="$(pwd)" cd "${PWD_ON_ENTRY}" GetAbsolutePath "${relpath}" cd "${savepwd}" } #@------------------------------------------------------------------------- #+ translator-clean-all - Clean all translator install/build directories translator-clean-all() { StepBanner "TRANSLATOR" "Clean all" rm -rf "${TC_BUILD}"/translator* rm -rf "${INSTALL_TRANSLATOR}"* } #@ translator-all - Build and install all of the translators. translator-all() { StepBanner \ "SANDBOXED TC [prod=${SBTC_PRODUCTION}] [arches=${SBTC_ARCHES_ALL}]" # Build the SDK if it not already present. sdk # Also build private libs to allow building nexes without the IRT # segment gap. Specifically, only the sandboxed translator nexes # are built without IRT support to gain address space and reduce # swap file usage. Also libsrpc and its dependencies are now considered # private libs because they are not in the real SDK sdk-private-libs if ${SBTC_PRODUCTION}; then # Build each architecture separately. local arch for arch in ${SBTC_ARCHES_LLVM} ; do llvm-sb ${arch} done for arch in ${SBTC_ARCHES_ALL} ; do binutils-gold-sb ${arch} done else # Using arch `universal` builds the sandboxed tools from a single # .pexe which support all targets. llvm-sb universal binutils-gold-sb universal if ${PNACL_PRUNE}; then # The universal pexes have already been translated. # They don't need to stick around. rm -rf "$(GetTranslatorInstallDir universal)" fi fi # Copy native libs to translator install dir. mkdir -p ${INSTALL_TRANSLATOR}/translator cp -a ${INSTALL_LIB_NATIVE}* ${INSTALL_TRANSLATOR}/translator driver-install-translator if ${PNACL_PRUNE}; then sdk-clean fi } #+ translator-prune Remove leftover files like pexes from pnacl_translator #+ build and from translator-archive-pexes. translator-prune() { find "${INSTALL_TRANSLATOR}" -name "*.pexe" -exec "rm" {} + } #+ translator-clean - #+ Clean one translator install/build translator-clean() { local arch=$1 StepBanner "TRANSLATOR" "Clean ${arch}" rm -rf "$(GetTranslatorInstallDir ${arch})" rm -rf "$(GetTranslatorBuildDir ${arch})" } speculative-add() { local mod="$1" SPECULATIVE_REBUILD_SET="${SPECULATIVE_REBUILD_SET} ${mod}" } speculative-check() { local mod="$1" local search=$(echo "${SPECULATIVE_REBUILD_SET}" | grep -F "$mod") [ ${#search} -gt 0 ] return $? } #@ clean - Clean the build and install directories. clean() { StepBanner "CLEAN" "Cleaning build, log, and install directories." clean-logs clean-build clean-install clean-scons } #@ fast-clean - Clean everything except LLVM. fast-clean() { local did_backup=false local backup_dir="${PNACL_ROOT}/fast-clean-llvm-backup" if [ -d "${TC_BUILD_LLVM}" ]; then rm -rf "${backup_dir}" mv "${TC_BUILD_LLVM}" "${backup_dir}" did_backup=true fi clean if ${did_backup} ; then mkdir -p "${TC_BUILD}" mv "${backup_dir}" "${TC_BUILD_LLVM}" fi } #+ clean-scons - Clean scons-out directory clean-scons() { rm -rf "${SCONS_OUT}" } #+ clean-build - Clean all build directories clean-build() { rm -rf "${TC_BUILD}" } #+ clean-install - Clean install directories clean-install() { rm -rf "${INSTALL_ROOT}" } #+ libs-clean - Removes the library directories libs-clean() { StepBanner "LIBS-CLEAN" "Cleaning ${INSTALL_ROOT}/libs-*" rm -rf "${INSTALL_LIB}"/* rm -rf "${INSTALL_LIB_NATIVE}"* } #@------------------------------------------------------------------------- prune-host() { echo "stripping binaries (binutils)" strip "${BINUTILS_INSTALL_DIR}"/bin/* echo "stripping binaries (llvm)" if ! strip "${LLVM_INSTALL_DIR}"/bin/* ; then echo "NOTE: some failures during stripping are expected" fi echo "removing unused clang shared lib" rm -rf "${LLVM_INSTALL_DIR}"/${SO_DIR}/*clang${SO_EXT} echo "removing unused binutils binaries" rm -rf "${LLVM_INSTALL_DIR}"/bin/le32-nacl-elfedit rm -rf "${LLVM_INSTALL_DIR}"/bin/le32-nacl-gprof rm -rf "${LLVM_INSTALL_DIR}"/bin/le32-nacl-objcopy echo "removing unused LLVM/Clang binaries" rm -rf "${LLVM_INSTALL_DIR}"/bin/bc-wrap rm -rf "${LLVM_INSTALL_DIR}"/bin/bugpoint rm -rf "${LLVM_INSTALL_DIR}"/bin/c-index-test rm -rf "${LLVM_INSTALL_DIR}"/bin/clang-* rm -rf "${LLVM_INSTALL_DIR}"/bin/llc rm -rf "${LLVM_INSTALL_DIR}"/bin/lli rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-ar rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-bcanalyzer rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-config rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-cov rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-diff rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-dwarfdump rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-extract rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-mcmarkup rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-prof rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-ranlib rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-readobj rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-rtdyld rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-size rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-stress rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-symbolizer rm -rf "${LLVM_INSTALL_DIR}"/bin/macho-dump rm -rf "${LLVM_INSTALL_DIR}"/bin/pso-stub rm -rf "${LLVM_INSTALL_DIR}"/bin/*-tblgen echo "removing llvm & clang headers" rm -rf "${LLVM_INSTALL_DIR}"/include echo "removing docs/ and share/" rm -rf "${LLVM_INSTALL_DIR}"/docs rm -rf "${LLVM_INSTALL_DIR}"/share echo "removing unused libs" rm -rf "${LLVM_INSTALL_DIR}"/lib/*.a rm -rf "${LLVM_INSTALL_DIR}"/lib/bfd-plugins rm -rf "${LLVM_INSTALL_DIR}"/lib/BugpointPasses.so rm -rf "${LLVM_INSTALL_DIR}"/lib/LLVMHello.so } #+ prune - Prune toolchain prune() { StepBanner "PRUNE" "Pruning toolchain" local dir_size_before=$(get_dir_size_in_mb ${INSTALL_ROOT}) SubBanner "Size before: ${INSTALL_ROOT} ${dir_size_before}MB" prune-host echo "removing .pyc files" rm -f "${INSTALL_BIN}"/pydir/*.pyc local dir_size_after=$(get_dir_size_in_mb "${INSTALL_ROOT}") SubBanner "Size after: ${INSTALL_ROOT} ${dir_size_after}MB" } #+ tarball - Produce tarball file tarball() { if [ ! -n "${1:-}" ]; then echo "Error: tarball needs a tarball name." >&2 exit 1 fi local tarball="$(ArgumentToAbsolutePath "$1")" StepBanner "TARBALL" "Creating tar ball ${tarball}" tar zcf "${tarball}" -C "${INSTALL_ROOT}" . ls -l ${tarball} } translator-tarball() { if [ ! -n "${1:-}" ]; then echo "Error: tarball needs a tarball name." >&2 exit 1 fi local tarball="$(ArgumentToAbsolutePath "$1")" StepBanner "TARBALL" "Creating translator tar ball ${tarball}" tar zcf "${tarball}" -C "${INSTALL_TRANSLATOR}" . } ######################################################################### # CLIENT BINARIES (SANDBOXED) ######################################################################### check-arch() { local arch=$1 for valid_arch in i686 x86_64 armv7 universal ; do if [ "${arch}" == "${valid_arch}" ] ; then return fi done Fatal "ERROR: Unsupported arch [$1]. Must be: i686, x86_64, armv7, universal" } llvm-sb-setup() { local arch=$1 LLVM_SB_LOG_PREFIX="llvm.sb.${arch}" LLVM_SB_OBJDIR="$(GetTranslatorBuildDir ${arch})/llvm-sb" # The SRPC headers are included directly from the nacl tree, as they are # not in the SDK. libsrpc should have already been built by the # build.sh sdk-private-libs step. # This is always statically linked. # The LLVM sandboxed build uses the normally-disallowed external # function __nacl_get_arch(). Allow that for now. local flags="-static -I$(GetAbsolutePath ${NACL_ROOT}/..) \ --pnacl-disable-abi-check " LLVM_SB_CONFIGURE_ENV=( AR="${PNACL_AR}" \ AS="${PNACL_AS}" \ CC="${PNACL_CC} ${flags}" \ CXX="${PNACL_CXX} ${flags}" \ LD="${PNACL_LD} ${flags}" \ NM="${PNACL_NM}" \ RANLIB="${PNACL_RANLIB}" \ BUILD_CC="${HOST_CLANG}" \ BUILD_CXX="${HOST_CLANG}++") } #+------------------------------------------------------------------------- #+ llvm-sb - Build and install llvm tools (sandboxed) llvm-sb() { local arch=$1 check-arch ${arch} llvm-sb-setup ${arch} StepBanner "LLVM-SB" "Sandboxed pnacl-llc [${arch}]" local srcdir="${TC_SRC_LLVM}" assert-dir "${srcdir}" "You need to checkout llvm." if llvm-sb-needs-configure ${arch} ; then llvm-sb-clean ${arch} llvm-sb-configure ${arch} else SkipBanner "LLVM-SB" "configure ${arch}" fi llvm-sb-make ${arch} llvm-sb-install ${arch} } llvm-sb-needs-configure() { [ ! -f "${LLVM_SB_OBJDIR}/config.status" ] return $? } # llvm-sb-clean - Clean llvm tools (sandboxed) llvm-sb-clean() { local arch=$1 StepBanner "LLVM-SB" "Clean ${arch}" local objdir="${LLVM_SB_OBJDIR}" rm -rf "${objdir}" mkdir -p "${objdir}" } # llvm-sb-configure - Configure llvm tools (sandboxed) llvm-sb-configure() { local arch=$1 StepBanner "LLVM-SB" "Configure ${arch}" local srcdir="${TC_SRC_LLVM}" local objdir="${LLVM_SB_OBJDIR}" local installdir="$(GetTranslatorInstallDir ${arch})" local targets="" # For LLVM, "x86" brings in both i686 and x86_64. case ${arch} in i686) targets=x86 ;; x86_64) targets=x86 ;; armv7) targets=arm ;; universal) targets=x86,arm ;; esac spushd "${objdir}" # TODO(jvoung): remove ac_cv_func_getrusage=no once newlib has getrusage # in its headers. Otherwise, configure thinks that we can link in # getrusage (stub is in libnacl), but we can't actually compile code # that uses ::getrusage because it's not in headers: # https://code.google.com/p/nativeclient/issues/detail?id=3657 # Similar with getrlimit/setrlimit where struct rlimit isn't defined. RunWithLog \ ${LLVM_SB_LOG_PREFIX}.configure \ env -i \ PATH="/usr/bin:/bin" \ ${srcdir}/configure \ "${LLVM_SB_CONFIGURE_ENV[@]}" \ --prefix=${installdir} \ --host=nacl \ --enable-targets=${targets} \ --disable-assertions \ --enable-pic=no \ --enable-static \ --enable-shared=no \ --disable-jit \ --enable-optimized \ --enable-libcpp \ --target=${CROSS_TARGET_ARM} \ llvm_cv_link_use_export_dynamic=no \ ac_cv_func_getrusage=no \ ac_cv_func_getrlimit=no \ ac_cv_func_setrlimit=no spopd } # llvm-sb-make - Make llvm tools (sandboxed) llvm-sb-make() { local arch=$1 StepBanner "LLVM-SB" "Make ${arch}" local objdir="${LLVM_SB_OBJDIR}" spushd "${objdir}" ts-touch-open "${objdir}" local tools_to_build="pnacl-llc" local export_dyn_env="llvm_cv_link_use_export_dynamic=no" local isjit=0 RunWithLog ${LLVM_SB_LOG_PREFIX}.make \ env -i PATH="/usr/bin:/bin:${HOST_CLANG_PATH}" \ LD_LIBRARY_PATH="${HOST_LIBCXX}/lib" \ ONLY_TOOLS="${tools_to_build}" \ NACL_SANDBOX=1 \ KEEP_SYMBOLS=1 \ NO_DEAD_STRIP=1 \ VERBOSE=1 \ BUILD_CC="${HOST_CLANG}" \ BUILD_CXX="${HOST_CLANG}++" \ BUILD_CXXFLAGS="-stdlib=libc++ -I${HOST_LIBCXX}/include/c++/v1" \ BUILD_LDFLAGS="-L${HOST_LIBCXX}/lib" \ ${export_dyn_env} \ make ${MAKE_OPTS} tools-only ts-touch-commit "${objdir}" spopd } # llvm-sb-install - Install llvm tools (sandboxed) llvm-sb-install() { local arch=$1 StepBanner "LLVM-SB" "Install ${arch}" local toolname="pnacl-llc" local installdir="$(GetTranslatorInstallDir ${arch})"/bin mkdir -p "${installdir}" spushd "${installdir}" local objdir="${LLVM_SB_OBJDIR}" cp -f "${objdir}"/Release*/bin/${toolname} . mv -f ${toolname} ${toolname}.pexe local arches=${arch} if [[ "${arch}" == "universal" ]]; then arches="${SBTC_ARCHES_ALL}" elif [[ "${arch}" == "i686" ]]; then # LLVM does not separate the i686 and x86_64 backends. # Translate twice to get both nexes. arches="i686 x86_64" fi local have_segment_gap="false" translate-sb-tool ${toolname} "${arches}" "${have_segment_gap}" install-sb-tool ${toolname} "${arches}" spopd } # translate-sb-tool # # Translate .pexe to ..nexe in the current directory. translate-sb-tool() { local toolname=$1 local arches=$2 local have_segment_gap=$3 local pexe="${toolname}.pexe" if ${PNACL_PRUNE}; then # Only strip debug, to preserve symbol names for testing. This is okay # because we strip the native nexe later anyway. # So, why bother stripping here at all? # It does appear to affect the size of the nexe: # http://code.google.com/p/nativeclient/issues/detail?id=3305 ${PNACL_STRIP} --strip-debug "${pexe}" fi local tarch for tarch in ${arches}; do local nexe="${toolname}.${tarch}.nexe" StepBanner "TRANSLATE" \ "Translating ${toolname}.pexe to ${tarch} (background)" # NOTE: we are using --noirt to build without a segment gap # since we aren't loading the IRT for the translator nexes. # # Compiling with -ffunction-sections, -fdata-sections, --gc-sections # helps reduce the size a bit. If you want to use --gc-sections to test out: # http://code.google.com/p/nativeclient/issues/detail?id=1591 # you will need to do a build without these flags. local translate_flags="-ffunction-sections -fdata-sections --gc-sections \ --allow-llvm-bitcode-input -arch ${tarch} " if ! ${have_segment_gap}; then translate_flags+="--noirt " fi "${PNACL_TRANSLATE}" ${translate_flags} "${pexe}" -o "${nexe}" & QueueLastProcess done StepBanner "TRANSLATE" "Waiting for translation processes to finish" QueueWait # Test that certain symbols have been pruned before stripping. if [ "${toolname}" == "pnacl-llc" ]; then for tarch in ${arches}; do local nexe="${toolname}.${tarch}.nexe" local llvm_host_glob="${LLVM_INSTALL_DIR}/lib/libLLVM*so" python "${PNACL_ROOT}/prune_test.py" "${PNACL_NM}" \ "${llvm_host_glob}" "${nexe}" done fi if ${PNACL_PRUNE}; then # Strip the nexes. for tarch in ${arches}; do local nexe="${toolname}.${tarch}.nexe" ${PNACL_STRIP} "${nexe}" done fi StepBanner "TRANSLATE" "Done." } # install-sb-tool # # Install ..nexe from the current directory # into the right location (as .nexe) install-sb-tool() { local toolname="$1" local arches="$2" local tarch for tarch in ${arches}; do local installbin="$(GetTranslatorInstallDir ${tarch})"/bin mkdir -p "${installbin}" mv -f ${toolname}.${tarch}.nexe "${installbin}"/${toolname}.nexe if ${PNACL_BUILDBOT}; then spushd "${installbin}" local tag="${toolname}_${tarch}_size" print-tagged-tool-sizes "${tag}" "$(pwd)/${toolname}.nexe" spopd fi done } GetTranslatorBuildDir() { local arch="$1" echo "${TC_BUILD}/translator-${arch//_/-}" } GetTranslatorInstallDir() { local arch case $1 in i686) arch=x86-32 ;; x86_64) arch=x86-64 ;; armv7) arch=arm ;; default) arch=$1 ;; esac echo "${INSTALL_TRANSLATOR}"/translator/${arch} } ### Sandboxed version of gold. #+------------------------------------------------------------------------- #+ binutils-gold-sb - Build and install gold (sandboxed) #+ This is the replacement for the old #+ final sandboxed linker which was bfd based. #+ It has nothing to do with the bitcode linker #+ which is also gold based. binutils-gold-sb() { local arch=$1 check-arch ${arch} StepBanner "GOLD-NATIVE-SB" "(libiberty + gold) ${arch}" local srcdir="${TC_SRC_BINUTILS}" assert-dir "${srcdir}" "You need to checkout gold." binutils-gold-sb-clean ${arch} binutils-gold-sb-configure ${arch} binutils-gold-sb-make ${arch} binutils-gold-sb-install ${arch} } # binutils-gold-sb-clean - Clean gold binutils-gold-sb-clean() { local arch=$1 StepBanner "GOLD-NATIVE-SB" "Clean ${arch}" local objdir="$(GetTranslatorBuildDir ${arch})/binutils-gold-sb" rm -rf "${objdir}" mkdir -p "${objdir}" } # binutils-gold-sb-configure - Configure binutils for gold (unsandboxed) binutils-gold-sb-configure() { local arch=$1 local srcdir="${TC_SRC_BINUTILS}" local objdir="$(GetTranslatorBuildDir ${arch})/binutils-gold-sb" local installbin="$(GetTranslatorInstallDir ${arch})/bin" # The SRPC headers are included directly from the nacl tree, as they are # not in the SDK. libsrpc should have already been built by the # build.sh sdk-private-libs step # The Gold sandboxed build uses the normally-disallowed external # function __nacl_get_arch(). Allow that for now. # local flags="-static -I$(GetAbsolutePath ${NACL_ROOT}/..) \ -fno-exceptions -O3 --pnacl-disable-abi-check " local configure_env=( AR="${PNACL_AR}" \ AS="${PNACL_AS}" \ CC="${PNACL_CC} ${flags}" \ CXX="${PNACL_CXX} ${flags}" \ CC_FOR_BUILD="${CC}" \ CXX_FOR_BUILD="${CXX}" \ LD="${PNACL_LD} ${flags}" \ NM="${PNACL_NM}" \ RANLIB="${PNACL_RANLIB}" ) local gold_targets="" case ${arch} in i686) gold_targets=i686-pc-nacl ;; x86_64) gold_targets=x86_64-pc-nacl ;; armv7) gold_targets=arm-pc-nacl ;; universal) gold_targets=i686-pc-nacl,x86_64-pc-nacl,arm-pc-nacl ;; esac # gold always adds "target" to the enabled targets so we are # little careful to not build too much # Note: we are (ab)using target for both --host and --target # which configure expects to be present local target if [ ${arch} == "universal" ] ; then target=i686-pc-nacl else target=${gold_targets} fi StepBanner "GOLD-NATIVE-SB" "Configure (libiberty)" # Gold depends on liberty only for a few functions: # xrealloc, lbasename, etc. # we could remove these if necessary. mkdir -p "${objdir}/libiberty" spushd "${objdir}/libiberty" StepBanner "GOLD-NATIVE-SB" "Dir [$(pwd)]" local log_prefix="binutils-gold.sb.${arch}" RunWithLog "${log_prefix}".configure \ env -i \ PATH="/usr/bin:/bin" \ "${configure_env[@]}" \ ${srcdir}/libiberty/configure --prefix="${installbin}" \ --host=${target} \ --target=${target} spopd StepBanner "GOLD-NATIVE-SB" "Configure (gold) ${arch}" mkdir -p "${objdir}/gold" spushd "${objdir}/gold" StepBanner "GOLD-NATIVE-SB" "Dir [$(pwd)]" # Removed -Werror until upstream gold no longer has problems with new clang # warnings. http://code.google.com/p/nativeclient/issues/detail?id=2861 # TODO(sehr,robertm): remove this when gold no longer has these. # Disable readv. We have a stub for it, but not the accompanying headers # in newlib, like sys/uio.h to actually compile with it. RunWithLog "${log_prefix}".configure \ env -i \ PATH="/usr/bin:/bin" \ "${configure_env[@]}" \ CXXFLAGS="" \ CFLAGS="" \ ac_cv_search_zlibVersion=no \ ac_cv_header_sys_mman_h=no \ ac_cv_func_mmap=no \ ac_cv_func_mallinfo=no \ ac_cv_func_readv=no \ ac_cv_prog_cc_g=no \ ac_cv_prog_cxx_g=no \ ${srcdir}/gold/configure --prefix="${installbin}" \ --enable-targets=${gold_targets} \ --host=${target} \ --target=${target} \ --disable-nls \ --enable-plugins=no \ --enable-naclsrpc=yes \ --disable-werror \ --with-sysroot="${NONEXISTENT_PATH}" # Note: the extra ac_cv settings: # * eliminate unnecessary use of zlib # * eliminate use of mmap # (those should not have much impact on the non-sandboxed # version but help in the sandboxed case) # We also disable debug (-g) because the bitcode files become too big # (with ac_cv_prog_cc_g). # There's no point in setting the correct path as sysroot, because we # want the toolchain to be relocatable. The driver will use ld command-line # option --sysroot= to override this value and set it to the correct path. # However, we need to include --with-sysroot during configure to get this # option. So fill in a non-sense, non-existent path. spopd } # binutils-gold-sb-make - Make binutils (sandboxed) binutils-gold-sb-make() { local arch=${1} local objdir="$(GetTranslatorBuildDir ${arch})/binutils-gold-sb" ts-touch-open "${objdir}/" StepBanner "GOLD-NATIVE-SB" "Make (liberty) ${arch}" spushd "${objdir}/libiberty" RunWithLog "binutils-gold.liberty.sb.${arch}".make \ env -i PATH="/usr/bin:/bin" \ make ${MAKE_OPTS} spopd StepBanner "GOLD-NATIVE-SB" "Make (gold) ${arch}" spushd "${objdir}/gold" RunWithLog "binutils-gold.sb.${arch}".make \ env -i PATH="/usr/bin:/bin" \ make ${MAKE_OPTS} ld-new spopd ts-touch-commit "${objdir}" } # binutils-gold-sb-install - Install gold binutils-gold-sb-install() { local arch=$1 local objdir="$(GetTranslatorBuildDir ${arch})/binutils-gold-sb" local installbin="$(GetTranslatorInstallDir ${arch})/bin" StepBanner "GOLD-NATIVE-SB" "Install [${installbin}] ${arch}" mkdir -p "${installbin}" spushd "${installbin}" # Install just "ld" cp "${objdir}"/gold/ld-new ld.pexe # Translate and install local arches=${arch} if [[ "${arch}" == "universal" ]]; then arches="${SBTC_ARCHES_ALL}" fi local have_segment_gap=true translate-sb-tool ld "${arches}" ${have_segment_gap} install-sb-tool ld "${arches}" spopd } ######################################################################### # < SDK > ######################################################################### SCONS_ARGS=(MODE=nacl -j${PNACL_CONCURRENCY} bitcode=1 disable_nosys_linker_warnings=1 naclsdk_validate=0 --verbose) SDK_IS_SETUP=false sdk-setup() { if ${SDK_IS_SETUP} && [ $# -eq 0 ]; then return 0 fi SDK_IS_SETUP=true SDK_INSTALL_ROOT="${INSTALL_ROOT}/le32-nacl" SDK_INSTALL_LIB="${SDK_INSTALL_ROOT}/lib" SDK_INSTALL_INCLUDE="${SDK_INSTALL_ROOT}/include" } sdk() { sdk-setup "$@" StepBanner "SDK" sdk-clean sdk-headers sdk-libs } #+ sdk-clean - Clean sdk stuff sdk-clean() { sdk-setup "$@" StepBanner "SDK" "Clean" rm -rf "${SDK_INSTALL_LIB}"/{libnacl*.a,libpthread.a,libnosys.a} rm -rf "${SDK_INSTALL_INCLUDE}"/{irt*.h,pthread.h,semaphore.h,nacl} # clean scons obj dirs rm -rf "${SCONS_OUT}"/nacl-*-pnacl* } sdk-headers() { sdk-setup "$@" mkdir -p "${SDK_INSTALL_INCLUDE}" local extra_flags="" local neutral_platform="x86-32" StepBanner "SDK" "Install headers" spushd "${NACL_ROOT}" RunWithLog "sdk.headers" \ ./scons \ "${SCONS_ARGS[@]}" \ ${extra_flags} \ platform=${neutral_platform} \ pnacl_newlib_dir="${INSTALL_ROOT}" \ install_headers \ includedir="$(PosixToSysPath "${SDK_INSTALL_INCLUDE}")" spopd } sdk-libs() { sdk-setup "$@" StepBanner "SDK" "Install libraries" mkdir -p "${SDK_INSTALL_LIB}" local extra_flags="" local neutral_platform="x86-32" spushd "${NACL_ROOT}" RunWithLog "sdk.libs.bitcode" \ ./scons \ "${SCONS_ARGS[@]}" \ ${extra_flags} \ platform=${neutral_platform} \ pnacl_newlib_dir="${INSTALL_ROOT}" \ install_lib \ libdir="$(PosixToSysPath "${SDK_INSTALL_LIB}")" spopd } # This builds lib*_private.a, to allow building the llc and ld nexes without # the IRT and without the segment gap. sdk-private-libs() { sdk-setup "$@" StepBanner "SDK" "Private (non-IRT) libs" spushd "${NACL_ROOT}" local neutral_platform="x86-32" RunWithLog "sdk.libs_private.bitcode" \ ./scons \ -j${PNACL_CONCURRENCY} \ bitcode=1 \ platform=${neutral_platform} \ pnacl_newlib_dir="${INSTALL_ROOT}" \ --verbose \ libnacl_sys_private \ libpthread_private \ libnacl_dyncode_private \ libplatform \ libimc \ libimc_syscalls \ libsrpc \ libgio local out_dir_prefix="${SCONS_OUT}"/nacl-x86-32-pnacl-pexe-clang local outdir="${out_dir_prefix}"/lib mkdir -p "${SDK_INSTALL_LIB}" cp "${outdir}"/lib*_private.a \ "${outdir}"/lib{platform,imc,imc_syscalls,srpc,gio}.a "${SDK_INSTALL_LIB}" spopd } #+------------------------------------------------------------------------- #@ driver - Install driver scripts. driver() { StepBanner "DRIVER" driver-install } # install python scripts and redirector shell/batch scripts driver-install-python() { local destdir="$1" shift local pydir="${destdir}/pydir" StepBanner "DRIVER" "Installing driver adaptors to ${destdir}" rm -rf "${destdir}" mkdir -p "${destdir}" mkdir -p "${pydir}" spushd "${DRIVER_DIR}" # Copy python scripts cp $@ driver_log.py driver_env.py driver_temps.py \ *tools.py filetype.py loader.py nativeld.py "${pydir}" # Install redirector shell/batch scripts for name in $@; do local dest="${destdir}/${name/.py}" # In some situations cygwin cp messes up the permissions of the redirector # shell/batch scripts. Using cp -a seems to make sure it preserves them. cp -a redirect.sh "${dest}" chmod +x "${dest}" if ${BUILD_PLATFORM_WIN}; then cp -a redirect.bat "${dest}".bat fi done spopd } feature-version-file-install() { local install_root=$1 # Scons tests can check this version number to decide whether to # enable tests for toolchain bug fixes or new features. This allows # tests to be enabled on the toolchain buildbots/trybots before the # new toolchain version is rolled into the pinned version (i.e. before # the tests would pass on the main NaCl buildbots/trybots). # # If you are adding a test that depends on a toolchain change, you # can increment this version number manually. echo 6 > "${install_root}/FEATURE_VERSION" } # The driver is a simple python script which changes its behavior # depending on the name it is invoked as. driver-install() { local bindir=bin # On Linux we ship a fat toolchain with 2 sets of binaries defaulting to # x86-32 (mostly because of the 32 bit chrome bots). So the default # bin dir is 32, and the bin64 driver runs the 64 bit binaries if ${HOST_ARCH_X8664} && ${BUILD_PLATFORM_LINUX}; then bindir="bin64" # We want to be able to locally test a toolchain on 64 bit hosts without # building it twice and without extra env vars. So if a 32 bit toolchain # has not already been built, just symlink the bin dirs together. if [[ ! -d "${INSTALL_BIN}" ]]; then mkdir -p "${INSTALL_ROOT}" ln -s ${bindir} "${INSTALL_BIN}" fi fi # This directory (the ${INSTALL_ROOT}/${bindir} part) # should be kept in sync with INSTALL_BIN et al. local destdir="${INSTALL_ROOT}/${bindir}" driver-install-python "${destdir}" "pnacl-*.py" # Tell the driver the library mode and host arch echo """HAS_FRONTEND=1 HOST_ARCH=${HOST_ARCH}""" > "${destdir}"/driver.conf # On windows, copy the cygwin DLLs needed by the driver tools if ${BUILD_PLATFORM_WIN}; then StepBanner "DRIVER" "Copying cygwin libraries" local deps="gcc_s-1 iconv-2 win1 intl-8 stdc++-6 z" for name in ${deps}; do cp "/bin/cyg${name}.dll" "${destdir}" done fi # Install a REV file so that "pnacl-clang --version" knows the version # of the drivers themselves. DumpAllRevisions > "${destdir}/REV" feature-version-file-install ${INSTALL_ROOT} } #@ driver-install-translator - Install driver scripts for translator component driver-install-translator() { local destdir="${INSTALL_TRANSLATOR}/bin" driver-install-python "${destdir}" pnacl-translate.py echo """HAS_FRONTEND=0""" > "${destdir}"/driver.conf feature-version-file-install ${INSTALL_TRANSLATOR} } ###################################################################### ###################################################################### # # HELPER FUNCTIONS # # (These should not generally be used directly) # ###################################################################### ###################################################################### DumpAllRevisions() { one-line-rev-info ${NACL_ROOT} for d in ${PNACL_GIT_ROOT}/*/ ; do one-line-rev-info $d done } ###################################################################### ###################################################################### # < VERIFY > ###################################################################### ###################################################################### # Note: we could replace this with a modified version of tools/elf_checker.py # if we do not want to depend on binutils readonly NACL_OBJDUMP=${BINUTILS_INSTALL_DIR}/bin/${REAL_CROSS_TARGET}-objdump # Usage: VerifyArchive ExtractAndCheck() { local checker="$1" local pattern="$2" local archive="$3" local tmp="/tmp/ar-verify-${RANDOM}" rm -rf ${tmp} mkdir -p ${tmp} cp "${archive}" "${tmp}" spushd ${tmp} ${PNACL_AR} x $(basename ${archive}) # extract all the files local count=0 for i in ${pattern} ; do if [ ! -e "$i" ]; then # we may also see the unexpanded pattern here if there is no match continue fi count=$((count+1)) ${checker} $i done echo "PASS (${count} files)" rm -rf "${tmp}" spopd } IsLinkerScript() { local fname="$1" local type="$(file --brief --mime-type "${fname}")" case "$type" in text/x-c) # A linker script with C comments looks like C to "file". return 0 ;; text/plain) return 0 ;; esac return 1 } # Usage: VerifyLinkerScript VerifyLinkerScript() { local archive="$1" # Use preprocessor to strip the C-style comments. ${PNACL_PP} -xc "${archive}" | awk -v archive="$(basename ${archive})" ' BEGIN { status = 0 } NF == 0 || $1 == "#" { next } $1 == "INPUT" && $2 == "(" && $NF == ")" { next } { print "FAIL - unexpected linker script(?) contents:", archive status = 1 exit(status) } END { if (status == 0) print "PASS (trivial linker script)" } ' || exit -1 } # Usage: VerifyArchive VerifyArchive() { local checker="$1" local pattern="$2" local archive="$3" echo -n "verify $(basename "${archive}"): " if IsLinkerScript "${archive}"; then VerifyLinkerScript "${archive}" else ExtractAndCheck "$checker" "$pattern" "$archive" fi } # # verify-object-llvm # # Verifies that a given .o file is bitcode and free of ASMSs verify-object-llvm() { if ${PNACL_DIS} "$1" -o - | grep asm ; then echo echo "ERROR asm in $1" echo exit -1 fi if [ ${PIPESTATUS[0]} -ne 0 ]; then exit -1 fi } check-elf-abi() { # Temporarily disable ELF abi check until DEPS roll return 0 local arch_info="$(${NACL_OBJDUMP} -f $1)" if ! grep -q $2 <<< ${arch_info} ; then echo "ERROR $1 - bad file format: $2 vs ${arch_info}\n" echo ${arch_info} exit -1 fi } # verify-object-arm # # Ensure that the ARCH properties are what we expect, this is a little # fragile and needs to be updated when tools change verify-object-arm() { check-elf-abi $1 "elf32-littlearm" # llvm-mc does not automatically insert these tags (unlike gnu-as). # So we exclude llvm-mc generated object files for now if [[ $1 == aeabi_read_tp.o || $1 == setjmp.o ]] ; then return fi arch_info="$("${PNACL_READELF}" -A "$1")" #TODO(robertm): some refactoring and cleanup needed if ! grep -q "Tag_FP_arch: VFPv3" <<< ${arch_info} ; then echo "ERROR $1 - bad Tag_FP_arch" #TODO(robertm): figure out what the right thing to do is here, c.f. # http://code.google.com/p/nativeclient/issues/detail?id=966 "${PNACL_READELF}" -A $1 | grep Tag_FP_arch exit -1 fi if ! grep -q "Tag_CPU_arch: v7" <<< ${arch_info} ; then echo "FAIL bad $1 Tag_CPU_arch" "${PNACL_READELF}" -A $1 | grep Tag_CPU_arch exit -1 fi if ! grep -q "Tag_Advanced_SIMD_arch: NEONv1" <<< ${arch_info} ; then echo "FAIL bad $1 Tag_Advanced_SIMD_arch" "${PNACL_READELF}" -A $1 | grep Tag_Advanced_SIMD_arch fi # Check that the file uses the ARM hard-float ABI (where VFP # registers D0-D7 (s0-s15) are used to pass arguments and results). if ! grep -q "Tag_ABI_VFP_args: VFP registers" <<< ${arch_info} ; then echo "FAIL bad $1 Tag_ABI_VFP_args" "${PNACL_READELF}" -A $1 | grep Tag_ABI_VFP_args fi } # verify-object-x86-32 # verify-object-x86-32() { check-elf-abi $1 "elf32-i386" } # verify-object-x86-64 # verify-object-x86-64() { check-elf-abi $1 "elf64-x86-64" } #+ verify-bitcode-dir - Verify that the files in a directory are bitcode. verify-bitcode-dir() { local dir="$1" # This avoids errors when * finds no matches. shopt -s nullglob SubBanner "VERIFY: ${dir}" for i in "${dir}"/*.a ; do verify-archive-llvm "$i" done for i in "${dir}"/*.bc ; do echo -n "verify $(basename "$i"): " verify-object-llvm "$i" echo "PASS (bitcode)" done for i in "${dir}"/*.o ; do Fatal "Native object file $i inside bitcode directory" done shopt -u nullglob } #+ verify-native-dir - Verify that files in a directory are native for arch. verify-native-dir() { local arch="$1" local dir="$2" SubBanner "VERIFY: ${dir}" # This avoids errors when * finds no matches. shopt -s nullglob for i in "${dir}"/*.o ; do verify-object-${arch} "$i" done for i in "${dir}"/*.a ; do verify-archive-${arch} "$i" done for i in "${dir}"/*.bc "${dir}"/*.pso ; do Fatal "Bitcode file $i found inside native directory" done shopt -u nullglob } # # verify-archive-llvm # Verifies that a given archive is bitcode and free of ASMSs # verify-archive-llvm() { # Currently all the files are .o in the llvm archives. # Eventually more and more should be .bc. VerifyArchive verify-object-llvm '*.bc *.o' "$@" } # # verify-archive-arm # Verifies that a given archive is a proper arm achive # verify-archive-arm() { VerifyArchive verify-object-arm '*.o *.ons' "$@" } # # verify-archive-x86-32 # Verifies that a given archive is a proper x86-32 achive # verify-archive-x86-32() { VerifyArchive verify-object-x86-32 '*.o *.ons' "$@" } # # verify-archive-x86-64 # Verifies that a given archive is a proper x86-64 achive # verify-archive-x86-64() { VerifyArchive verify-object-x86-64 '*.o *.ons' "$@" } #@------------------------------------------------------------------------- #+ verify - Verifies that the pnacl-untrusted ELF files #+ are of the correct architecture. verify() { StepBanner "VERIFY" verify-bitcode verify-native } verify-bitcode() { verify-bitcode-dir "${INSTALL_LIB}" } verify-native() { local arch for arch in arm x86-32 x86-64; do verify-native-dir ${arch} "${INSTALL_LIB_NATIVE}${arch}" done } #+ verify-triple-build #+ Verify that the sandboxed translator produces an identical #+ translation of itself (pnacl-llc.pexe) as the unsandboxed translator. #+ (NOTE: This function is experimental/untested) verify-triple-build() { local arch=$1 StepBanner "VERIFY" "Verifying triple build for ${arch}" local bindir="$(GetTranslatorInstallDir ${arch})/bin" local llc_nexe="${bindir}/pnacl-llc.nexe" local llc_pexe="${bindir}/pnacl-llc.pexe" assert-file "${llc_nexe}" "sandboxed llc for ${arch} does not exist" assert-file "${llc_pexe}" "pnacl-llc.pexe does not exist" local flags="--pnacl-sb --pnacl-driver-verbose" if [ ${arch} == "arm" ] ; then # Use emulator if we are not on ARM local hostarch=$(uname -m) if ! [[ "${BUILD_ARCH}" =~ arm ]]; then flags+=" --pnacl-use-emulator" fi fi local triple_install_dir="$(GetTranslatorInstallDir ${arch})/triple-build" mkdir -p ${triple_install_dir} local new_llc_nexe="${triple_install_dir}/pnacl-llc.rebuild.nexe" mkdir -p "${triple_install_dir}" StepBanner "VERIFY" "Translating ${llc_pexe} using sandboxed tools (${arch})" local sb_translator="${INSTALL_TRANSLATOR}/bin/pnacl-translate" RunWithLog "verify.triple.build" \ "${sb_translator}" ${flags} -arch ${arch} "${llc_pexe}" -o "${new_llc_nexe}" if ! cmp --silent "${llc_nexe}" "${new_llc_nexe}" ; then Banner "TRIPLE BUILD VERIFY FAILED" echo "Expected these files to be identical, but they are not:" echo " ${archllc}" echo " ${newllc}" exit -1 fi StepBanner "VERIFY" "Verified ${arch} OK" } ###################################################################### ###################################################################### # # UTILITIES # ###################################################################### ###################################################################### #@------------------------------------------------------------------------- #@ show-config show-config() { Banner "Config Settings:" echo "PNACL_BUILDBOT: ${PNACL_BUILDBOT}" echo "PNACL_CONCURRENCY: ${PNACL_CONCURRENCY}" echo "PNACL_DEBUG: ${PNACL_DEBUG}" echo "PNACL_PRUNE: ${PNACL_PRUNE}" echo "PNACL_VERBOSE: ${PNACL_VERBOSE}" echo "INSTALL_ROOT: ${INSTALL_ROOT}" Banner "Your Environment:" env | grep PNACL Banner "uname info for builder:" uname -a } #@ help - Usage information. help() { Usage } #@ help-full - Usage information including internal functions. help-full() { Usage2 } has-trusted-toolchain() { if [ -f ${TOOLCHAIN_BASE}/arm_trusted/ld_script_arm_trusted ]; then return 0 else return 1 fi } check-for-trusted() { if ! ${PNACL_BUILD_ARM} ; then return fi if ! has-trusted-toolchain; then echo '*******************************************************************' echo '* The ARM trusted toolchain does not appear to be installed yet *' echo '* It is needed to run ARM tests. *' echo '* *' echo '* To download and install the trusted toolchain, run: *' echo '* *' echo '* $ pnacl/build.sh download-trusted *' echo '* *' echo '* To compile the trusted toolchain, use: *' echo '* *' echo '* $ tools/llvm/trusted-toolchain-creator.sh trusted_sdk *' echo '* (warning: this takes a while) *' echo '*******************************************************************' # If building on the bots, do not continue since it needs to run ARM tests. if ${PNACL_BUILDBOT} ; then echo "Building on bots --> need ARM trusted toolchain to run tests!" exit -1 elif trusted-tc-confirm ; then echo "Continuing without ARM trusted toolchain" PNACL_BUILD_ARM=false else echo "Okay, stopping." exit -1 fi fi } trusted-tc-confirm() { echo echo "Do you wish to continue without the ARM trusted TC (skip ARM testing)?" echo "" confirm-yes "Continue" return $? } DebugRun() { if ${PNACL_DEBUG} || ${PNACL_BUILDBOT}; then "$@" fi } ###################################################################### # Generate chromium perf bot logs for tracking the size of a binary. # print-tagged-tool-sizes() { local tag="$1" local binary="$2" # size output look like: # text data bss dec hex filename # 354421 16132 168920 539473 83b51 .../tool local sizes=($(${PNACL_SIZE} -B "${binary}" | grep '[0-9]\+')) echo "RESULT ${tag}: text= ${sizes[0]} bytes" echo "RESULT ${tag}: data= ${sizes[1]} bytes" echo "RESULT ${tag}: bss= ${sizes[2]} bytes" echo "RESULT ${tag}: total= ${sizes[3]} bytes" local file_size=($(du --bytes "${binary}")) echo "RESULT ${tag}: file_size= ${file_size[0]} bytes" } ###################################################################### ###################################################################### # # < TIME STAMPING > # ###################################################################### ###################################################################### ts-dir-changed() { local tsfile="$1" local dir="$2" if [ -f "${tsfile}" ]; then local MODIFIED=$(find "${dir}" -type f -newer "${tsfile}") [ ${#MODIFIED} -gt 0 ] ret=$? else true ret=$? fi return $ret } # Check if the source for a given build has been modified ts-modified() { local srcdir="$1" local objdir="$2" local tsfile="${objdir}/${TIMESTAMP_FILENAME}" ts-dir-changed "${tsfile}" "${srcdir}" return $? } ts-touch() { local tsfile="$1" touch "${tsfile}" } # Record the time when make begins, but don't yet # write that to the timestamp file. # (Just in case make fails) ts-touch-open() { local objdir="$1" local tsfile="${objdir}/${TIMESTAMP_FILENAME}" local tsfile_open="${objdir}/${TIMESTAMP_FILENAME}_OPEN" rm -f "${tsfile}" touch "${tsfile_open}" } # Write the timestamp. (i.e. make has succeeded) ts-touch-commit() { local objdir="$1" local tsfile="${objdir}/${TIMESTAMP_FILENAME}" local tsfile_open="${objdir}/${TIMESTAMP_FILENAME}_OPEN" mv -f "${tsfile_open}" "${tsfile}" } # ts-newer-than dirA dirB # Compare the make timestamps in both object directories. # returns true (0) if dirA is newer than dirB # returns false (1) otherwise. # # This functions errs on the side of returning 0, since # that forces a rebuild anyway. ts-newer-than() { local objdir1="$1" local objdir2="$2" local tsfile1="${objdir1}/${TIMESTAMP_FILENAME}" local tsfile2="${objdir2}/${TIMESTAMP_FILENAME}" if [ ! -d "${objdir1}" ]; then return 0; fi if [ ! -d "${objdir2}" ]; then return 0; fi if [ ! -f "${tsfile1}" ]; then return 0; fi if [ ! -f "${tsfile2}" ]; then return 0; fi local MODIFIED=$(find "${tsfile1}" -newer "${tsfile2}") if [ ${#MODIFIED} -gt 0 ]; then return 0 fi return 1 } # Don't define any functions after this or they won't show up in completions function-completions() { if [ $# = 0 ]; then set -- ""; fi compgen -A function -- $1 exit 0 } ###################################################################### ###################################################################### # # < MAIN > # ###################################################################### ###################################################################### mkdir -p "${INSTALL_ROOT}" if [ $# = 0 ]; then set -- help; fi # Avoid reference to undefined $1. # Accept one -- argument for some compatibility with google3 if [ $1 = "--tab_completion_word" ]; then set -- function-completions $2 fi if [ "$(type -t $1)" != "function" ]; then #Usage echo "ERROR: unknown function '$1'." >&2 echo "For help, try:" echo " $0 help" exit 1 fi "$@"