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.
9 # Turn on/off debugging mode
10 readonly PNACL_DEBUG=${PNACL_DEBUG:-false}
12 # True if the scripts are running on the build bots.
13 readonly PNACL_BUILDBOT=${PNACL_BUILDBOT:-false}
15 # Dump all build output to stdout
16 readonly PNACL_VERBOSE=${PNACL_VERBOSE:-false}
18 readonly TIME_AT_STARTUP=$(date '+%s')
26 TC_LOG_ALL="${TC_LOG}/ALL"
29 ######################################################################
31 ######################################################################
33 BUILD_PLATFORM=$(uname | tr '[A-Z]' '[a-z]')
34 BUILD_PLATFORM_LINUX=false
35 BUILD_PLATFORM_MAC=false
36 BUILD_PLATFORM_WIN=false
38 if [ "${BUILD_PLATFORM}" == "linux" ] ; then
39 BUILD_PLATFORM_LINUX=true
40 SCONS_BUILD_PLATFORM=linux
41 BUILD_ARCH=${BUILD_ARCH:-$(uname -m)}
45 elif [[ "${BUILD_PLATFORM}" =~ cygwin_nt ]]; then
47 BUILD_PLATFORM_WIN=true
48 SCONS_BUILD_PLATFORM=win
49 # force 32 bit host because build is also 32 bit on windows.
50 HOST_ARCH=${HOST_ARCH:-x86_32}
51 BUILD_ARCH=${BUILD_ARCH:-x86_32}
54 SO_DIR=bin # On Windows, DLLs are placed in bin/
55 # because the dynamic loader searches %PATH%
56 elif [ "${BUILD_PLATFORM}" == "darwin" ] ; then
58 BUILD_PLATFORM_MAC=true
59 SCONS_BUILD_PLATFORM=mac
60 # On mac, uname -m is a lie. We always do 64 bit host builds, on
61 # 64 bit build machines
62 HOST_ARCH=${HOST_ARCH:-x86_64}
63 BUILD_ARCH=${BUILD_ARCH:-x86_64}
68 echo "Unknown system '${BUILD_PLATFORM}'"
72 readonly BUILD_PLATFORM
73 readonly BUILD_PLATFORM_LINUX
74 readonly BUILD_PLATFORM_MAC
75 readonly BUILD_PLATFORM_WIN
76 readonly SCONS_BUILD_PLATFORM
80 BUILD_ARCH_X8632=false
81 BUILD_ARCH_X8664=false
84 if [ "${BUILD_ARCH}" == "x86_32" ] ||
85 [ "${BUILD_ARCH}" == "i386" ] ||
86 [ "${BUILD_ARCH}" == "i686" ] ; then
89 elif [ "${BUILD_ARCH}" == "x86_64" ] ; then
91 elif [ "${BUILD_ARCH}" == "armv7l" ] ; then
93 elif [ "${BUILD_ARCH}" == "mips32" ] ||
94 [ "${BUILD_ARCH}" == "mips" ] ; then
97 echo "Unknown build arch '${BUILD_ARCH}'"
101 readonly BUILD_ARCH_X8632
102 readonly BUILD_ARCH_X8664
103 readonly BUILD_ARCH_ARM
104 readonly BUILD_ARCH_MIPS
107 HOST_ARCH=${HOST_ARCH:-${BUILD_ARCH}}
108 HOST_ARCH_X8632=false
109 HOST_ARCH_X8664=false
112 if [ "${HOST_ARCH}" == "x86_32" ] ||
113 [ "${HOST_ARCH}" == "i386" ] ||
114 [ "${HOST_ARCH}" == "i686" ] ; then
117 elif [ "${HOST_ARCH}" == "x86_64" ] ; then
119 elif [ "${HOST_ARCH}" == "armv7l" ] ; then
121 elif [ "${HOST_ARCH}" == "mips32" ] ||
122 [ "${HOST_ARCH}" == "mips" ] ; then
125 echo "Unknown host arch '${HOST_ARCH}'"
129 readonly HOST_ARCH_X8632
130 readonly HOST_ARCH_X8664
131 readonly HOST_ARCH_ARM
132 readonly HOST_ARCH_MIPS
134 if [ "${BUILD_ARCH}" != "${HOST_ARCH}" ]; then
135 if ! { ${BUILD_ARCH_X8664} && ${HOST_ARCH_X8632}; }; then
136 echo "Cross builds other than build=x86_64 with host=x86_32 not supported"
141 if ${BUILD_PLATFORM_WIN}; then
142 readonly GCLIENT="gclient.bat"
143 readonly GIT="git.bat"
145 readonly SVN="svn.bat"
147 readonly GCLIENT="gclient"
153 # On Windows, scons expects Windows-style paths (C:\foo\bar)
154 # This function converts cygwin posix paths to Windows-style paths.
155 # On all other platforms, this function does nothing to the path.
158 if ${BUILD_PLATFORM_WIN}; then
159 cygpath -w "$(GetAbsolutePath "${path}")"
166 ######################################################################
167 # Git repository tools
168 ######################################################################
173 local status=$(${GIT} status --porcelain --untracked-files=no)
179 git-assert-no-changes() {
181 if git-has-changes "${dir}"; then
182 Banner "ERROR: Repository ${dir} has local changes"
187 ######################################################################
188 # Subversion repository tools
189 ######################################################################
194 local repo_rev=$(svn-get-revision "${dir}")
195 [ "${repo_rev}" == "${rev}" ]
199 #+ svn-get-revision <dir>
203 local rev=$(${SVN} info | grep 'Revision: ' | cut -b 11-)
204 if ! [[ "${rev}" =~ ^[0-9]+$ ]]; then
205 echo "Invalid revision number '${rev}' or invalid repository '${dir}'" 1>&2
212 #+ svn-checkout <url> <repodir> - Checkout an SVN repository
218 if [ ! -d "${dir}" ]; then
219 StepBanner "SVN-CHECKOUT" "Checking out ${url}"
220 RunWithLog "svn-checkout" ${SVN} co "${url}" "${dir}" -r "${rev}"
222 SkipBanner "SVN-CHECKOUT" "Using existing SVN repository for ${url}"
226 #+ svn-update <dir> <rev> - Update an SVN repository
232 "SVN repository $(basename "${dir}") doesn't exist."
235 if [[ "$rev" == "tip" ]]; then
236 RunWithLog "svn-update" ${SVN} update
238 RunWithLog "svn-update" ${SVN} update -r ${rev}
246 local STATUS=$(${SVN} status)
248 [ "${STATUS}" != "" ]
252 #+ svn-assert-no-changes <dir> - Assert an svn repo has no local changes
253 svn-assert-no-changes() {
255 if svn-has-changes "${dir}" ; then
256 local name=$(basename "${dir}")
257 Banner "ERROR: Repository ${name} has local changes"
263 ######################################################################
264 # vcs rev info helper
265 ######################################################################
270 git-one-line-rev-info() {
271 local commit=$(${GIT} log -n 1 | head -1 | get-field 2)
272 local url=$(egrep "^[^a-z]+url = " .git/config | head -1 | get-field 3)
273 # variable bypass does implicit whitespace strip
274 echo "[GIT] ${url}: ${commit}"
277 svn-one-line-rev-info() {
278 local url=$(${SVN} info | egrep 'URL:' | get-field 2)
279 local rev=$(${SVN} info | egrep 'Revision:' | get-field 2)
280 echo "[SVN] ${url}: ${rev}"
283 #+ one-line-rev-info <dir> - show one line summmary for
284 one-line-rev-info() {
287 svn-one-line-rev-info
288 elif [ -d .git ]; then
290 git-one-line-rev-info
292 echo "[$1] Unknown version control system"
297 ######################################################################
299 ######################################################################
301 #@ progress - Show build progress (open in another window)
303 StepBanner "PROGRESS WINDOW"
306 if [ -f "${TC_LOG_ALL}" ]; then
307 if tail --version > /dev/null; then
309 tail -s 0.05 --max-unchanged-stats=20 --follow=name "${TC_LOG_ALL}"
312 tail -F "${TC_LOG_ALL}"
319 #+ clean-logs - Clean all logs
326 LogEcho "-------------------------------------------------------------------"
327 LogEcho "ENTERING: $1"
328 pushd "$1" > /dev/null
333 LogEcho "LEAVING: $(pwd)"
335 LogEcho "-------------------------------------------------------------------"
336 LogEcho "ENTERING: $(pwd)"
341 echo "$*" >> "${TC_LOG_ALL}"
345 local log="${TC_LOG}/$1"
351 if ${PNACL_VERBOSE}; then
352 echo "RUNNING: " "$@" | tee "${log}" | tee -a "${TC_LOG_ALL}"
353 "$@" 2>&1 | tee "${log}" | tee -a "${TC_LOG_ALL}"
356 echo "RUNNING: " "$@" | tee -a "${TC_LOG_ALL}" &> "${log}"
357 "$@" 2>&1 | tee -a "${TC_LOG_ALL}" &> "${log}"
360 if [ ${ret} -ne 0 ]; then
366 echo "LOGFILE: ${log}"
370 if ${PNACL_BUILDBOT}; then
371 echo "BEGIN LOGFILE Contents."
373 echo "END LOGFILE Contents."
381 # Pretty print, respecting parameter grouping
383 local has_space=$(echo "$I" | grep " ")
384 if [ ${#has_space} -gt 0 ]; then
399 if [ ! -d "${dir}" ]; then
400 Banner "ERROR: ${msg}"
409 if [ ! -f "${fn}" ]; then
410 Banner "ERROR: ${fn} does not exist. ${msg}"
416 egrep "^#@" "${SCRIPT_PATH}" | cut -b 3-
420 egrep "^#(@|\+)" "${SCRIPT_PATH}" | cut -b 3-
425 echo " *********************************************************************"
431 echo " *********************************************************************"
436 if [ $# -eq 1 ]; then
438 echo "-------------------------------------------------------------------"
439 local padding=$(RepeatStr ' ' 28)
440 echo "${padding}${module}"
441 echo "-------------------------------------------------------------------"
444 local padding=$(RepeatStr ' ' $((20-${#module})) )
445 echo "[$(TimeStamp)] ${module}${padding}" "$@"
450 if date --version &> /dev/null ; then
452 date -d "now - ${TIME_AT_STARTUP}sec" '+%M:%S'
454 # Other 'date' (assuming BSD for now)
455 local time_now=$(date '+%s')
456 local time_delta=$[ ${time_now} - ${TIME_AT_STARTUP} ]
457 date -j -f "%s" "${time_delta}" "+%M:%S"
463 echo "----------------------------------------------------------------------"
465 echo "----------------------------------------------------------------------"
469 StepBanner "$1" "Skipping $2, already up to date."
477 while [ $count -gt 0 ]; do
493 assert-bin "makeinfo" "makeinfo not found. Please install 'texinfo' package."
494 assert-bin "bison" "bison not found. Please install 'bison' package."
495 assert-bin "flex" "flex not found. Please install 'flex' package."
496 assert-bin "gclient" "gclient not found in PATH. Please install depot_tools."
503 if ! which "$exe" > /dev/null; then
510 local F=$(file -b "$1")
511 [[ "${F}" =~ "ELF" ]]
515 local F=$(file -b "$1")
516 [[ "${F}" =~ "Mach-O" ]]
520 local F=$(file -b "$1")
521 [[ "${F}" =~ "shell" ]]
524 get_dir_size_in_mb() {
525 du -msc "$1" | tail -1 | egrep -o "[0-9]+"
531 echo -n "${msg} [Y/N]? "
534 if [ "${YESNO}" == "N" ] || [ "${YESNO}" == "n" ]; then
537 if [ "${YESNO}" == "Y" ] || [ "${YESNO}" == "y" ]; then
543 # On Linux with GNU readlink, "readlink -f" would be a quick way
544 # of getting an absolute path, but MacOS has BSD readlink.
549 if [ -d "${relpath}" ]; then
553 reldir="$(dirname "${relpath}")"
554 relname="/$(basename "${relpath}")"
557 local absdir="$(cd "${reldir}" && pwd)"
558 echo "${absdir}${relname}"
562 # The Queue* functions provide a simple way of keeping track
563 # of multiple background processes in order to ensure that:
564 # 1) they all finish successfully (with return value 0), and
565 # 2) they terminate if the master process is killed/interrupted.
566 # (This is done using a bash "trap" handler)
575 # echo "Waiting for commands finish..."
578 # TODO(pdox): Right now, this abstraction is only used for
579 # paralellizing translations in the self-build. If we're going
580 # to use this for anything more complex, then throttling the
581 # number of active processes to exactly PNACL_CONCURRENCY would
582 # be a useful feature.
586 CT_WAIT_QUEUE+=" ${pid}"
587 if ! QueueConcurrent ; then
593 [ ${PNACL_CONCURRENCY} -gt 1 ]
597 for pid in ${CT_WAIT_QUEUE} ; do
603 # Add a trap so that if the user Ctrl-C's or kills
604 # this script while background processes are running,
605 # the background processes don't keep going.
606 trap 'QueueKill' SIGINT SIGTERM SIGHUP
609 echo "Killing queued processes: ${CT_WAIT_QUEUE}"
610 for pid in ${CT_WAIT_QUEUE} ; do
611 kill ${pid} &> /dev/null || true
618 [ "${CT_WAIT_QUEUE}" == "" ]