Upstream version 5.34.92.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_X8632=false
81 BUILD_ARCH_X8664=false
82 BUILD_ARCH_ARM=false
83 BUILD_ARCH_MIPS=false
84 if [ "${BUILD_ARCH}" == "x86_32" ] ||
85    [ "${BUILD_ARCH}" == "i386" ] ||
86    [ "${BUILD_ARCH}" == "i686" ] ; then
87   BUILD_ARCH=x86_32
88   BUILD_ARCH_X8632=true
89 elif [ "${BUILD_ARCH}" == "x86_64" ] ; then
90   BUILD_ARCH_X8664=true
91 elif [ "${BUILD_ARCH}" == "armv7l" ] ; then
92   BUILD_ARCH_ARM=true
93 elif [ "${BUILD_ARCH}" == "mips32" ] ||
94      [ "${BUILD_ARCH}" == "mips" ] ; then
95   BUILD_ARCH_MIPS=true
96 else
97   echo "Unknown build arch '${BUILD_ARCH}'"
98   exit -1
99 fi
100 readonly BUILD_ARCH
101 readonly BUILD_ARCH_X8632
102 readonly BUILD_ARCH_X8664
103 readonly BUILD_ARCH_ARM
104 readonly BUILD_ARCH_MIPS
105
106
107 HOST_ARCH=${HOST_ARCH:-${BUILD_ARCH}}
108 HOST_ARCH_X8632=false
109 HOST_ARCH_X8664=false
110 HOST_ARCH_ARM=false
111 HOST_ARCH_MIPS=false
112 if [ "${HOST_ARCH}" == "x86_32" ] ||
113    [ "${HOST_ARCH}" == "i386" ] ||
114    [ "${HOST_ARCH}" == "i686" ] ; then
115   HOST_ARCH=x86_32
116   HOST_ARCH_X8632=true
117 elif [ "${HOST_ARCH}" == "x86_64" ] ; then
118   HOST_ARCH_X8664=true
119 elif [ "${HOST_ARCH}" == "armv7l" ] ; then
120   HOST_ARCH_ARM=true
121 elif [ "${HOST_ARCH}" == "mips32" ] ||
122      [ "${HOST_ARCH}" == "mips" ] ; then
123   HOST_ARCH_MIPS=true
124 else
125   echo "Unknown host arch '${HOST_ARCH}'"
126   exit -1
127 fi
128 readonly HOST_ARCH
129 readonly HOST_ARCH_X8632
130 readonly HOST_ARCH_X8664
131 readonly HOST_ARCH_ARM
132 readonly HOST_ARCH_MIPS
133
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"
137     exit -1
138   fi
139 fi
140
141 if ${BUILD_PLATFORM_WIN}; then
142    readonly GCLIENT="gclient.bat"
143    readonly GIT="git.bat"
144    readonly HG="hg.bat"
145    readonly SVN="svn.bat"
146 else
147    readonly GCLIENT="gclient"
148    readonly GIT="git"
149    readonly HG="hg"
150    readonly SVN="svn"
151 fi
152
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.
156 PosixToSysPath() {
157   local path="$1"
158   if ${BUILD_PLATFORM_WIN}; then
159     cygpath -w "$(GetAbsolutePath "${path}")"
160   else
161     echo "${path}"
162   fi
163 }
164
165
166 ######################################################################
167 # Git repository tools
168 ######################################################################
169
170 git-has-changes() {
171   local dir=$1
172   spushd "${dir}"
173   local status=$(${GIT} status --porcelain --untracked-files=no)
174   spopd
175   [[ ${#status} > 0 ]]
176   return $?
177 }
178
179 git-assert-no-changes() {
180   local dir=$1
181   if git-has-changes "${dir}"; then
182     Banner "ERROR: Repository ${dir} has local changes"
183     exit -1
184   fi
185 }
186
187 ######################################################################
188 # Subversion repository tools
189 ######################################################################
190
191 svn-at-revision() {
192   local dir="$1"
193   local rev="$2"
194   local repo_rev=$(svn-get-revision "${dir}")
195   [ "${repo_rev}" == "${rev}" ]
196   return $?
197 }
198
199 #+ svn-get-revision <dir>
200 svn-get-revision() {
201   local dir="$1"
202   spushd "${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
206     exit -1
207   fi
208   spopd
209   echo "${rev}"
210 }
211
212 #+ svn-checkout <url> <repodir> - Checkout an SVN repository
213 svn-checkout() {
214   local url="$1"
215   local dir="$2"
216   local rev="$3"
217
218   if [ ! -d "${dir}" ]; then
219     StepBanner "SVN-CHECKOUT" "Checking out ${url}"
220     RunWithLog "svn-checkout" ${SVN} co "${url}" "${dir}" -r "${rev}"
221   else
222     SkipBanner "SVN-CHECKOUT" "Using existing SVN repository for ${url}"
223   fi
224 }
225
226 #+ svn-update <dir> <rev> - Update an SVN repository
227 svn-update() {
228   local dir="$1"
229   local rev="$2"
230
231   assert-dir "$dir" \
232     "SVN repository $(basename "${dir}") doesn't exist."
233
234   spushd "${dir}"
235   if [[ "$rev" == "tip" ]]; then
236     RunWithLog "svn-update" ${SVN} update
237   else
238     RunWithLog "svn-update" ${SVN} update -r ${rev}
239   fi
240   spopd
241 }
242
243 svn-has-changes() {
244   local dir="$1"
245   spushd "${dir}"
246   local STATUS=$(${SVN} status)
247   spopd
248   [ "${STATUS}" != "" ]
249   return $?
250 }
251
252 #+ svn-assert-no-changes <dir> - Assert an svn repo has no local changes
253 svn-assert-no-changes() {
254   local dir="$1"
255   if svn-has-changes "${dir}" ; then
256     local name=$(basename "${dir}")
257     Banner "ERROR: Repository ${name} has local changes"
258     exit -1
259   fi
260 }
261
262
263 ######################################################################
264 # vcs rev info helper
265 ######################################################################
266 get-field () {
267   cut -d " " -f $1
268 }
269
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}"
275 }
276
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}"
281 }
282
283 #+ one-line-rev-info <dir> - show one line summmary for
284 one-line-rev-info() {
285   spushd $1
286   if [ -d .svn ]; then
287     svn-one-line-rev-info
288   elif [ -d .git ]; then
289     # we currently only
290     git-one-line-rev-info
291   else
292     echo "[$1] Unknown version control system"
293   fi
294   spopd
295 }
296
297 ######################################################################
298 # Logging tools
299 ######################################################################
300
301 #@ progress              - Show build progress (open in another window)
302 progress() {
303   StepBanner "PROGRESS WINDOW"
304
305   while true; do
306     if [ -f "${TC_LOG_ALL}" ]; then
307       if tail --version > /dev/null; then
308         # GNU coreutils tail
309         tail -s 0.05 --max-unchanged-stats=20 --follow=name "${TC_LOG_ALL}"
310       else
311         # MacOS tail
312         tail -F "${TC_LOG_ALL}"
313       fi
314     fi
315     sleep 1
316   done
317 }
318
319 #+ clean-logs            - Clean all logs
320 clean-logs() {
321   rm -rf "${TC_LOG}"
322 }
323
324 # Logged pushd
325 spushd() {
326   LogEcho "-------------------------------------------------------------------"
327   LogEcho "ENTERING: $1"
328   pushd "$1" > /dev/null
329 }
330
331 # Logged popd
332 spopd() {
333   LogEcho "LEAVING: $(pwd)"
334   popd > /dev/null
335   LogEcho "-------------------------------------------------------------------"
336   LogEcho "ENTERING: $(pwd)"
337 }
338
339 LogEcho() {
340   mkdir -p "${TC_LOG}"
341   echo "$*" >> "${TC_LOG_ALL}"
342 }
343
344 RunWithLog() {
345   local log="${TC_LOG}/$1"
346
347   mkdir -p "${TC_LOG}"
348
349   shift 1
350   local ret=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}"
354     ret=${PIPESTATUS[0]}
355   else
356     echo "RUNNING: " "$@" | tee -a "${TC_LOG_ALL}" &> "${log}"
357     "$@" 2>&1 | tee -a "${TC_LOG_ALL}" &> "${log}"
358     ret=${PIPESTATUS[0]}
359   fi
360   if [ ${ret} -ne 0 ]; then
361     echo
362     Banner "ERROR"
363     echo -n "COMMAND:"
364     PrettyPrint "$@"
365     echo
366     echo "LOGFILE: ${log}"
367     echo
368     echo "PWD: $(pwd)"
369     echo
370     if ${PNACL_BUILDBOT}; then
371       echo "BEGIN LOGFILE Contents."
372       cat "${log}"
373       echo "END LOGFILE Contents."
374     fi
375     return 1
376   fi
377   return 0
378 }
379
380 PrettyPrint() {
381   # Pretty print, respecting parameter grouping
382   for I in "$@"; do
383     local has_space=$(echo "$I" | grep " ")
384     if [ ${#has_space} -gt 0 ]; then
385       echo -n ' "'
386       echo -n "$I"
387       echo -n '"'
388     else
389       echo -n " $I"
390     fi
391   done
392   echo
393 }
394
395 assert-dir() {
396   local dir="$1"
397   local msg="$2"
398
399   if [ ! -d "${dir}" ]; then
400     Banner "ERROR: ${msg}"
401     exit -1
402   fi
403 }
404
405 assert-file() {
406   local fn="$1"
407   local msg="$2"
408
409   if [ ! -f "${fn}" ]; then
410     Banner "ERROR: ${fn} does not exist. ${msg}"
411     exit -1
412   fi
413 }
414
415 Usage() {
416   egrep "^#@" "${SCRIPT_PATH}" | cut -b 3-
417 }
418
419 Usage2() {
420   egrep "^#(@|\+)" "${SCRIPT_PATH}" | cut -b 3-
421 }
422
423 Banner() {
424   echo ""
425   echo " *********************************************************************"
426   echo " | "
427   for arg in "$@" ; do
428     echo " | ${arg}"
429   done
430   echo " | "
431   echo " *********************************************************************"
432 }
433
434 StepBanner() {
435   local module="$1"
436   if [ $# -eq 1 ]; then
437     echo ""
438     echo "-------------------------------------------------------------------"
439     local padding=$(RepeatStr ' ' 28)
440     echo "${padding}${module}"
441     echo "-------------------------------------------------------------------"
442   else
443     shift 1
444     local padding=$(RepeatStr ' ' $((20-${#module})) )
445     echo "[$(TimeStamp)] ${module}${padding}" "$@"
446   fi
447 }
448
449 TimeStamp() {
450   if date --version &> /dev/null ; then
451     # GNU 'date'
452     date -d "now - ${TIME_AT_STARTUP}sec" '+%M:%S'
453   else
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"
458   fi
459 }
460
461
462 SubBanner() {
463   echo "----------------------------------------------------------------------"
464   echo " $@"
465   echo "----------------------------------------------------------------------"
466 }
467
468 SkipBanner() {
469     StepBanner "$1" "Skipping $2, already up to date."
470 }
471
472 RepeatStr() {
473   local str="$1"
474   local count=$2
475   local ret=""
476
477   while [ $count -gt 0 ]; do
478     ret="${ret}${str}"
479     count=$((count-1))
480   done
481   echo "$ret"
482 }
483
484
485 Fatal() {
486   echo 1>&2
487   echo "$@" 1>&2
488   echo 1>&2
489   exit -1
490 }
491
492 PackageCheck() {
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."
497 }
498
499 assert-bin() {
500   local exe="$1"
501   local msg="$2"
502
503   if ! which "$exe" > /dev/null; then
504     Banner "ERROR: $msg"
505     exit -1
506   fi
507 }
508
509 is-ELF() {
510   local F=$(file -b "$1")
511   [[ "${F}" =~ "ELF" ]]
512 }
513
514 is-Mach() {
515   local F=$(file -b "$1")
516   [[ "${F}" =~ "Mach-O" ]]
517 }
518
519 is-shell-script() {
520   local F=$(file -b "$1")
521   [[ "${F}" =~ "shell" ]]
522 }
523
524 get_dir_size_in_mb() {
525   du -msc "$1" | tail -1 | egrep -o "[0-9]+"
526 }
527
528 confirm-yes() {
529   local msg="$1"
530   while true; do
531     echo -n "${msg} [Y/N]? "
532     local YESNO
533     read YESNO
534     if [ "${YESNO}" == "N" ] || [ "${YESNO}" == "n" ]; then
535       return 1
536     fi
537     if [ "${YESNO}" == "Y" ] || [ "${YESNO}" == "y" ]; then
538       return 0
539     fi
540   done
541 }
542
543 # On Linux with GNU readlink, "readlink -f" would be a quick way
544 # of getting an absolute path, but MacOS has BSD readlink.
545 GetAbsolutePath() {
546   local relpath=$1
547   local reldir
548   local relname
549   if [ -d "${relpath}" ]; then
550     reldir="${relpath}"
551     relname=""
552   else
553     reldir="$(dirname "${relpath}")"
554     relname="/$(basename "${relpath}")"
555   fi
556
557   local absdir="$(cd "${reldir}" && pwd)"
558   echo "${absdir}${relname}"
559 }
560
561
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)
567 #
568 # Example Usage:
569 #     command1 &
570 #     QueueLastProcess
571 #     command2 &
572 #     QueueLastProcess
573 #     command3 &
574 #     QueueLastProcess
575 #     echo "Waiting for commands finish..."
576 #     QueueWait
577 #
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.
583 CT_WAIT_QUEUE=""
584 QueueLastProcess() {
585   local pid=$!
586   CT_WAIT_QUEUE+=" ${pid}"
587   if ! QueueConcurrent ; then
588     QueueWait
589   fi
590 }
591
592 QueueConcurrent() {
593   [ ${PNACL_CONCURRENCY} -gt 1 ]
594 }
595
596 QueueWait() {
597   for pid in ${CT_WAIT_QUEUE} ; do
598     wait ${pid}
599   done
600   CT_WAIT_QUEUE=""
601 }
602
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
607 QueueKill() {
608   echo
609   echo "Killing queued processes: ${CT_WAIT_QUEUE}"
610   for pid in ${CT_WAIT_QUEUE} ; do
611     kill ${pid} &> /dev/null || true
612   done
613   echo
614   CT_WAIT_QUEUE=""
615 }
616
617 QueueEmpty() {
618   [ "${CT_WAIT_QUEUE}" == "" ]
619 }