c938f638151893b0b1e25fa9647b5f847321d19c
[platform/framework/web/crosswalk.git] / src / native_client / pnacl / build.sh
1 #!/bin/bash
2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5 #
6 #@                 PNaCl toolchain build script
7 #@-------------------------------------------------------------------
8 #@ This script builds the ARM and PNaCl untrusted toolchains.
9 #@ It MUST be run from the native_client/ directory.
10 ######################################################################
11 # Directory Layout Description
12 ######################################################################
13 #
14 # All directories are relative to BASE which is
15 # On Linux: native_client/toolchain/pnacl_linux_x86/
16 # On Mac: native_client/toolchain/pnacl_mac_x86/
17 # On Windows: native_client/toolchain/pnacl_win_x86/
18 #
19 ######################################################################
20
21 set -o nounset
22 set -o errexit
23
24 PWD_ON_ENTRY="$(pwd)"
25 # The script is located in "native_client/pnacl/".
26 # Set pwd to pnacl/
27 cd "$(dirname "$0")"
28 if [[ $(basename "$(pwd)") != "pnacl" ]] ; then
29   echo "ERROR: cannot find pnacl/ directory"
30   exit -1
31 fi
32
33 source scripts/common-tools.sh
34
35 readonly PNACL_ROOT="$(pwd)"
36 readonly NACL_ROOT="$(GetAbsolutePath ..)"
37 readonly SCONS_OUT="${NACL_ROOT}/scons-out"
38
39 SetScriptPath "${PNACL_ROOT}/build.sh"
40 SetLogDirectory "${PNACL_ROOT}/build/log"
41
42 readonly TOOLCHAIN_BUILD="${NACL_ROOT}/toolchain_build/toolchain_build_pnacl.py"
43
44 # For different levels of make parallelism change this in your env
45 readonly PNACL_CONCURRENCY=${PNACL_CONCURRENCY:-8}
46 # Concurrency for builds using the host's system compiler (which might be goma)
47 readonly PNACL_CONCURRENCY_HOST=${PNACL_CONCURRENCY_HOST:-${PNACL_CONCURRENCY}}
48 PNACL_PRUNE=${PNACL_PRUNE:-false}
49 PNACL_BUILD_ARM=true
50 PNACL_BUILD_MIPS=${PNACL_BUILD_MIPS:-false}
51
52 if ${BUILD_PLATFORM_MAC} || ${BUILD_PLATFORM_WIN}; then
53   # We don't yet support building ARM tools for mac or windows.
54   PNACL_BUILD_ARM=false
55   PNACL_BUILD_MIPS=false
56 fi
57
58 # PNaCl builds libc++/libc++abi as well as libstdc++, allowing users to
59 # choose which to use through the -stdlib=XXX command-line argument.
60 #
61 # The following strings are used for banner names as well as file and
62 # folder names. These names are created by the libraries themselves, and
63 # expected by their dependents. Changing them would be ill-advised.
64 readonly LIB_CXX_NAME="libc++"
65 readonly LIB_STDCPP_NAME="libstdc++"
66
67 # TODO(pdox): Decide what the target should really permanently be
68 readonly CROSS_TARGET_ARM=arm-none-linux-gnueabi
69 readonly BINUTILS_TARGET=arm-pc-nacl
70 readonly REAL_CROSS_TARGET=le32-nacl
71 readonly NACL64_TARGET=x86_64-nacl
72
73 readonly DRIVER_DIR="${PNACL_ROOT}/driver"
74 readonly ARM_ARCH=armv7-a
75 readonly ARM_FPU=vfp
76
77 readonly TOOLCHAIN_ROOT="${NACL_ROOT}/toolchain"
78
79 readonly NNACL_BASE="${TOOLCHAIN_ROOT}/${SCONS_BUILD_PLATFORM}_x86"
80 readonly NNACL_NEWLIB_ROOT="${NNACL_BASE}_newlib"
81 readonly NNACL_ARM_NEWLIB_ROOT="${TOOLCHAIN_ROOT}/linux_arm_newlib"
82
83 readonly PNACL_MAKE_OPTS="${PNACL_MAKE_OPTS:-}"
84 readonly MAKE_OPTS="-j${PNACL_CONCURRENCY} VERBOSE=1 ${PNACL_MAKE_OPTS}"
85 readonly MAKE_OPTS_HOST="-j${PNACL_CONCURRENCY_HOST} VERBOSE=1 ${PNACL_MAKE_OPTS}"
86
87 readonly NONEXISTENT_PATH="/going/down/the/longest/road/to/nowhere"
88
89 # For speculative build status output. ( see status function )
90 # Leave this blank, it will be filled during processing.
91 SPECULATIVE_REBUILD_SET=""
92
93 readonly PNACL_SUPPORT="${PNACL_ROOT}/support"
94
95 readonly THIRD_PARTY="${NACL_ROOT}"/../third_party
96 readonly NACL_SRC_THIRD_PARTY_MOD="${NACL_ROOT}/src/third_party_mod"
97
98 # Git sources
99 readonly PNACL_GIT_ROOT="${PNACL_ROOT}/git"
100 readonly TC_SRC_BINUTILS="${PNACL_GIT_ROOT}/binutils"
101 readonly TC_SRC_LLVM="${PNACL_GIT_ROOT}/llvm"
102 readonly TC_SRC_GCC="${PNACL_GIT_ROOT}/gcc"
103 readonly TC_SRC_NEWLIB="${PNACL_GIT_ROOT}/nacl-newlib"
104 readonly TC_SRC_LIBSTDCPP="${TC_SRC_GCC}/${LIB_STDCPP_NAME}-v3"
105 readonly TC_SRC_COMPILER_RT="${PNACL_GIT_ROOT}/compiler-rt"
106 readonly TC_SRC_CLANG="${PNACL_GIT_ROOT}/clang"
107 readonly TC_SRC_LIBCXX="${PNACL_GIT_ROOT}/libcxx"
108
109 readonly SERVICE_RUNTIME_SRC="${NACL_ROOT}/src/trusted/service_runtime"
110 readonly EXPORT_HEADER_SCRIPT="${SERVICE_RUNTIME_SRC}/export_header.py"
111 readonly NACL_SYS_HEADERS="${SERVICE_RUNTIME_SRC}/include"
112 readonly NEWLIB_INCLUDE_DIR="${TC_SRC_NEWLIB}/newlib/libc/sys/nacl"
113
114 # The location of each project. These should be absolute paths.
115 readonly TC_BUILD="${PNACL_ROOT}/build"
116 readonly TC_BUILD_LLVM="${TC_BUILD}/llvm_${HOST_ARCH}"
117 readonly TC_BUILD_BINUTILS="${TC_BUILD}/binutils_${HOST_ARCH}"
118 readonly TC_BUILD_BINUTILS_LIBERTY="${TC_BUILD}/binutils-liberty"
119 TC_BUILD_NEWLIB="${TC_BUILD}/newlib"
120 readonly TC_BUILD_COMPILER_RT="${TC_BUILD}/compiler_rt"
121 readonly TC_BUILD_GCC="${TC_BUILD}/gcc"
122 readonly NACL_HEADERS_TS="${TC_BUILD}/nacl.sys.timestamp"
123
124 readonly TIMESTAMP_FILENAME="make-timestamp"
125
126 # PNaCl toolchain installation directories (absolute paths)
127 readonly TOOLCHAIN_LABEL="${TOOLCHAIN_LABEL:-pnacl_${BUILD_PLATFORM}_x86}"
128 readonly INSTALL_ROOT="${TOOLCHAIN_ROOT}/${TOOLCHAIN_LABEL}"
129 readonly INSTALL_BIN="${INSTALL_ROOT}/bin"
130
131 # Bitcode lib directories (including static bitcode libs)
132 INSTALL_LIB="${INSTALL_ROOT}/lib"
133
134 # Native nacl lib directories
135 # The pattern `${INSTALL_LIB_NATIVE}${arch}' is used in many places.
136 readonly INSTALL_LIB_NATIVE="${INSTALL_ROOT}/lib-"
137 readonly INSTALL_LIB_ARM="${INSTALL_LIB_NATIVE}arm"
138 readonly INSTALL_LIB_X8632="${INSTALL_LIB_NATIVE}x86-32"
139 readonly INSTALL_LIB_X8664="${INSTALL_LIB_NATIVE}x86-64"
140 readonly INSTALL_LIB_MIPS32="${INSTALL_LIB_NATIVE}mips32"
141
142 # PNaCl client-translators (sandboxed) binary locations
143 readonly INSTALL_TRANSLATOR="${TOOLCHAIN_ROOT}/pnacl_translator"
144
145
146 # The INSTALL_HOST directory has host binaries and libs which
147 # are part of the toolchain (e.g. llvm and binutils).
148 # There are also tools-x86 and tools-arm which have host binaries which
149 # are not part of the toolchain but might be useful in the SDK, e.g.
150 # arm sel_ldr and x86-hosted arm/mips validators.
151 readonly INSTALL_HOST="${INSTALL_ROOT}/host_${HOST_ARCH}"
152
153 # Component installation directories
154 readonly LLVM_INSTALL_DIR="${INSTALL_HOST}"
155 readonly BINUTILS_INSTALL_DIR="${INSTALL_HOST}"
156 readonly BFD_PLUGIN_DIR="${BINUTILS_INSTALL_DIR}/lib/bfd-plugins"
157 readonly FAKE_INSTALL_DIR="${INSTALL_HOST}/fake"
158 NEWLIB_INSTALL_DIR="${INSTALL_ROOT}/usr"
159
160 # Location of the PNaCl tools defined for configure invocations.
161 readonly PNACL_CC="${INSTALL_BIN}/pnacl-clang"
162 readonly PNACL_CXX="${INSTALL_BIN}/pnacl-clang++"
163 readonly PNACL_LD="${INSTALL_BIN}/pnacl-ld"
164 readonly PNACL_PP="${INSTALL_BIN}/pnacl-clang -E"
165 readonly PNACL_AR="${INSTALL_BIN}/pnacl-ar"
166 readonly PNACL_RANLIB="${INSTALL_BIN}/pnacl-ranlib"
167 readonly PNACL_AS="${INSTALL_BIN}/pnacl-as"
168 readonly PNACL_DIS="${INSTALL_BIN}/pnacl-dis"
169 readonly PNACL_FINALIZE="${INSTALL_BIN}/pnacl-finalize"
170 readonly PNACL_NM="${INSTALL_BIN}/pnacl-nm"
171 readonly PNACL_TRANSLATE="${INSTALL_BIN}/pnacl-translate"
172 readonly PNACL_READELF="${INSTALL_BIN}/pnacl-readelf"
173 readonly PNACL_SIZE="${BINUTILS_INSTALL_DIR}/bin/${REAL_CROSS_TARGET}-size"
174 readonly PNACL_STRIP="${INSTALL_BIN}/pnacl-strip"
175 readonly ILLEGAL_TOOL="${INSTALL_BIN}"/pnacl-illegal
176
177 GetNNaClTool() {
178   local arch=$1
179   case ${arch} in
180     x86-32) echo ${NNACL_NEWLIB_ROOT}/bin/i686-nacl-gcc ;;
181     x86-64) echo ${NNACL_NEWLIB_ROOT}/bin/x86_64-nacl-gcc ;;
182     arm) echo ${NNACL_ARM_NEWLIB_ROOT}/bin/arm-nacl-gcc ;;
183     mips32)
184       # No NNaCl for mips
185       echo -n "${PNACL_CC} -arch mips32 --pnacl-bias=mips32 "
186       echo "--pnacl-allow-translate --pnacl-allow-native" ;;
187     *) Fatal "Unexpected argument to GetNNaClTool: $*" ;;
188   esac
189 }
190
191 # For a production (release) build, we want the sandboxed
192 # translator to only contain the code needed to handle
193 # its own architecture. For example, the translator shipped with
194 # an X86-32 browser would only be able to translate to X86-32 code.
195 # This is so that the translator binary is as small as possible.
196 #
197 # If SBTC_PRODUCTION is true, then the translators are built
198 # separately, one for each architecture, so that each translator
199 # can only target its own architecture.
200 #
201 # If SBTC_PRODUCTION is false, then we instead use PNaCl to
202 # build a `fat` translator which can target all supported
203 # architectures. This translator is built as a .pexe
204 # which can then be translated to each individual architecture.
205 SBTC_PRODUCTION=${SBTC_PRODUCTION:-true}
206
207 # Which arches to build for our sandboxed toolchain.
208 SBTC_ARCHES_ALL=${SBTC_ARCHES_ALL:-"armv7 i686 x86_64"}
209
210 get-sbtc-llvm-arches() {
211 # For LLVM i686 brings in both i686 and x86_64.  De-dupe that.
212   echo ${SBTC_ARCHES_ALL} \
213     | sed 's/x86_64/i686/' | sed 's/i686\(.*\)i686/i686\1/'
214 }
215 SBTC_ARCHES_LLVM=$(get-sbtc-llvm-arches)
216
217
218 CC=${CC:-gcc}
219 CXX=${CXX:-g++}
220 AR=${AR:-ar}
221 RANLIB=${RANLIB:-ranlib}
222
223 if ${HOST_ARCH_X8632}; then
224   # These are simple compiler wrappers to force 32bit builds
225   CC="${PNACL_ROOT}/scripts/mygcc32"
226   CXX="${PNACL_ROOT}/scripts/myg++32"
227 fi
228
229 # Set up some environment variables to build flavored bitcode libs
230 setup-biased-bitcode-env() {
231  local arch=$1
232   case ${arch} in
233     portable)
234       BIASED_BC_CFLAGS=""
235       NEWLIB_INSTALL_DIR="${INSTALL_ROOT}/usr"
236       NEWLIB_TARGET=${REAL_CROSS_TARGET}
237       TC_BUILD_NEWLIB="${TC_BUILD}/newlib-portable"
238       INSTALL_LIB="${INSTALL_ROOT}/lib"
239       LIB_CPP_BUILD="${TC_BUILD}/c++-stdlib-newlib-portable"
240       LIB_CPP_INSTALL_DIR="${INSTALL_ROOT}/usr"
241       ;;
242     x86-64)
243       BIASED_BC_CFLAGS="--target=x86_64-nacl"
244       NEWLIB_INSTALL_DIR="${INSTALL_ROOT}/usr-bc-${arch}"
245       # Do this to avoid .S files in newlib that clang doesn't like
246       NEWLIB_TARGET="${REAL_CROSS_TARGET}"
247       TC_BUILD_NEWLIB="${TC_BUILD}/newlib-${arch}"
248       INSTALL_LIB="${INSTALL_ROOT}/lib-bc-${arch}"
249       LIB_CPP_BUILD="${TC_BUILD}/c++-stdlib-newlib-${arch}"
250       LIB_CPP_INSTALL_DIR="${INSTALL_ROOT}/usr-bc-${arch}"
251       ;;
252     *)
253       echo "Newlib architectures other than portable and x86-64 not implemented yet"
254       exit 1
255   esac
256 }
257
258 setup-lib-cpp-env() {
259   # NOTE: we do not expect the assembler or linker to be used for libs
260   #       hence the use of ILLEGAL_TOOL.
261
262   STD_ENV_FOR_LIB_CPP=(
263     CC_FOR_BUILD="${CC}"
264     CC="${PNACL_CC}"
265     CXX="${PNACL_CXX}"
266     RAW_CXX_FOR_TARGET="${PNACL_CXX}"
267     LD="${ILLEGAL_TOOL}"
268     CFLAGS="-g -O2 -mllvm -inline-threshold=5 ${BIASED_BC_CFLAGS}"
269     CXXFLAGS="-g -O2 -mllvm -inline-threshold=5 ${BIASED_BC_CFLAGS}"
270     CFLAGS_FOR_TARGET="-g -O2 -mllvm -inline-threshold=5 ${BIASED_BC_CFLAGS}"
271     CXXFLAGS_FOR_TARGET="-g -O2 -mllvm -inline-threshold=5 ${BIASED_BC_CFLAGS}"
272     CC_FOR_TARGET="${PNACL_CC}"
273     GCC_FOR_TARGET="${PNACL_CC}"
274     CXX_FOR_TARGET="${PNACL_CXX}"
275     AR="${PNACL_AR}"
276     AR_FOR_TARGET="${PNACL_AR}"
277     NM_FOR_TARGET="${PNACL_NM}"
278     RANLIB="${PNACL_RANLIB}"
279     RANLIB_FOR_TARGET="${PNACL_RANLIB}"
280     AS_FOR_TARGET="${ILLEGAL_TOOL}"
281     LD_FOR_TARGET="${ILLEGAL_TOOL}"
282     OBJDUMP_FOR_TARGET="${ILLEGAL_TOOL}" )
283 }
284
285 setup-newlib-env() {
286   local arch=$1
287   setup-biased-bitcode-env ${arch}
288
289   STD_ENV_FOR_NEWLIB=(
290     # TODO(robertm): get rid of '-allow-asm' here once we have a way of
291     # distinguishing "good" from "bad" asms.
292     CFLAGS_FOR_TARGET="-allow-asm -g -O2 -mllvm -inline-threshold=5 ${BIASED_BC_CFLAGS}"
293     CXXFLAGS_FOR_TARGET="-allow-asm -g -O2 -mllvm -inline-threshold=5 ${BIASED_BC_CFLAGS}"
294     CC_FOR_TARGET="${PNACL_CC}"
295     GCC_FOR_TARGET="${PNACL_CC}"
296     CXX_FOR_TARGET="${PNACL_CXX}"
297     AR_FOR_TARGET="${PNACL_AR}"
298     NM_FOR_TARGET="${PNACL_NM}"
299     RANLIB_FOR_TARGET="${PNACL_RANLIB}"
300     READELF_FOR_TARGET="${PNACL_READELF}"
301     OBJDUMP_FOR_TARGET="${ILLEGAL_TOOL}"
302     AS_FOR_TARGET="${ILLEGAL_TOOL}"
303     LD_FOR_TARGET="${ILLEGAL_TOOL}"
304     STRIP_FOR_TARGET="${ILLEGAL_TOOL}" )
305 }
306
307 # The gold plugin that we use is documented at
308 # http://llvm.org/docs/GoldPlugin.html
309 # Despite its name it is actually used by both gold and bfd. The changes to
310 # this file to enable its use are:
311 # * Build shared
312 # * --enable-gold and --enable-plugin when building binutils
313 # * --with-binutils-include when building binutils
314 # * linking the plugin in bfd-plugins
315
316 ######################################################################
317 ######################################################################
318 #
319 #                     < USER ACCESSIBLE FUNCTIONS >
320 #
321 ######################################################################
322 ######################################################################
323
324 # Convert a path given on the command-line to an absolute path.
325 # This takes into account the fact that we changed directories at the
326 # beginning of this script. PWD_ON_ENTRY is used to remember the
327 # initial working directory.
328 ArgumentToAbsolutePath() {
329   local relpath="$1"
330   local savepwd="$(pwd)"
331   cd "${PWD_ON_ENTRY}"
332   GetAbsolutePath "${relpath}"
333   cd "${savepwd}"
334 }
335
336 #@ sync-sources          - check out repos needed to build toolchain
337 sync-sources() {
338   StepBanner "SYNC SOURCES"
339   python ${TOOLCHAIN_BUILD} --legacy-repo-sync
340   newlib-nacl-headers
341 }
342
343 git-sync() {
344   local gitbase="${PNACL_GIT_ROOT}"
345   # Disable depot tools auto-update for these invocations. (It
346   # will still get updated when it is invoked at the start of each build,
347   # and we don't want it updating from cygwin here)
348   export DEPOT_TOOLS_UPDATE=0
349
350   mkdir -p "${gitbase}"
351   cp "${PNACL_ROOT}"/gclient_template "${gitbase}/.gclient"
352
353   if ! [ -d "${gitbase}/dummydir" ]; then
354     spushd "${gitbase}"
355     ${GCLIENT} update --verbose -j1
356     spopd
357   fi
358
359   newlib-nacl-headers-clean
360   cp "${PNACL_ROOT}"/DEPS "${gitbase}"/dummydir
361   spushd "${gitbase}"
362   ${GCLIENT} update --verbose -j1
363   spopd
364
365   # Copy nacl headers into newlib tree.
366   newlib-nacl-headers
367 }
368
369 gerrit-upload() {
370   # Upload to gerrit code review
371   # (Note: normally we use Rietveld code review. This is only useful if
372   # e.g. we want external users to use gerrit instead of rietveld so we can
373   # easily merge their commits without giving them direct access). But
374   # this at least documents the specifics of uploading to our repo
375   # TODO(dschuff): Find a good way to persist the user's login. maybe
376   # do something like what depot tools does
377   if ! [ -f ~/.gerrit_username ]; then
378     echo "Enter your gerrit username: "
379     read user
380     echo "Saving gerrit username (${user}) to ~/.gerrit_username"
381     echo ${user} > ~/.gerrit_username
382   else
383     local user=$(cat ~/.gerrit_username)
384   fi
385   cd "${TC_SRC_LLVM}"
386   git push ssh://${user}@gerrit.chromium.org:29418/native_client/pnacl-llvm \
387     HEAD:refs/for/master
388 }
389
390 #@-------------------------------------------------------------------------
391
392 #@ download-trusted      - Download and Install trusted SDKs (arm,x86-32,x86-64)
393 #@                         (your untrusted build will not be modified)
394 download-trusted() {
395   StepBanner "DOWNLOAD-TRUSTED" "Downloading trusted toolchains"
396   local installdir="${INSTALL_ROOT}"
397   local tmpdir="${installdir}-backup"
398   local dldir="${installdir}-downloaded"
399
400   rm -rf "${dldir}"
401
402   if [ -d "${tmpdir}" ]; then
403     echo "ERROR: It is not expected that directory '${tmpdir}' exists."
404     echo "       Please delete it if you don't need it"
405     exit -1
406   fi
407
408   if [ -d "${installdir}" ]; then
409     mv "${installdir}" "${tmpdir}"
410   fi
411
412   download-toolchains
413
414   if [ -d "${installdir}" ]; then
415     mv "${installdir}" "${dldir}"
416   fi
417
418   if [ -d "${tmpdir}" ]; then
419     mv "${tmpdir}" "${installdir}"
420   fi
421 }
422
423 #@-------------------------------------------------------------------------
424
425 #@ download-toolchains   - Download and Install all SDKs (arm,x86-32,x86-64)
426
427 download-toolchains() {
428   ${GCLIENT} runhooks --force --verbose
429 }
430
431 #@ libs                  - install native libs and build bitcode libs
432 libs() {
433   libs-clean
434   newlib portable
435   newlib x86-64
436   libs-support
437   for arch in arm x86-32 x86-64 mips32; do
438     dummy-irt-shim ${arch}
439   done
440   compiler-rt-all
441   libgcc_eh-all
442   lib-cpp ${LIB_CXX_NAME} portable
443   lib-cpp ${LIB_CXX_NAME} x86-64
444   lib-cpp ${LIB_STDCPP_NAME} portable
445   lib-cpp ${LIB_STDCPP_NAME} x86-64
446 }
447
448 #@ everything            - Build and install untrusted SDK. no translator
449 everything() {
450   sync-sources
451   build-all
452 }
453
454 #@ build-all does everything AFTER getting the sources
455 build-all() {
456   mkdir -p "${INSTALL_ROOT}"
457   # This is needed to build misc-tools and run ARM tests.
458   # We check this early so that there are no surprises later, and we can
459   # handle all user interaction early.
460   check-for-trusted
461
462   clean-install
463
464   clean-logs
465
466   build-host
467
468   driver
469
470   libs
471
472   # NOTE: we delay the tool building till after the sdk is essentially
473   #      complete, so that sdk sanity checks don't fail
474   misc-tools
475   cp "${PNACL_ROOT}/README" "${INSTALL_ROOT}"
476   verify
477
478   if ${PNACL_PRUNE}; then
479     prune
480   fi
481 }
482
483 #@ Build just the host binaries
484 build-host() {
485   binutils
486   llvm
487   if ${PNACL_PRUNE}; then
488     prune-host
489   fi
490 }
491
492 #@ everything-translator   - Build and install untrusted SDK AND translator
493 everything-translator() {
494   everything
495   translator-all
496   driver-install-translator
497 }
498
499 #@ translator-archive-pexes <tarball> -archive gold and llc pexes
500 #@                      <tarball> should be an absolute pathname,
501 #@                      and should have tar.bz2 as the suffix (as that is
502 #@                      what will be produced).
503 #@
504 #@                      This must run before pexes are pruned.
505 translator-archive-pexes() {
506   local tarball=$1
507
508   if [[ "${tarball#*.}" != "tar.bz2" ]]; then
509     echo "translator-archive-pexes: ${tarball} not named with .tar.bz2 suffix"
510     exit 1
511   fi
512   local tarball_no_bz2=${tarball%.*}
513
514   # Clear tarball before appending files to it.
515   rm -f ${tarball}
516
517   # Archive LD
518   for arch in ${SBTC_ARCHES_ALL} ; do
519     local pexe_dir="$(GetTranslatorInstallDir ${arch})/bin"
520     echo "pexe_dir is ${pexe_dir}"
521     # Label the pexes by architecture.
522     local pexe_ld="${pexe_dir}/ld.${arch}"
523     cp "${pexe_dir}/ld.pexe" "${pexe_ld}.nonfinal.pexe"
524     ${PNACL_FINALIZE} "${pexe_ld}.nonfinal.pexe" -o "${pexe_ld}.final.pexe"
525     local all="${pexe_ld}.final.pexe"
526     file ${all}
527     ls -l ${all}
528     # strip all path components
529     tar rf ${tarball_no_bz2}  --transform 's!^.*/!!' ${all}
530   done
531
532   # Archive LLC (which combines x86 and x86_64).
533   for arch in ${SBTC_ARCHES_LLVM} ; do
534     local pexe_dir="$(GetTranslatorInstallDir ${arch})/bin"
535     echo "pexe_dir is ${pexe_dir}"
536     # Label the pexes by architecture.
537     local pexe_llc="${pexe_dir}/pnacl-llc.${arch}"
538     cp "${pexe_dir}/pnacl-llc.pexe" "${pexe_llc}.nonfinal.pexe"
539     ${PNACL_FINALIZE} "${pexe_llc}.nonfinal.pexe" \
540       -o "${pexe_llc}.final.pexe"
541     local all="${pexe_llc}.final.pexe"
542     file ${all}
543     ls -l ${all}
544     # strip all path components
545     tar rf ${tarball_no_bz2}  --transform 's!^.*/!!' ${all}
546   done
547   bzip2 ${tarball_no_bz2}
548 }
549
550
551 #+ translator-clean-all  - Clean all translator install/build directories
552 translator-clean-all() {
553   StepBanner "TRANSLATOR" "Clean all"
554   rm -rf "${TC_BUILD}"/translator*
555   rm -rf "${INSTALL_TRANSLATOR}"*
556 }
557
558 #@ translator-all   -  Build and install all of the translators.
559 translator-all() {
560   StepBanner \
561     "SANDBOXED TC [prod=${SBTC_PRODUCTION}] [arches=${SBTC_ARCHES_ALL}]"
562
563   # Build the SDK if it not already present.
564   sdk
565   # Also build private libs to allow building nexes without the IRT
566   # segment gap.  Specifically, only the sandboxed translator nexes
567   # are built without IRT support to gain address space and reduce
568   # swap file usage. Also libsrpc and its dependencies are now considered
569   # private libs because they are not in the real SDK
570   sdk-private-libs
571
572   binutils-liberty
573   if ${SBTC_PRODUCTION}; then
574     # Build each architecture separately.
575     local arch
576     for arch in ${SBTC_ARCHES_LLVM} ; do
577       llvm-sb ${arch}
578     done
579     for arch in ${SBTC_ARCHES_ALL} ; do
580       binutils-gold-sb ${arch}
581     done
582   else
583     # Using arch `universal` builds the sandboxed tools from a single
584     # .pexe which support all targets.
585     llvm-sb universal
586     binutils-gold-sb universal
587     if ${PNACL_PRUNE}; then
588       # The universal pexes have already been translated.
589       # They don't need to stick around.
590       rm -rf "$(GetTranslatorInstallDir universal)"
591     fi
592   fi
593
594   # Copy native libs to translator install dir.
595   cp -a ${INSTALL_LIB_NATIVE}* ${INSTALL_TRANSLATOR}
596
597   driver-install-translator
598
599   if ${PNACL_PRUNE}; then
600     sdk-clean newlib
601   fi
602 }
603
604
605 #+ translator-prune    Remove leftover files like pexes from pnacl_translator
606 #+                     build and from translator-archive-pexes.
607 translator-prune() {
608   find "${INSTALL_TRANSLATOR}" -name "*.pexe" -exec "rm" {} +
609 }
610
611
612 #+ translator-clean <arch> -
613 #+     Clean one translator install/build
614 translator-clean() {
615   local arch=$1
616   StepBanner "TRANSLATOR" "Clean ${arch}"
617   rm -rf "$(GetTranslatorInstallDir ${arch})"
618   rm -rf "$(GetTranslatorBuildDir ${arch})"
619 }
620
621 #@ all                   - Alias for 'everything'
622 all() {
623   everything
624 }
625
626 #@ status                - Show status of build directories
627 status() {
628   # TODO(robertm): this is currently broken
629   StepBanner "BUILD STATUS"
630
631   status-helper "BINUTILS"             binutils
632   status-helper "LLVM"                 llvm
633
634   status-helper "NEWLIB"               newlib
635   status-helper "C++ Standard Library" lib-cpp
636 }
637
638 status-helper() {
639   local title="$1"
640   local mod="$2"
641
642   if ${mod}-needs-configure; then
643     StepBanner "$title" "NEEDS FULL REBUILD"
644     speculative-add "${mod}"
645   elif ${mod}-needs-make; then
646     StepBanner "$title" "NEEDS MAKE (INCREMENTAL)"
647     speculative-add "${mod}"
648   else
649     StepBanner "$title" "OK (UP TO DATE)"
650   fi
651 }
652
653 speculative-add() {
654   local mod="$1"
655   SPECULATIVE_REBUILD_SET="${SPECULATIVE_REBUILD_SET} ${mod}"
656 }
657
658 speculative-check() {
659   local mod="$1"
660   local search=$(echo "${SPECULATIVE_REBUILD_SET}" | grep -F "$mod")
661   [ ${#search} -gt 0 ]
662   return $?
663 }
664
665
666
667 #@ clean                 - Clean the build and install directories.
668 clean() {
669   StepBanner "CLEAN" "Cleaning build, log, and install directories."
670
671   clean-logs
672   clean-build
673   clean-install
674   clean-scons
675 }
676
677 #@ fast-clean            - Clean everything except LLVM.
678 fast-clean() {
679   local did_backup=false
680   local backup_dir="${PNACL_ROOT}/fast-clean-llvm-backup"
681
682   if [ -d "${TC_BUILD_LLVM}" ]; then
683     rm -rf "${backup_dir}"
684     mv "${TC_BUILD_LLVM}" "${backup_dir}"
685     did_backup=true
686   fi
687
688   clean
689
690   if ${did_backup} ; then
691     mkdir -p "${TC_BUILD}"
692     mv "${backup_dir}" "${TC_BUILD_LLVM}"
693   fi
694 }
695
696 #+ clean-scons           - Clean scons-out directory
697 clean-scons() {
698   rm -rf "${SCONS_OUT}"
699 }
700
701 #+ clean-build           - Clean all build directories
702 clean-build() {
703   rm -rf "${TC_BUILD}"
704 }
705
706 #+ clean-install         - Clean install directories
707 clean-install() {
708   rm -rf "${INSTALL_ROOT}"
709 }
710
711 #+ libs-clean            - Removes the library directories
712 libs-clean() {
713   StepBanner "LIBS-CLEAN" "Cleaning ${INSTALL_ROOT}/libs-*"
714   rm -rf "${INSTALL_LIB}"/*
715   rm -rf "${INSTALL_LIB_NATIVE}"*
716 }
717
718
719 #@-------------------------------------------------------------------------
720
721 prune-host() {
722   echo "stripping binaries (binutils)"
723   strip "${BINUTILS_INSTALL_DIR}"/bin/*
724
725   echo "stripping binaries (llvm)"
726   if ! strip "${LLVM_INSTALL_DIR}"/bin/* ; then
727     echo "NOTE: some failures during stripping are expected"
728   fi
729
730   echo "removing unused clang shared lib"
731   rm -rf "${LLVM_INSTALL_DIR}"/${SO_DIR}/*clang${SO_EXT}
732
733   echo "removing unused binutils binaries"
734   rm -rf "${LLVM_INSTALL_DIR}"/bin/le32-nacl-elfedit
735   rm -rf "${LLVM_INSTALL_DIR}"/bin/le32-nacl-gprof
736   rm -rf "${LLVM_INSTALL_DIR}"/bin/le32-nacl-objcopy
737
738   echo "removing unused LLVM/Clang binaries"
739   rm -rf "${LLVM_INSTALL_DIR}"/bin/bc-wrap
740   rm -rf "${LLVM_INSTALL_DIR}"/bin/bugpoint
741   rm -rf "${LLVM_INSTALL_DIR}"/bin/c-index-test
742   rm -rf "${LLVM_INSTALL_DIR}"/bin/clang-*
743   rm -rf "${LLVM_INSTALL_DIR}"/bin/llc
744   rm -rf "${LLVM_INSTALL_DIR}"/bin/lli
745   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-ar
746   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-bcanalyzer
747   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-config
748   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-cov
749   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-diff
750   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-dwarfdump
751   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-extract
752   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-mcmarkup
753   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-prof
754   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-ranlib
755   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-readobj
756   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-rtdyld
757   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-size
758   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-stress
759   rm -rf "${LLVM_INSTALL_DIR}"/bin/llvm-symbolizer
760   rm -rf "${LLVM_INSTALL_DIR}"/bin/macho-dump
761   rm -rf "${LLVM_INSTALL_DIR}"/bin/pso-stub
762   rm -rf "${LLVM_INSTALL_DIR}"/bin/*-tblgen
763
764   echo "removing llvm & clang headers"
765   rm -rf "${LLVM_INSTALL_DIR}"/include
766
767   echo "removing docs/ and share/"
768   rm -rf "${LLVM_INSTALL_DIR}"/docs
769   rm -rf "${LLVM_INSTALL_DIR}"/share
770
771   echo "removing unused libs"
772   rm -rf "${LLVM_INSTALL_DIR}"/lib/*.a
773   rm -rf "${LLVM_INSTALL_DIR}"/lib/bfd-plugins
774   rm -rf "${LLVM_INSTALL_DIR}"/lib/BugpointPasses.so
775   rm -rf "${LLVM_INSTALL_DIR}"/lib/LLVMHello.so
776 }
777
778 #+ prune                 - Prune toolchain
779 prune() {
780   StepBanner "PRUNE" "Pruning toolchain"
781   local dir_size_before=$(get_dir_size_in_mb ${INSTALL_ROOT})
782
783   SubBanner "Size before: ${INSTALL_ROOT} ${dir_size_before}MB"
784
785   prune-host
786
787   echo "removing .pyc files"
788   rm -f "${INSTALL_BIN}"/pydir/*.pyc
789
790   local dir_size_after=$(get_dir_size_in_mb "${INSTALL_ROOT}")
791   SubBanner "Size after: ${INSTALL_ROOT} ${dir_size_after}MB"
792 }
793
794 #+ tarball <filename>    - Produce tarball file
795 tarball() {
796   if [ ! -n "${1:-}" ]; then
797     echo "Error: tarball needs a tarball name." >&2
798     exit 1
799   fi
800   local tarball="$(ArgumentToAbsolutePath "$1")"
801   StepBanner "TARBALL" "Creating tar ball ${tarball}"
802   tar zcf "${tarball}" -C "${INSTALL_ROOT}" .
803   ls -l ${tarball}
804 }
805
806 translator-tarball() {
807   if [ ! -n "${1:-}" ]; then
808     echo "Error: tarball needs a tarball name." >&2
809     exit 1
810   fi
811   local tarball="$(ArgumentToAbsolutePath "$1")"
812   StepBanner "TARBALL" "Creating translator tar ball ${tarball}"
813   tar zcf "${tarball}" -C "${INSTALL_TRANSLATOR}" .
814 }
815
816 #########################################################################
817 #                              < LLVM >
818 #########################################################################
819
820
821 #+-------------------------------------------------------------------------
822 #+ llvm                  - Configure, build and install LLVM.
823
824 llvm() {
825   StepBanner "LLVM (${HOST_ARCH} HOST)"
826
827   local srcdir="${TC_SRC_LLVM}"
828
829   assert-dir "${srcdir}" "You need to checkout LLVM."
830
831   if llvm-needs-configure; then
832     llvm-clean
833     llvm-configure
834   else
835     SkipBanner "LLVM" "configure"
836   fi
837
838   if llvm-needs-make; then
839     llvm-make
840   else
841     SkipBanner "LLVM" "make"
842   fi
843
844   llvm-install
845 }
846
847 #+ llvm-clean            - Clean LLVM completely
848 llvm-clean() {
849   StepBanner "LLVM" "Clean"
850   local objdir="${TC_BUILD_LLVM}"
851   rm -rf ${objdir}
852   mkdir -p ${objdir}
853 }
854
855 #+ llvm-link-clang       - Add tools/clang symlink into llvm directory
856 llvm-link-clang() {
857   rm -f "${TC_SRC_LLVM}"/tools/clang
858   # Symbolic link named : ${TC_SRC_LLVM}/tools/clang
859   # Needs to point to   : ${TC_SRC_CLANG}
860   ln -sf "${TC_SRC_CLANG}" "${TC_SRC_LLVM}"/tools/clang
861 }
862
863 #+ llvm-unlink-clang     - Remove tools/clang symlink from llvm directory
864 llvm-unlink-clang() {
865   if [ -d "${TC_SRC_LLVM}" ]; then
866     rm -f "${TC_SRC_LLVM}"/tools/clang
867   fi
868 }
869
870 # Default case - Optimized configure
871 LLVM_EXTRA_OPTIONS="--enable-optimized"
872
873 #+ llvm-configure        - Run LLVM configure
874 llvm-configure() {
875   StepBanner "LLVM" "Configure"
876
877   local srcdir="${TC_SRC_LLVM}"
878   local objdir="${TC_BUILD_LLVM}"
879
880   mkdir -p "${objdir}"
881   spushd "${objdir}"
882
883   # Some components like ARMDisassembler may time out when built with -O3.
884   # If we ever start using MSVC, we may also need to tone down the opt level
885   # (see the settings in the CMake file for those components).
886   local llvm_extra_opts=${LLVM_EXTRA_OPTIONS}
887   if ${BUILD_PLATFORM_MAC}; then
888     llvm_extra_opts="${LLVM_EXTRA_OPTIONS} --with-optimize-option=-O2"
889   fi
890
891   llvm-link-clang
892   # The --with-binutils-include is to allow llvm to build the gold plugin
893   # re: --enable-targets  "x86" brings in both i686 and x86_64.
894   # Disabling zlib features for now to reduce set of shared lib deps.
895   # This may disable things like compressed debug info:
896   # https://code.google.com/p/nativeclient/issues/detail?id=3592
897   local binutils_include="${TC_SRC_BINUTILS}/include"
898   RunWithLog "llvm.configure" \
899       env -i PATH="${PATH}" \
900              MAKE_OPTS=${MAKE_OPTS_HOST} \
901              CC="${CC}" \
902              CXX="${CXX}" \
903              ${srcdir}/configure \
904              --enable-shared \
905              --enable-zlib=no \
906              --disable-jit \
907              --with-binutils-include=${binutils_include} \
908              --enable-targets=x86,arm,mips \
909              --prefix="${LLVM_INSTALL_DIR}" \
910              --program-prefix= \
911              ${llvm_extra_opts}
912
913
914   spopd
915 }
916
917 #+ llvm-configure-ninja - Configure with cmake for ninja build
918 # Not used by default. Call manually. Pass build type (Release or Debug)
919 # as an argument; The default is Release.
920 llvm-configure-ninja() {
921   StepBanner "LLVM" "Configure (Cmake-ninja)"
922
923   local srcdir="${TC_SRC_LLVM}"
924   local objdir="${TC_BUILD_LLVM}"
925   local buildtype="${1:-Release}"
926
927   mkdir -p "${objdir}"
928   spushd "${objdir}"
929
930   llvm-link-clang
931   local binutils_include="${TC_SRC_BINUTILS}/include"
932   # Disabling zlib features for now to reduce set of shared lib deps.
933   # This may disable things like compressed debug info:
934   # https://code.google.com/p/nativeclient/issues/detail?id=3592
935   RunWithLog "llvm.configure.cmake" \
936     env \
937       cmake -G Ninja \
938       -DCMAKE_BUILD_TYPE=${buildtype} \
939       -DCMAKE_INSTALL_PREFIX="${LLVM_INSTALL_DIR}" \
940       -DCMAKE_INSTALL_RPATH='$ORIGIN/../lib' \
941       -DBUILD_SHARED_LIBS=ON \
942       -DLLVM_TARGETS_TO_BUILD="X86;ARM;Mips" \
943       -DLLVM_ENABLE_ASSERTIONS=ON \
944       -ULLVM_ENABLE_ZLIB \
945       -DLLVM_BUILD_TESTS=ON \
946       -DLLVM_APPEND_VC_REV=ON \
947       -DLLVM_BINUTILS_INCDIR="${binutils_include}" \
948       ${srcdir}
949   spopd
950 }
951
952 #+ llvm-configure-dbg        - Run LLVM configure
953 #  Not used by default. Call manually.
954 llvm-configure-dbg() {
955   StepBanner "LLVM" "Configure With Debugging"
956   LLVM_EXTRA_OPTIONS="--disable-optimized \
957         --enable-debug-runtime \
958         --enable-assertions "
959   llvm-configure
960 }
961
962
963 llvm-needs-configure() {
964   [ ! -f "${TC_BUILD_LLVM}/config.status" \
965     -a ! -f "${TC_BUILD_LLVM}/build.ninja" ]
966   return $?
967 }
968
969 llvm-needs-make() {
970   local objdir="${TC_BUILD_LLVM}"
971   ts-modified "${TC_SRC_LLVM}" "${objdir}" ||
972     ts-modified "${TC_SRC_CLANG}" "${objdir}"
973   return $?
974 }
975
976 #+ llvm-make             - Run LLVM 'make'
977 llvm-make() {
978   StepBanner "LLVM" "Make"
979
980   local srcdir="${TC_SRC_LLVM}"
981   local objdir="${TC_BUILD_LLVM}"
982   llvm-link-clang
983
984   spushd "${objdir}"
985
986   ts-touch-open "${objdir}"
987
988   if [ -f "${TC_BUILD_LLVM}/build.ninja" ]; then
989     if [ -f "${TC_BUILD_LLVM}/config.status" ]; then
990       echo "ERROR: Found multiple build system files in ${TC_BUILD_LLVM}"
991       exit 1
992     fi
993     echo "Using ninja"
994     ninja
995   else
996     RunWithLog llvm.make \
997       env -i PATH="${PATH}" \
998       MAKE_OPTS="${MAKE_OPTS_HOST}" \
999       NACL_SANDBOX=0 \
1000       CC="${CC}" \
1001       CXX="${CXX}" \
1002       make ${MAKE_OPTS_HOST} all
1003   fi
1004
1005   ts-touch-commit  "${objdir}"
1006
1007   spopd
1008 }
1009
1010 #+ llvm-install          - Install LLVM
1011 llvm-install() {
1012   StepBanner "LLVM" "Install"
1013
1014   spushd "${TC_BUILD_LLVM}"
1015   llvm-link-clang
1016   if [ -f "${TC_BUILD_LLVM}/build.ninja" ]; then
1017     echo "Using ninja"
1018     RunWithLog llvm.install ninja install
1019   else
1020     RunWithLog llvm.install \
1021       env -i PATH=/usr/bin/:/bin \
1022       MAKE_OPTS="${MAKE_OPTS}" \
1023       NACL_SANDBOX=0 \
1024       CC="${CC}" \
1025       CXX="${CXX}" \
1026       make ${MAKE_OPTS} install
1027   fi
1028   spopd
1029
1030   # This is really part of libgcc_eh, but gets blown away by the ninja build.
1031   install-unwind-header
1032 }
1033
1034 #########################################################################
1035 #########################################################################
1036 #     < LIBGCC_EH >
1037 #########################################################################
1038 #########################################################################
1039
1040 libgcc_eh-all() {
1041   StepBanner "LIBGCC_EH (from GCC 4.6)"
1042
1043   libgcc_eh arm
1044   libgcc_eh mips32
1045   libgcc_eh x86-32
1046   libgcc_eh x86-64
1047 }
1048
1049 libgcc_eh-setup() {
1050   local arch=$1
1051   local flags=$2
1052   # For x86 we use nacl-gcc to build libgcc_eh because of some issues with
1053   # LLVM's handling of the gcc intrinsics used in the library. See
1054   # https://code.google.com/p/nativeclient/issues/detail?id=1933
1055   # and http://llvm.org/bugs/show_bug.cgi?id=8541
1056   # For ARM, LLVM does work and we use it to avoid dealing with the fact that
1057   # arm-nacl-gcc uses different libgcc support functions than PNaCl.
1058   if [ ${arch} == "arm" ]; then
1059     LIBGCC_EH_ENV=(
1060       CC="${PNACL_CC} ${flags} -arch ${arch} --pnacl-bias=${arch} \
1061          --pnacl-allow-translate --pnacl-allow-native" \
1062       AR="${PNACL_AR}" \
1063       NM="${PNACL_NM}" \
1064       RANLIB="${PNACL_RANLIB}")
1065   else
1066     LIBGCC_EH_ENV=(
1067       CC="$(GetNNaClTool ${arch}) ${flags}" \
1068       AR="${PNACL_AR}" \
1069       NM="${PNACL_NM}" \
1070       RANLIB="${PNACL_RANLIB}")
1071   fi
1072 }
1073
1074 libgcc_eh() {
1075   local arch=$1
1076
1077   local objdir="${TC_BUILD}/libgcc_eh-${arch}-newlib"
1078   local subdir="${objdir}/fake-target/libgcc"
1079   local installdir="${INSTALL_LIB_NATIVE}${arch}"
1080   local label="(${arch} libgcc_eh.a)"
1081
1082   mkdir -p "${installdir}"
1083   rm -rf "${installdir}"/libgcc_eh*
1084   rm -rf "${objdir}"
1085
1086   # Setup fake gcc build directory.
1087   mkdir -p "${objdir}"/gcc
1088   cp -a "${PNACL_ROOT}"/scripts/libgcc-newlib.mvars \
1089         "${objdir}"/gcc/libgcc.mvars
1090   cp -a "${PNACL_ROOT}"/scripts/libgcc-tconfig.h "${objdir}"/gcc/tconfig.h
1091   touch "${objdir}"/gcc/tm.h
1092
1093   install-unwind-header
1094
1095   mkdir -p "${subdir}"
1096   spushd "${subdir}"
1097   local flags=""
1098   flags+=" -DENABLE_RUNTIME_CHECKING"
1099
1100   libgcc_eh-setup ${arch} "${flags}"
1101
1102   StepBanner "LIBGCC_EH" "Configure ${label}"
1103   RunWithLog libgcc.${arch}.configure \
1104     env -i \
1105       PATH="/usr/bin:/bin" \
1106       /bin/sh \
1107       "${TC_SRC_GCC}"/libgcc/configure \
1108         "${LIBGCC_EH_ENV[@]}" \
1109         --prefix="${FAKE_INSTALL_DIR}" \
1110         --enable-shared \
1111         --host=i686-nacl
1112         # --enable-shared is needed because the EH functions end
1113         # up in libgcc.a if shared libs are disabled.
1114         #
1115         # The "--host" field is needed to enable cross-compiling.
1116         # It introduces extra configuration files in libgcc/config, but these
1117         # appear to affect libgcc, not libgcc_eh.
1118         # TODO(pdox): Create a fake target to get rid of i686 here.
1119
1120   StepBanner "LIBGCC_EH" "Make ${label}"
1121   RunWithLog libgcc.${arch}.make make libgcc_eh.a
1122   spopd
1123
1124   StepBanner "LIBGCC_EH" "Install ${label}"
1125   cp ${subdir}/libgcc_eh.a "${installdir}"
1126 }
1127
1128 install-unwind-header() {
1129   # TODO(pdox):
1130   # We need to establish an unwind ABI, since this is part of the ABI
1131   # exposed to the bitcode by the translator. This header should not vary
1132   # across compilers or C libraries.
1133   local install="/usr/bin/install -c -m 644"
1134   ${install} ${TC_SRC_GCC}/gcc/unwind-generic.h \
1135              ${LLVM_INSTALL_DIR}/lib/clang/3.3/include/unwind.h
1136 }
1137
1138 #########################################################################
1139 #########################################################################
1140 #     < COMPILER-RT >
1141 #########################################################################
1142 #########################################################################
1143
1144 compiler-rt-all() {
1145   StepBanner "COMPILER-RT (LIBGCC)"
1146   compiler-rt arm
1147   compiler-rt mips32
1148   compiler-rt x86-32
1149   compiler-rt x86-64
1150 }
1151
1152
1153 #+ compiler-rt           - build/install llvm's replacement for libgcc.a
1154 compiler-rt() {
1155   local arch=$1
1156   local src="${TC_SRC_COMPILER_RT}/lib"
1157   local objdir="${TC_BUILD_COMPILER_RT}-${arch}"
1158   local installdir="${INSTALL_LIB_NATIVE}${arch}"
1159   StepBanner "compiler rt" "build (${arch})"
1160
1161   rm -rf "${objdir}"
1162   mkdir -p "${objdir}"
1163
1164   spushd "${objdir}"
1165   RunWithLog libgcc.${arch}.make \
1166       make -j ${PNACL_CONCURRENCY} -f ${src}/Makefile-pnacl libgcc.a \
1167         CC="${PNACL_CC}" \
1168         AR="${PNACL_AR}" \
1169         "SRC_DIR=${src}" \
1170         "CFLAGS=-arch ${arch} -DPNACL_${arch} --pnacl-allow-translate -O3"
1171
1172   StepBanner "compiler rt" "install (${arch})"
1173   mkdir -p "${installdir}"
1174   cp libgcc.a "${installdir}"
1175   spopd
1176 }
1177
1178 #########################################################################
1179 #########################################################################
1180 #                          < LIBSTDC++/LIBC++ >
1181 #########################################################################
1182 #########################################################################
1183
1184 check-lib-cpp() {
1185   local lib=$1
1186   if [ ${lib} != ${LIB_CXX_NAME} ] && [ ${lib} != ${LIB_STDCPP_NAME} ]; then
1187     echo "ERROR: Unsupported C++ Standard Library '${lib}'. Choose one of: ${LIB_CXX_NAME}, ${LIB_STDCPP_NAME}"
1188     exit -1
1189   fi
1190 }
1191
1192 LIB_CPP_IS_SETUP=false
1193 lib-cpp-setup() {
1194   if ${LIB_CPP_IS_SETUP} && [ $# -eq 0 ]; then
1195     return 0
1196   fi
1197   local arch=$1
1198   setup-biased-bitcode-env ${arch}
1199   LIB_CPP_IS_SETUP=true
1200 }
1201
1202 lib-cpp() {
1203   local lib=$1
1204   local arch=$2
1205   check-lib-cpp "${lib}"
1206   lib-cpp-setup "${arch}"
1207   StepBanner "C++ Standard Library" "(BITCODE $*)"
1208
1209   if lib-cpp-needs-configure "${lib}" "${arch}"; then
1210     lib-cpp-clean "${lib}"
1211     lib-cpp-configure "${lib}" "${arch}"
1212   else
1213     StepBanner "${lib}" "configure"
1214   fi
1215
1216   if lib-cpp-needs-make "${lib}" "${arch}"; then
1217     lib-cpp-make "${lib}" "${arch}"
1218   else
1219     SkipBanner "${lib}" "make"
1220   fi
1221
1222   lib-cpp-install "${lib}" "${arch}"
1223   LIB_CPP_IS_SETUP=false
1224 }
1225
1226 #+ lib-cpp-clean - clean libc++/libstdc++ in bitcode
1227 lib-cpp-clean() {
1228   local lib=$1
1229   StepBanner "${lib}" "Clean"
1230   rm -rf ${TC_BUILD}/${lib}*
1231 }
1232
1233 lib-cpp-needs-configure() {
1234   local lib=$1
1235   local arch=$2
1236   lib-cpp-setup "${arch}"
1237   local objdir="${LIB_CPP_BUILD}-${lib}"
1238   ts-newer-than "${TC_BUILD_LLVM}" "${objdir}" && return 0
1239   [ ! -f "${objdir}/config.status" ]
1240   return $?
1241 }
1242
1243 lib-cpp-configure() {
1244   local lib=$1
1245   local arch=$2
1246   lib-cpp-setup "${arch}"
1247   StepBanner "${lib}" "Configure"
1248   local objdir="${LIB_CPP_BUILD}-${lib}"
1249   local subdir="${objdir}/pnacl-target"
1250   local flags=""
1251   mkdir -p "${subdir}"
1252   spushd "${subdir}"
1253
1254   flags+="--with-newlib --disable-shared --disable-rpath"
1255
1256   setup-lib-cpp-env
1257
1258   if [ ${lib} == ${LIB_CXX_NAME} ]; then
1259     local srcdir="${TC_SRC_LIBCXX}"
1260     # HAS_THREAD_LOCAL is used by libc++abi's exception storage, the
1261     # fallback is pthread otherwise.
1262     local cflags="-g -O2 -mllvm -inline-threshold=5 ${BIASED_BC_CFLAGS} \
1263       -DHAS_THREAD_LOCAL=1"
1264     # LLVM's lit is used to test libc++. run.py serves as a shell that
1265     # translates pexe->nexe and executes in sel_ldr. The libc++ test
1266     # suite needs to be told to use pnacl-clang++'s "system library",
1267     # which happens to be libc++ when the -stdlib parameter is used.
1268     # The target architecture is set through the PNACL_RUN_ARCH
1269     # environment variable (``-arch env``).
1270     local litargs="--verbose"
1271     litargs+=" --param shell_prefix='${NACL_ROOT}/run.py -arch env --retries=1'"
1272     litargs+=" --param exe_suffix='.pexe'"
1273     litargs+=" --param use_system_lib=true"
1274     litargs+=" --param link_flags='-std=gnu++11 --pnacl-exceptions=sjlj'"
1275     # TODO(jfb) CMAKE_???_COMPILER_WORKS can be removed once the PNaCl
1276     #           driver scripts stop confusing cmake for libc++. See:
1277     #           https://code.google.com/p/nativeclient/issues/detail?id=3661
1278     RunWithLog libcxx.configure \
1279       env \
1280       cmake -G "Unix Makefiles" \
1281       -DCMAKE_CXX_COMPILER_WORKS=1 \
1282       -DCMAKE_C_COMPILER_WORKS=1 \
1283       -DCMAKE_INSTALL_PREFIX="${LIB_CPP_INSTALL_DIR}" \
1284       -DCMAKE_BUILD_TYPE=Release \
1285       -DCMAKE_C_COMPILER="${PNACL_CC}" \
1286       -DCMAKE_CXX_COMPILER="${PNACL_CXX}" \
1287       -DCMAKE_AR="${PNACL_AR}" \
1288       -DCMAKE_NM="${PNACL_NM}" \
1289       -DCMAKE_RANLIB="${PNACL_RANLIB}" \
1290       -DCMAKE_LD="${ILLEGAL_TOOL}" \
1291       -DCMAKE_AS="${ILLEGAL_TOOL}" \
1292       -DCMAKE_OBJDUMP="${ILLEGAL_TOOL}" \
1293       -DCMAKE_C_FLAGS="-std=gnu11 ${cflags}" \
1294       -DCMAKE_CXX_FLAGS="-std=gnu++11 ${cflags}" \
1295       -DLIT_EXECUTABLE="${TC_SRC_LLVM}/utils/lit/lit.py" \
1296       -DLLVM_LIT_ARGS="${litargs}" \
1297       -DLIBCXX_ENABLE_CXX0X=0 \
1298       -DLIBCXX_ENABLE_SHARED=0 \
1299       -DLIBCXX_CXX_ABI=libcxxabi \
1300       -DLIBCXX_LIBCXXABI_INCLUDE_PATHS="${TC_SRC_LIBCXX}/../libcxxabi/include" \
1301       ${flags} \
1302       ${srcdir}
1303   else
1304     local srcdir="${TC_SRC_LIBSTDCPP}"
1305     RunWithLog libstdcpp.configure \
1306       env -i PATH=/usr/bin/:/bin \
1307       "${STD_ENV_FOR_LIB_CPP[@]}" \
1308       "${srcdir}"/configure \
1309       --host="${CROSS_TARGET_ARM}" \
1310       --prefix="${LIB_CPP_INSTALL_DIR}" \
1311       --enable-cxx-flags="-D__SIZE_MAX__=4294967295" \
1312       --disable-multilib \
1313       --disable-linux-futex \
1314       --disable-libstdcxx-time \
1315       --disable-sjlj-exceptions \
1316       --disable-libstdcxx-pch \
1317       ${flags}
1318   fi
1319   spopd
1320 }
1321
1322 lib-cpp-needs-make() {
1323   local lib=$1
1324   local arch=$2
1325   lib-cpp-setup "${arch}"
1326   local srcdir="${TC_SRC_LIBSTDCPP}" && \
1327     [ ${lib} == ${LIB_CXX_NAME} ] && srcdir="${TC_SRC_LIBCXX}"
1328   local objdir="${LIB_CPP_BUILD}-${lib}"
1329
1330   ts-modified "${srcdir}" "${objdir}"
1331   return $?
1332 }
1333
1334 lib-cpp-make() {
1335   local lib=$1
1336   local arch=$2
1337   lib-cpp-setup "${arch}"
1338   StepBanner "${lib}" "Make"
1339   local objdir="${LIB_CPP_BUILD}-${lib}"
1340
1341   ts-touch-open "${objdir}"
1342
1343   spushd "${objdir}/pnacl-target"
1344   setup-lib-cpp-env
1345   RunWithLog "${lib}.make" \
1346     env -i PATH=/usr/bin/:/bin \
1347     make \
1348     "${STD_ENV_FOR_LIB_CPP[@]}" \
1349     ${MAKE_OPTS}
1350   spopd
1351
1352   ts-touch-commit "${objdir}"
1353 }
1354
1355 lib-cpp-install() {
1356   local lib=$1
1357   local arch=$2
1358   lib-cpp-setup "${arch}"
1359   StepBanner "${lib}" "Install"
1360   local objdir="${LIB_CPP_BUILD}-${lib}"
1361
1362   spushd "${objdir}/pnacl-target"
1363
1364   # Clean the existing installation
1365   local include_dir=""
1366   if [ ${lib} == ${LIB_CXX_NAME} ]; then
1367     include_dir="v[0-9]"
1368   else
1369     include_dir="[0-9].[0-9].[0-9]"
1370   fi
1371   rm -rf "${LIB_CPP_INSTALL_DIR}"/include/c++/"${include_dir}"
1372   rm -rf "${LIB_CPP_INSTALL_DIR}"/lib/"${lib}"*
1373
1374   # install headers (=install-data)
1375   # for good measure make sure we do not keep any old headers
1376   setup-lib-cpp-env
1377   if [ ${lib} == ${LIB_CXX_NAME} ]; then
1378     RunWithLog "${lib}.install" \
1379       make \
1380       "${STD_ENV_FOR_LIB_CPP[@]}" \
1381       ${MAKE_OPTS} install
1382   else
1383     RunWithLog "${lib}.install" \
1384       make \
1385       "${STD_ENV_FOR_LIB_CPP[@]}" \
1386       ${MAKE_OPTS} install-data
1387   fi
1388
1389   # Install bitcode library
1390   mkdir -p "${LIB_CPP_INSTALL_DIR}/lib"
1391   if [ ${lib} == ${LIB_CXX_NAME} ]; then
1392     cp "${objdir}/pnacl-target/lib/${LIB_CXX_NAME}.a" \
1393       "${LIB_CPP_INSTALL_DIR}/lib"
1394   else
1395     cp "${objdir}/pnacl-target/src/.libs/${LIB_STDCPP_NAME}.a" \
1396       "${LIB_CPP_INSTALL_DIR}/lib"
1397   fi
1398   spopd
1399
1400   # libstdc++ installs a file with an abnormal name: "libstdc++*-gdb.py"
1401   # The asterisk may be due to a bug in libstdc++ Makefile/configure.
1402   # This causes problems on the Windows bot (during cleanup, toolchain
1403   # directory delete fails due to the bad character).
1404   # Rename it to get rid of the asterisk.
1405   if [ ${lib} == ${LIB_STDCPP_NAME} ]; then
1406     spushd "${LIB_CPP_INSTALL_DIR}/lib"
1407     mv -f ${LIB_STDCPP_NAME}'*'-gdb.py ${LIB_STDCPP_NAME}-gdb.py
1408     spopd
1409   fi
1410 }
1411
1412 #########################################################################
1413 #########################################################################
1414 #                          < Tools >
1415 #########################################################################
1416 #########################################################################
1417
1418 build-validator() {
1419   local arch=$1
1420   StepBanner "MISC-TOOLS" "Building validator ("${arch}")"
1421   spushd "${NACL_ROOT}"
1422   RunWithLog ${arch}_ncval_core \
1423     ./scons MODE=opt-host \
1424     sysinfo=0 \
1425     ${arch}-ncval-core
1426   cp ${SCONS_OUT}/opt-linux-x86-32/obj/src/trusted/\
1427 validator_${arch}/${arch}-ncval-core ${INSTALL_ROOT}/tools-x86
1428   spopd
1429 }
1430
1431 #+ misc-tools            - Build and install sel_ldr and validator for ARM.
1432 misc-tools() {
1433   if ${PNACL_BUILD_ARM} ; then
1434     StepBanner "MISC-TOOLS" "Building sel_ldr (arm)"
1435
1436     # TODO(robertm): revisit some of these options
1437     spushd "${NACL_ROOT}"
1438     RunWithLog arm_sel_ldr \
1439       ./scons MODE=opt-host \
1440       platform=arm \
1441       naclsdk_validate=0 \
1442       sysinfo=0 \
1443       -j${PNACL_CONCURRENCY} \
1444       sel_ldr
1445     rm -rf  "${INSTALL_ROOT}/tools-arm"
1446     mkdir "${INSTALL_ROOT}/tools-arm"
1447     local sconsdir="${SCONS_OUT}/opt-${SCONS_BUILD_PLATFORM}-arm"
1448     cp "${sconsdir}/obj/src/trusted/service_runtime/sel_ldr" \
1449        "${INSTALL_ROOT}/tools-arm"
1450     spopd
1451   else
1452     StepBanner "MISC-TOOLS" "Skipping arm sel_ldr (No trusted arm toolchain)"
1453   fi
1454
1455   # TODO(petarj): It would be nice to build MIPS sel_ldr on builbots later.
1456   if [ "${PNACL_BUILD_MIPS}" == "true" ] ; then
1457     StepBanner "MISC-TOOLS" "Building sel_ldr (mips32)"
1458     spushd "${NACL_ROOT}"
1459     RunWithLog mips32_sel_ldr \
1460       ./scons MODE=opt-host \
1461       platform=mips32 \
1462       naclsdk_validate=0 \
1463       sysinfo=0 \
1464       -j${PNACL_CONCURRENCY} \
1465       sel_ldr
1466     rm -rf  "${INSTALL_ROOT}/tools-mips32"
1467     mkdir "${INSTALL_ROOT}/tools-mips32"
1468     local sconsdir="scons-out/opt-${SCONS_BUILD_PLATFORM}-mips32"
1469     cp "${sconsdir}/obj/src/trusted/service_runtime/sel_ldr" \
1470        "${INSTALL_ROOT}/tools-mips32"
1471     spopd
1472   else
1473     StepBanner "MISC-TOOLS" "Skipping mips sel_ldr (No trusted mips toolchain)"
1474   fi
1475
1476   if ${BUILD_PLATFORM_LINUX} ; then
1477     rm -rf  "${INSTALL_ROOT}/tools-x86"
1478     mkdir "${INSTALL_ROOT}/tools-x86"
1479     for target in arm mips; do
1480       build-validator $target
1481     done
1482   else
1483     for target in arm mips; do
1484       StepBanner "MISC-"${target} "Skipping " ${target} " validator (Not yet supported on Mac)"
1485     done
1486   fi
1487 }
1488
1489 #########################################################################
1490 #     < BINUTILS >
1491 #########################################################################
1492
1493 #+-------------------------------------------------------------------------
1494 #+ binutils          - Build and install binutils (cross-tools)
1495 binutils() {
1496   StepBanner "BINUTILS (${HOST_ARCH} HOST)"
1497
1498   local srcdir="${TC_SRC_BINUTILS}"
1499
1500   assert-dir "${srcdir}" "You need to checkout binutils."
1501
1502   if binutils-needs-configure; then
1503     binutils-clean
1504     binutils-configure
1505   else
1506     SkipBanner "BINUTILS" "configure"
1507   fi
1508
1509   if binutils-needs-make; then
1510     binutils-make
1511   else
1512     SkipBanner "BINUTILS" "make"
1513   fi
1514   binutils-install
1515 }
1516
1517 #+ binutils-clean    - Clean binutils
1518 binutils-clean() {
1519   StepBanner "BINUTILS" "Clean"
1520   local objdir="${TC_BUILD_BINUTILS}"
1521   rm -rf ${objdir}
1522 }
1523
1524 #+ binutils-configure- Configure binutils for ARM
1525 binutils-configure() {
1526   StepBanner "BINUTILS" "Configure"
1527
1528   local srcdir="${TC_SRC_BINUTILS}"
1529   local objdir="${TC_BUILD_BINUTILS}"
1530
1531   # enable multiple targets so that we can use the same ar with all .o files
1532   local targ="arm-pc-nacl,i686-pc-nacl,x86_64-pc-nacl,mipsel-pc-nacl"
1533   mkdir -p "${objdir}"
1534   spushd "${objdir}"
1535
1536   # The linux escaping is horrible but apparently the only way of doing this:
1537   # c.f.:  http://sourceware.org/ml/binutils/2009-05/msg00252.html
1538   # all we try to do here is to add "$ORIGIN/../lib to "rpath".
1539   # If you ever touch this please make sure that rpath is correct via:
1540   # objdump -p toolchain/${TOOLCHAIN_LABEL}/host/bin/le32-nacl-ld.gold
1541   # objdump -p toolchain/${TOOLCHAIN_LABEL}/host/bin/le32-nacl-objdump
1542   if ${BUILD_PLATFORM_LINUX} ; then
1543       local flags='-Xlinker -rpath -Xlinker '"'"'$\\$$\$$\\$$\$$ORIGIN/../lib'"'"
1544       local shared='yes'
1545       local zlib='--without-zlib'
1546   else
1547       # The shared build for binutils on mac is currently disabled.
1548       # A mac-expert needs to look at this but
1549       # It seems that on mac the linker is storing "full" library paths into
1550       # the dynamic image, e.g, for the llc dynamic image we see  paths like:
1551       # @executable_path/../lib/libLLVM-3.3svn.dylib
1552       # This only works if at linktime the libraries are already at
1553       # @executable_path/../lib which is not the case for mac
1554       #local flags="-Xlinker -rpath -Xlinker '@executable_path/../lib'"
1555       local flags=''
1556       local shared='no'
1557       local zlib=''
1558   fi
1559   # The --enable-gold and --enable-plugins options are on so that we
1560   # can use gold's support for plugin to link PNaCl modules, and use
1561   # gold as the final linker. We do not use bfd ld, and it is disabled
1562   # in part because we do not have its MIPS support downstream.
1563
1564   # We llvm's mc for assembly so we no longer build gas
1565   RunWithLog binutils.configure \
1566       env -i \
1567       PATH="${PATH}" \
1568       CC="${CC}" \
1569       CXX="${CXX}" \
1570       LDFLAGS="${flags}" \
1571       ${srcdir}/configure \
1572           --prefix="${BINUTILS_INSTALL_DIR}" \
1573           --target=${BINUTILS_TARGET} \
1574           --program-prefix=${REAL_CROSS_TARGET}- \
1575           --enable-targets=${targ} \
1576           --enable-shared=${shared} \
1577           --enable-gold=default \
1578           --enable-ld=no \
1579           --disable-nls \
1580           --enable-plugins \
1581           --disable-werror \
1582           --without-gas \
1583           ${zlib} \
1584           --with-sysroot="${NONEXISTENT_PATH}"
1585   # There's no point in setting the correct path as sysroot, because we
1586   # want the toolchain to be relocatable. The driver will use ld command-line
1587   # option --sysroot= to override this value and set it to the correct path.
1588   # However, we need to include --with-sysroot during configure to get this
1589   # option. So fill in a non-sense, non-existent path.
1590
1591   spopd
1592 }
1593
1594 binutils-needs-configure() {
1595   [ ! -f "${TC_BUILD_BINUTILS}/config.status" ]
1596   return $?
1597 }
1598
1599 binutils-needs-make() {
1600   local srcdir="${TC_SRC_BINUTILS}"
1601   local objdir="${TC_BUILD_BINUTILS}"
1602   local ret=1
1603   ts-modified "$srcdir" "$objdir" && ret=0
1604   return ${ret}
1605 }
1606
1607 #+ binutils-make     - Make binutils for ARM
1608 binutils-make() {
1609   StepBanner "BINUTILS" "Make"
1610   local objdir="${TC_BUILD_BINUTILS}"
1611   spushd "${objdir}"
1612
1613   ts-touch-open "${objdir}"
1614
1615   if ${BUILD_PLATFORM_LINUX}; then
1616     RunWithLog binutils.make \
1617       env -i PATH="/usr/bin:/bin" \
1618       ac_cv_search_zlibVersion=no \
1619       make ${MAKE_OPTS_HOST}
1620   else
1621     local control_parallel=""
1622     if ${BUILD_PLATFORM_MAC}; then
1623       # Try to avoid parallel builds for Mac to see if it avoids flake.
1624       # http://code.google.com/p/nativeclient/issues/detail?id=2926
1625       control_parallel="-j1"
1626     fi
1627     RunWithLog binutils.make \
1628       env -i PATH="${PATH}" \
1629       make ${MAKE_OPTS_HOST} ${control_parallel}
1630   fi
1631
1632   ts-touch-commit "${objdir}"
1633
1634   spopd
1635 }
1636
1637 #+ binutils-install  - Install binutils for ARM
1638 binutils-install() {
1639   StepBanner "BINUTILS" "Install"
1640   local objdir="${TC_BUILD_BINUTILS}"
1641   spushd "${objdir}"
1642
1643   RunWithLog binutils.install \
1644     env -i PATH="/usr/bin:/bin" \
1645     make \
1646       install ${MAKE_OPTS}
1647
1648   # TODO(robertm): remove this once we manage to avoid building
1649   #                ld in the first place
1650   echo "pruning hack: ${BINUTILS_INSTALL_DIR}"
1651   rm -f "${BINUTILS_INSTALL_DIR}/bin/${REAL_CROSS_TARGET}-ld"
1652   rm -f "${BINUTILS_INSTALL_DIR}/bin/${REAL_CROSS_TARGET}-ld.bfd"
1653
1654   # Also remove "${BINUTILS_INSTALL_DIR}/${BINUTILS_TARGET}" which contains
1655   # duplicate binaries and unused linker scripts
1656   echo "remove unused ${BINUTILS_INSTALL_DIR}/${BINUTILS_TARGET}/"
1657   rm -rf "${BINUTILS_INSTALL_DIR}/${BINUTILS_TARGET}/"
1658
1659   # Move binutils shared libs to host/lib.
1660   # The first "*" expands to the host string, e.g.
1661   # x86_64-unknown-linux-gnu
1662   if ${BUILD_PLATFORM_LINUX} ; then
1663     echo "move shared libs to ${BINUTILS_INSTALL_DIR}/${SO_DIR}"
1664     for lib in ${BINUTILS_INSTALL_DIR}/*/${BINUTILS_TARGET}/lib/lib*${SO_EXT}
1665     do
1666       echo "moving ${lib}"
1667       mv ${lib} ${BINUTILS_INSTALL_DIR}/${SO_DIR}
1668     done
1669   fi
1670
1671   # NOTE: this needs to come AFTER the moving of the shared libs
1672   # TODO(robertm): this needs to be augmented for mac and windows
1673   echo "remove unused (remaining) binutils static libs and headers"
1674   rm -rf "${BINUTILS_INSTALL_DIR}/i686-pc-linux-gnu" \
1675          "${BINUTILS_INSTALL_DIR}/x86_64-unknown-linux-gnu"
1676
1677   spopd
1678 }
1679
1680 #+-------------------------------------------------------------------------
1681 #+ binutils-liberty      - Build native binutils libiberty
1682 binutils-liberty() {
1683   local srcdir="${TC_SRC_BINUTILS}"
1684
1685   assert-dir "${srcdir}" "You need to checkout binutils."
1686
1687   if binutils-liberty-needs-configure; then
1688     binutils-liberty-clean
1689     binutils-liberty-configure
1690   else
1691     SkipBanner "BINUTILS-LIBERTY" "configure"
1692   fi
1693
1694   if binutils-liberty-needs-make; then
1695     binutils-liberty-make
1696   else
1697     SkipBanner "BINUTILS-LIBERTY" "make"
1698   fi
1699 }
1700
1701 binutils-liberty-needs-configure() {
1702   [ ! -f "${TC_BUILD_BINUTILS_LIBERTY}/config.status" ]
1703   return $?
1704 }
1705
1706 #+ binutils-liberty-clean    - Clean binutils-liberty
1707 binutils-liberty-clean() {
1708   StepBanner "BINUTILS-LIBERTY" "Clean"
1709   local objdir="${TC_BUILD_BINUTILS_LIBERTY}"
1710   rm -rf ${objdir}
1711 }
1712
1713 #+ binutils-liberty-configure - Configure binutils-liberty
1714 binutils-liberty-configure() {
1715   StepBanner "BINUTILS-LIBERTY" "Configure"
1716
1717   local srcdir="${TC_SRC_BINUTILS}"
1718   local objdir="${TC_BUILD_BINUTILS_LIBERTY}"
1719
1720   mkdir -p "${objdir}"
1721   spushd "${objdir}"
1722   RunWithLog binutils.liberty.configure \
1723       env -i \
1724       PATH="${PATH}" \
1725       CC="${CC}" \
1726       CXX="${CXX}" \
1727       ${srcdir}/configure
1728   spopd
1729 }
1730
1731 binutils-liberty-needs-make() {
1732   local srcdir="${TC_SRC_BINUTILS}"
1733   local objdir="${TC_BUILD_BINUTILS_LIBERTY}"
1734
1735   ts-modified "$srcdir" "$objdir"
1736   return $?
1737 }
1738
1739 #+ binutils-liberty-make - Make binutils-liberty
1740 binutils-liberty-make() {
1741   StepBanner "BINUTILS-LIBERTY" "Make"
1742   local srcdir="${TC_SRC_BINUTILS}"
1743   local objdir="${TC_BUILD_BINUTILS_LIBERTY}"
1744   spushd "${objdir}"
1745
1746   ts-touch-open "${objdir}"
1747
1748   RunWithLog binutils.liberty.make \
1749       env -i \
1750       PATH="${PATH}" \
1751       CC="${CC}" \
1752       CXX="${CXX}" \
1753       make ${MAKE_OPTS_HOST} all-libiberty
1754
1755   ts-touch-commit "${objdir}"
1756
1757   spopd
1758 }
1759
1760 #########################################################################
1761 #     CLIENT BINARIES (SANDBOXED)
1762 #########################################################################
1763
1764 check-arch() {
1765   local arch=$1
1766   for valid_arch in i686 x86_64 armv7 universal ; do
1767     if [ "${arch}" == "${valid_arch}" ] ; then
1768       return
1769     fi
1770   done
1771
1772   Fatal "ERROR: Unsupported arch [$1]. Must be: i686, x86_64, armv7, universal"
1773 }
1774
1775 llvm-sb-setup() {
1776   local arch=$1
1777   LLVM_SB_LOG_PREFIX="llvm.sb.${arch}"
1778   LLVM_SB_OBJDIR="$(GetTranslatorBuildDir ${arch})/llvm-sb"
1779
1780   # The SRPC headers are included directly from the nacl tree, as they are
1781   # not in the SDK. libsrpc should have already been built by the
1782   # build.sh sdk-private-libs step.
1783   # This is always statically linked.
1784   # The LLVM sandboxed build uses the normally-disallowed external
1785   # function __nacl_get_arch().  Allow that for now.
1786   local flags="-static -I$(GetAbsolutePath ${NACL_ROOT}/..) \
1787     --pnacl-disable-abi-check "
1788
1789   LLVM_SB_CONFIGURE_ENV=(
1790     AR="${PNACL_AR}" \
1791     AS="${PNACL_AS}" \
1792     CC="${PNACL_CC} ${flags}" \
1793     CXX="${PNACL_CXX} ${flags}" \
1794     LD="${PNACL_LD} ${flags}" \
1795     NM="${PNACL_NM}" \
1796     RANLIB="${PNACL_RANLIB}")
1797 }
1798
1799 #+-------------------------------------------------------------------------
1800 #+ llvm-sb <arch>- Build and install llvm tools (sandboxed)
1801 llvm-sb() {
1802   local arch=$1
1803   check-arch ${arch}
1804   llvm-sb-setup ${arch}
1805   StepBanner "LLVM-SB" "Sandboxed pnacl-llc [${arch}]"
1806   local srcdir="${TC_SRC_LLVM}"
1807   assert-dir "${srcdir}" "You need to checkout llvm."
1808
1809   if llvm-sb-needs-configure ${arch} ; then
1810     llvm-sb-clean ${arch}
1811     llvm-sb-configure ${arch}
1812   else
1813     SkipBanner "LLVM-SB" "configure ${arch}"
1814   fi
1815
1816   llvm-sb-make ${arch}
1817   llvm-sb-install ${arch}
1818 }
1819
1820 llvm-sb-needs-configure() {
1821   [ ! -f "${LLVM_SB_OBJDIR}/config.status" ]
1822   return $?
1823 }
1824
1825 # llvm-sb-clean          - Clean llvm tools (sandboxed)
1826 llvm-sb-clean() {
1827   local arch=$1
1828   StepBanner "LLVM-SB" "Clean ${arch}"
1829   local objdir="${LLVM_SB_OBJDIR}"
1830
1831   rm -rf "${objdir}"
1832   mkdir -p "${objdir}"
1833 }
1834
1835 # llvm-sb-configure - Configure llvm tools (sandboxed)
1836 llvm-sb-configure() {
1837   local arch=$1
1838
1839   StepBanner "LLVM-SB" "Configure ${arch}"
1840   local srcdir="${TC_SRC_LLVM}"
1841   local objdir="${LLVM_SB_OBJDIR}"
1842   local installdir="$(GetTranslatorInstallDir ${arch})"
1843   local targets=""
1844   # For LLVM, "x86" brings in both i686 and x86_64.
1845   case ${arch} in
1846     i686) targets=x86 ;;
1847     x86_64) targets=x86 ;;
1848     armv7) targets=arm ;;
1849     universal) targets=x86,arm ;;
1850   esac
1851
1852   spushd "${objdir}"
1853   # TODO(jvoung): remove ac_cv_func_getrusage=no once newlib has getrusage
1854   # in its headers.  Otherwise, configure thinks that we can link in
1855   # getrusage (stub is in libnacl), but we can't actually compile code
1856   # that uses ::getrusage because it's not in headers:
1857   # https://code.google.com/p/nativeclient/issues/detail?id=3657
1858   RunWithLog \
1859       ${LLVM_SB_LOG_PREFIX}.configure \
1860       env -i \
1861       PATH="/usr/bin:/bin" \
1862       ${srcdir}/configure \
1863         "${LLVM_SB_CONFIGURE_ENV[@]}" \
1864         --prefix=${installdir} \
1865         --host=nacl \
1866         --enable-targets=${targets} \
1867         --disable-assertions \
1868         --enable-pic=no \
1869         --enable-static \
1870         --enable-shared=no \
1871         --disable-jit \
1872         --enable-optimized \
1873         --target=${CROSS_TARGET_ARM} \
1874         llvm_cv_link_use_export_dynamic=no \
1875         ac_cv_func_getrusage=no
1876   spopd
1877 }
1878
1879 # llvm-sb-make - Make llvm tools (sandboxed)
1880 llvm-sb-make() {
1881   local arch=$1
1882   StepBanner "LLVM-SB" "Make ${arch}"
1883   local objdir="${LLVM_SB_OBJDIR}"
1884
1885   spushd "${objdir}"
1886   ts-touch-open "${objdir}"
1887
1888   local tools_to_build="pnacl-llc"
1889   local export_dyn_env="llvm_cv_link_use_export_dynamic=no"
1890   local isjit=0
1891   RunWithLog ${LLVM_SB_LOG_PREFIX}.make \
1892       env -i PATH="/usr/bin:/bin" \
1893       ONLY_TOOLS="${tools_to_build}" \
1894       NACL_SANDBOX=1 \
1895       KEEP_SYMBOLS=1 \
1896       VERBOSE=1 \
1897       ${export_dyn_env} \
1898       make ${MAKE_OPTS} tools-only
1899
1900   ts-touch-commit "${objdir}"
1901
1902   spopd
1903 }
1904
1905 # llvm-sb-install - Install llvm tools (sandboxed)
1906 llvm-sb-install() {
1907   local arch=$1
1908   StepBanner "LLVM-SB" "Install ${arch}"
1909
1910   local toolname="pnacl-llc"
1911   local installdir="$(GetTranslatorInstallDir ${arch})"/bin
1912   mkdir -p "${installdir}"
1913   spushd "${installdir}"
1914   local objdir="${LLVM_SB_OBJDIR}"
1915   cp -f "${objdir}"/Release*/bin/${toolname} .
1916   mv -f ${toolname} ${toolname}.pexe
1917   local arches=${arch}
1918   if [[ "${arch}" == "universal" ]]; then
1919     arches="${SBTC_ARCHES_ALL}"
1920   elif [[ "${arch}" == "i686" ]]; then
1921     # LLVM does not separate the i686 and x86_64 backends.
1922     # Translate twice to get both nexes.
1923     arches="i686 x86_64"
1924   fi
1925   translate-sb-tool ${toolname} "${arches}"
1926   install-sb-tool ${toolname} "${arches}"
1927   spopd
1928 }
1929
1930 # translate-sb-tool <toolname> <arches>
1931 #
1932 # Translate <toolname>.pexe to <toolname>.<arch>.nexe in the current directory.
1933 translate-sb-tool() {
1934   local toolname=$1
1935   local arches=$2
1936   local pexe="${toolname}.pexe"
1937   if ${PNACL_PRUNE}; then
1938     # Only strip debug, to preserve symbol names for testing. This is okay
1939     # because we strip the native nexe later anyway.
1940     # So, why bother stripping here at all?
1941     # It does appear to affect the size of the nexe:
1942     # http://code.google.com/p/nativeclient/issues/detail?id=3305
1943     ${PNACL_STRIP} --strip-debug "${pexe}"
1944   fi
1945
1946   local tarch
1947   for tarch in ${arches}; do
1948     local nexe="${toolname}.${tarch}.nexe"
1949     StepBanner "TRANSLATE" \
1950                "Translating ${toolname}.pexe to ${tarch} (background)"
1951     # NOTE: we are using --noirt to build without a segment gap
1952     # since we aren't loading the IRT for the translator nexes.
1953     #
1954     # Compiling with -ffunction-sections, -fdata-sections, --gc-sections
1955     # helps reduce the size a bit. If you want to use --gc-sections to test out:
1956     # http://code.google.com/p/nativeclient/issues/detail?id=1591
1957     # you will need to do a build without these flags.
1958     "${PNACL_TRANSLATE}" -ffunction-sections -fdata-sections --gc-sections \
1959       --allow-llvm-bitcode-input --noirt -arch ${tarch} "${pexe}" -o "${nexe}" &
1960     QueueLastProcess
1961   done
1962   StepBanner "TRANSLATE" "Waiting for translation processes to finish"
1963   QueueWait
1964
1965   # Test that certain symbols have been pruned before stripping.
1966   if [ "${toolname}" == "pnacl-llc" ]; then
1967     for tarch in ${arches}; do
1968       local nexe="${toolname}.${tarch}.nexe"
1969       local llvm_host_glob="${LLVM_INSTALL_DIR}/lib/libLLVM*so"
1970       python "${PNACL_ROOT}/prune_test.py" "${PNACL_NM}" \
1971         "${llvm_host_glob}" "${nexe}"
1972     done
1973   fi
1974
1975   if ${PNACL_PRUNE}; then
1976     # Strip the nexes.
1977     for tarch in ${arches}; do
1978       local nexe="${toolname}.${tarch}.nexe"
1979       ${PNACL_STRIP} "${nexe}"
1980     done
1981   fi
1982   StepBanner "TRANSLATE" "Done."
1983 }
1984
1985 # install-sb-tool <toolname> <arches>
1986 #
1987 # Install <toolname>.<arch>.nexe from the current directory
1988 # into the right location (as <toolname>.nexe)
1989 install-sb-tool() {
1990   local toolname="$1"
1991   local arches="$2"
1992   local tarch
1993   for tarch in ${arches}; do
1994     local installbin="$(GetTranslatorInstallDir ${tarch})"/bin
1995     mkdir -p "${installbin}"
1996     mv -f ${toolname}.${tarch}.nexe "${installbin}"/${toolname}.nexe
1997     if ${PNACL_BUILDBOT}; then
1998       spushd "${installbin}"
1999       local tag="${toolname}_${tarch}_size"
2000       print-tagged-tool-sizes "${tag}" "$(pwd)/${toolname}.nexe"
2001       spopd
2002     fi
2003   done
2004 }
2005
2006 GetTranslatorBuildDir() {
2007   local arch="$1"
2008   echo "${TC_BUILD}/translator-${arch//_/-}"
2009 }
2010
2011 GetTranslatorInstallDir() {
2012   local arch="$1"
2013   echo "${INSTALL_TRANSLATOR}"/${arch}
2014 }
2015
2016 ### Sandboxed version of gold.
2017
2018 #+-------------------------------------------------------------------------
2019 #+ binutils-gold-sb - Build and install gold (sandboxed)
2020 #+                    This is the replacement for the old
2021 #+                    final sandboxed linker which was bfd based.
2022 #+                    It has nothing to do with the bitcode linker
2023 #+                    which is also gold based.
2024 binutils-gold-sb() {
2025   local arch=$1
2026   check-arch ${arch}
2027   StepBanner "GOLD-NATIVE-SB" "(libiberty + gold) ${arch}"
2028
2029   local srcdir="${TC_SRC_BINUTILS}"
2030   assert-dir "${srcdir}" "You need to checkout gold."
2031
2032   binutils-gold-sb-clean ${arch}
2033   binutils-gold-sb-configure ${arch}
2034   binutils-gold-sb-make ${arch}
2035   binutils-gold-sb-install ${arch}
2036 }
2037
2038 # binutils-gold-sb-clean - Clean gold
2039 binutils-gold-sb-clean() {
2040   local arch=$1
2041   StepBanner "GOLD-NATIVE-SB" "Clean ${arch}"
2042   local objdir="$(GetTranslatorBuildDir ${arch})/binutils-gold-sb"
2043
2044   rm -rf "${objdir}"
2045   mkdir -p "${objdir}"
2046 }
2047
2048 # binutils-gold-sb-configure - Configure binutils for gold (unsandboxed)
2049 binutils-gold-sb-configure() {
2050   local arch=$1
2051   local srcdir="${TC_SRC_BINUTILS}"
2052   local objdir="$(GetTranslatorBuildDir ${arch})/binutils-gold-sb"
2053   local installbin="$(GetTranslatorInstallDir ${arch})/bin"
2054
2055   # The SRPC headers are included directly from the nacl tree, as they are
2056   # not in the SDK. libsrpc should have already been built by the
2057   # build.sh sdk-private-libs step
2058   # The Gold sandboxed build uses the normally-disallowed external
2059   # function __nacl_get_arch().  Allow that for now.
2060   #
2061   # TODO(jfb) Gold currently only builds with libstdc++.
2062   local flags="-static -I$(GetAbsolutePath ${NACL_ROOT}/..) \
2063     -fno-exceptions -O3 --pnacl-disable-abi-check -stdlib=${LIB_STDCPP_NAME} "
2064   local configure_env=(
2065     AR="${PNACL_AR}" \
2066     AS="${PNACL_AS}" \
2067     CC="${PNACL_CC} ${flags}" \
2068     CXX="${PNACL_CXX} ${flags}" \
2069     CC_FOR_BUILD="${CC}" \
2070     CXX_FOR_BUILD="${CXX}" \
2071     LD="${PNACL_LD} ${flags}" \
2072     NM="${PNACL_NM}" \
2073     RANLIB="${PNACL_RANLIB}"
2074   )
2075   local gold_targets=""
2076   case ${arch} in
2077     i686)      gold_targets=i686-pc-nacl ;;
2078     x86_64)    gold_targets=x86_64-pc-nacl ;;
2079     armv7)     gold_targets=arm-pc-nacl ;;
2080     universal)
2081       gold_targets=i686-pc-nacl,x86_64-pc-nacl,arm-pc-nacl ;;
2082   esac
2083
2084   # gold always adds "target" to the enabled targets so we are
2085   # little careful to not build too much
2086   # Note: we are (ab)using target for both --host and --target
2087   #       which configure expects to be present
2088   local target
2089   if [ ${arch} == "universal" ] ; then
2090     target=i686-pc-nacl
2091   else
2092     target=${gold_targets}
2093   fi
2094
2095   StepBanner "GOLD-NATIVE-SB" "Configure (libiberty)"
2096   # Gold depends on liberty only for a few functions:
2097   # xrealloc, lbasename, etc.
2098   # we could remove these if necessary.
2099
2100   mkdir -p "${objdir}/libiberty"
2101   spushd "${objdir}/libiberty"
2102   StepBanner "GOLD-NATIVE-SB" "Dir [$(pwd)]"
2103   local log_prefix="binutils-gold.sb.${arch}"
2104   RunWithLog "${log_prefix}".configure \
2105     env -i \
2106     PATH="/usr/bin:/bin" \
2107     "${configure_env[@]}" \
2108     ${srcdir}/libiberty/configure --prefix="${installbin}" \
2109     --host=${target} \
2110     --target=${target}
2111   spopd
2112
2113   StepBanner "GOLD-NATIVE-SB" "Configure (gold) ${arch}"
2114   mkdir -p "${objdir}/gold"
2115   spushd "${objdir}/gold"
2116   StepBanner "GOLD-NATIVE-SB" "Dir [$(pwd)]"
2117   # Removed -Werror until upstream gold no longer has problems with new clang
2118   # warnings. http://code.google.com/p/nativeclient/issues/detail?id=2861
2119   # TODO(sehr,robertm): remove this when gold no longer has these.
2120   RunWithLog "${log_prefix}".configure \
2121     env -i \
2122     PATH="/usr/bin:/bin" \
2123     "${configure_env[@]}" \
2124     CXXFLAGS="" \
2125     CFLAGS="" \
2126     ac_cv_search_zlibVersion=no \
2127     ac_cv_header_sys_mman_h=no \
2128     ac_cv_func_mmap=no \
2129     ac_cv_func_mallinfo=no \
2130     ac_cv_prog_cc_g=no \
2131     ac_cv_prog_cxx_g=no \
2132     ${srcdir}/gold/configure --prefix="${installbin}" \
2133                                       --enable-targets=${gold_targets} \
2134                                       --host=${target} \
2135                                       --target=${target} \
2136                                       --disable-nls \
2137                                       --enable-plugins=no \
2138                                       --enable-naclsrpc=yes \
2139                                       --disable-werror \
2140                                       --with-sysroot="${NONEXISTENT_PATH}"
2141   # Note: the extra ac_cv settings:
2142   # * eliminate unnecessary use of zlib
2143   # * eliminate use of mmap
2144   # (those should not have much impact on the non-sandboxed
2145   # version but help in the sandboxed case)
2146   # We also disable debug (-g) because the bitcode files become too big
2147   # (with ac_cv_prog_cc_g).
2148
2149   # There's no point in setting the correct path as sysroot, because we
2150   # want the toolchain to be relocatable. The driver will use ld command-line
2151   # option --sysroot= to override this value and set it to the correct path.
2152   # However, we need to include --with-sysroot during configure to get this
2153   # option. So fill in a non-sense, non-existent path.
2154   spopd
2155 }
2156
2157 # binutils-gold-sb-make - Make binutils (sandboxed)
2158 binutils-gold-sb-make() {
2159   local arch=${1}
2160   local objdir="$(GetTranslatorBuildDir ${arch})/binutils-gold-sb"
2161   ts-touch-open "${objdir}/"
2162
2163   StepBanner "GOLD-NATIVE-SB" "Make (liberty) ${arch}"
2164   spushd "${objdir}/libiberty"
2165
2166   RunWithLog "binutils-gold.liberty.sb.${arch}".make \
2167       env -i PATH="/usr/bin:/bin" \
2168       make ${MAKE_OPTS}
2169   spopd
2170
2171   StepBanner "GOLD-NATIVE-SB" "Make (gold) ${arch}"
2172   spushd "${objdir}/gold"
2173   RunWithLog "binutils-gold.sb.${arch}".make \
2174       env -i PATH="/usr/bin:/bin" \
2175       make ${MAKE_OPTS} ld-new
2176   spopd
2177
2178   ts-touch-commit "${objdir}"
2179 }
2180
2181 # binutils-gold-sb-install - Install gold
2182 binutils-gold-sb-install() {
2183   local objdir="$(GetTranslatorBuildDir ${arch})/binutils-gold-sb"
2184   local installbin="$(GetTranslatorInstallDir ${arch})/bin"
2185
2186   StepBanner "GOLD-NATIVE-SB" "Install [${installbin}] ${arch}"
2187
2188   mkdir -p "${installbin}"
2189   spushd "${installbin}"
2190
2191   # Install just "ld"
2192   cp "${objdir}"/gold/ld-new ld.pexe
2193
2194   # Translate and install
2195   local arches=${arch}
2196   if [[ "${arch}" == "universal" ]]; then
2197     arches="${SBTC_ARCHES_ALL}"
2198   fi
2199   translate-sb-tool ld "${arches}"
2200   install-sb-tool ld "${arches}"
2201   spopd
2202 }
2203
2204
2205 #+-------------------------------------------------------------------------
2206 #########################################################################
2207 #     < NEWLIB-BITCODE >
2208 #########################################################################
2209
2210 #+ newlib - Build and install newlib in bitcode.
2211 newlib() {
2212   local arch=$1
2213   setup-newlib-env ${arch}
2214   StepBanner "NEWLIB (${arch})"
2215
2216   if newlib-needs-configure; then
2217     newlib-clean
2218     newlib-configure ${arch}
2219   else
2220     SkipBanner "NEWLIB" "configure"
2221   fi
2222
2223   if newlib-needs-make; then
2224     newlib-make ${arch}
2225   else
2226     SkipBanner "NEWLIB" "make"
2227   fi
2228
2229   newlib-install ${arch}
2230 }
2231
2232 #+ newlib-clean  - Clean bitcode newlib.
2233 newlib-clean() {
2234   StepBanner "NEWLIB" "Clean"
2235   rm -rf "${TC_BUILD_NEWLIB}"
2236 }
2237
2238 newlib-needs-configure() {
2239   ts-newer-than "${TC_BUILD_LLVM}" \
2240                 "${TC_BUILD_NEWLIB}" && return 0
2241
2242   [ ! -f "${TC_BUILD_NEWLIB}/config.status" ]
2243   return #?
2244 }
2245
2246 #+ newlib-configure - Configure bitcode Newlib
2247 newlib-configure() {
2248   local arch=$1
2249   setup-newlib-env ${arch}
2250   StepBanner "NEWLIB" "Configure (${NEWLIB_TARGET})"
2251
2252   local srcdir="${TC_SRC_NEWLIB}"
2253   local objdir="${TC_BUILD_NEWLIB}"
2254   mkdir -p "${objdir}"
2255   spushd "${objdir}"
2256
2257   RunWithLog "newlib.${arch}.configure" \
2258     env -i \
2259     PATH="/usr/bin:/bin" \
2260     "${STD_ENV_FOR_NEWLIB[@]}" \
2261     ${srcdir}/configure \
2262         --disable-multilib \
2263         --prefix="${NEWLIB_INSTALL_DIR}" \
2264         --disable-newlib-supplied-syscalls \
2265         --disable-texinfo \
2266         --disable-libgloss \
2267         --enable-newlib-iconv \
2268         --enable-newlib-iconv-from-encodings=UTF-8,UTF-16LE,UCS-4LE,UTF-16,UCS-4 \
2269         --enable-newlib-iconv-to-encodings=UTF-8,UTF-16LE,UCS-4LE,UTF-16,UCS-4 \
2270         --enable-newlib-io-long-long \
2271         --enable-newlib-io-long-double \
2272         --enable-newlib-io-c99-formats \
2273         --enable-newlib-mb \
2274         --target="${NEWLIB_TARGET}"
2275
2276   spopd
2277 }
2278
2279 newlib-needs-make() {
2280   local srcdir="${TC_SRC_NEWLIB}"
2281   local objdir="${TC_BUILD_NEWLIB}"
2282
2283   ts-modified "$srcdir" "$objdir"
2284   return $?
2285 }
2286
2287 #+ newlib-make           - Make bitcode Newlib
2288 newlib-make() {
2289   local arch=$1
2290   setup-newlib-env ${arch}
2291   StepBanner "NEWLIB" "Make"
2292   local srcdir="${TC_SRC_NEWLIB}"
2293   local objdir="${TC_BUILD_NEWLIB}"
2294
2295   ts-touch-open "${objdir}"
2296
2297   spushd "${objdir}"
2298   RunWithLog "newlib.${arch}.make" \
2299     env -i PATH="/usr/bin:/bin" \
2300     make \
2301       "${STD_ENV_FOR_NEWLIB[@]}" \
2302       ${MAKE_OPTS}
2303   spopd
2304
2305   ts-touch-commit "${objdir}"
2306
2307 }
2308
2309 #+ newlib-install        - Install Bitcode Newlib using build env.
2310 newlib-install() {
2311   local arch=$1
2312   setup-newlib-env ${arch}
2313   StepBanner "NEWLIB" "Install"
2314   local objdir="${TC_BUILD_NEWLIB}"
2315
2316   spushd "${objdir}"
2317
2318   # NOTE: we might be better off not using install, as we are already
2319   #       doing a bunch of copying of headers and libs further down
2320   RunWithLog newlib.install \
2321     env -i PATH="/usr/bin:/bin" \
2322       make \
2323       "${STD_ENV_FOR_NEWLIB[@]}" \
2324       install ${MAKE_OPTS}
2325   spopd
2326
2327   # Newlib installs files into usr/${NEWLIB_TARGET}/*
2328   # Get rid of the ${NEWLIB_TARGET}/ prefix.
2329   spushd "${NEWLIB_INSTALL_DIR}"
2330   mkdir -p lib include
2331   mv -f ${NEWLIB_TARGET}/lib/* lib
2332   rm -rf  include/sys include/machine
2333   mv -f ${NEWLIB_TARGET}/include/* include
2334   rmdir ${NEWLIB_TARGET}/lib
2335   rmdir ${NEWLIB_TARGET}/include
2336   rmdir ${NEWLIB_TARGET}
2337
2338   cp "${NACL_ROOT}/src/untrusted/pthread/pthread.h" \
2339     "${NACL_ROOT}/src/untrusted/pthread/semaphore.h" \
2340     include
2341   # Copy the nacl_random.h header, which is needed by the libc++ build. It
2342   # uses the IRT so should be safe to include in the toolchain tarball.
2343   mkdir include/nacl
2344   cp "${NACL_ROOT}/src/untrusted/nacl/nacl_random.h" \
2345     include/nacl
2346   spopd
2347 }
2348
2349 libs-support() {
2350   StepBanner "LIBS-SUPPORT"
2351   libs-support-newlib-crt1 portable
2352   libs-support-newlib-crt1 x86-64
2353   libs-support-bitcode portable
2354   libs-support-bitcode x86-64
2355
2356   local arch
2357   for arch in arm x86-32 x86-64 mips32; do
2358     libs-support-native ${arch}
2359   done
2360
2361   libs-support-unsandboxed
2362 }
2363
2364 libs-support-newlib-crt1() {
2365   local arch=$1
2366   setup-biased-bitcode-env ${arch}
2367   mkdir -p "${INSTALL_LIB}"
2368   spushd "${PNACL_SUPPORT}/bitcode"
2369
2370   StepBanner "LIBS-SUPPORT-NEWLIB" \
2371              "Install crt1.x & crt1_for_eh.x (linker scripts)"
2372   # Two versions of crt1.x exist, for different scenarios (with and without EH).
2373   # See: https://code.google.com/p/nativeclient/issues/detail?id=3069
2374   cp crt1.x "${INSTALL_LIB}"/crt1.x
2375   cp crt1_for_eh.x "${INSTALL_LIB}"/crt1_for_eh.x
2376   spopd
2377 }
2378
2379 libs-support-bitcode() {
2380   local arch=$1
2381   setup-biased-bitcode-env ${arch}
2382   local build_dir="${TC_BUILD}/libs-support-bitcode-${arch}"
2383   local cc_cmd="${PNACL_CC} -Wall -Werror -O2 ${BIASED_BC_CFLAGS}"
2384
2385   mkdir -p "${build_dir}"
2386   spushd "${PNACL_SUPPORT}/bitcode"
2387   # Install crti.bc (empty _init/_fini)
2388   StepBanner "LIBS-SUPPORT" "Install ${arch} crti.bc"
2389   ${cc_cmd} -c crti.c -o "${build_dir}"/crti.bc
2390
2391   # Install crtbegin bitcode (__cxa_finalize for C++)
2392   StepBanner "LIBS-SUPPORT" "Install ${arch} crtbegin.bc"
2393   # NOTE: we do not have an "end" version of ththis
2394   ${cc_cmd} -c crtbegin.c -o "${build_dir}"/crtbegin.bc
2395
2396   # Install unwind_stubs.bc (stubs for _Unwind_* functions when libgcc_eh
2397   # is not included in the native link).
2398   StepBanner "LIBS-SUPPORT" "Install ${arch} unwind_stubs.bc"
2399   ${cc_cmd} -c unwind_stubs.c -o "${build_dir}"/unwind_stubs.bc
2400   StepBanner "LIBS-SUPPORT" "Install ${arch} sjlj_eh_redirect.bc"
2401   ${cc_cmd} -c sjlj_eh_redirect.c -o "${build_dir}"/sjlj_eh_redirect.bc
2402
2403   # Install libpnaclmm.a (__atomic_*).
2404   StepBanner "LIBS-SUPPORT" "Install ${arch} libpnaclmm.a"
2405   ${cc_cmd} -c pnaclmm.c -o "${build_dir}"/pnaclmm.bc
2406   ${PNACL_AR} rc "${build_dir}"/libpnaclmm.a "${build_dir}"/pnaclmm.bc
2407
2408   spopd
2409
2410   # Install to actual lib directories.
2411   spushd "${build_dir}"
2412   local files="crti.bc crtbegin.bc libpnaclmm.a unwind_stubs.bc sjlj_eh_redirect.bc"
2413   mkdir -p "${INSTALL_LIB}"
2414   cp -f ${files} "${INSTALL_LIB}"
2415   spopd
2416 }
2417
2418 libs-support-native() {
2419   local arch=$1
2420   local destdir="${INSTALL_LIB_NATIVE}"${arch}
2421   local label="LIBS-SUPPORT (${arch})"
2422   mkdir -p "${destdir}"
2423
2424   local flags="--pnacl-allow-native --pnacl-allow-translate -Wall -Werror"
2425   local cc_cmd="${PNACL_CC} -arch ${arch} --pnacl-bias=${arch} ${flags} \
2426       -I../../.. -O3"
2427
2428   spushd "${PNACL_SUPPORT}"
2429
2430   # NOTE: one of the reasons why we build these native is
2431   #       the shim library on x86-64
2432   #       c.f.: https://sites.google.com/a/google.com/nativeclient/project-pnacl/c-exception-handling
2433   # Compile crtbegin.o / crtend.o
2434   StepBanner "${label}" "Install crtbegin.o / crtend.o"
2435
2436   # Build two versions of crtbegin: one that relies on later linking with
2437   # libgcc_eh and one that doesn't.
2438   # See: https://code.google.com/p/nativeclient/issues/detail?id=3069
2439   ${cc_cmd} -c crtbegin.c -o "${destdir}"/crtbegin.o
2440   ${cc_cmd} -c crtbegin.c -DLINKING_WITH_LIBGCC_EH \
2441             -o "${destdir}"/crtbegin_for_eh.o
2442   ${cc_cmd} -c crtend.c -o "${destdir}"/crtend.o
2443
2444   # Make libcrt_platform.a
2445   StepBanner "${label}" "Install libcrt_platform.a"
2446   local tmpdir="${TC_BUILD}/libs-support-native"
2447   rm -rf "${tmpdir}"
2448   mkdir -p "${tmpdir}"
2449   ${cc_cmd} -c pnacl_irt.c -o "${tmpdir}"/pnacl_irt.o
2450   ${cc_cmd} -c setjmp_${arch/-/_}.S -o "${tmpdir}"/setjmp.o
2451
2452   # Some of the support code lives in third_party/ because it's based on code
2453   # from other open-source projects.
2454   ${cc_cmd} \
2455     -c "${NACL_SRC_THIRD_PARTY_MOD}/pnacl_native_newlib_subset/string.c" \
2456     -std=c99 -o "${tmpdir}"/string.o
2457
2458   # For ARM, also compile aeabi_read_tp.S
2459   if  [ ${arch} == arm ] ; then
2460     ${cc_cmd} -c aeabi_read_tp.S -o "${tmpdir}"/aeabi_read_tp.o
2461   fi
2462   spopd
2463
2464   ${PNACL_AR} rc "${destdir}"/libcrt_platform.a "${tmpdir}"/*.o
2465 }
2466
2467 libs-support-unsandboxed() {
2468   if ${BUILD_PLATFORM_LINUX}; then
2469     local arch=linux-x86-32
2470     StepBanner "LIBS-SUPPORT (${arch})" "Install unsandboxed_irt.o"
2471     local destdir="${INSTALL_LIB_NATIVE}"${arch}
2472     mkdir -p ${destdir}
2473     gcc -m32 -O2 -Wall -Werror -I${NACL_ROOT}/.. -DNACL_LINUX=1 -c \
2474         ${PNACL_SUPPORT}/unsandboxed_irt.c -o ${destdir}/unsandboxed_irt.o
2475   fi
2476 }
2477
2478
2479 # Build the dummy "libpnacl_irt_shim.a", which is useful for building
2480 # commandline programs.  It cannot be used to build PPAPI programs
2481 # because it does not actually shim the PPAPI interfaces.
2482 # The library is named the same as the real PPAPI shim to ensure that
2483 # the commandlines are the same.
2484 # This must be built after newlib(), since it uses headers like <stdint.h>.
2485 dummy-irt-shim() {
2486   local arch=$1
2487   local destdir="${INSTALL_LIB_NATIVE}"${arch}
2488   local label="DUMMY-IRT-SHIM (${arch})"
2489   mkdir -p "${destdir}"
2490
2491   local flags="--pnacl-allow-native --pnacl-allow-translate -Wall -Werror"
2492   local cc_cmd="${PNACL_CC} -arch ${arch} ${flags}"
2493
2494   spushd "${PNACL_SUPPORT}"
2495   StepBanner "${label}" "Install libpnacl_irt_shim_dummy.a"
2496   local tmpdir="${TC_BUILD}/dummy-irt-shim"
2497   rm -rf "${tmpdir}"
2498   mkdir -p "${tmpdir}"
2499   ${cc_cmd} -c dummy_shim_entry.c -o "${tmpdir}"/dummy_shim_entry.o
2500   spopd
2501
2502   ${PNACL_AR} rc "${destdir}"/libpnacl_irt_shim_dummy.a "${tmpdir}"/*.o
2503 }
2504
2505 #########################################################################
2506 #     < SDK >
2507 #########################################################################
2508 SCONS_ARGS=(MODE=nacl
2509             -j${PNACL_CONCURRENCY}
2510             bitcode=1
2511             disable_nosys_linker_warnings=1
2512             naclsdk_validate=0
2513             --verbose)
2514
2515 SDK_IS_SETUP=false
2516 sdk-setup() {
2517   if ${SDK_IS_SETUP} && [ $# -eq 0 ]; then
2518     return 0
2519   fi
2520   SDK_IS_SETUP=true
2521
2522   SDK_INSTALL_ROOT="${INSTALL_ROOT}/sdk"
2523   SDK_INSTALL_LIB="${SDK_INSTALL_ROOT}/lib"
2524   SDK_INSTALL_INCLUDE="${SDK_INSTALL_ROOT}/include"
2525 }
2526
2527 sdk() {
2528   sdk-setup "$@"
2529   StepBanner "SDK"
2530   sdk-clean
2531   sdk-headers
2532   sdk-libs
2533   sdk-verify
2534 }
2535
2536 #+ sdk-clean             - Clean sdk stuff
2537 sdk-clean() {
2538   sdk-setup "$@"
2539   StepBanner "SDK" "Clean"
2540   rm -rf "${SDK_INSTALL_ROOT}"
2541
2542   # clean scons obj dirs
2543   rm -rf "${SCONS_OUT}"/nacl-*-pnacl*
2544 }
2545
2546 sdk-headers() {
2547   sdk-setup "$@"
2548   mkdir -p "${SDK_INSTALL_INCLUDE}"
2549
2550   local extra_flags=""
2551   local neutral_platform="x86-32"
2552
2553   StepBanner "SDK" "Install headers"
2554   spushd "${NACL_ROOT}"
2555   # TODO(pnacl-team): remove this pnaclsdk_mode once we have a better story
2556   # about host binary type (x86-32 vs x86-64).  SCons only knows how to use
2557   # x86-32 host binaries right now, so we need pnaclsdk_mode to override that.
2558   RunWithLog "sdk.headers" \
2559       ./scons \
2560       "${SCONS_ARGS[@]}" \
2561       ${extra_flags} \
2562       platform=${neutral_platform} \
2563       pnaclsdk_mode="custom:${INSTALL_ROOT}" \
2564       install_headers \
2565       includedir="$(PosixToSysPath "${SDK_INSTALL_INCLUDE}")"
2566   spopd
2567 }
2568
2569 sdk-libs() {
2570   sdk-setup "$@"
2571   StepBanner "SDK" "Install libraries"
2572   mkdir -p "${SDK_INSTALL_LIB}"
2573
2574   local extra_flags=""
2575   local neutral_platform="x86-32"
2576
2577   spushd "${NACL_ROOT}"
2578   # See above TODO about pnaclsdk_mode.
2579   RunWithLog "sdk.libs.bitcode" \
2580       ./scons \
2581       "${SCONS_ARGS[@]}" \
2582       ${extra_flags} \
2583       platform=${neutral_platform} \
2584       pnaclsdk_mode="custom:${INSTALL_ROOT}" \
2585       install_lib \
2586       libdir="$(PosixToSysPath "${SDK_INSTALL_LIB}")"
2587   spopd
2588 }
2589
2590 # This builds lib*_private.a, to allow building the llc and ld nexes without
2591 # the IRT and without the segment gap.
2592 sdk-private-libs() {
2593   sdk-setup "$@"
2594   StepBanner "SDK" "Private (non-IRT) libs"
2595   spushd "${NACL_ROOT}"
2596
2597   local neutral_platform="x86-32"
2598   # See above TODO about pnaclsdk_mode.
2599   RunWithLog "sdk.libs_private.bitcode" \
2600     ./scons \
2601     -j${PNACL_CONCURRENCY} \
2602     bitcode=1 \
2603     platform=${neutral_platform} \
2604     pnaclsdk_mode="custom:${INSTALL_ROOT}" \
2605     --verbose \
2606     libnacl_sys_private \
2607     libpthread_private \
2608     libnacl_dyncode_private \
2609     libplatform \
2610     libimc \
2611     libimc_syscalls \
2612     libsrpc \
2613     libgio
2614
2615   local out_dir_prefix="${SCONS_OUT}"/nacl-x86-32-pnacl-pexe-clang
2616   local outdir="${out_dir_prefix}"/lib
2617   mkdir -p "${SDK_INSTALL_LIB}"
2618   cp "${outdir}"/lib*_private.a \
2619      "${outdir}"/lib{platform,imc,imc_syscalls,srpc,gio}.a "${SDK_INSTALL_LIB}"
2620   spopd
2621 }
2622
2623 sdk-verify() {
2624   sdk-setup "$@"
2625   StepBanner "SDK" "Verify"
2626
2627   # Verify bitcode libraries
2628   verify-bitcode-dir "${SDK_INSTALL_LIB}"
2629 }
2630
2631 newlib-nacl-headers-clean() {
2632   # Clean the include directory and revert it to its pure state
2633   if [ -d "${TC_SRC_NEWLIB}" ]; then
2634     rm -rf "${NEWLIB_INCLUDE_DIR}"
2635     # If the script is interrupted right here,
2636     # then NEWLIB_INCLUDE_DIR will not exist, and the repository
2637     # will be in a bad state. This will be fixed during the next
2638     # invocation by newlib-nacl-headers.
2639
2640     spushd "$(dirname "${NEWLIB_INCLUDE_DIR}")"
2641     RunWithLog "newlib-nacl-headers-clean" \
2642       ${GIT} checkout "$(basename "${NEWLIB_INCLUDE_DIR}")"
2643     spopd
2644   fi
2645 }
2646
2647 #+ newlib-nacl-headers   - Install NaCl headers to newlib
2648 newlib-nacl-headers() {
2649   StepBanner "newlib-nacl-headers" "Adding nacl headers to newlib"
2650
2651   assert-dir "${TC_SRC_NEWLIB}" "Newlib is not checked out"
2652
2653   # Make sure the headers directory has no local changes
2654   newlib-nacl-headers-check
2655   newlib-nacl-headers-clean
2656
2657   # Install the headers
2658   "${EXPORT_HEADER_SCRIPT}" \
2659       "${NACL_SYS_HEADERS}" \
2660       "${NEWLIB_INCLUDE_DIR}"
2661
2662   # Record the header install time
2663   ts-touch "${NACL_HEADERS_TS}"
2664 }
2665
2666 #+ newlib-nacl-headers-check - Make sure the newlib nacl headers haven't
2667 #+                             been modified since the last install.
2668 newlib-nacl-headers-check() {
2669   # The condition where NEWLIB_INCLUDE_DIR does not exist may have been
2670   # caused by an incomplete call to newlib-nacl-headers-clean().
2671   # Let it pass this check so that the clean will be able to finish.
2672   # See the comment in newlib-nacl-headers-clean()
2673   if ! [ -d "${TC_SRC_NEWLIB}" ] ||
2674      ! [ -d "${NEWLIB_INCLUDE_DIR}" ]; then
2675     return 0
2676   fi
2677
2678   # Already clean?
2679   if ! git-has-changes "${NEWLIB_INCLUDE_DIR}" ; then
2680     return 0
2681   fi
2682
2683   if ts-dir-changed "${NACL_HEADERS_TS}" "${NEWLIB_INCLUDE_DIR}"; then
2684     echo ""
2685     echo "*******************************************************************"
2686     echo "*                            ERROR                                *"
2687     echo "*      The NewLib include directory has local modifications       *"
2688     echo "*******************************************************************"
2689     echo "* The NewLib include directory should not be modified directly.   *"
2690     echo "* Instead, modifications should be done from:                     *"
2691     echo "*   src/trusted/service_runtime/include                           *"
2692     echo "*                                                                 *"
2693     echo "* To destroy the local changes to newlib, run:                    *"
2694     echo "*  pnacl/build.sh newlib-nacl-headers-clean                       *"
2695     echo "*******************************************************************"
2696     echo ""
2697     if ${PNACL_BUILDBOT} ; then
2698       newlib-nacl-headers-clean
2699     else
2700       exit -1
2701     fi
2702   fi
2703 }
2704
2705
2706 #+-------------------------------------------------------------------------
2707 #@ driver                - Install driver scripts.
2708 driver() {
2709   StepBanner "DRIVER"
2710   driver-install
2711 }
2712
2713 # install python scripts and redirector shell/batch scripts
2714 driver-install-python() {
2715   local destdir="$1"
2716   shift
2717   local pydir="${destdir}/pydir"
2718
2719   StepBanner "DRIVER" "Installing driver adaptors to ${destdir}"
2720   rm -rf "${destdir}"
2721   mkdir -p "${destdir}"
2722   mkdir -p "${pydir}"
2723
2724   spushd "${DRIVER_DIR}"
2725
2726   # Copy python scripts
2727   cp $@ driver_log.py driver_env.py *tools.py filetype.py loader.py "${pydir}"
2728
2729   # Install redirector shell/batch scripts
2730   for name in $@; do
2731     local dest="${destdir}/${name/.py}"
2732     # In some situations cygwin cp messes up the permissions of the redirector
2733     # shell/batch scripts. Using cp -a seems to make sure it preserves them.
2734     cp -a redirect.sh "${dest}"
2735     chmod +x "${dest}"
2736     if ${BUILD_PLATFORM_WIN}; then
2737       cp -a redirect.bat "${dest}".bat
2738     fi
2739   done
2740   spopd
2741 }
2742
2743 feature-version-file-install() {
2744   # Scons tests can check this version number to decide whether to
2745   # enable tests for toolchain bug fixes or new features.  This allows
2746   # tests to be enabled on the toolchain buildbots/trybots before the
2747   # new toolchain version is rolled into TOOL_REVISIONS (i.e. before
2748   # the tests would pass on the main NaCl buildbots/trybots).
2749   #
2750   # If you are adding a test that depends on a toolchain change, you
2751   # can increment this version number manually.
2752   echo 4 > "${INSTALL_ROOT}/FEATURE_VERSION"
2753 }
2754
2755 # The driver is a simple python script which changes its behavior
2756 # depending on the name it is invoked as.
2757 driver-install() {
2758   local bindir=bin
2759   # On Linux we ship a fat toolchain with 2 sets of binaries defaulting to
2760   # x86-32 (mostly because of the 32 bit chrome bots). So the default
2761   # bin dir is 32, and the bin64 driver runs the 64 bit binaries
2762   if ${HOST_ARCH_X8664} && ${BUILD_PLATFORM_LINUX}; then
2763     bindir="bin64"
2764     # We want to be able to locally test a toolchain on 64 bit hosts without
2765     # building it twice and without extra env vars. So if a 32 bit toolchain
2766     # has not already been built, just symlink the bin dirs together.
2767     if [[ ! -d "${INSTALL_BIN}" ]]; then
2768       mkdir -p "${INSTALL_ROOT}"
2769       ln -s ${bindir} "${INSTALL_BIN}"
2770     fi
2771   fi
2772
2773   # This directory (the ${INSTALL_ROOT}/${bindir} part)
2774   # should be kept in sync with INSTALL_BIN et al.
2775   local destdir="${INSTALL_ROOT}/${bindir}"
2776
2777   driver-install-python "${destdir}" "pnacl-*.py"
2778
2779   # Tell the driver the library mode and host arch
2780   echo """HAS_FRONTEND=1
2781 HOST_ARCH=${HOST_ARCH}""" > "${destdir}"/driver.conf
2782
2783   # On windows, copy the cygwin DLLs needed by the driver tools
2784   if ${BUILD_PLATFORM_WIN}; then
2785     StepBanner "DRIVER" "Copying cygwin libraries"
2786     local deps="gcc_s-1 iconv-2 win1 intl-8 stdc++-6 z"
2787     for name in ${deps}; do
2788       cp "/bin/cyg${name}.dll" "${destdir}"
2789     done
2790   fi
2791
2792   # Install a REV file so that "pnacl-clang --version" knows the version
2793   # of the drivers themselves.
2794   DumpAllRevisions > "${destdir}/REV"
2795
2796   feature-version-file-install
2797 }
2798
2799 #@ driver-install-translator - Install driver scripts for translator component
2800 driver-install-translator() {
2801   local destdir="${INSTALL_TRANSLATOR}/bin"
2802
2803   driver-install-python "${destdir}" pnacl-translate.py pnacl-nativeld.py
2804
2805   echo """HAS_FRONTEND=0""" > "${destdir}"/driver.conf
2806 }
2807
2808 ######################################################################
2809 ######################################################################
2810 #
2811 #                           HELPER FUNCTIONS
2812 #
2813 #             (These should not generally be used directly)
2814 #
2815 ######################################################################
2816 ######################################################################
2817
2818 DumpAllRevisions() {
2819   one-line-rev-info ${NACL_ROOT}
2820   for d in ${PNACL_ROOT}/git/*/ ; do
2821     one-line-rev-info $d
2822   done
2823 }
2824
2825 ######################################################################
2826 ######################################################################
2827 #     < VERIFY >
2828 ######################################################################
2829 ######################################################################
2830
2831 # Note: we could replace this with a modified version of tools/elf_checker.py
2832 #       if we do not want to depend on binutils
2833 readonly NACL_OBJDUMP=${BINUTILS_INSTALL_DIR}/bin/${REAL_CROSS_TARGET}-objdump
2834
2835 # Usage: VerifyArchive <checker> <pattern> <filename>
2836 ExtractAndCheck() {
2837   local checker="$1"
2838   local pattern="$2"
2839   local archive="$3"
2840   local tmp="/tmp/ar-verify-${RANDOM}"
2841   rm -rf ${tmp}
2842   mkdir -p ${tmp}
2843   cp "${archive}" "${tmp}"
2844   spushd ${tmp}
2845   ${PNACL_AR} x $(basename ${archive})
2846   # extract all the files
2847   local count=0
2848   for i in ${pattern} ; do
2849     if [ ! -e "$i" ]; then
2850       # we may also see the unexpanded pattern here if there is no match
2851       continue
2852     fi
2853     count=$((count+1))
2854     ${checker} $i
2855   done
2856   echo "PASS  (${count} files)"
2857   rm -rf "${tmp}"
2858   spopd
2859 }
2860
2861 IsLinkerScript() {
2862   local fname="$1"
2863   local type="$(file --brief --mime-type "${fname}")"
2864   case "$type" in
2865     text/x-c)
2866       # A linker script with C comments looks like C to "file".
2867       return 0
2868       ;;
2869     text/plain)
2870       return 0
2871       ;;
2872   esac
2873   return 1
2874 }
2875
2876 # Usage: VerifyLinkerScript <filename>
2877 VerifyLinkerScript() {
2878   local archive="$1"
2879   # Use preprocessor to strip the C-style comments.
2880   ${PNACL_PP} -xc "${archive}" | awk -v archive="$(basename ${archive})" '
2881     BEGIN { status = 0 }
2882     NF == 0 || $1 == "#" { next }
2883     $1 == "INPUT" && $2 == "(" && $NF == ")" { next }
2884     {
2885       print "FAIL - unexpected linker script(?) contents:", archive
2886       status = 1
2887       exit(status)
2888     }
2889     END { if (status == 0) print "PASS  (trivial linker script)" }
2890 ' || exit -1
2891 }
2892
2893 # Usage: VerifyArchive <checker> <pattern> <filename>
2894 VerifyArchive() {
2895   local checker="$1"
2896   local pattern="$2"
2897   local archive="$3"
2898   echo -n "verify $(basename "${archive}"): "
2899   if IsLinkerScript "${archive}"; then
2900     VerifyLinkerScript "${archive}"
2901   else
2902     ExtractAndCheck "$checker" "$pattern" "$archive"
2903   fi
2904 }
2905
2906 #
2907 # verify-object-llvm <obj>
2908 #
2909 #   Verifies that a given .o file is bitcode and free of ASMSs
2910 verify-object-llvm() {
2911   if ${PNACL_DIS} "$1" -o - | grep asm ; then
2912     echo
2913     echo "ERROR asm in $1"
2914     echo
2915     exit -1
2916   fi
2917   if [ ${PIPESTATUS[0]} -ne 0 ]; then
2918     exit -1
2919   fi
2920 }
2921
2922
2923 check-elf-abi() {
2924   # Temporarily disable ELF abi check until DEPS roll
2925   return 0
2926
2927   local arch_info="$(${NACL_OBJDUMP} -f $1)"
2928   if ! grep -q $2 <<< ${arch_info} ; then
2929     echo "ERROR $1 - bad file format: $2 vs ${arch_info}\n"
2930     echo ${arch_info}
2931     exit -1
2932   fi
2933 }
2934
2935
2936 # verify-object-arm <obj>
2937 #
2938 #   Ensure that the ARCH properties are what we expect, this is a little
2939 #   fragile and needs to be updated when tools change
2940 verify-object-arm() {
2941   check-elf-abi $1 "elf32-littlearm"
2942   # llvm-mc does not automatically insert these tags (unlike gnu-as).
2943   # So we exclude llvm-mc generated object files for now
2944   if [[ $1 == aeabi_read_tp.o || $1 == setjmp.o ]] ; then
2945     return
2946   fi
2947   arch_info="$("${PNACL_READELF}" -A "$1")"
2948   #TODO(robertm): some refactoring and cleanup needed
2949   if ! grep -q "Tag_FP_arch: VFPv3" <<< ${arch_info} ; then
2950     echo "ERROR $1 - bad Tag_FP_arch"
2951     #TODO(robertm): figure out what the right thing to do is here, c.f.
2952     # http://code.google.com/p/nativeclient/issues/detail?id=966
2953     "${PNACL_READELF}" -A $1 | grep  Tag_FP_arch
2954     exit -1
2955   fi
2956
2957   if ! grep -q "Tag_CPU_arch: v7" <<< ${arch_info} ; then
2958     echo "FAIL bad $1 Tag_CPU_arch"
2959     "${PNACL_READELF}" -A $1 | grep Tag_CPU_arch
2960     exit -1
2961   fi
2962
2963   if ! grep -q "Tag_Advanced_SIMD_arch: NEONv1" <<< ${arch_info} ; then
2964     echo "FAIL bad $1 Tag_Advanced_SIMD_arch"
2965     "${PNACL_READELF}" -A $1 | grep Tag_Advanced_SIMD_arch
2966   fi
2967
2968   # Check that the file uses the ARM hard-float ABI (where VFP
2969   # registers D0-D7 (s0-s15) are used to pass arguments and results).
2970   if ! grep -q "Tag_ABI_VFP_args: VFP registers" <<< ${arch_info} ; then
2971     echo "FAIL bad $1 Tag_ABI_VFP_args"
2972     "${PNACL_READELF}" -A $1 | grep Tag_ABI_VFP_args
2973   fi
2974 }
2975
2976
2977 # verify-object-x86-32 <obj>
2978 #
2979 verify-object-x86-32() {
2980   check-elf-abi $1 "elf32-i386"
2981 }
2982
2983 # verify-object-x86-64 <obj>
2984 #
2985 verify-object-x86-64() {
2986   check-elf-abi $1 "elf64-x86-64"
2987 }
2988
2989 #+ verify-bitcode-dir    - Verify that the files in a directory are bitcode.
2990 verify-bitcode-dir() {
2991   local dir="$1"
2992   # This avoids errors when * finds no matches.
2993   shopt -s nullglob
2994   SubBanner "VERIFY: ${dir}"
2995   for i in "${dir}"/*.a ; do
2996     verify-archive-llvm "$i"
2997   done
2998   for i in "${dir}"/*.bc ; do
2999     echo -n "verify $(basename "$i"): "
3000     verify-object-llvm "$i"
3001     echo "PASS (bitcode)"
3002   done
3003   for i in "${dir}"/*.o ; do
3004     Fatal "Native object file $i inside bitcode directory"
3005   done
3006   shopt -u nullglob
3007 }
3008
3009
3010 #+ verify-native-dir     - Verify that files in a directory are native for arch.
3011 verify-native-dir() {
3012   local arch="$1"
3013   local dir="$2"
3014
3015   SubBanner "VERIFY: ${dir}"
3016
3017   # This avoids errors when * finds no matches.
3018   shopt -s nullglob
3019   for i in "${dir}"/*.o ; do
3020     verify-object-${arch} "$i"
3021   done
3022
3023   for i in "${dir}"/*.a ; do
3024     verify-archive-${arch} "$i"
3025   done
3026
3027   for i in "${dir}"/*.bc "${dir}"/*.pso ; do
3028     Fatal "Bitcode file $i found inside native directory"
3029   done
3030   shopt -u nullglob
3031 }
3032
3033 #
3034 # verify-archive-llvm <archive>
3035 # Verifies that a given archive is bitcode and free of ASMSs
3036 #
3037 verify-archive-llvm() {
3038   # Currently all the files are .o in the llvm archives.
3039   # Eventually more and more should be .bc.
3040   VerifyArchive verify-object-llvm '*.bc *.o' "$@"
3041 }
3042
3043 #
3044 # verify-archive-arm <archive>
3045 # Verifies that a given archive is a proper arm achive
3046 #
3047 verify-archive-arm() {
3048   VerifyArchive verify-object-arm '*.o *.ons' "$@"
3049 }
3050
3051 #
3052 # verify-archive-x86-32 <archive>
3053 # Verifies that a given archive is a proper x86-32 achive
3054 #
3055 verify-archive-x86-32() {
3056   VerifyArchive verify-object-x86-32 '*.o *.ons' "$@"
3057 }
3058
3059 #
3060 # verify-archive-x86-64 <archive>
3061 # Verifies that a given archive is a proper x86-64 achive
3062 #
3063 verify-archive-x86-64() {
3064   VerifyArchive verify-object-x86-64 '*.o *.ons' "$@"
3065 }
3066
3067 #@-------------------------------------------------------------------------
3068 #+ verify                - Verifies that toolchain/pnacl-untrusted ELF files
3069 #+                         are of the correct architecture.
3070 verify() {
3071   StepBanner "VERIFY"
3072   verify-bitcode
3073   verify-native
3074 }
3075
3076 verify-bitcode() {
3077   verify-bitcode-dir "${INSTALL_LIB}"
3078 }
3079
3080 verify-native() {
3081   local arch
3082   for arch in arm x86-32 x86-64; do
3083     verify-native-dir ${arch} "${INSTALL_LIB_NATIVE}${arch}"
3084   done
3085 }
3086
3087 #+ verify-triple-build <arch>
3088 #+     Verify that the sandboxed translator produces an identical
3089 #+     translation of itself (pnacl-llc.pexe) as the unsandboxed translator.
3090 #+     (NOTE: This function is experimental/untested)
3091 verify-triple-build() {
3092   local arch=$1
3093   StepBanner "VERIFY" "Verifying triple build for ${arch}"
3094
3095   local bindir="$(GetTranslatorInstallDir ${arch})/bin"
3096   local llc_nexe="${bindir}/pnacl-llc.nexe"
3097   local llc_pexe="${bindir}/pnacl-llc.pexe"
3098   assert-file "${llc_nexe}" "sandboxed llc for ${arch} does not exist"
3099   assert-file "${llc_pexe}" "pnacl-llc.pexe does not exist"
3100
3101   local flags="--pnacl-sb --pnacl-driver-verbose"
3102
3103   if [ ${arch} == "arm" ] ; then
3104     # Use emulator if we are not on ARM
3105     local hostarch=$(uname -m)
3106     if ! [[ "${BUILD_ARCH}" =~ arm ]]; then
3107       flags+=" --pnacl-use-emulator"
3108     fi
3109   fi
3110
3111   local triple_install_dir="$(GetTranslatorInstallDir ${arch})/triple-build"
3112   mkdir -p ${triple_install_dir}
3113   local new_llc_nexe="${triple_install_dir}/pnacl-llc.rebuild.nexe"
3114   mkdir -p "${triple_install_dir}"
3115   StepBanner "VERIFY" "Translating ${llc_pexe} using sandboxed tools (${arch})"
3116   local sb_translator="${INSTALL_TRANSLATOR}/bin/pnacl-translate"
3117   RunWithLog "verify.triple.build" \
3118     "${sb_translator}" ${flags} -arch ${arch} "${llc_pexe}" -o "${new_llc_nexe}"
3119
3120   if ! cmp --silent "${llc_nexe}" "${new_llc_nexe}" ; then
3121     Banner "TRIPLE BUILD VERIFY FAILED"
3122     echo "Expected these files to be identical, but they are not:"
3123     echo "  ${archllc}"
3124     echo "  ${newllc}"
3125     exit -1
3126   fi
3127   StepBanner "VERIFY" "Verified ${arch} OK"
3128 }
3129
3130 ######################################################################
3131 ######################################################################
3132 #
3133 # UTILITIES
3134 #
3135 ######################################################################
3136 ######################################################################
3137
3138 #@-------------------------------------------------------------------------
3139 #@ show-config
3140 show-config() {
3141   Banner "Config Settings:"
3142   echo "PNACL_BUILDBOT:    ${PNACL_BUILDBOT}"
3143   echo "PNACL_CONCURRENCY: ${PNACL_CONCURRENCY}"
3144   echo "PNACL_DEBUG:       ${PNACL_DEBUG}"
3145   echo "PNACL_PRUNE:       ${PNACL_PRUNE}"
3146   echo "PNACL_VERBOSE:     ${PNACL_VERBOSE}"
3147   echo "INSTALL_ROOT:      ${INSTALL_ROOT}"
3148   Banner "Your Environment:"
3149   env | grep PNACL
3150   Banner "uname info for builder:"
3151   uname -a
3152   Banner "Revisions:"
3153   DumpAllRevisions
3154 }
3155
3156 #@ help                  - Usage information.
3157 help() {
3158   Usage
3159 }
3160
3161 #@ help-full             - Usage information including internal functions.
3162 help-full() {
3163   Usage2
3164 }
3165
3166 has-trusted-toolchain() {
3167   if [ -f ${TOOLCHAIN_ROOT}/linux_arm-trusted/ld_script_arm_trusted ]; then
3168     return 0
3169   else
3170     return 1
3171   fi
3172 }
3173
3174 check-for-trusted() {
3175   if ! ${PNACL_BUILD_ARM} ; then
3176     return
3177   fi
3178
3179   if ! has-trusted-toolchain; then
3180     echo '*******************************************************************'
3181     echo '*   The ARM trusted toolchain does not appear to be installed yet *'
3182     echo '*   It is needed to run ARM tests.                                *'
3183     echo '*                                                                 *'
3184     echo '*   To download and install the trusted toolchain, run:           *'
3185     echo '*                                                                 *'
3186     echo '*       $ pnacl/build.sh download-trusted                         *'
3187     echo '*                                                                 *'
3188     echo '*   To compile the trusted toolchain, use:                        *'
3189     echo '*                                                                 *'
3190     echo '*       $ tools/llvm/trusted-toolchain-creator.sh trusted_sdk     *'
3191     echo '*               (warning: this takes a while)                     *'
3192     echo '*******************************************************************'
3193
3194     # If building on the bots, do not continue since it needs to run ARM tests.
3195     if ${PNACL_BUILDBOT} ; then
3196       echo "Building on bots --> need ARM trusted toolchain to run tests!"
3197       exit -1
3198     elif trusted-tc-confirm ; then
3199       echo "Continuing without ARM trusted toolchain"
3200       PNACL_BUILD_ARM=false
3201     else
3202       echo "Okay, stopping."
3203       exit -1
3204     fi
3205   fi
3206 }
3207
3208 trusted-tc-confirm() {
3209   echo
3210   echo "Do you wish to continue without the ARM trusted TC (skip ARM testing)?"
3211   echo ""
3212   confirm-yes "Continue"
3213   return $?
3214 }
3215
3216 DebugRun() {
3217   if ${PNACL_DEBUG} || ${PNACL_BUILDBOT}; then
3218     "$@"
3219   fi
3220 }
3221
3222 ######################################################################
3223 # Generate chromium perf bot logs for tracking the size of a binary.
3224 #
3225 print-tagged-tool-sizes() {
3226   local tag="$1"
3227   local binary="$2"
3228
3229   # size output look like:
3230   #    text   data     bss     dec    hex  filename
3231   #  354421  16132  168920  539473  83b51  .../tool
3232   local sizes=($(${PNACL_SIZE} -B "${binary}" | grep '[0-9]\+'))
3233   echo "RESULT ${tag}: text= ${sizes[0]} bytes"
3234   echo "RESULT ${tag}: data= ${sizes[1]} bytes"
3235   echo "RESULT ${tag}: bss= ${sizes[2]} bytes"
3236   echo "RESULT ${tag}: total= ${sizes[3]} bytes"
3237 }
3238
3239 ######################################################################
3240 ######################################################################
3241 #
3242 #                           < TIME STAMPING >
3243 #
3244 ######################################################################
3245 ######################################################################
3246
3247 ts-dir-changed() {
3248   local tsfile="$1"
3249   local dir="$2"
3250
3251   if [ -f "${tsfile}" ]; then
3252     local MODIFIED=$(find "${dir}" -type f -newer "${tsfile}")
3253     [ ${#MODIFIED} -gt 0 ]
3254     ret=$?
3255   else
3256     true
3257     ret=$?
3258   fi
3259   return $ret
3260 }
3261
3262 # Check if the source for a given build has been modified
3263 ts-modified() {
3264   local srcdir="$1"
3265   local objdir="$2"
3266   local tsfile="${objdir}/${TIMESTAMP_FILENAME}"
3267
3268   ts-dir-changed "${tsfile}" "${srcdir}"
3269   return $?
3270 }
3271
3272 ts-touch() {
3273   local tsfile="$1"
3274   touch "${tsfile}"
3275 }
3276
3277 # Record the time when make begins, but don't yet
3278 # write that to the timestamp file.
3279 # (Just in case make fails)
3280
3281 ts-touch-open() {
3282   local objdir="$1"
3283   local tsfile="${objdir}/${TIMESTAMP_FILENAME}"
3284   local tsfile_open="${objdir}/${TIMESTAMP_FILENAME}_OPEN"
3285
3286   rm -f "${tsfile}"
3287   touch "${tsfile_open}"
3288 }
3289
3290
3291 # Write the timestamp. (i.e. make has succeeded)
3292
3293 ts-touch-commit() {
3294   local objdir="$1"
3295   local tsfile="${objdir}/${TIMESTAMP_FILENAME}"
3296   local tsfile_open="${objdir}/${TIMESTAMP_FILENAME}_OPEN"
3297
3298   mv -f "${tsfile_open}" "${tsfile}"
3299 }
3300
3301
3302 # ts-newer-than dirA dirB
3303 # Compare the make timestamps in both object directories.
3304 # returns true (0) if dirA is newer than dirB
3305 # returns false (1) otherwise.
3306 #
3307 # This functions errs on the side of returning 0, since
3308 # that forces a rebuild anyway.
3309
3310 ts-newer-than() {
3311   local objdir1="$1"
3312   local objdir2="$2"
3313
3314   local tsfile1="${objdir1}/${TIMESTAMP_FILENAME}"
3315   local tsfile2="${objdir2}/${TIMESTAMP_FILENAME}"
3316
3317   if [ ! -d "${objdir1}" ]; then return 0; fi
3318   if [ ! -d "${objdir2}" ]; then return 0; fi
3319
3320   if [ ! -f "${tsfile1}" ]; then return 0; fi
3321   if [ ! -f "${tsfile2}" ]; then return 0; fi
3322
3323   local MODIFIED=$(find "${tsfile1}" -newer "${tsfile2}")
3324   if [ ${#MODIFIED} -gt 0 ]; then
3325     return 0
3326   fi
3327   return 1
3328 }
3329
3330
3331 # Don't define any functions after this or they won't show up in completions
3332 function-completions() {
3333   if [ $# = 0 ]; then set -- ""; fi
3334   compgen -A function -- $1
3335   exit 0
3336 }
3337
3338 ######################################################################
3339 ######################################################################
3340 #
3341 #                               < MAIN >
3342 #
3343 ######################################################################
3344 ######################################################################
3345
3346 mkdir -p "${INSTALL_ROOT}"
3347 PackageCheck
3348
3349 if [ $# = 0 ]; then set -- help; fi  # Avoid reference to undefined $1.
3350
3351 # Accept one -- argument for some compatibility with google3
3352 if [ $1 = "--tab_completion_word" ]; then
3353   set -- function-completions $2
3354 fi
3355
3356 if [ "$(type -t $1)" != "function" ]; then
3357   #Usage
3358   echo "ERROR: unknown function '$1'." >&2
3359   echo "For help, try:"
3360   echo "    $0 help"
3361   exit 1
3362 fi
3363
3364 "$@"