Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client / pnacl / scripts / common-tools.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 set -o nounset
7 set -o errexit
8
9 # Turn on/off debugging mode
10 readonly PNACL_DEBUG=${PNACL_DEBUG:-false}
11
12 # True if the scripts are running on the build bots.
13 readonly PNACL_BUILDBOT=${PNACL_BUILDBOT:-false}
14
15 # Dump all build output to stdout
16 readonly PNACL_VERBOSE=${PNACL_VERBOSE:-false}
17
18 readonly TIME_AT_STARTUP=$(date '+%s')
19
20 SetScriptPath() {
21   SCRIPT_PATH="$1"
22 }
23
24 SetLogDirectory() {
25   TC_LOG="$1"
26   TC_LOG_ALL="${TC_LOG}/ALL"
27 }
28
29 ######################################################################
30 # Detect system type
31 ######################################################################
32
33 BUILD_PLATFORM=$(uname | tr '[A-Z]' '[a-z]')
34 BUILD_PLATFORM_LINUX=false
35 BUILD_PLATFORM_MAC=false
36 BUILD_PLATFORM_WIN=false
37
38 if [ "${BUILD_PLATFORM}" == "linux" ] ; then
39   BUILD_PLATFORM_LINUX=true
40   SCONS_BUILD_PLATFORM=linux
41   BUILD_ARCH=${BUILD_ARCH:-$(uname -m)}
42   EXEC_EXT=
43   SO_EXT=.so
44   SO_DIR=lib
45 elif [[ "${BUILD_PLATFORM}" =~ cygwin_nt ]]; then
46   BUILD_PLATFORM=win
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}
52   EXEC_EXT=.exe
53   SO_EXT=.dll
54   SO_DIR=bin  # On Windows, DLLs are placed in bin/
55               # because the dynamic loader searches %PATH%
56 elif [ "${BUILD_PLATFORM}" == "darwin" ] ; then
57   BUILD_PLATFORM=mac
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}
64   EXEC_EXT=
65   SO_EXT=.dylib
66   SO_DIR=lib
67 else
68   echo "Unknown system '${BUILD_PLATFORM}'"
69   exit -1
70 fi
71
72 readonly BUILD_PLATFORM
73 readonly BUILD_PLATFORM_LINUX
74 readonly BUILD_PLATFORM_MAC
75 readonly BUILD_PLATFORM_WIN
76 readonly SCONS_BUILD_PLATFORM
77 readonly SO_EXT
78 readonly SO_DIR
79
80 BUILD_ARCH_SHORT=${BUILD_ARCH}
81 BUILD_ARCH_X8632=false
82 BUILD_ARCH_X8664=false
83 BUILD_ARCH_ARM=false
84 BUILD_ARCH_MIPS=false
85 if [ "${BUILD_ARCH}" == "x86_32" ] ||
86    [ "${BUILD_ARCH}" == "i386" ] ||
87    [ "${BUILD_ARCH}" == "i686" ] ; then
88   BUILD_ARCH=x86_32
89   BUILD_ARCH_X8632=true
90   BUILD_ARCH_SHORT=x86
91 elif [ "${BUILD_ARCH}" == "x86_64" ] ; then
92   BUILD_ARCH_X8664=true
93   BUILD_ARCH_SHORT=x86
94 elif [ "${BUILD_ARCH}" == "armv7l" ] ; then
95   BUILD_ARCH_ARM=true
96   BUILD_ARCH_SHORT=arm
97 elif [ "${BUILD_ARCH}" == "mips32" ] ||
98      [ "${BUILD_ARCH}" == "mips" ] ; then
99   BUILD_ARCH_MIPS=true
100   BUILD_ARCH_SHORT=mips
101 else
102   echo "Unknown build arch '${BUILD_ARCH}'"
103   exit -1
104 fi
105 readonly BUILD_ARCH
106 readonly BUILD_ARCH_SHORT
107 readonly BUILD_ARCH_X8632
108 readonly BUILD_ARCH_X8664
109 readonly BUILD_ARCH_ARM
110 readonly BUILD_ARCH_MIPS
111
112
113 HOST_ARCH=${HOST_ARCH:-${BUILD_ARCH}}
114 HOST_ARCH_X8632=false
115 HOST_ARCH_X8664=false
116 HOST_ARCH_ARM=false
117 HOST_ARCH_MIPS=false
118 if [ "${HOST_ARCH}" == "x86_32" ] ||
119    [ "${HOST_ARCH}" == "i386" ] ||
120    [ "${HOST_ARCH}" == "i686" ] ; then
121   HOST_ARCH=x86_32
122   HOST_ARCH_X8632=true
123 elif [ "${HOST_ARCH}" == "x86_64" ] ; then
124   HOST_ARCH_X8664=true
125 elif [ "${HOST_ARCH}" == "armv7l" ] ; then
126   HOST_ARCH_ARM=true
127 elif [ "${HOST_ARCH}" == "mips32" ] ||
128      [ "${HOST_ARCH}" == "mips" ] ; then
129   HOST_ARCH_MIPS=true
130 else
131   echo "Unknown host arch '${HOST_ARCH}'"
132   exit -1
133 fi
134 readonly HOST_ARCH
135 readonly HOST_ARCH_X8632
136 readonly HOST_ARCH_X8664
137 readonly HOST_ARCH_ARM
138 readonly HOST_ARCH_MIPS
139
140 if [ "${BUILD_ARCH}" != "${HOST_ARCH}" ]; then
141   if ! { ${BUILD_ARCH_X8664} && ${HOST_ARCH_X8632}; }; then
142     echo "Cross builds other than build=x86_64 with host=x86_32 not supported"
143     exit -1
144   fi
145 fi
146
147 if ${BUILD_PLATFORM_WIN}; then
148    readonly GCLIENT="gclient.bat"
149    readonly GIT="git.bat"
150    readonly HG="hg.bat"
151    readonly SVN="svn.bat"
152 else
153    readonly GCLIENT="gclient"
154    readonly GIT="git"
155    readonly HG="hg"
156    readonly SVN="svn"
157 fi
158
159 # On Windows, scons expects Windows-style paths (C:\foo\bar)
160 # This function converts cygwin posix paths to Windows-style paths.
161 # On all other platforms, this function does nothing to the path.
162 PosixToSysPath() {
163   local path="$1"
164   if ${BUILD_PLATFORM_WIN}; then
165     cygpath -w "$(GetAbsolutePath "${path}")"
166   else
167     echo "${path}"
168   fi
169 }
170
171
172 ######################################################################
173 # Git repository tools
174 ######################################################################
175
176 git-has-changes() {
177   local dir=$1
178   spushd "${dir}"
179   local status=$(${GIT} status --porcelain --untracked-files=no)
180   spopd
181   [[ ${#status} > 0 ]]
182   return $?
183 }
184
185 git-assert-no-changes() {
186   local dir=$1
187   if git-has-changes "${dir}"; then
188     Banner "ERROR: Repository ${dir} has local changes"
189     exit -1
190   fi
191 }
192
193 ######################################################################
194 # Subversion repository tools
195 ######################################################################
196
197 svn-at-revision() {
198   local dir="$1"
199   local rev="$2"
200   local repo_rev=$(svn-get-revision "${dir}")
201   [ "${repo_rev}" == "${rev}" ]
202   return $?
203 }
204
205 #+ svn-get-revision <dir>
206 svn-get-revision() {
207   local dir="$1"
208   spushd "${dir}"
209   local rev=$(${SVN} info | grep 'Revision: ' | cut -b 11-)
210   if ! [[ "${rev}" =~ ^[0-9]+$ ]]; then
211     echo "Invalid revision number '${rev}' or invalid repository '${dir}'" 1>&2
212     exit -1
213   fi
214   spopd
215   echo "${rev}"
216 }
217
218 #+ svn-checkout <url> <repodir> - Checkout an SVN repository
219 svn-checkout() {
220   local url="$1"
221   local dir="$2"
222   local rev="$3"
223
224   if [ ! -d "${dir}" ]; then
225     StepBanner "SVN-CHECKOUT" "Checking out ${url}"
226     RunWithLog "svn-checkout" ${SVN} co "${url}" "${dir}" -r "${rev}"
227   else
228     SkipBanner "SVN-CHECKOUT" "Using existing SVN repository for ${url}"
229   fi
230 }
231
232 #+ svn-update <dir> <rev> - Update an SVN repository
233 svn-update() {
234   local dir="$1"
235   local rev="$2"
236
237   assert-dir "$dir" \
238     "SVN repository $(basename "${dir}") doesn't exist."
239
240   spushd "${dir}"
241   if [[ "$rev" == "tip" ]]; then
242     RunWithLog "svn-update" ${SVN} update
243   else
244     RunWithLog "svn-update" ${SVN} update -r ${rev}
245   fi
246   spopd
247 }
248
249 svn-has-changes() {
250   local dir="$1"
251   spushd "${dir}"
252   local STATUS=$(${SVN} status)
253   spopd
254   [ "${STATUS}" != "" ]
255   return $?
256 }
257
258 #+ svn-assert-no-changes <dir> - Assert an svn repo has no local changes
259 svn-assert-no-changes() {
260   local dir="$1"
261   if svn-has-changes "${dir}" ; then
262     local name=$(basename "${dir}")
263     Banner "ERROR: Repository ${name} has local changes"
264     exit -1
265   fi
266 }
267
268
269 ######################################################################
270 # vcs rev info helper
271 ######################################################################
272 get-field () {
273   cut -d " " -f $1
274 }
275
276 git-one-line-rev-info() {
277     local commit=$(${GIT} log -n 1 | head -1 | get-field 2)
278     local url=$(egrep "^[^a-z]+url = " .git/config | head -1 | get-field 3)
279     # variable bypass does implicit whitespace strip
280     echo "[GIT] ${url}: ${commit}"
281 }
282
283 svn-one-line-rev-info() {
284     local url=$(${SVN} info | egrep 'URL:' | get-field 2)
285     local rev=$(${SVN} info | egrep 'Revision:' | get-field 2)
286     echo "[SVN] ${url}: ${rev}"
287 }
288
289 #+ one-line-rev-info <dir> - show one line summmary for
290 one-line-rev-info() {
291   spushd $1
292   if [ -d .svn ]; then
293     svn-one-line-rev-info
294   elif [ -d .git ]; then
295     # we currently only
296     git-one-line-rev-info
297   else
298     echo "[$1] Unknown version control system"
299   fi
300   spopd
301 }
302
303 ######################################################################
304 # Logging tools
305 ######################################################################
306
307 #@ progress              - Show build progress (open in another window)
308 progress() {
309   StepBanner "PROGRESS WINDOW"
310
311   while true; do
312     if [ -f "${TC_LOG_ALL}" ]; then
313       if tail --version > /dev/null; then
314         # GNU coreutils tail
315         tail -s 0.05 --max-unchanged-stats=20 --follow=name "${TC_LOG_ALL}"
316       else
317         # MacOS tail
318         tail -F "${TC_LOG_ALL}"
319       fi
320     fi
321     sleep 1
322   done
323 }
324
325 #+ clean-logs            - Clean all logs
326 clean-logs() {
327   rm -rf "${TC_LOG}"
328 }
329
330 # Logged pushd
331 spushd() {
332   LogEcho "-------------------------------------------------------------------"
333   LogEcho "ENTERING: $1"
334   pushd "$1" > /dev/null
335 }
336
337 # Logged popd
338 spopd() {
339   LogEcho "LEAVING: $(pwd)"
340   popd > /dev/null
341   LogEcho "-------------------------------------------------------------------"
342   LogEcho "ENTERING: $(pwd)"
343 }
344
345 LogEcho() {
346   mkdir -p "${TC_LOG}"
347   echo "$*" >> "${TC_LOG_ALL}"
348 }
349
350 RunWithLog() {
351   local log="${TC_LOG}/$1"
352
353   mkdir -p "${TC_LOG}"
354
355   shift 1
356   local ret=1
357   if ${PNACL_VERBOSE}; then
358     echo "RUNNING: " "$@" | tee "${log}" | tee -a "${TC_LOG_ALL}"
359     "$@" 2>&1 | tee "${log}" | tee -a "${TC_LOG_ALL}"
360     ret=${PIPESTATUS[0]}
361   else
362     echo "RUNNING: " "$@" | tee -a "${TC_LOG_ALL}" &> "${log}"
363     "$@" 2>&1 | tee -a "${TC_LOG_ALL}" &> "${log}"
364     ret=${PIPESTATUS[0]}
365   fi
366   if [ ${ret} -ne 0 ]; then
367     echo
368     Banner "ERROR"
369     echo -n "COMMAND:"
370     PrettyPrint "$@"
371     echo
372     echo "LOGFILE: ${log}"
373     echo
374     echo "PWD: $(pwd)"
375     echo
376     if ${PNACL_BUILDBOT}; then
377       echo "BEGIN LOGFILE Contents."
378       cat "${log}"
379       echo "END LOGFILE Contents."
380     fi
381     return 1
382   fi
383   return 0
384 }
385
386 PrettyPrint() {
387   # Pretty print, respecting parameter grouping
388   for I in "$@"; do
389     local has_space=$(echo "$I" | grep " ")
390     if [ ${#has_space} -gt 0 ]; then
391       echo -n ' "'
392       echo -n "$I"
393       echo -n '"'
394     else
395       echo -n " $I"
396     fi
397   done
398   echo
399 }
400
401 assert-dir() {
402   local dir="$1"
403   local msg="$2"
404
405   if [ ! -d "${dir}" ]; then
406     Banner "ERROR: ${msg}"
407     exit -1
408   fi
409 }
410
411 assert-file() {
412   local fn="$1"
413   local msg="$2"
414
415   if [ ! -f "${fn}" ]; then
416     Banner "ERROR: ${fn} does not exist. ${msg}"
417     exit -1
418   fi
419 }
420
421 Usage() {
422   egrep "^#@" "${SCRIPT_PATH}" | cut -b 3-
423 }
424
425 Usage2() {
426   egrep "^#(@|\+)" "${SCRIPT_PATH}" | cut -b 3-
427 }
428
429 Banner() {
430   echo ""
431   echo " *********************************************************************"
432   echo " | "
433   for arg in "$@" ; do
434     echo " | ${arg}"
435   done
436   echo " | "
437   echo " *********************************************************************"
438 }
439
440 StepBanner() {
441   local module="$1"
442   if [ $# -eq 1 ]; then
443     echo ""
444     echo "-------------------------------------------------------------------"
445     local padding=$(RepeatStr ' ' 28)
446     echo "${padding}${module}"
447     echo "-------------------------------------------------------------------"
448   else
449     shift 1
450     local padding=$(RepeatStr ' ' $((20-${#module})) )
451     echo "[$(TimeStamp)] ${module}${padding}" "$@"
452   fi
453 }
454
455 TimeStamp() {
456   if date --version &> /dev/null ; then
457     # GNU 'date'
458     date -d "now - ${TIME_AT_STARTUP}sec" '+%M:%S'
459   else
460     # Other 'date' (assuming BSD for now)
461     local time_now=$(date '+%s')
462     local time_delta=$[ ${time_now} - ${TIME_AT_STARTUP} ]
463     date -j -f "%s" "${time_delta}" "+%M:%S"
464   fi
465 }
466
467
468 SubBanner() {
469   echo "----------------------------------------------------------------------"
470   echo " $@"
471   echo "----------------------------------------------------------------------"
472 }
473
474 SkipBanner() {
475     StepBanner "$1" "Skipping $2, already up to date."
476 }
477
478 RepeatStr() {
479   local str="$1"
480   local count=$2
481   local ret=""
482
483   while [ $count -gt 0 ]; do
484     ret="${ret}${str}"
485     count=$((count-1))
486   done
487   echo "$ret"
488 }
489
490
491 Fatal() {
492   echo 1>&2
493   echo "$@" 1>&2
494   echo 1>&2
495   exit -1
496 }
497
498 is-ELF() {
499   local F=$(file -b "$1")
500   [[ "${F}" =~ "ELF" ]]
501 }
502
503 is-Mach() {
504   local F=$(file -b "$1")
505   [[ "${F}" =~ "Mach-O" ]]
506 }
507
508 is-shell-script() {
509   local F=$(file -b "$1")
510   [[ "${F}" =~ "shell" ]]
511 }
512
513 get_dir_size_in_mb() {
514   du -msc "$1" | tail -1 | egrep -o "[0-9]+"
515 }
516
517 confirm-yes() {
518   local msg="$1"
519   while true; do
520     echo -n "${msg} [Y/N]? "
521     local YESNO
522     read YESNO
523     if [ "${YESNO}" == "N" ] || [ "${YESNO}" == "n" ]; then
524       return 1
525     fi
526     if [ "${YESNO}" == "Y" ] || [ "${YESNO}" == "y" ]; then
527       return 0
528     fi
529   done
530 }
531
532 # On Linux with GNU readlink, "readlink -f" would be a quick way
533 # of getting an absolute path, but MacOS has BSD readlink.
534 GetAbsolutePath() {
535   local relpath=$1
536   local reldir
537   local relname
538   if [ -d "${relpath}" ]; then
539     reldir="${relpath}"
540     relname=""
541   else
542     reldir="$(dirname "${relpath}")"
543     relname="/$(basename "${relpath}")"
544   fi
545
546   local absdir="$(cd "${reldir}" && pwd)"
547   echo "${absdir}${relname}"
548 }
549
550
551 # The Queue* functions provide a simple way of keeping track
552 # of multiple background processes in order to ensure that:
553 # 1) they all finish successfully (with return value 0), and
554 # 2) they terminate if the master process is killed/interrupted.
555 #    (This is done using a bash "trap" handler)
556 #
557 # Example Usage:
558 #     command1 &
559 #     QueueLastProcess
560 #     command2 &
561 #     QueueLastProcess
562 #     command3 &
563 #     QueueLastProcess
564 #     echo "Waiting for commands finish..."
565 #     QueueWait
566 #
567 # TODO(pdox): Right now, this abstraction is only used for
568 # paralellizing translations in the self-build. If we're going
569 # to use this for anything more complex, then throttling the
570 # number of active processes to exactly PNACL_CONCURRENCY would
571 # be a useful feature.
572 CT_WAIT_QUEUE=""
573 QueueLastProcess() {
574   local pid=$!
575   CT_WAIT_QUEUE+=" ${pid}"
576   if ! QueueConcurrent ; then
577     QueueWait
578   fi
579 }
580
581 QueueConcurrent() {
582   [ ${PNACL_CONCURRENCY} -gt 1 ]
583 }
584
585 QueueWait() {
586   for pid in ${CT_WAIT_QUEUE} ; do
587     wait ${pid}
588   done
589   CT_WAIT_QUEUE=""
590 }
591
592 # Add a trap so that if the user Ctrl-C's or kills
593 # this script while background processes are running,
594 # the background processes don't keep going.
595 trap 'QueueKill' SIGINT SIGTERM SIGHUP
596 QueueKill() {
597   echo
598   echo "Killing queued processes: ${CT_WAIT_QUEUE}"
599   for pid in ${CT_WAIT_QUEUE} ; do
600     kill ${pid} &> /dev/null || true
601   done
602   echo
603   CT_WAIT_QUEUE=""
604 }
605
606 QueueEmpty() {
607   [ "${CT_WAIT_QUEUE}" == "" ]
608 }