* Build failed in step 'Dumping user-supplied crosstool-NG configuration'
@ 2012-09-26 3:46 Blair Burtan
2012-09-26 6:54 ` Per Arnold Blaasmo
0 siblings, 1 reply; 10+ messages in thread
From: Blair Burtan @ 2012-09-26 3:46 UTC (permalink / raw)
To: crossgcc
Trying to build a arm-unknown-linux-gnueabi toolchain and I get the
following output:
[INFO ] Performing some trivial sanity checks
[INFO ] Build started 20120925.195532
[00:00] / touch: /backtrace: Permission denied
[ERROR]
[ERROR] >>
[ERROR] >> Build failed in step 'Dumping user-supplied crosstool-NG
configuration'
[ERROR] >> called in step '(top-level)'
[ERROR] >>
[ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@158]
[ERROR] >> called from: main[scripts/crosstool-NG.sh@103]
[00:00] / touch: /backtrace: Permission denied
[ERROR]
[ERROR] >>
[ERROR] >> Build failed in step 'Dumping user-supplied crosstool-NG
configuration'
[ERROR] >> called in step '(top-level)'
[ERROR] >>
[ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@158]
[ERROR] >> called from: main[scripts/crosstool-NG.sh@103]
[ERROR] >>
[ERROR] >> For more info on this error, look at the file: 'build.log'
[ERROR] >> There is a list of known issues, some with workarounds, in:
[ERROR] >>
'/Volumes/CrosstoolCompile/foo/share/doc/crosstool-ng/ct-ng.1.16.0/B - Known
issues.txt'
[ERROR]
[ERROR] (elapsed: 0:00.00)
[00:00] / make: *** [build] Error 1
The build.log looks like this:
[DEBUG] Testing '! ( -n )'
[DEBUG] Testing '! ( -n )'
[DEBUG] Testing '! ( -n )'
[DEBUG] ==> Executing: 'mkdir' '-p'
'/Volumes/CrosstoolCompile/x-tool/.build'
[DEBUG] ==> Executing: 'touch'
'/Volumes/CrosstoolCompile/x-tool/.build/foo'
[DEBUG] Testing '! ( -f /Volumes/CrosstoolCompile/x-tool/.build/FOO )'
[DEBUG] ==> Executing: 'rm' '-f'
'/Volumes/CrosstoolCompile/x-tool/.build/foo'
[DEBUG] Testing '-f /bin/bash -a -x /bin/bash'
[DEBUG] Creating bin-override for tools in
'/Volumes/CrosstoolCompile/x-tool/.build/tools'
[DEBUG] ==> Executing: 'mkdir' '-p'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin'
[DEBUG] Creating script-override for 'install' ->
'"/opt/local/bin/ginstall"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/install'
[DEBUG] Creating script-override for 'bash' -> '"/bin/bash"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/bash'
[DEBUG] Creating script-override for 'awk' -> '"/sw/bin/awk"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/awk'
[DEBUG] Creating script-override for 'grep' -> '"/usr/bin/grep"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/grep'
[DEBUG] Creating script-override for 'make' -> '"/usr/bin/make"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/make'
[DEBUG] Creating script-override for 'sed' -> '"/opt/local/bin/gsed"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/sed'
[DEBUG] Creating script-override for 'libtool' ->
'"/opt/local/bin/glibtool"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/libtool'
[DEBUG] Creating script-override for 'libtoolize' ->
'"/opt/local/bin/glibtoolize"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/libtoolize'
[DEBUG] Creating script-override for 'objcopy' ->
'"/opt/local/bin/gobjcopy"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/objcopy'
[DEBUG] Creating script-override for 'objdump' ->
'"/opt/local/bin/gobjdump"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/objdump'
[DEBUG] Creating script-override for 'readelf' ->
'"/opt/local/bin/greadelf"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/readelf'
[DEBUG] Creating script-override for 'patch' -> '"/usr/bin/patch"'
[DEBUG] ==> Executing: 'chmod' '700'
'/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/patch'
[INFO ] Build started 20120925.195532
[DEBUG] =================================================================
[DEBUG] Dumping user-supplied crosstool-NG configuration
[DEBUG] ==> Executing: 'grep' '-E' '^(# |)CT_' '.config'
[DEBUG] grep: empty (sub)expression
[ERROR]
[ERROR] >>
[ERROR] >> Build failed in step 'Dumping user-supplied crosstool-NG
configuration'
[ERROR] >> called in step '(top-level)'
[ERROR] >>
[ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@158]
[ERROR] >> called from: main[scripts/crosstool-NG.sh@103]
[ERROR]
[ERROR] >>
[ERROR] >> Build failed in step 'Dumping user-supplied crosstool-NG
configuration'
[ERROR] >> called in step '(top-level)'
[ERROR] >>
[ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@158]
[ERROR] >> called from: main[scripts/crosstool-NG.sh@103]
[ERROR] >>
[ERROR] >> For more info on this error, look at the file: 'build.log'
[ERROR] >> There is a list of known issues, some with workarounds, in:
[ERROR] >>
'/Volumes/CrosstoolCompile/foo/share/doc/crosstool-ng/ct-ng.1.16.0/B - Known
issues.txt'
[ERROR]
[ERROR] (elapsed: 0:00.00)
--
For unsubscribe information see http://sourceware.org/lists.html#faq
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Build failed in step 'Dumping user-supplied crosstool-NG configuration'
2012-09-26 3:46 Build failed in step 'Dumping user-supplied crosstool-NG configuration' Blair Burtan
@ 2012-09-26 6:54 ` Per Arnold Blaasmo
2012-09-26 15:30 ` Blair Burtan
0 siblings, 1 reply; 10+ messages in thread
From: Per Arnold Blaasmo @ 2012-09-26 6:54 UTC (permalink / raw)
To: Blair Burtan; +Cc: crossgcc
Hi,
I got the same problem when trying to build on a Mac Pro with Osx.
Are you building on a Mac.?
The reason being that the bsd-grep on Mac does not work with this
expression.
So I installed grep from macports. That fixed it for me.
$ grep --version
grep (BSD grep) 2.5.1-FreeBSD
$ /opt/local/bin/grep --version
/opt/local/bin/grep (GNU grep) 2.12
Regards
Per A.
On 26. sep. 2012 05:46, Blair Burtan wrote:
> Trying to build a arm-unknown-linux-gnueabi toolchain and I get the
> following output:
>
> [INFO ] Performing some trivial sanity checks
> [INFO ] Build started 20120925.195532
> [00:00] / touch: /backtrace: Permission denied
> [ERROR]
> [ERROR] >>
> [ERROR] >> Build failed in step 'Dumping user-supplied crosstool-NG
> configuration'
> [ERROR] >> called in step '(top-level)'
> [ERROR] >>
> [ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@158]
> [ERROR] >> called from: main[scripts/crosstool-NG.sh@103]
> [00:00] / touch: /backtrace: Permission denied
> [ERROR]
> [ERROR] >>
> [ERROR] >> Build failed in step 'Dumping user-supplied crosstool-NG
> configuration'
> [ERROR] >> called in step '(top-level)'
> [ERROR] >>
> [ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@158]
> [ERROR] >> called from: main[scripts/crosstool-NG.sh@103]
> [ERROR] >>
> [ERROR] >> For more info on this error, look at the file: 'build.log'
> [ERROR] >> There is a list of known issues, some with workarounds, in:
> [ERROR] >>
> '/Volumes/CrosstoolCompile/foo/share/doc/crosstool-ng/ct-ng.1.16.0/B - Known
> issues.txt'
> [ERROR]
> [ERROR] (elapsed: 0:00.00)
> [00:00] / make: *** [build] Error 1
>
>
>
> The build.log looks like this:
>
> [DEBUG] Testing '! ( -n )'
> [DEBUG] Testing '! ( -n )'
> [DEBUG] Testing '! ( -n )'
> [DEBUG] ==> Executing: 'mkdir' '-p'
> '/Volumes/CrosstoolCompile/x-tool/.build'
> [DEBUG] ==> Executing: 'touch'
> '/Volumes/CrosstoolCompile/x-tool/.build/foo'
> [DEBUG] Testing '! ( -f /Volumes/CrosstoolCompile/x-tool/.build/FOO )'
> [DEBUG] ==> Executing: 'rm' '-f'
> '/Volumes/CrosstoolCompile/x-tool/.build/foo'
> [DEBUG] Testing '-f /bin/bash -a -x /bin/bash'
> [DEBUG] Creating bin-override for tools in
> '/Volumes/CrosstoolCompile/x-tool/.build/tools'
> [DEBUG] ==> Executing: 'mkdir' '-p'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin'
> [DEBUG] Creating script-override for 'install' ->
> '"/opt/local/bin/ginstall"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/install'
> [DEBUG] Creating script-override for 'bash' -> '"/bin/bash"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/bash'
> [DEBUG] Creating script-override for 'awk' -> '"/sw/bin/awk"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/awk'
> [DEBUG] Creating script-override for 'grep' -> '"/usr/bin/grep"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/grep'
> [DEBUG] Creating script-override for 'make' -> '"/usr/bin/make"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/make'
> [DEBUG] Creating script-override for 'sed' -> '"/opt/local/bin/gsed"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/sed'
> [DEBUG] Creating script-override for 'libtool' ->
> '"/opt/local/bin/glibtool"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/libtool'
> [DEBUG] Creating script-override for 'libtoolize' ->
> '"/opt/local/bin/glibtoolize"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/libtoolize'
> [DEBUG] Creating script-override for 'objcopy' ->
> '"/opt/local/bin/gobjcopy"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/objcopy'
> [DEBUG] Creating script-override for 'objdump' ->
> '"/opt/local/bin/gobjdump"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/objdump'
> [DEBUG] Creating script-override for 'readelf' ->
> '"/opt/local/bin/greadelf"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/readelf'
> [DEBUG] Creating script-override for 'patch' -> '"/usr/bin/patch"'
> [DEBUG] ==> Executing: 'chmod' '700'
> '/Volumes/CrosstoolCompile/x-tool/.build/tools/bin/patch'
> [INFO ] Build started 20120925.195532
> [DEBUG] =================================================================
> [DEBUG] Dumping user-supplied crosstool-NG configuration
> [DEBUG] ==> Executing: 'grep' '-E' '^(# |)CT_' '.config'
> [DEBUG] grep: empty (sub)expression
> [ERROR]
> [ERROR] >>
> [ERROR] >> Build failed in step 'Dumping user-supplied crosstool-NG
> configuration'
> [ERROR] >> called in step '(top-level)'
> [ERROR] >>
> [ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@158]
> [ERROR] >> called from: main[scripts/crosstool-NG.sh@103]
> [ERROR]
> [ERROR] >>
> [ERROR] >> Build failed in step 'Dumping user-supplied crosstool-NG
> configuration'
> [ERROR] >> called in step '(top-level)'
> [ERROR] >>
> [ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@158]
> [ERROR] >> called from: main[scripts/crosstool-NG.sh@103]
> [ERROR] >>
> [ERROR] >> For more info on this error, look at the file: 'build.log'
> [ERROR] >> There is a list of known issues, some with workarounds, in:
> [ERROR] >>
> '/Volumes/CrosstoolCompile/foo/share/doc/crosstool-ng/ct-ng.1.16.0/B - Known
> issues.txt'
> [ERROR]
> [ERROR] (elapsed: 0:00.00)
>
>
>
>
> --
> For unsubscribe information see http://sourceware.org/lists.html#faq
>
>
>
--
For unsubscribe information see http://sourceware.org/lists.html#faq
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Build failed in step 'Dumping user-supplied crosstool-NG configuration'
2012-09-26 6:54 ` Per Arnold Blaasmo
@ 2012-09-26 15:30 ` Blair Burtan
2012-09-26 16:56 ` Yann E. MORIN
0 siblings, 1 reply; 10+ messages in thread
From: Blair Burtan @ 2012-09-26 15:30 UTC (permalink / raw)
To: per-arnold.blaasmo; +Cc: crossgcc
That was the problem but not quite the complete solution. I had to modify
the grep path to point to the MacPorts verison when I built ct-ng. I also
had to use ginstall instead of the OSX install.
> Hi,
> I got the same problem when trying to build on a Mac Pro with Osx.
> Are you building on a Mac.?
>
> The reason being that the bsd-grep on Mac does not work with this
> expression.
>
> So I installed grep from macports. That fixed it for me.
>
> $ grep --version
> grep (BSD grep) 2.5.1-FreeBSD
>
> $ /opt/local/bin/grep --version
> /opt/local/bin/grep (GNU grep) 2.12
>
--
For unsubscribe information see http://sourceware.org/lists.html#faq
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Build failed in step 'Dumping user-supplied crosstool-NG configuration'
2012-09-26 15:30 ` Blair Burtan
@ 2012-09-26 16:56 ` Yann E. MORIN
2014-08-06 2:27 ` [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes Fabian Freyer
0 siblings, 1 reply; 10+ messages in thread
From: Yann E. MORIN @ 2012-09-26 16:56 UTC (permalink / raw)
To: crossgcc; +Cc: Blair Burtan, per-arnold.blaasmo
Blair, All,
[Please, do not top-post]
On Wednesday 26 September 2012 17:30:12 Blair Burtan wrote:
> That was the problem but not quite the complete solution. I had to modify
> the grep path to point to the MacPorts verison when I built ct-ng. I also
> had to use ginstall instead of the OSX install.
./configure --help
[--SNIP--]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-install=PATH Specify the full PATH to a BSD-compatible install
--with-sed=PATH Specify the full PATH to GNU sed
--with-objcopy=PATH Specify the full PATH to GNU objcopy
--with-objdump=PATH Specify the full PATH to GNU objdump
--with-ranlib=PATH Specify the full PATH to GNU ranlib
--with-readelf=PATH Specify the full PATH to GNU readelf
--with-bash=PATH Specify the full PATH to GNU bash >= 3.1
--with-awk=PATH Specify the full PATH to GNU awk
--with-make=PATH Specify the full PATH to GNU make >= 3.80
--with-libtool=PATH Specify the full PATH to GNU libtool >= 1.5.26
--with-libtoolize=PATH Specify the full PATH to GNU libtoolize >= 1.5.26
--with-automake=PATH Specify the full PATH to GNU automake >= 1.10
[--SNIP--]
That's how you tell crosstool-NG what tools to use if the default ones are
not the GNU ones.
Alternatively, that's also explained at length in the documentation:
docs/C - Misc. tutorials.txt
And there is also a table of contents for the documentation:
docs/0 - Table of content.txt
Regards,
Yann E. MORIN.
--
.-----------------.--------------------.------------------.--------------------.
| Yann E. MORIN | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software Designer | \ / CAMPAIGN | ___ |
| +33 223 225 172 `------------.-------: X AGAINST | \e/ There is no |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL | v conspiracy. |
'------------------------------^-------^------------------^--------------------'
--
For unsubscribe information see http://sourceware.org/lists.html#faq
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes
2012-09-26 16:56 ` Yann E. MORIN
@ 2014-08-06 2:27 ` Fabian Freyer
2014-08-06 2:40 ` Fabian Freyer
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Fabian Freyer @ 2014-08-06 2:27 UTC (permalink / raw)
To: Yann E. MORIN; +Cc: crossgcc
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
- From 3847ffad3f1c7757d34b7a24279f5bb3b64b4c87 Mon Sep 17 00:00:00 2001
Hi,
On 26/09/12 18:56, Yann E. MORIN wrote:
> On Wednesday 26 September 2012 17:30:12 Blair Burtan wrote:
>> That was the problem but not quite the complete solution. I had to modify
>> the grep path to point to the MacPorts verison when I built ct-ng. I also
>> had to use ginstall instead of the OSX install.
>
> ./configure --help
> [--SNIP--]
> Optional Packages:
> --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
> --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
> --with-install=PATH Specify the full PATH to a BSD-compatible install
> --with-sed=PATH Specify the full PATH to GNU sed
> --with-objcopy=PATH Specify the full PATH to GNU objcopy
> --with-objdump=PATH Specify the full PATH to GNU objdump
> --with-ranlib=PATH Specify the full PATH to GNU ranlib
> --with-readelf=PATH Specify the full PATH to GNU readelf
> --with-bash=PATH Specify the full PATH to GNU bash >= 3.1
> --with-awk=PATH Specify the full PATH to GNU awk
> --with-make=PATH Specify the full PATH to GNU make >= 3.80
> --with-libtool=PATH Specify the full PATH to GNU libtool >= 1.5.26
> --with-libtoolize=PATH Specify the full PATH to GNU libtoolize >= 1.5.26
> --with-automake=PATH Specify the full PATH to GNU automake >= 1.10
> [--SNIP--]
>
> That's how you tell crosstool-NG what tools to use if the default ones are
> not the GNU ones.
While it is possible to tell crosstool-NG to use custom GNU tools for several
tools, it is not possible for all tools, especially for grep and sed. This
causes ct-ng build to fail:
[ERROR] >>
[ERROR] >> Build failed in step '(top-level)'
[ERROR] >>
[ERROR] >> Error happened in: CT_DoForceRmdir[scripts/functions@458]
[ERROR] >> called from: main[scripts/crosstool-NG.sh@238]
[ERROR] >>
One of the problems here is also that on BSD installs, including OS X, GNU
tools are often installed with a prefixed 'g', in this case "ggrep" and "gsed".
There is no way to tell crosstool-NG to use ggrep instead of grep, and
adjusting $PATH does not help either.
I have created a small (not counting the changes due to the scripts/functions
rename) patch that adds --with-grep and substitues @@CT_sed@@ for sed in a few
places where sed from PATH is used and GNU-specific options are used. I can
confirm this works for me on Darwin using GNU tools installed via homebrew using
the following ./configure options:
./configure --prefix=$(pwd) --exec-prefix=$(pwd) \
--with-objcopy=gobjcopy \
--with-objdump=gobjdump \
--with-readelf=greadelf \
--with-libtool=glibtool \
--with-libtoolize=glibtoolize \
--with-install=ginstall \
--with-sed=gsed \
--with-awk=gawk \
--with-grep=ggrep
I have not yet tested that this patch works flawlessly on Linux using default
./configure options. I'd like to submit the following patch for testing.
Regards,
Fabian Freyer
- ---
Makefile.in | 5 +-
configure.ac | 6 +
scripts/crosstool-NG.sh.in | 6 +-
scripts/functions | 1395 --------------------------------------------
scripts/functions.in | 1395 ++++++++++++++++++++++++++++++++++++++++++++
scripts/xldd.in | 2 +-
6 files changed, 1409 insertions(+), 1400 deletions(-)
delete mode 100644 scripts/functions
create mode 100644 scripts/functions.in
diff --git a/Makefile.in b/Makefile.in
index 01759b6..cd68baa 100644
- --- a/Makefile.in
+++ b/Makefile.in
@@ -59,7 +59,7 @@ export datarootdir := @datarootdir@
export install := @INSTALL@
export bash := @_BASH@
export awk := @_AWK@
- -export grep := @GREP@
+export grep := @_GREP@
export make := @MAKE@
export sed := @SED@
export libtool := @LIBTOOL@
@@ -142,6 +142,7 @@ uninstall: real-uninstall
# Build rules
build-bin: $(PROG_NAME) \
+ scripts/functions \
scripts/crosstool-NG.sh \
scripts/saveSample.sh \
scripts/showTuple.sh
@@ -174,6 +175,8 @@ define sed_it
-e 's,@@CT_make@@,$(make),g;' \
-e 's,@@CT_bash@@,$(bash),g;' \
-e 's,@@CT_awk@@,$(awk),g;' \
+ -e 's,@@CT_grep@@,$(grep),g;' \
+ -e 's,@@CT_sed@@,$(sed),g;' \
$< >$@
endef
diff --git a/configure.ac b/configure.ac
index f8c67be..27238ab 100644
- --- a/configure.ac
+++ b/configure.ac
@@ -94,6 +94,12 @@ AC_ARG_WITH([install],
[Specify the full PATH to a BSD-compatible install]),
[INSTALL=$withval])
AC_PROG_INSTALL
+AC_CACHE_VAL([ac_cv_path_GREP],
+ [AC_ARG_WITH([grep],
+ AS_HELP_STRING([--with-grep=PATH],
+ [Specify the full PATH to GNU grep]),
+ [ac_cv_path_GREP=$withval])])
+AC_SUBST([_GREP], [$ac_cv_path_GREP])
AC_PROG_GREP
AC_PROG_EGREP
AS_IF(
diff --git a/scripts/crosstool-NG.sh.in b/scripts/crosstool-NG.sh.in
index 3699500..4b9011d 100644
- --- a/scripts/crosstool-NG.sh.in
+++ b/scripts/crosstool-NG.sh.in
@@ -125,7 +125,7 @@ CT_DoLog INFO "Build started ${CT_STAR_DATE_HUMAN}"
# We really need to extract from ,config and not .config.2, as we
# do want the kconfig's values, not our mangled config with arrays.
CT_DoStep DEBUG "Dumping user-supplied crosstool-NG configuration"
- -CT_DoExecLog DEBUG grep -E '^(# |)CT_' .config
+CT_DoExecLog DEBUG @@CT_grep@@ -E '^(# |)CT_' .config
CT_EndStep
CT_DoLog DEBUG "Unsetting and unexporting MAKEFLAGS"
@@ -570,9 +570,9 @@ if [ -z "${CT_RESTART}" ]; then
CT_DoLog EXTRA " build = ${CT_REAL_BUILD}"
CT_DoLog EXTRA " host = ${CT_REAL_HOST}"
CT_DoLog EXTRA " target = ${CT_TARGET}"
- - set |grep -E '^CT_.+=' |sort |CT_DoLog DEBUG
+ set |@@CT_grep@@ -E '^CT_.+=' |sort |CT_DoLog DEBUG
CT_DoLog DEBUG "Other environment:"
- - printenv |grep -v -E '^CT_.+=' |CT_DoLog DEBUG
+ printenv |@@CT_grep@@ -v -E '^CT_.+=' |CT_DoLog DEBUG
CT_EndStep
fi
diff --git a/scripts/functions b/scripts/functions
deleted file mode 100644
index 2e4d4fa..0000000
- --- a/scripts/functions
+++ /dev/null
@@ -1,1395 +0,0 @@
- -# This file contains some usefull common functions -*- sh -*-
- -# Copyright 2007 Yann E. MORIN
- -# Licensed under the GPL v2. See COPYING in the root of this package
- -
- -# Prepare the fault handler
- -CT_OnError() {
- - local ret=$?
- - local result
- - local old_trap
- - local intro
- - local file line func
- - local step step_depth
- -
- - # To avoid printing the backtace for each sub-shell
- - # up to the top-level, just remember we've dumped it
- - if [ ! -f "${CT_WORK_DIR}/backtrace" ]; then
- - touch "${CT_WORK_DIR}/backtrace"
- -
- - # Print steps backtrace
- - step_depth=${CT_STEP_COUNT}
- - CT_STEP_COUNT=1 # To have a zero-indentation
- - CT_DoLog ERROR ""
- - CT_DoLog ERROR ">>"
- - intro="Build failed"
- - for((step=step_depth; step>0; step--)); do
- - CT_DoLog ERROR ">> ${intro} in step '${CT_STEP_MESSAGE[${step}]}'"
- - intro=" called"
- - done
- -
- - # Print functions backtrace
- - intro="Error happened in"
- - CT_DoLog ERROR ">>"
- - for((depth=1; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
- - file="${BASH_SOURCE[${depth}]#${CT_LIB_DIR}/}"
- - func="${FUNCNAME[${depth}]}"
- - line="@${BASH_LINENO[${depth}-1]:-?}"
- - CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
- - intro=" called from"
- - done
- -
- - # If the user asked for interactive debugging, dump him/her to a shell
- - if [ "${CT_DEBUG_INTERACTIVE}" = "y" ]; then
- - # We do not want this sub-shell exit status to be caught, because
- - # it is absolutely legit that it exits with non-zero.
- - # Save the trap handler to restore it after our debug-shell
- - old_trap="$(trap -p ERR)"
- - trap -- ERR
- - (
- - exec >&6 2>&7 <&8
- - printf "\r \n\nCurrent command"
- - if [ -n "${cur_cmd}" ]; then
- - printf ":\n %s\n" "${cur_cmd}"
- - else
- - printf " (unknown), "
- - fi
- - printf "exited with error code: %d\n" ${ret}
- - printf "Please fix it up and finish by exiting the shell with one of these values:\n"
- - printf " 1 fixed, continue with next build command\n"
- - if [ -n "${cur_cmd}" ]; then
- - printf " 2 repeat this build command\n"
- - fi
- - printf " 3 abort build\n\n"
- - while true; do
- - ${bash} --rcfile <(printf "PS1='ct-ng:\w> '\nPROMPT_COMMAND=''\n") -i
- - result=$?
- - case $result in
- - 1) printf "\nContinuing past the failed command.\n\n"
- - break
- - ;;
- - 2) if [ -n "${cur_cmd}" ]; then
- - printf "\nRe-trying last command.\n\n"
- - break
- - fi
- - ;;
- - 3) break;;
- - esac
- - printf "\nPlease exit with one of these values:\n"
- - printf " 1 fixed, continue with next build command\n"
- - if [ -n "${cur_cmd}" ]; then
- - printf " 2 repeat this build command\n"
- - fi
- - printf " 3 abort build\n"
- - done
- - exit $result
- - )
- - result=$?
- - # Restore the trap handler
- - eval "${old_trap}"
- - case "${result}" in
- - 1) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/skip"; return;;
- - 2) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/repeat"; return;;
- - # 3 is an abort, continue...
- - esac
- - fi
- - fi
- -
- - # And finally, in top-level shell, print some hints
- - if [ ${BASH_SUBSHELL} -eq 0 ]; then
- - # Help diagnose the error
- - CT_STEP_COUNT=1 # To have a zero-indentation
- - CT_DoLog ERROR ">>"
- - if [ "${CT_LOG_TO_FILE}" = "y" ]; then
- - CT_DoLog ERROR ">> For more info on this error, look at the file: '${tmp_log_file#${CT_TOP_DIR}/}'"
- - fi
- - CT_DoLog ERROR ">> There is a list of known issues, some with workarounds, in:"
- - CT_DoLog ERROR ">> '${CT_DOC_DIR#${CT_TOP_DIR}/}/B - Known issues.txt'"
- -
- - CT_DoLog ERROR ""
- - CT_DoEnd ERROR
- - rm -f "${CT_WORK_DIR}/backtrace"
- - fi
- - exit $ret
- -}
- -
- -# Install the fault handler
- -trap CT_OnError ERR
- -
- -# Inherit the fault handler in subshells and functions
- -set -E
- -
- -# Make pipes fail on the _first_ failed command
- -# Not supported on bash < 3.x, but we need it, so drop the obsoleting bash-2.x
- -set -o pipefail
- -
- -# Don't hash commands' locations, and search every time it is requested.
- -# This is slow, but needed because of the static/shared core gcc which shall
- -# always match to shared if it exists, and only fallback to static if the
- -# shared is not found
- -set +o hashall
- -
- -# Log policy:
- -# - first of all, save stdout so we can see the live logs: fd #6
- -# (also save stdin and stderr for use by CT_DEBUG_INTERACTIVE)
- -exec 6>&1 7>&2 8<&0
- -# - then point stdout to the log file
- -tmp_log_file="${CT_TOP_DIR}/build.log"
- -rm -f "${tmp_log_file}"
- -exec >>"${tmp_log_file}"
- -
- -# The different log levels:
- -CT_LOG_LEVEL_ERROR=0
- -CT_LOG_LEVEL_WARN=1
- -CT_LOG_LEVEL_INFO=2
- -CT_LOG_LEVEL_EXTRA=3
- -CT_LOG_LEVEL_CFG=4
- -CT_LOG_LEVEL_FILE=5
- -CT_LOG_LEVEL_STATE=6
- -CT_LOG_LEVEL_ALL=7
- -CT_LOG_LEVEL_DEBUG=8
- -
- -# Make it easy to use \n and !
- -CR=$(printf "\n")
- -BANG='!'
- -
- -# A function to log what is happening
- -# Different log level are available:
- -# - ERROR: A serious, fatal error occurred
- -# - WARN: A non fatal, non serious error occurred, take your responsbility with the generated build
- -# - INFO: Informational messages
- -# - EXTRA: Extra informational messages
- -# - CFG: Output of various "./configure"-type scripts
- -# - FILE: File / archive unpacking.
- -# - STATE: State save & restore
- -# - ALL: Component's build messages
- -# - DEBUG: Internal debug messages
- -# Usage: CT_DoLog <level> [message]
- -# If message is empty, then stdin will be logged.
- -CT_DoLog() {
- - local max_level LEVEL level cur_l cur_L
- - local l
- - eval max_level="\${CT_LOG_LEVEL_${CT_LOG_LEVEL_MAX}}"
- - # Set the maximum log level to DEBUG if we have none
- - [ -z "${max_level}" ] && max_level=${CT_LOG_LEVEL_DEBUG}
- -
- - LEVEL="$1"; shift
- - eval level="\${CT_LOG_LEVEL_${LEVEL}}"
- -
- - if [ $# -eq 0 ]; then
- - cat -
- - else
- - printf "%s\n" "${*}"
- - fi |( IFS="${CR}" # We want the full lines, even leading spaces
- - _prog_bar_cpt=0
- - _prog_bar[0]='/'
- - _prog_bar[1]='-'
- - _prog_bar[2]='\'
- - _prog_bar[3]='|'
- - indent=$((2*CT_STEP_COUNT))
- - while read line; do
- - case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
- - y,*"warning:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
- - y,*"WARNING:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
- - *"error:"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
- - *"make["*"]: *** ["*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
- - *) cur_L="${LEVEL}"; cur_l="${level}";;
- - esac
- - # There will always be a log file (stdout, fd #1), be it /dev/null
- - printf "[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}"
- - if [ ${cur_l} -le ${max_level} ]; then
- - # Only print to console (fd #6) if log level is high enough.
- - printf "${CT_LOG_PROGRESS_BAR:+\r}[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}" >&6
- - fi
- - if [ "${CT_LOG_PROGRESS_BAR}" = "y" ]; then
- - printf "\r[%02d:%02d] %s " $((SECONDS/60)) $((SECONDS%60)) "${_prog_bar[$((_prog_bar_cpt/10))]}" >&6
- - _prog_bar_cpt=$(((_prog_bar_cpt+1)%40))
- - fi
- - done
- - )
- -
- - return 0
- -}
- -
- -# Execute an action, and log its messages
- -# It is possible to even log local variable assignments (a-la: var=val ./cmd opts)
- -# Usage: CT_DoExecLog <level> [VAR=val...] <command> [parameters...]
- -CT_DoExecLog() {
- - local level="$1"
- - local cur_cmd
- - local ret
- - shift
- - (
- - for i in "$@"; do
- - cur_cmd+="'${i}' "
- - done
- - while true; do
- - case "${1}" in
- - *=*) eval export "'${1}'"; shift;;
- - *) break;;
- - esac
- - done
- - # This while-loop goes hand-in-hand with the ERR trap handler:
- - # - if the command terminates successfully, then we hit the break
- - # statement, and we exit the loop
- - # - if the command terminates in error, then the ERR handler kicks
- - # in, then:
- - # - if the user did *not* ask for interactive debugging, the ERR
- - # handler exits, and we hit the end of the sub-shell
- - # - if the user did ask for interactive debugging, the ERR handler
- - # spawns a shell. Upon termination of this shell, the ERR handler
- - # examines the exit status of the shell:
- - # - if 1, the ERR handler returns; then we hit the else statement,
- - # then the break, and we exit the 'while' loop, to continue the
- - # build;
- - # - if 2, the ERR handler touches the repeat file, and returns;
- - # then we hit the if statement, and we loop for one more
- - # iteration;
- - # - if 3, the ERR handler exits with the command's exit status,
- - # and we're dead;
- - # - for any other exit status of the shell, the ERR handler
- - # prints an informational message, and respawns the shell
- - #
- - # This allows a user to get an interactive shell that has the same
- - # environment (PATH and so on) that the failed command was ran with.
- - while true; do
- - rm -f "${CT_BUILD_DIR}/repeat"
- - CT_DoLog DEBUG "==> Executing: ${cur_cmd}"
- - "${@}" 2>&1 |CT_DoLog "${level}"
- - ret="${?}"
- - if [ -f "${CT_BUILD_DIR}/repeat" ]; then
- - rm -f "${CT_BUILD_DIR}/repeat"
- - continue
- - elif [ -f "${CT_BUILD_DIR}/skip" ]; then
- - rm -f "${CT_BUILD_DIR}/skip"
- - ret=0
- - break
- - else
- - break
- - fi
- - done
- - exit ${ret}
- - )
- - # Catch failure of the sub-shell
- - [ $? -eq 0 ]
- -}
- -
- -# Tail message to be logged whatever happens
- -# Usage: CT_DoEnd <level>
- -CT_DoEnd()
- -{
- - local level="$1"
- - CT_STOP_DATE=$(CT_DoDate +%s%N)
- - CT_STOP_DATE_HUMAN=$(CT_DoDate +%Y%m%d.%H%M%S)
- - if [ "${level}" != "ERROR" ]; then
- - CT_DoLog "${level:-INFO}" "Build completed at ${CT_STOP_DATE_HUMAN}"
- - fi
- - elapsed=$((CT_STOP_DATE-CT_STAR_DATE))
- - elapsed_min=$((elapsed/(60*1000*1000*1000)))
- - elapsed_sec=$(printf "%02d" $(((elapsed%(60*1000*1000*1000))/(1000*1000*1000))))
- - elapsed_csec=$(printf "%02d" $(((elapsed%(1000*1000*1000))/(10*1000*1000))))
- - CT_DoLog ${level:-INFO} "(elapsed: ${elapsed_min}:${elapsed_sec}.${elapsed_csec})"
- -}
- -
- -# Remove entries referring to . and other relative paths
- -# Usage: CT_SanitizePath
- -CT_SanitizePath() {
- - local new
- - local p
- - local IFS=:
- - for p in $PATH; do
- - # Only accept absolute paths;
- - # Note: as a special case the empty string in PATH is equivalent to .
- - if [ -n "${p}" -a -z "${p%%/*}" ]; then
- - new="${new}${new:+:}${p}"
- - fi
- - done
- - PATH="${new}"
- -}
- -
- -# Sanitise the directory name contained in the variable passed as argument:
- -# - remove duplicate /
- -# Usage: CT_SanitiseVarDir CT_PREFIX_DIR
- -CT_SanitiseVarDir() {
- - local var
- - local old_dir
- - local new_dir
- -
- - for var in "$@"; do
- - eval "old_dir=\"\${${var}}\""
- - new_dir="$( printf "${old_dir}" \
- - |sed -r -e 's:/+:/:g;' \
- - )"
- - eval "${var}=\"${new_dir}\""
- - CT_DoLog DEBUG "Sanitised '${var}': '${old_dir}' -> '${new_dir}'"
- - done
- -}
- -
- -# Abort the execution with an error message
- -# Usage: CT_Abort <message>
- -CT_Abort() {
- - CT_DoLog ERROR "$1"
- - false
- -}
- -
- -# Test a condition, and print a message if satisfied
- -# Usage: CT_Test <message> <tests>
- -CT_Test() {
- - local ret
- - local m="$1"
- - shift
- - CT_DoLog DEBUG "Testing '! ( $* )'"
- - test "$@" && CT_DoLog WARN "$m"
- - return 0
- -}
- -
- -# Test a condition, and abort with an error message if satisfied
- -# Usage: CT_TestAndAbort <message> <tests>
- -CT_TestAndAbort() {
- - local m="$1"
- - shift
- - CT_DoLog DEBUG "Testing '! ( $* )'"
- - test "$@" && CT_Abort "$m"
- - return 0
- -}
- -
- -# Test a condition, and abort with an error message if not satisfied
- -# Usage: CT_TestAndAbort <message> <tests>
- -CT_TestOrAbort() {
- - local m="$1"
- - shift
- - CT_DoLog DEBUG "Testing '$*'"
- - test "$@" || CT_Abort "$m"
- - return 0
- -}
- -
- -# Test the presence of a tool, or abort if not found
- -# Usage: CT_HasOrAbort <tool>
- -CT_HasOrAbort() {
- - CT_TestAndAbort "'${1}' not found and needed for successful toolchain build." -z "$(CT_Which "${1}")"
- - return 0
- -}
- -
- -# Search a program: wrap "which" for those system where "which"
- -# verbosely says there is no match (such as on Mandriva).
- -# Usage: CT_Which <filename>
- -CT_Which() {
- - which "$1" 2>/dev/null || true
- -}
- -
- -# Get current date with nanosecond precision
- -# On those system not supporting nanosecond precision, faked with rounding down
- -# to the highest entire second
- -# Usage: CT_DoDate <fmt>
- -CT_DoDate() {
- - date "$1" |sed -r -e 's/%?N$/000000000/;'
- -}
- -
- -CT_STEP_COUNT=1
- -CT_STEP_MESSAGE[${CT_STEP_COUNT}]="(top-level)"
- -# Memorise a step being done so that any error is caught
- -# Usage: CT_DoStep <loglevel> <message>
- -CT_DoStep() {
- - local start=$(CT_DoDate +%s%N)
- - CT_DoLog "$1" "================================================================="
- - CT_DoLog "$1" "$2"
- - CT_STEP_COUNT=$((CT_STEP_COUNT+1))
- - CT_STEP_LEVEL[${CT_STEP_COUNT}]="$1"; shift
- - CT_STEP_START[${CT_STEP_COUNT}]="${start}"
- - CT_STEP_MESSAGE[${CT_STEP_COUNT}]="$1"
- - return 0
- -}
- -
- -# End the step just being done
- -# Usage: CT_EndStep
- -CT_EndStep() {
- - local stop=$(CT_DoDate +%s%N)
- - local duration=$(printf "%032d" $((stop-${CT_STEP_START[${CT_STEP_COUNT}]})) |sed -r -e 's/([[:digit:]]{2})[[:digit:]]{7}$/\.\1/; s/^0+//; s/^\./0\./;')
- - local elapsed=$(printf "%02d:%02d" $((SECONDS/60)) $((SECONDS%60)))
- - local level="${CT_STEP_LEVEL[${CT_STEP_COUNT}]}"
- - local message="${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}"
- - CT_STEP_COUNT=$((CT_STEP_COUNT-1))
- - CT_DoLog "${level}" "${message}: done in ${duration}s (at ${elapsed})"
- - return 0
- -}
- -
- -# Pushes into a directory, and pops back
- -CT_Pushd() {
- - CT_DoLog DEBUG "Entering '$1'"
- - pushd "$1" >/dev/null 2>&1
- -}
- -CT_Popd() {
- - popd >/dev/null 2>&1
- -}
- -
- -# Create a dir and cd or pushd into it
- -# Usage: CT_mkdir_cd <dir/to/create>
- -# CT_mkdir_pushd <dir/to/create>
- -CT_mkdir_cd() {
- - local dir="${1}"
- -
- - mkdir -p "${dir}"
- - cd "${dir}"
- -}
- -CT_mkdir_pushd() {
- - local dir="${1}"
- -
- - mkdir -p "${dir}"
- - CT_Pushd "${dir}"
- -}
- -
- -# Creates a temporary directory
- -# $1: variable to assign to
- -# Usage: CT_MktempDir foo
- -CT_MktempDir() {
- - # Some mktemp do not allow more than 6 Xs
- - eval "$1"=$(mktemp -q -d "${CT_BUILD_DIR}/tmp.XXXXXX")
- - CT_TestOrAbort "Could not make temporary directory" -n "${!1}" -a -d "${!1}"
- - CT_DoLog DEBUG "Made temporary directory '${!1}'"
- - return 0
- -}
- -
- -# Removes one or more directories, even if it is read-only, or its parent is
- -# Usage: CT_DoForceRmdir dir [...]
- -CT_DoForceRmdir() {
- - local dir
- - local mode
- - for dir in "${@}"; do
- - [ -d "${dir}" ] || continue
- - case "$CT_SYS_OS" in
- - Linux|CYGWIN*)
- - mode="$(stat -c '%a' "$(dirname "${dir}")")"
- - ;;
- - Darwin|*BSD)
- - mode="$(stat -f '%Lp' "$(dirname "${dir}")")"
- - ;;
- - *)
- - CT_Abort "Unhandled host OS $CT_SYS_OS"
- - ;;
- - esac
- - CT_DoExecLog ALL chmod u+w "$(dirname "${dir}")"
- - CT_DoExecLog ALL chmod -R u+w "${dir}"
- - CT_DoExecLog ALL rm -rf "${dir}"
- - CT_DoExecLog ALL chmod ${mode} "$(dirname "${dir}")"
- - done
- -}
- -
- -# Echoes the specified string on stdout until the pipe breaks.
- -# Doesn't fail
- -# $1: string to echo
- -# Usage: CT_DoYes "" |make oldconfig
- -CT_DoYes() {
- - yes "$1" || true
- -}
- -
- -# Add the specified directory to LD_LIBRARY_PATH, and export it
- -# If the specified patch is already present, just export
- -# $1: path to add
- -# $2: add as 'first' or 'last' path, 'first' is assumed if $2 is empty
- -# Usage CT_SetLibPath /some/where/lib [first|last]
- -CT_SetLibPath() {
- - local path="$1"
- - local pos="$2"
- -
- - case ":${LD_LIBRARY_PATH}:" in
- - *:"${path}":*) ;;
- - *) case "${pos}" in
- - last)
- - CT_DoLog DEBUG "Adding '${path}' at end of LD_LIBRARY_PATH"
- - LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${path}"
- - ;;
- - first|"")
- - CT_DoLog DEBUG "Adding '${path}' at start of LD_LIBRARY_PATH"
- - LD_LIBRARY_PATH="${path}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
- - ;;
- - *)
- - CT_Abort "Incorrect position '${pos}' to add '${path}' to LD_LIBRARY_PATH"
- - ;;
- - esac
- - ;;
- - esac
- - CT_DoLog DEBUG "==> LD_LIBRARY_PATH='${LD_LIBRARY_PATH}'"
- - export LD_LIBRARY_PATH
- -}
- -
- -# Build up the list of allowed tarball extensions
- -# Add them in the prefered order; most preferred comes first
- -CT_DoListTarballExt() {
- - if [ "${CT_CONFIGURE_has_xz}" = "y" ]; then
- - printf ".tar.xz\n"
- - fi
- - if [ "${CT_CONFIGURE_has_lzma}" = "y" \
- - -o "${CT_CONFIGURE_has_xz}" = "y" ]; then
- - printf ".tar.lzma\n"
- - fi
- - printf ".tar.bz2\n"
- - printf ".tar.gz\n.tgz\n"
- - printf ".tar\n"
- - printf ".zip\n"
- -}
- -
- -# Get the file name extension of a component
- -# Usage: CT_GetFileExtension <component_name-component_version> [extension]
- -# If found, echoes the extension to stdout, and return 0
- -# If not found, echoes nothing on stdout, and return !0.
- -CT_GetFileExtension() {
- - local ext
- - local file="$1"
- - shift
- - local first_ext="$1"
- -
- - # we need to also check for an empty extension for those very
- - # peculiar components that don't have one (such as sstrip from
- - # buildroot).
- - for ext in ${first_ext} $(CT_DoListTarballExt) /.git ''; do
- - if [ -e "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
- - echo "${ext}"
- - exit 0
- - fi
- - done
- -
- - exit 1
- -}
- -
- -# Try to retrieve the specified URL (HTTP or FTP)
- -# Usage: CT_DoGetFile <URL>
- -# This functions always returns true (0), as it can be legitimate not
- -# to find the requested URL (think about snapshots, different layouts
- -# for different gcc versions, etc...).
- -CT_DoGetFile() {
- - local url="${1}"
- - local dest="${CT_TARBALLS_DIR}/${url##*/}"
- - local tmp="${dest}.tmp-dl"
- -
- - # Remove potential left-over from a previous run
- - rm -f "${tmp}"
- -
- - # We also retry a few times, in case there is a transient error (eg. behind
- - # a dynamic IP that changes during the transfer...)
- - # With automated download as we are doing, it can be very dangerous to
- - # continue the downloads. It's far better to simply overwrite the
- - # destination file.
- - # Some company networks have firewalls to connect to the internet, but it's
- - # not easy to detect them, so force a global ${CT_CONNECT_TIMEOUT}-second
- - # timeout.
- - if [ ${CT_CONNECT_TIMEOUT} = -1 ]; then
- - T=
- - else
- - T="-T ${CT_CONNECT_TIMEOUT}"
- - fi
- - if CT_DoExecLog ALL wget --passive-ftp --tries=3 -nc \
- - --progress=dot:binary \
- - ${T} \
- - -O "${tmp}" \
- - "${url}"
- - then
- - # Success, we got it, good!
- - mv "${tmp}" "${dest}"
- - CT_DoLog DEBUG "Got it from: \"${url}\""
- - else
- - # Woops...
- - rm -f "${tmp}"
- - CT_DoLog DEBUG "Not at this location: \"${url}\""
- - fi
- -}
- -
- -# This function tries to retrieve a tarball form a local directory
- -# Usage: CT_GetLocal <basename> [.extension]
- -CT_GetLocal() {
- - local basename="$1"
- - local first_ext="$2"
- - local ext
- -
- - # Do we already have it in *our* tarballs dir?
- - if ext="$( CT_GetFileExtension "${basename}" ${first_ext} )"; then
- - CT_DoLog DEBUG "Already have '${basename}'"
- - return 0
- - fi
- -
- - if [ -n "${CT_LOCAL_TARBALLS_DIR}" ]; then
- - CT_DoLog DEBUG "Trying to retrieve an already downloaded copy of '${basename}'"
- - # We'd rather have a bzip2'ed tarball, then gzipped tarball, plain tarball,
- - # or, as a failover, a file without extension.
- - for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
- - CT_DoLog DEBUG "Trying '${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}'"
- - if [ -r "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" -a \
- - "${CT_FORCE_DOWNLOAD}" != "y" ]; then
- - CT_DoLog DEBUG "Got '${basename}' from local storage"
- - CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" "${CT_TARBALLS_DIR}/${basename}${ext}"
- - return 0
- - fi
- - done
- - fi
- - return 1
- -}
- -
- -# This function gets the custom source from either a tarball or directory
- -# Usage: CT_GetCustom <component> <custom_version> <custom_location>
- -CT_GetCustom() {
- - local custom_component="$1"
- - local custom_version="$2"
- - local custom_location="$3"
- - local custom_name="${custom_component}-${custom_version}"
- -
- - CT_TestAndAbort "${custom_name}: CT_CUSTOM_LOCATION_ROOT_DIR or ${custom_component}'s CUSTOM_LOCATION must be set." \
- - -z "${CT_CUSTOM_LOCATION_ROOT_DIR}" -a -z "${custom_location}"
- -
- - if [ -n "${CT_CUSTOM_LOCATION_ROOT_DIR}" \
- - -a -z "${custom_location}" ]; then
- - custom_location="${CT_CUSTOM_LOCATION_ROOT_DIR}/${custom_component}"
- - fi
- -
- - CT_DoLog EXTRA "Using '${custom_name}' from custom location"
- - if [ ! -d "${custom_location}" ]; then
- - # We need to know the custom tarball extension,
- - # so we can create a properly-named symlink, which
- - # we use later on in 'extract'
- - case "${custom_location}" in
- - *.tar.xz) custom_name="${custom_name}.tar.xz";;
- - *.tar.bz2) custom_name="${custom_name}.tar.bz2";;
- - *.tar.gz|*.tgz) custom_name="${custom_name}.tar.gz";;
- - *.tar) custom_name="${custom_name}.tar";;
- - *) CT_Abort "Unknown extension for custom tarball '${custom_location}'";;
- - esac
- - CT_DoExecLog DEBUG ln -sf "${custom_location}" \
- - "${CT_TARBALLS_DIR}/${custom_name}"
- - else
- - CT_DoExecLog DEBUG ln -snf "${custom_location}" \
- - "${CT_SRC_DIR}/${custom_name}"
- - fi
- -}
- -
- -# This function saves the specified to local storage if possible,
- -# and if so, symlinks it for later usage
- -# Usage: CT_SaveLocal </full/path/file.name>
- -CT_SaveLocal() {
- - local file="$1"
- - local basename="${file##*/}"
- -
- - if [ "${CT_SAVE_TARBALLS}" = "y" ]; then
- - CT_DoLog EXTRA "Saving '${basename}' to local storage"
- - # The file may already exist if downloads are forced: remove it first
- - CT_DoExecLog ALL rm -f "${CT_LOCAL_TARBALLS_DIR}/${basename}"
- - CT_DoExecLog ALL mv -f "${file}" "${CT_LOCAL_TARBALLS_DIR}"
- - CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}" "${file}"
- - fi
- -}
- -
- -# Download the file from one of the URLs passed as argument
- -# Usage: CT_GetFile <basename> [.extension] <url> [url ...]
- -CT_GetFile() {
- - local ext
- - local -a URLS
- - local url
- - local file="$1"
- - local first_ext
- - shift
- - # If next argument starts with a dot, then this is not an URL,
- - # and we can consider that it is a preferred extension.
- - case "$1" in
- - .*) first_ext="$1"
- - shift
- - ;;
- - esac
- -
- - # Does it exist localy?
- - if CT_GetLocal "${file}" ${first_ext}; then
- - return 0
- - fi
- - # No, it does not...
- -
- - # If not allowed to download from the Internet, don't
- - if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
- - CT_DoLog DEBUG "Not allowed to download from the Internet, aborting ${file} download"
- - return 1
- - fi
- -
- - # Try to retrieve the file
- - CT_DoLog EXTRA "Retrieving '${file}'"
- -
- - # Add URLs on the LAN mirror
- - if [ "${CT_USE_MIRROR}" = "y" ]; then
- - CT_TestOrAbort "Please set the mirror base URL" -n "${CT_MIRROR_BASE_URL}"
- - URLS+=( "${CT_MIRROR_BASE_URL}/${file%-*}" )
- - URLS+=( "${CT_MIRROR_BASE_URL}" )
- - fi
- -
- - if [ "${CT_FORCE_MIRROR}" != "y" ]; then
- - URLS+=( "${@}" )
- - fi
- -
- - # Scan all URLs in turn, and try to grab a tarball from there
- - # Do *not* try git trees (ext=/.git), this is handled in a specific
- - # wrapper, below
- - for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
- - # Try all urls in turn
- - for url in "${URLS[@]}"; do
- - [ -n "${url}" ] || continue
- - CT_DoLog DEBUG "Trying '${url}/${file}${ext}'"
- - CT_DoGetFile "${url}/${file}${ext}"
- - if [ -f "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
- - CT_DoLog DEBUG "Got '${file}' from the Internet"
- - CT_SaveLocal "${CT_TARBALLS_DIR}/${file}${ext}"
- - return 0
- - fi
- - done
- - done
- -
- - # Just return error, someone may want to catch and handle the error
- - # (eg. glibc/eglibc add-ons can be missing).
- - return 1
- -}
- -
- -# Checkout from CVS, and build the associated tarball
- -# The tarball will be called ${basename}.tar.bz2
- -# Prerequisite: either the server does not require password,
- -# or the user must already be logged in.
- -# 'tag' is the tag to retrieve. Must be specified, but can be empty.
- -# If dirname is specified, then module will be renamed to dirname
- -# prior to building the tarball.
- -# Usage: CT_GetCVS <basename> <url> <module> <tag> [dirname[=subdir]]
- -# Note: if '=subdir' is given, then it is used instead of 'module'.
- -CT_GetCVS() {
- - local basename="$1"
- - local uri="$2"
- - local module="$3"
- - local tag="${4:+-r ${4}}"
- - local dirname="$5"
- - local tmp_dir
- -
- - # First try locally, then the mirror
- - if CT_GetFile "${basename}"; then
- - # Got it! Return early! :-)
- - return 0
- - fi
- -
- - if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
- - CT_DoLog WARN "Downloads forbidden, not trying cvs retrieval"
- - return 1
- - fi
- -
- - CT_MktempDir tmp_dir
- - CT_Pushd "${tmp_dir}"
- -
- - CT_DoExecLog ALL cvs -z 9 -d "${uri}" co -P ${tag} "${module}"
- - if [ -n "${dirname}" ]; then
- - case "${dirname}" in
- - *=*)
- - CT_DoExecLog DEBUG mv "${dirname#*=}" "${dirname%%=*}"
- - CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname%%=*}"
- - ;;
- - *)
- - CT_DoExecLog ALL mv "${module}" "${dirname}"
- - CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname:-${module}}"
- - ;;
- - esac
- - fi
- - CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
- -
- - CT_Popd
- - CT_DoExecLog ALL rm -rf "${tmp_dir}"
- -}
- -
- -# Check out from SVN, and build the associated tarball
- -# The tarball will be called ${basename}.tar.bz2
- -# Prerequisite: either the server does not require password,
- -# or the user must already be logged in.
- -# 'rev' is the revision to retrieve
- -# Usage: CT_GetSVN <basename> <url> [rev]
- -CT_GetSVN() {
- - local basename="$1"
- - local uri="$2"
- - local rev="$3"
- -
- - # First try locally, then the mirror
- - if CT_GetFile "${basename}"; then
- - # Got it! Return early! :-)
- - return 0
- - fi
- -
- - if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
- - CT_DoLog WARN "Downloads forbidden, not trying svn retrieval"
- - return 1
- - fi
- -
- - CT_MktempDir tmp_dir
- - CT_Pushd "${tmp_dir}"
- -
- - if ! CT_DoExecLog ALL svn export ${rev:+-r ${rev}} "${uri}" "${basename}"; then
- - CT_DoLog WARN "Could not retrieve '${basename}'"
- - return 1
- - fi
- - CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${basename}"
- - CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
- -
- - CT_Popd
- - CT_DoExecLog ALL rm -rf "${tmp_dir}"
- -}
- -
- -# Clone a git tree
- -# Tries the given URLs in turn until one can get cloned. No tarball will be created.
- -# Prerequisites: either the server does not require password,
- -# or the user has already taken any action to authenticate to the server.
- -# The cloned tree will *not* be stored in the local tarballs dir!
- -# Usage: CT_GetGit <basename> <cset> <url>
- -CT_GetGit() {
- - local basename="${1}"
- - local cset="${2}"
- - local url="${3}"
- - local file="${basename}-${cset}.tar.gz"
- - local dir="${CT_TARBALLS_DIR}/${basename}-${cset}.git"
- - local dest="${CT_TARBALLS_DIR}/${file}"
- - local tmp="${CT_TARBALLS_DIR}/${file}.tmp-dl"
- -
- - # Do we alreadyhave it?
- - if CT_GetLocal "${file}"; then
- - return 0
- - fi
- - # Nope...
- -
- - if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
- - CT_DoLog WARN "Downloads forbidden, not trying git retrieval"
- - return 1
- - fi
- -
- - # Add URLs on the LAN mirror
- - # We subvert the normal download method, just to look for
- - # looking at the local mirror
- - if CT_GetFile "${basename}-${cset}" .tar.gz; then
- - return 0
- - fi
- -
- - CT_DoLog EXTRA "Retrieving '${basename}-${cset}' (git)"
- -
- - # Remove potential left-over from a previous run
- - CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
- -
- - if CT_DoExecLog ALL git clone "${url}" "${dir}"; then
- - # Yep, cloned OK
- - CT_Pushd "${dir}"
- - CT_DoExecLog ALL git archive --format=tar \
- - --prefix="${basename}-${cset}/" \
- - -o "${tmp}.tar" \
- - "${cset}"
- - CT_DoExecLog ALL gzip -9 "${tmp}.tar"
- - CT_DoExecLog ALL mv -f "${tmp}.tar.gz" "${dest}"
- - CT_SaveLocal "${dest}"
- - CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
- - CT_Popd
- - else
- - # Woops...
- - CT_DoExecLog ALL rm -rf "${dir}"
- - CT_DoLog Debug "Could not clone '${basename}'"
- - return 1
- - fi
- -}
- -
- -# Extract a tarball
- -# Some tarballs need to be extracted in specific places. Eg.: glibc addons
- -# must be extracted in the glibc directory; uCLibc locales must be extracted
- -# in the extra/locale sub-directory of uClibc. This is taken into account
- -# by the caller, that did a 'cd' into the correct path before calling us
- -# and sets nochdir to 'nochdir'.
- -# Note also that this function handles the git trees!
- -# Usage: CT_Extract [nochdir] <basename> [options]
- -# where 'options' are dependent on the source (eg. git branch/tag...)
- -CT_Extract() {
- - local nochdir="$1"
- - local basename
- - local ext
- - local lzma_prog
- - local -a tar_opts
- -
- - if [ "${nochdir}" = "nochdir" ]; then
- - shift
- - nochdir="$(pwd)"
- - else
- - nochdir="${CT_SRC_DIR}"
- - fi
- -
- - basename="$1"
- - shift
- -
- - if ! ext="$(CT_GetFileExtension "${basename}")"; then
- - CT_DoLog WARN "'${basename}' not found in '${CT_TARBALLS_DIR}'"
- - return 1
- - fi
- - local full_file="${CT_TARBALLS_DIR}/${basename}${ext}"
- -
- - # Check if already extracted
- - if [ -e "${CT_SRC_DIR}/.${basename}.extracted" ]; then
- - CT_DoLog DEBUG "Already extracted '${basename}'"
- - return 0
- - fi
- -
- - # Check if previously partially extracted
- - if [ -e "${CT_SRC_DIR}/.${basename}.extracting" ]; then
- - CT_DoLog ERROR "The '${basename}' sources were partially extracted."
- - CT_DoLog ERROR "Please remove first:"
- - CT_DoLog ERROR " - the source dir for '${basename}', in '${CT_SRC_DIR}'"
- - CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${basename}.extracting'"
- - CT_Abort "I'll stop now to avoid any carnage..."
- - fi
- - CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracting"
- -
- - CT_Pushd "${nochdir}"
- -
- - CT_DoLog EXTRA "Extracting '${basename}'"
- - CT_DoExecLog FILE mkdir -p "${basename}"
- - tar_opts=( "--strip-components=1" )
- - tar_opts+=( "-C" "${basename}" )
- - tar_opts+=( "-xv" )
- -
- - # One note here:
- - # - lzma can be handled either with 'xz' or 'lzma'
- - # - we get lzma tarball only if either or both are available
- - # - so, if we get an lzma tarball, and either 'xz' or 'lzma' is
- - # missing, we can assume the other is available
- - if [ "${CT_CONFIGURE_has_lzma}" = "y" ]; then
- - lzma_prog="lzma -fdc"
- - else
- - lzma_prog="xz -fdc"
- - fi
- - case "${ext}" in
- - .tar.xz) xz -fdc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
- - .tar.lzma) ${lzma_prog} "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
- - .tar.bz2) bzip2 -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
- - .tar.gz|.tgz) gzip -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
- - .tar) CT_DoExecLog FILE tar "${tar_opts[@]}" -f "${full_file}";;
- - .zip) CT_DoExecLog FILE unzip "${@}" "${full_file}";;
- - /.git) CT_ExtractGit "${basename}" "${@}";;
- - *) CT_DoLog WARN "Don't know how to handle '${basename}${ext}': unknown extension"
- - return 1
- - ;;
- - esac
- -
- - # Don't mark as being extracted for git
- - case "${ext}" in
- - /.git) ;;
- - *) CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracted";;
- - esac
- - CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${basename}.extracting"
- -
- - CT_Popd
- -}
- -
- -# Create a working git clone of a local git repository
- -# Usage: CT_ExtractGit <basename> [ref]
- -# where 'ref' is the reference to use:
- -# the full name of a branch, like "remotes/origin/branch_name"
- -# a date as understandable by git, like "YYYY-MM-DD[ hh[:mm[:ss]]]"
- -# a tag name
- -# If 'ref' is not given, the current repository HEAD will be used
- -CT_ExtractGit() {
- - local basename="${1}"
- - local ref="${2}"
- - local repo
- - local ref_type
- -
- - # pushd now to be able to get git revlist in case ref is a date
- - repo="${CT_TARBALLS_DIR}/${basename}"
- - CT_Pushd "${repo}"
- -
- - # What kind of reference is ${ref} ?
- - if [ -z "${ref}" ]; then
- - ref_type=head
- - ref=$(git rev-list -n1 HEAD)
- - elif git tag |grep -E "^${ref}$" >/dev/null 2>&1; then
- - ref_type=tag
- - elif git branch -a --no-color |grep -E "^. ${ref}$" >/dev/null 2>&1; then
- - ref_type=branch
- - elif date -d "${ref}" >/dev/null 2>&1; then
- - ref_type=date
- - ref=$(git rev-list -n1 --before="${ref}")
- - else
- - CT_Abort "Reference '${ref}' is an incorrect git reference: neither tag, branch nor date"
- - fi
- -
- - CT_Popd
- -
- - CT_DoExecLog FILE rmdir "${basename}"
- - case "${ref_type}" in
- - branch) CT_DoExecLog FILE git clone -b "${ref}" "${repo}" "${basename}" ;;
- - *) CT_DoExecLog FILE git clone "${repo}" "${basename}"
- - CT_Pushd "${basename}"
- - CT_DoExecLog FILE git checkout "${ref}"
- - CT_Popd
- - ;;
- - esac
- -}
- -
- -# Patches the specified component
- -# See CT_Extract, above, for explanations on 'nochdir'
- -# Usage: CT_Patch [nochdir] <packagename> <packageversion>
- -# If the package directory is *not* packagename-packageversion, then
- -# the caller must cd into the proper directory first, and call us
- -# with nochdir
- -CT_Patch() {
- - local nochdir="$1"
- - local pkgname
- - local version
- - local pkgdir
- - local base_file
- - local ver_file
- - local d
- - local -a patch_dirs
- - local bundled_patch_dir
- - local local_patch_dir
- - local bundled_exp_patch_dir
- - local local_exp_patch_dir
- -
- - if [ "${nochdir}" = "nochdir" ]; then
- - shift
- - pkgname="$1"
- - version="$2"
- - pkgdir="${pkgname}-${version}"
- - nochdir="$(pwd)"
- - else
- - pkgname="$1"
- - version="$2"
- - pkgdir="${pkgname}-${version}"
- - nochdir="${CT_SRC_DIR}/${pkgdir}"
- - fi
- -
- - # Check if already patched
- - if [ -e "${CT_SRC_DIR}/.${pkgdir}.patched" ]; then
- - CT_DoLog DEBUG "Already patched '${pkgdir}'"
- - return 0
- - fi
- -
- - # Check if already partially patched
- - if [ -e "${CT_SRC_DIR}/.${pkgdir}.patching" ]; then
- - CT_DoLog ERROR "The '${pkgdir}' sources were partially patched."
- - CT_DoLog ERROR "Please remove first:"
- - CT_DoLog ERROR " - the source dir for '${pkgdir}', in '${CT_SRC_DIR}'"
- - CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.extracted'"
- - CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.patching'"
- - CT_Abort "I'll stop now to avoid any carnage..."
- - fi
- - touch "${CT_SRC_DIR}/.${pkgdir}.patching"
- -
- - CT_Pushd "${nochdir}"
- -
- - CT_DoLog EXTRA "Patching '${pkgdir}'"
- -
- - bundled_patch_dir="${CT_LIB_DIR}/patches/${pkgname}/${version}"
- - local_patch_dir="${CT_LOCAL_PATCH_DIR}/${pkgname}/${version}"
- -
- - # Check for experimental patches, if enabled.
- - if [ "${CT_EXPERIMENTAL_PATCHES}" = "y" ]; then
- - bundled_exp_patch_dir="${CT_LIB_DIR}/patches/experimental/${pkgname}/${version}"
- - local_exp_patch_dir="${CT_LOCAL_PATCH_DIR}/experimental/${pkgname}/${version}"
- - fi
- -
- - case "${CT_PATCH_ORDER}" in
- - bundled) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
- - local) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}");;
- - bundled,local) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}" "${local_patch_dir}" "${local_exp_patch_dir}");;
- - local,bundled) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}" "${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
- - none) patch_dirs=;;
- - esac
- -
- - for d in "${patch_dirs[@]}"; do
- - CT_DoLog DEBUG "Looking for patches in '${d}'..."
- - if [ -n "${d}" -a -d "${d}" ]; then
- - for p in "${d}"/*.patch; do
- - if [ -f "${p}" ]; then
- - CT_DoExecLog ALL patch --no-backup-if-mismatch -g0 -F1 -p1 -f -i "${p}"
- - fi
- - done
- - if [ "${CT_PATCH_SINGLE}" = "y" ]; then
- - break
- - fi
- - fi
- - done
- -
- - if [ "${CT_OVERIDE_CONFIG_GUESS_SUB}" = "y" ]; then
- - CT_DoLog ALL "Overiding config.guess and config.sub"
- - for cfg in config_guess config_sub; do
- - eval ${cfg}="${CT_LIB_DIR}/scripts/${cfg/_/.}"
- - [ -e "${CT_TOP_DIR}/scripts/${cfg/_/.}" ] && eval ${cfg}="${CT_TOP_DIR}/scripts/${cfg/_/.}"
- - # Can't use CT_DoExecLog because of the '{} \;' to be passed un-mangled to find
- - find . -type f -name "${cfg/_/.}" -exec cp -v "${!cfg}" {} \; |CT_DoLog ALL
- - done
- - fi
- -
- - CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${pkgdir}.patched"
- - CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${pkgdir}.patching"
- -
- - CT_Popd
- -}
- -
- -# Two wrappers to call config.(guess|sub) either from CT_TOP_DIR or CT_LIB_DIR.
- -# Those from CT_TOP_DIR, if they exist, will be be more recent than those from CT_LIB_DIR.
- -CT_DoConfigGuess() {
- - if [ -x "${CT_TOP_DIR}/scripts/config.guess" ]; then
- - "${CT_TOP_DIR}/scripts/config.guess"
- - else
- - "${CT_LIB_DIR}/scripts/config.guess"
- - fi
- -}
- -
- -CT_DoConfigSub() {
- - if [ -x "${CT_TOP_DIR}/scripts/config.sub" ]; then
- - "${CT_TOP_DIR}/scripts/config.sub" "$@"
- - else
- - "${CT_LIB_DIR}/scripts/config.sub" "$@"
- - fi
- -}
- -
- -# Compute the target tuple from what is provided by the user
- -# Usage: CT_DoBuildTargetTuple
- -# In fact this function takes the environment variables to build the target
- -# tuple. It is needed both by the normal build sequence, as well as the
- -# sample saving sequence.
- -CT_DoBuildTargetTuple() {
- - # Set the endianness suffix, and the default endianness gcc option
- - case "${CT_ARCH_ENDIAN}" in
- - big)
- - target_endian_eb=eb
- - target_endian_be=be
- - target_endian_el=
- - target_endian_le=
- - CT_ARCH_ENDIAN_CFLAG="-mbig-endian"
- - CT_ARCH_ENDIAN_LDFLAG="-Wl,-EB"
- - ;;
- - little)
- - target_endian_eb=
- - target_endian_be=
- - target_endian_el=el
- - target_endian_le=le
- - CT_ARCH_ENDIAN_CFLAG="-mlittle-endian"
- - CT_ARCH_ENDIAN_LDFLAG="-Wl,-EL"
- - ;;
- - esac
- -
- - # Set the bitness suffix
- - case "${CT_ARCH_BITNESS}" in
- - 32)
- - target_bits_32=32
- - target_bits_64=
- - ;;
- - 64)
- - target_bits_32=
- - target_bits_64=64
- - ;;
- - esac
- -
- - # Build the default architecture tuple part
- - CT_TARGET_ARCH="${CT_ARCH}${CT_ARCH_SUFFIX}"
- -
- - # Set defaults for the system part of the tuple. Can be overriden
- - # by architecture-specific values.
- - case "${CT_LIBC}" in
- - *glibc) CT_TARGET_SYS=gnu;;
- - uClibc) CT_TARGET_SYS=uclibc;;
- - *) CT_TARGET_SYS=elf;;
- - esac
- -
- - # Set the default values for ARCH, ABI, CPU, TUNE, FPU and FLOAT
- - unset CT_ARCH_ARCH_CFLAG CT_ARCH_ABI_CFLAG CT_ARCH_CPU_CFLAG CT_ARCH_TUNE_CFLAG CT_ARCH_FPU_CFLAG CT_ARCH_FLOAT_CFLAG
- - unset CT_ARCH_WITH_ARCH CT_ARCH_WITH_ABI CT_ARCH_WITH_CPU CT_ARCH_WITH_TUNE CT_ARCH_WITH_FPU CT_ARCH_WITH_FLOAT
- - [ "${CT_ARCH_ARCH}" ] && { CT_ARCH_ARCH_CFLAG="-march=${CT_ARCH_ARCH}"; CT_ARCH_WITH_ARCH="--with-arch=${CT_ARCH_ARCH}"; }
- - [ "${CT_ARCH_ABI}" ] && { CT_ARCH_ABI_CFLAG="-mabi=${CT_ARCH_ABI}"; CT_ARCH_WITH_ABI="--with-abi=${CT_ARCH_ABI}"; }
- - [ "${CT_ARCH_CPU}" ] && { CT_ARCH_CPU_CFLAG="-mcpu=${CT_ARCH_CPU}"; CT_ARCH_WITH_CPU="--with-cpu=${CT_ARCH_CPU}"; }
- - [ "${CT_ARCH_TUNE}" ] && { CT_ARCH_TUNE_CFLAG="-mtune=${CT_ARCH_TUNE}"; CT_ARCH_WITH_TUNE="--with-tune=${CT_ARCH_TUNE}"; }
- - [ "${CT_ARCH_FPU}" ] && { CT_ARCH_FPU_CFLAG="-mfpu=${CT_ARCH_FPU}"; CT_ARCH_WITH_FPU="--with-fpu=${CT_ARCH_FPU}"; }
- -
- - case "${CT_ARCH_FLOAT}" in
- - hard)
- - CT_ARCH_FLOAT_CFLAG="-mhard-float"
- - CT_ARCH_WITH_FLOAT="--with-float=hard"
- - ;;
- - soft)
- - CT_ARCH_FLOAT_CFLAG="-msoft-float"
- - CT_ARCH_WITH_FLOAT="--with-float=soft"
- - ;;
- - softfp)
- - CT_ARCH_FLOAT_CFLAG="-mfloat-abi=softfp"
- - CT_ARCH_WITH_FLOAT="--with-float=softfp"
- - ;;
- - esac
- -
- - # Build the default kernel tuple part
- - CT_TARGET_KERNEL="${CT_KERNEL}"
- -
- - # Overide the default values with the components specific settings
- - CT_DoArchTupleValues
- - CT_DoKernelTupleValues
- -
- - # Finish the target tuple construction
- - CT_TARGET="${CT_TARGET_ARCH}"
- - CT_TARGET="${CT_TARGET}${CT_TARGET_VENDOR:+-${CT_TARGET_VENDOR}}"
- - CT_TARGET="${CT_TARGET}${CT_TARGET_KERNEL:+-${CT_TARGET_KERNEL}}"
- - CT_TARGET="${CT_TARGET}${CT_TARGET_SYS:+-${CT_TARGET_SYS}}"
- -
- - # Sanity checks
- - __sed_alias=""
- - if [ -n "${CT_TARGET_ALIAS_SED_EXPR}" ]; then
- - __sed_alias=$(echo "${CT_TARGET}" |sed -r -e "${CT_TARGET_ALIAS_SED_EXPR}")
- - fi
- - case ":${CT_TARGET_VENDOR}:${CT_TARGET_ALIAS}:${__sed_alias}:" in
- - :*" "*:*:*:) CT_Abort "Don't use spaces in the vendor string, it breaks things.";;
- - :*"-"*:*:*:) CT_Abort "Don't use dashes in the vendor string, it breaks things.";;
- - :*:*" "*:*:) CT_Abort "Don't use spaces in the target alias, it breaks things.";;
- - :*:*:*" "*:) CT_Abort "Don't use spaces in the target sed transform, it breaks things.";;
- - esac
- -
- - # Canonicalise it
- - CT_TARGET=$(CT_DoConfigSub "${CT_TARGET}")
- - # Prepare the target CFLAGS
- - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ENDIAN_CFLAG}"
- - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ARCH_CFLAG}"
- - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ABI_CFLAG}"
- - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_CPU_CFLAG}"
- - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_TUNE_CFLAG}"
- - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FPU_CFLAG}"
- - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FLOAT_CFLAG}"
- -
- - # Now on for the target LDFLAGS
- - CT_ARCH_TARGET_LDFLAGS="${CT_ARCH_TARGET_LDFLAGS} ${CT_ARCH_ENDIAN_LDFLAG}"
- -}
- -
- -# This function does pause the build until the user strikes "Return"
- -# Usage: CT_DoPause [optional_message]
- -CT_DoPause() {
- - local foo
- - local message="${1:-Pausing for your pleasure}"
- - CT_DoLog INFO "${message}"
- - read -p "Press 'Enter' to continue, or Ctrl-C to stop..." foo >&6
- - return 0
- -}
- -
- -# This function creates a tarball of the specified directory, but
- -# only if it exists
- -# Usage: CT_DoTarballIfExists <dir> <tarball_basename> [extra_tar_options [...]]
- -CT_DoTarballIfExists() {
- - local dir="$1"
- - local tarball="$2"
- - shift 2
- - local -a extra_tar_opts=( "$@" )
- - local -a compress
- -
- - case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
- - y) compress=( gzip -c -3 - ); tar_ext=.gz;;
- - *) compress=( cat - ); tar_ext=;;
- - esac
- -
- - if [ -d "${dir}" ]; then
- - CT_DoLog DEBUG " Saving '${dir}'"
- - { tar c -C "${dir}" -v -f - "${extra_tar_opts[@]}" . \
- - |"${compress[@]}" >"${tarball}.tar${tar_ext}" ;
- - } 2>&1 |sed -r -e 's/^/ /;' |CT_DoLog STATE
- - else
- - CT_DoLog STATE " Not saving '${dir}': does not exist"
- - fi
- -}
- -
- -# This function extracts a tarball to the specified directory, but
- -# only if the tarball exists
- -# Usage: CT_DoExtractTarballIfExists <tarball_basename> <dir> [extra_tar_options [...]]
- -CT_DoExtractTarballIfExists() {
- - local tarball="$1"
- - local dir="$2"
- - shift 2
- - local -a extra_tar_opts=( "$@" )
- - local -a uncompress
- -
- - case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
- - y) uncompress=( gzip -c -d ); tar_ext=.gz;;
- - *) uncompress=( cat ); tar_ext=;;
- - esac
- -
- - if [ -f "${tarball}.tar${tar_ext}" ]; then
- - CT_DoLog DEBUG " Restoring '${dir}'"
- - CT_DoForceRmdir "${dir}"
- - CT_DoExecLog DEBUG mkdir -p "${dir}"
- - { "${uncompress[@]}" "${tarball}.tar${tar_ext}" \
- - |tar x -C "${dir}" -v -f - "${extra_tar_opts[@]}" ;
- - } 2>&1 |sed -r -e 's/^/ /;' |CT_DoLog STATE
- - else
- - CT_DoLog STATE " Not restoring '${dir}': does not exist"
- - fi
- -}
- -
- -# This function saves the state of the toolchain to be able to restart
- -# at any one point
- -# Usage: CT_DoSaveState <next_step_name>
- -CT_DoSaveState() {
- - [ "${CT_DEBUG_CT_SAVE_STEPS}" = "y" ] || return 0
- - local state_name="$1"
- - local state_dir="${CT_STATE_DIR}/${state_name}"
- -
- - # Log this to the log level required by the user
- - CT_DoLog ${CT_LOG_LEVEL_MAX} "Saving state to restart at step '${state_name}'..."
- -
- - rm -rf "${state_dir}"
- - mkdir -p "${state_dir}"
- -
- - CT_DoLog STATE " Saving environment and aliases"
- - # We must omit shell functions, and some specific bash variables
- - # that break when restoring the environment, later. We could do
- - # all the processing in the awk script, but a sed is easier...
- - set |awk '
- - BEGIN { _p = 1; }
- - $0~/^[^ ]+ \(\)/ { _p = 0; }
- - _p == 1
- - $0 == "}" { _p = 1; }
- - ' |sed -r -e '/^BASH_(ARGC|ARGV|LINENO|SOURCE|VERSINFO)=/d;
- - /^(UID|EUID)=/d;
- - /^(FUNCNAME|GROUPS|PPID|SHELLOPTS)=/d;' >"${state_dir}/env.sh"
- -
- - CT_DoTarballIfExists "${CT_BUILDTOOLS_PREFIX_DIR}" "${state_dir}/buildtools_dir"
- - CT_DoTarballIfExists "${CT_CONFIG_DIR}" "${state_dir}/config_dir"
- - CT_DoTarballIfExists "${CT_PREFIX_DIR}" "${state_dir}/prefix_dir" --exclude '*.log'
- -
- - CT_DoLog STATE " Saving log file"
- - exec >/dev/null
- - case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
- - y) gzip -3 -c "${tmp_log_file}" >"${state_dir}/log.gz";;
- - *) cat "${tmp_log_file}" >"${state_dir}/log";;
- - esac
- - exec >>"${tmp_log_file}"
- -}
- -
- -# This function restores a previously saved state
- -# Usage: CT_DoLoadState <state_name>
- -CT_DoLoadState(){
- - local state_name="$1"
- - local state_dir="${CT_STATE_DIR}/${state_name}"
- - local old_RESTART="${CT_RESTART}"
- - local old_STOP="${CT_STOP}"
- -
- - CT_TestOrAbort "The previous build did not reach the point where it could be restarted at '${CT_RESTART}'" -d "${state_dir}"
- -
- - # We need to do something special with the log file!
- - if [ "${CT_LOG_TO_FILE}" = "y" ]; then
- - exec >"${state_dir}/tail.log"
- - fi
- -
- - # Log this to the log level required by the user
- - CT_DoLog ${CT_LOG_LEVEL_MAX} "Restoring state at step '${state_name}', as requested."
- -
- - CT_DoExtractTarballIfExists "${state_dir}/prefix_dir" "${CT_PREFIX_DIR}"
- - CT_DoExtractTarballIfExists "${state_dir}/config_dir" "${CT_CONFIG_DIR}"
- - CT_DoExtractTarballIfExists "${state_dir}/buildtools_dir" "${CT_BUILDTOOLS_PREFIX_DIR}"
- -
- - # Restore the environment, discarding any error message
- - # (for example, read-only bash internals)
- - CT_DoLog STATE " Restoring environment"
- - . "${state_dir}/env.sh" >/dev/null 2>&1 || true
- -
- - # Restore the new RESTART and STOP steps
- - CT_RESTART="${old_RESTART}"
- - CT_STOP="${old_STOP}"
- - unset old_stop old_restart
- -
- - CT_DoLog STATE " Restoring log file"
- - exec >/dev/null
- - case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
- - y) gzip -dc "${state_dir}/log.gz" >"${tmp_log_file}";;
- - *) cat "${state_dir}/log" >"${tmp_log_file}";;
- - esac
- - cat "${state_dir}/tail.log" >>"${tmp_log_file}"
- - exec >>"${tmp_log_file}"
- - rm -f "${state_dir}/tail.log"
- -}
diff --git a/scripts/functions.in b/scripts/functions.in
new file mode 100644
index 0000000..51bf4a1
- --- /dev/null
+++ b/scripts/functions.in
@@ -0,0 +1,1395 @@
+# This file contains some usefull common functions -*- sh -*-
+# Copyright 2007 Yann E. MORIN
+# Licensed under the GPL v2. See COPYING in the root of this package
+
+# Prepare the fault handler
+CT_OnError() {
+ local ret=$?
+ local result
+ local old_trap
+ local intro
+ local file line func
+ local step step_depth
+
+ # To avoid printing the backtace for each sub-shell
+ # up to the top-level, just remember we've dumped it
+ if [ ! -f "${CT_WORK_DIR}/backtrace" ]; then
+ touch "${CT_WORK_DIR}/backtrace"
+
+ # Print steps backtrace
+ step_depth=${CT_STEP_COUNT}
+ CT_STEP_COUNT=1 # To have a zero-indentation
+ CT_DoLog ERROR ""
+ CT_DoLog ERROR ">>"
+ intro="Build failed"
+ for((step=step_depth; step>0; step--)); do
+ CT_DoLog ERROR ">> ${intro} in step '${CT_STEP_MESSAGE[${step}]}'"
+ intro=" called"
+ done
+
+ # Print functions backtrace
+ intro="Error happened in"
+ CT_DoLog ERROR ">>"
+ for((depth=1; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
+ file="${BASH_SOURCE[${depth}]#${CT_LIB_DIR}/}"
+ func="${FUNCNAME[${depth}]}"
+ line="@${BASH_LINENO[${depth}-1]:-?}"
+ CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
+ intro=" called from"
+ done
+
+ # If the user asked for interactive debugging, dump him/her to a shell
+ if [ "${CT_DEBUG_INTERACTIVE}" = "y" ]; then
+ # We do not want this sub-shell exit status to be caught, because
+ # it is absolutely legit that it exits with non-zero.
+ # Save the trap handler to restore it after our debug-shell
+ old_trap="$(trap -p ERR)"
+ trap -- ERR
+ (
+ exec >&6 2>&7 <&8
+ printf "\r \n\nCurrent command"
+ if [ -n "${cur_cmd}" ]; then
+ printf ":\n %s\n" "${cur_cmd}"
+ else
+ printf " (unknown), "
+ fi
+ printf "exited with error code: %d\n" ${ret}
+ printf "Please fix it up and finish by exiting the shell with one of these values:\n"
+ printf " 1 fixed, continue with next build command\n"
+ if [ -n "${cur_cmd}" ]; then
+ printf " 2 repeat this build command\n"
+ fi
+ printf " 3 abort build\n\n"
+ while true; do
+ ${bash} --rcfile <(printf "PS1='ct-ng:\w> '\nPROMPT_COMMAND=''\n") -i
+ result=$?
+ case $result in
+ 1) printf "\nContinuing past the failed command.\n\n"
+ break
+ ;;
+ 2) if [ -n "${cur_cmd}" ]; then
+ printf "\nRe-trying last command.\n\n"
+ break
+ fi
+ ;;
+ 3) break;;
+ esac
+ printf "\nPlease exit with one of these values:\n"
+ printf " 1 fixed, continue with next build command\n"
+ if [ -n "${cur_cmd}" ]; then
+ printf " 2 repeat this build command\n"
+ fi
+ printf " 3 abort build\n"
+ done
+ exit $result
+ )
+ result=$?
+ # Restore the trap handler
+ eval "${old_trap}"
+ case "${result}" in
+ 1) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/skip"; return;;
+ 2) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/repeat"; return;;
+ # 3 is an abort, continue...
+ esac
+ fi
+ fi
+
+ # And finally, in top-level shell, print some hints
+ if [ ${BASH_SUBSHELL} -eq 0 ]; then
+ # Help diagnose the error
+ CT_STEP_COUNT=1 # To have a zero-indentation
+ CT_DoLog ERROR ">>"
+ if [ "${CT_LOG_TO_FILE}" = "y" ]; then
+ CT_DoLog ERROR ">> For more info on this error, look at the file: '${tmp_log_file#${CT_TOP_DIR}/}'"
+ fi
+ CT_DoLog ERROR ">> There is a list of known issues, some with workarounds, in:"
+ CT_DoLog ERROR ">> '${CT_DOC_DIR#${CT_TOP_DIR}/}/B - Known issues.txt'"
+
+ CT_DoLog ERROR ""
+ CT_DoEnd ERROR
+ rm -f "${CT_WORK_DIR}/backtrace"
+ fi
+ exit $ret
+}
+
+# Install the fault handler
+trap CT_OnError ERR
+
+# Inherit the fault handler in subshells and functions
+set -E
+
+# Make pipes fail on the _first_ failed command
+# Not supported on bash < 3.x, but we need it, so drop the obsoleting bash-2.x
+set -o pipefail
+
+# Don't hash commands' locations, and search every time it is requested.
+# This is slow, but needed because of the static/shared core gcc which shall
+# always match to shared if it exists, and only fallback to static if the
+# shared is not found
+set +o hashall
+
+# Log policy:
+# - first of all, save stdout so we can see the live logs: fd #6
+# (also save stdin and stderr for use by CT_DEBUG_INTERACTIVE)
+exec 6>&1 7>&2 8<&0
+# - then point stdout to the log file
+tmp_log_file="${CT_TOP_DIR}/build.log"
+rm -f "${tmp_log_file}"
+exec >>"${tmp_log_file}"
+
+# The different log levels:
+CT_LOG_LEVEL_ERROR=0
+CT_LOG_LEVEL_WARN=1
+CT_LOG_LEVEL_INFO=2
+CT_LOG_LEVEL_EXTRA=3
+CT_LOG_LEVEL_CFG=4
+CT_LOG_LEVEL_FILE=5
+CT_LOG_LEVEL_STATE=6
+CT_LOG_LEVEL_ALL=7
+CT_LOG_LEVEL_DEBUG=8
+
+# Make it easy to use \n and !
+CR=$(printf "\n")
+BANG='!'
+
+# A function to log what is happening
+# Different log level are available:
+# - ERROR: A serious, fatal error occurred
+# - WARN: A non fatal, non serious error occurred, take your responsbility with the generated build
+# - INFO: Informational messages
+# - EXTRA: Extra informational messages
+# - CFG: Output of various "./configure"-type scripts
+# - FILE: File / archive unpacking.
+# - STATE: State save & restore
+# - ALL: Component's build messages
+# - DEBUG: Internal debug messages
+# Usage: CT_DoLog <level> [message]
+# If message is empty, then stdin will be logged.
+CT_DoLog() {
+ local max_level LEVEL level cur_l cur_L
+ local l
+ eval max_level="\${CT_LOG_LEVEL_${CT_LOG_LEVEL_MAX}}"
+ # Set the maximum log level to DEBUG if we have none
+ [ -z "${max_level}" ] && max_level=${CT_LOG_LEVEL_DEBUG}
+
+ LEVEL="$1"; shift
+ eval level="\${CT_LOG_LEVEL_${LEVEL}}"
+
+ if [ $# -eq 0 ]; then
+ cat -
+ else
+ printf "%s\n" "${*}"
+ fi |( IFS="${CR}" # We want the full lines, even leading spaces
+ _prog_bar_cpt=0
+ _prog_bar[0]='/'
+ _prog_bar[1]='-'
+ _prog_bar[2]='\'
+ _prog_bar[3]='|'
+ indent=$((2*CT_STEP_COUNT))
+ while read line; do
+ case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
+ y,*"warning:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
+ y,*"WARNING:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
+ *"error:"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
+ *"make["*"]: *** ["*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
+ *) cur_L="${LEVEL}"; cur_l="${level}";;
+ esac
+ # There will always be a log file (stdout, fd #1), be it /dev/null
+ printf "[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}"
+ if [ ${cur_l} -le ${max_level} ]; then
+ # Only print to console (fd #6) if log level is high enough.
+ printf "${CT_LOG_PROGRESS_BAR:+\r}[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}" >&6
+ fi
+ if [ "${CT_LOG_PROGRESS_BAR}" = "y" ]; then
+ printf "\r[%02d:%02d] %s " $((SECONDS/60)) $((SECONDS%60)) "${_prog_bar[$((_prog_bar_cpt/10))]}" >&6
+ _prog_bar_cpt=$(((_prog_bar_cpt+1)%40))
+ fi
+ done
+ )
+
+ return 0
+}
+
+# Execute an action, and log its messages
+# It is possible to even log local variable assignments (a-la: var=val ./cmd opts)
+# Usage: CT_DoExecLog <level> [VAR=val...] <command> [parameters...]
+CT_DoExecLog() {
+ local level="$1"
+ local cur_cmd
+ local ret
+ shift
+ (
+ for i in "$@"; do
+ cur_cmd+="'${i}' "
+ done
+ while true; do
+ case "${1}" in
+ *=*) eval export "'${1}'"; shift;;
+ *) break;;
+ esac
+ done
+ # This while-loop goes hand-in-hand with the ERR trap handler:
+ # - if the command terminates successfully, then we hit the break
+ # statement, and we exit the loop
+ # - if the command terminates in error, then the ERR handler kicks
+ # in, then:
+ # - if the user did *not* ask for interactive debugging, the ERR
+ # handler exits, and we hit the end of the sub-shell
+ # - if the user did ask for interactive debugging, the ERR handler
+ # spawns a shell. Upon termination of this shell, the ERR handler
+ # examines the exit status of the shell:
+ # - if 1, the ERR handler returns; then we hit the else statement,
+ # then the break, and we exit the 'while' loop, to continue the
+ # build;
+ # - if 2, the ERR handler touches the repeat file, and returns;
+ # then we hit the if statement, and we loop for one more
+ # iteration;
+ # - if 3, the ERR handler exits with the command's exit status,
+ # and we're dead;
+ # - for any other exit status of the shell, the ERR handler
+ # prints an informational message, and respawns the shell
+ #
+ # This allows a user to get an interactive shell that has the same
+ # environment (PATH and so on) that the failed command was ran with.
+ while true; do
+ rm -f "${CT_BUILD_DIR}/repeat"
+ CT_DoLog DEBUG "==> Executing: ${cur_cmd}"
+ "${@}" 2>&1 |CT_DoLog "${level}"
+ ret="${?}"
+ if [ -f "${CT_BUILD_DIR}/repeat" ]; then
+ rm -f "${CT_BUILD_DIR}/repeat"
+ continue
+ elif [ -f "${CT_BUILD_DIR}/skip" ]; then
+ rm -f "${CT_BUILD_DIR}/skip"
+ ret=0
+ break
+ else
+ break
+ fi
+ done
+ exit ${ret}
+ )
+ # Catch failure of the sub-shell
+ [ $? -eq 0 ]
+}
+
+# Tail message to be logged whatever happens
+# Usage: CT_DoEnd <level>
+CT_DoEnd()
+{
+ local level="$1"
+ CT_STOP_DATE=$(CT_DoDate +%s%N)
+ CT_STOP_DATE_HUMAN=$(CT_DoDate +%Y%m%d.%H%M%S)
+ if [ "${level}" != "ERROR" ]; then
+ CT_DoLog "${level:-INFO}" "Build completed at ${CT_STOP_DATE_HUMAN}"
+ fi
+ elapsed=$((CT_STOP_DATE-CT_STAR_DATE))
+ elapsed_min=$((elapsed/(60*1000*1000*1000)))
+ elapsed_sec=$(printf "%02d" $(((elapsed%(60*1000*1000*1000))/(1000*1000*1000))))
+ elapsed_csec=$(printf "%02d" $(((elapsed%(1000*1000*1000))/(10*1000*1000))))
+ CT_DoLog ${level:-INFO} "(elapsed: ${elapsed_min}:${elapsed_sec}.${elapsed_csec})"
+}
+
+# Remove entries referring to . and other relative paths
+# Usage: CT_SanitizePath
+CT_SanitizePath() {
+ local new
+ local p
+ local IFS=:
+ for p in $PATH; do
+ # Only accept absolute paths;
+ # Note: as a special case the empty string in PATH is equivalent to .
+ if [ -n "${p}" -a -z "${p%%/*}" ]; then
+ new="${new}${new:+:}${p}"
+ fi
+ done
+ PATH="${new}"
+}
+
+# Sanitise the directory name contained in the variable passed as argument:
+# - remove duplicate /
+# Usage: CT_SanitiseVarDir CT_PREFIX_DIR
+CT_SanitiseVarDir() {
+ local var
+ local old_dir
+ local new_dir
+
+ for var in "$@"; do
+ eval "old_dir=\"\${${var}}\""
+ new_dir="$( printf "${old_dir}" \
+ |@@CT_sed@@ -r -e 's:/+:/:g;' \
+ )"
+ eval "${var}=\"${new_dir}\""
+ CT_DoLog DEBUG "Sanitised '${var}': '${old_dir}' -> '${new_dir}'"
+ done
+}
+
+# Abort the execution with an error message
+# Usage: CT_Abort <message>
+CT_Abort() {
+ CT_DoLog ERROR "$1"
+ false
+}
+
+# Test a condition, and print a message if satisfied
+# Usage: CT_Test <message> <tests>
+CT_Test() {
+ local ret
+ local m="$1"
+ shift
+ CT_DoLog DEBUG "Testing '! ( $* )'"
+ test "$@" && CT_DoLog WARN "$m"
+ return 0
+}
+
+# Test a condition, and abort with an error message if satisfied
+# Usage: CT_TestAndAbort <message> <tests>
+CT_TestAndAbort() {
+ local m="$1"
+ shift
+ CT_DoLog DEBUG "Testing '! ( $* )'"
+ test "$@" && CT_Abort "$m"
+ return 0
+}
+
+# Test a condition, and abort with an error message if not satisfied
+# Usage: CT_TestAndAbort <message> <tests>
+CT_TestOrAbort() {
+ local m="$1"
+ shift
+ CT_DoLog DEBUG "Testing '$*'"
+ test "$@" || CT_Abort "$m"
+ return 0
+}
+
+# Test the presence of a tool, or abort if not found
+# Usage: CT_HasOrAbort <tool>
+CT_HasOrAbort() {
+ CT_TestAndAbort "'${1}' not found and needed for successful toolchain build." -z "$(CT_Which "${1}")"
+ return 0
+}
+
+# Search a program: wrap "which" for those system where "which"
+# verbosely says there is no match (such as on Mandriva).
+# Usage: CT_Which <filename>
+CT_Which() {
+ which "$1" 2>/dev/null || true
+}
+
+# Get current date with nanosecond precision
+# On those system not supporting nanosecond precision, faked with rounding down
+# to the highest entire second
+# Usage: CT_DoDate <fmt>
+CT_DoDate() {
+ date "$1" |@@CT_sed@@ -r -e 's/%?N$/000000000/;'
+}
+
+CT_STEP_COUNT=1
+CT_STEP_MESSAGE[${CT_STEP_COUNT}]="(top-level)"
+# Memorise a step being done so that any error is caught
+# Usage: CT_DoStep <loglevel> <message>
+CT_DoStep() {
+ local start=$(CT_DoDate +%s%N)
+ CT_DoLog "$1" "================================================================="
+ CT_DoLog "$1" "$2"
+ CT_STEP_COUNT=$((CT_STEP_COUNT+1))
+ CT_STEP_LEVEL[${CT_STEP_COUNT}]="$1"; shift
+ CT_STEP_START[${CT_STEP_COUNT}]="${start}"
+ CT_STEP_MESSAGE[${CT_STEP_COUNT}]="$1"
+ return 0
+}
+
+# End the step just being done
+# Usage: CT_EndStep
+CT_EndStep() {
+ local stop=$(CT_DoDate +%s%N)
+ local duration=$(printf "%032d" $((stop-${CT_STEP_START[${CT_STEP_COUNT}]})) |@@CT_sed@@ -r -e 's/([[:digit:]]{2})[[:digit:]]{7}$/\.\1/; s/^0+//; s/^\./0\./;')
+ local elapsed=$(printf "%02d:%02d" $((SECONDS/60)) $((SECONDS%60)))
+ local level="${CT_STEP_LEVEL[${CT_STEP_COUNT}]}"
+ local message="${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}"
+ CT_STEP_COUNT=$((CT_STEP_COUNT-1))
+ CT_DoLog "${level}" "${message}: done in ${duration}s (at ${elapsed})"
+ return 0
+}
+
+# Pushes into a directory, and pops back
+CT_Pushd() {
+ CT_DoLog DEBUG "Entering '$1'"
+ pushd "$1" >/dev/null 2>&1
+}
+CT_Popd() {
+ popd >/dev/null 2>&1
+}
+
+# Create a dir and cd or pushd into it
+# Usage: CT_mkdir_cd <dir/to/create>
+# CT_mkdir_pushd <dir/to/create>
+CT_mkdir_cd() {
+ local dir="${1}"
+
+ mkdir -p "${dir}"
+ cd "${dir}"
+}
+CT_mkdir_pushd() {
+ local dir="${1}"
+
+ mkdir -p "${dir}"
+ CT_Pushd "${dir}"
+}
+
+# Creates a temporary directory
+# $1: variable to assign to
+# Usage: CT_MktempDir foo
+CT_MktempDir() {
+ # Some mktemp do not allow more than 6 Xs
+ eval "$1"=$(mktemp -q -d "${CT_BUILD_DIR}/tmp.XXXXXX")
+ CT_TestOrAbort "Could not make temporary directory" -n "${!1}" -a -d "${!1}"
+ CT_DoLog DEBUG "Made temporary directory '${!1}'"
+ return 0
+}
+
+# Removes one or more directories, even if it is read-only, or its parent is
+# Usage: CT_DoForceRmdir dir [...]
+CT_DoForceRmdir() {
+ local dir
+ local mode
+ for dir in "${@}"; do
+ [ -d "${dir}" ] || continue
+ case "$CT_SYS_OS" in
+ Linux|CYGWIN*)
+ mode="$(stat -c '%a' "$(dirname "${dir}")")"
+ ;;
+ Darwin|*BSD)
+ mode="$(stat -f '%Lp' "$(dirname "${dir}")")"
+ ;;
+ *)
+ CT_Abort "Unhandled host OS $CT_SYS_OS"
+ ;;
+ esac
+ CT_DoExecLog ALL chmod u+w "$(dirname "${dir}")"
+ CT_DoExecLog ALL chmod -R u+w "${dir}"
+ CT_DoExecLog ALL rm -rf "${dir}"
+ CT_DoExecLog ALL chmod ${mode} "$(dirname "${dir}")"
+ done
+}
+
+# Echoes the specified string on stdout until the pipe breaks.
+# Doesn't fail
+# $1: string to echo
+# Usage: CT_DoYes "" |make oldconfig
+CT_DoYes() {
+ yes "$1" || true
+}
+
+# Add the specified directory to LD_LIBRARY_PATH, and export it
+# If the specified patch is already present, just export
+# $1: path to add
+# $2: add as 'first' or 'last' path, 'first' is assumed if $2 is empty
+# Usage CT_SetLibPath /some/where/lib [first|last]
+CT_SetLibPath() {
+ local path="$1"
+ local pos="$2"
+
+ case ":${LD_LIBRARY_PATH}:" in
+ *:"${path}":*) ;;
+ *) case "${pos}" in
+ last)
+ CT_DoLog DEBUG "Adding '${path}' at end of LD_LIBRARY_PATH"
+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${path}"
+ ;;
+ first|"")
+ CT_DoLog DEBUG "Adding '${path}' at start of LD_LIBRARY_PATH"
+ LD_LIBRARY_PATH="${path}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
+ ;;
+ *)
+ CT_Abort "Incorrect position '${pos}' to add '${path}' to LD_LIBRARY_PATH"
+ ;;
+ esac
+ ;;
+ esac
+ CT_DoLog DEBUG "==> LD_LIBRARY_PATH='${LD_LIBRARY_PATH}'"
+ export LD_LIBRARY_PATH
+}
+
+# Build up the list of allowed tarball extensions
+# Add them in the prefered order; most preferred comes first
+CT_DoListTarballExt() {
+ if [ "${CT_CONFIGURE_has_xz}" = "y" ]; then
+ printf ".tar.xz\n"
+ fi
+ if [ "${CT_CONFIGURE_has_lzma}" = "y" \
+ -o "${CT_CONFIGURE_has_xz}" = "y" ]; then
+ printf ".tar.lzma\n"
+ fi
+ printf ".tar.bz2\n"
+ printf ".tar.gz\n.tgz\n"
+ printf ".tar\n"
+ printf ".zip\n"
+}
+
+# Get the file name extension of a component
+# Usage: CT_GetFileExtension <component_name-component_version> [extension]
+# If found, echoes the extension to stdout, and return 0
+# If not found, echoes nothing on stdout, and return !0.
+CT_GetFileExtension() {
+ local ext
+ local file="$1"
+ shift
+ local first_ext="$1"
+
+ # we need to also check for an empty extension for those very
+ # peculiar components that don't have one (such as sstrip from
+ # buildroot).
+ for ext in ${first_ext} $(CT_DoListTarballExt) /.git ''; do
+ if [ -e "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
+ echo "${ext}"
+ exit 0
+ fi
+ done
+
+ exit 1
+}
+
+# Try to retrieve the specified URL (HTTP or FTP)
+# Usage: CT_DoGetFile <URL>
+# This functions always returns true (0), as it can be legitimate not
+# to find the requested URL (think about snapshots, different layouts
+# for different gcc versions, etc...).
+CT_DoGetFile() {
+ local url="${1}"
+ local dest="${CT_TARBALLS_DIR}/${url##*/}"
+ local tmp="${dest}.tmp-dl"
+
+ # Remove potential left-over from a previous run
+ rm -f "${tmp}"
+
+ # We also retry a few times, in case there is a transient error (eg. behind
+ # a dynamic IP that changes during the transfer...)
+ # With automated download as we are doing, it can be very dangerous to
+ # continue the downloads. It's far better to simply overwrite the
+ # destination file.
+ # Some company networks have firewalls to connect to the internet, but it's
+ # not easy to detect them, so force a global ${CT_CONNECT_TIMEOUT}-second
+ # timeout.
+ if [ ${CT_CONNECT_TIMEOUT} = -1 ]; then
+ T=
+ else
+ T="-T ${CT_CONNECT_TIMEOUT}"
+ fi
+ if CT_DoExecLog ALL wget --passive-ftp --tries=3 -nc \
+ --progress=dot:binary \
+ ${T} \
+ -O "${tmp}" \
+ "${url}"
+ then
+ # Success, we got it, good!
+ mv "${tmp}" "${dest}"
+ CT_DoLog DEBUG "Got it from: \"${url}\""
+ else
+ # Woops...
+ rm -f "${tmp}"
+ CT_DoLog DEBUG "Not at this location: \"${url}\""
+ fi
+}
+
+# This function tries to retrieve a tarball form a local directory
+# Usage: CT_GetLocal <basename> [.extension]
+CT_GetLocal() {
+ local basename="$1"
+ local first_ext="$2"
+ local ext
+
+ # Do we already have it in *our* tarballs dir?
+ if ext="$( CT_GetFileExtension "${basename}" ${first_ext} )"; then
+ CT_DoLog DEBUG "Already have '${basename}'"
+ return 0
+ fi
+
+ if [ -n "${CT_LOCAL_TARBALLS_DIR}" ]; then
+ CT_DoLog DEBUG "Trying to retrieve an already downloaded copy of '${basename}'"
+ # We'd rather have a bzip2'ed tarball, then gzipped tarball, plain tarball,
+ # or, as a failover, a file without extension.
+ for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
+ CT_DoLog DEBUG "Trying '${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}'"
+ if [ -r "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" -a \
+ "${CT_FORCE_DOWNLOAD}" != "y" ]; then
+ CT_DoLog DEBUG "Got '${basename}' from local storage"
+ CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" "${CT_TARBALLS_DIR}/${basename}${ext}"
+ return 0
+ fi
+ done
+ fi
+ return 1
+}
+
+# This function gets the custom source from either a tarball or directory
+# Usage: CT_GetCustom <component> <custom_version> <custom_location>
+CT_GetCustom() {
+ local custom_component="$1"
+ local custom_version="$2"
+ local custom_location="$3"
+ local custom_name="${custom_component}-${custom_version}"
+
+ CT_TestAndAbort "${custom_name}: CT_CUSTOM_LOCATION_ROOT_DIR or ${custom_component}'s CUSTOM_LOCATION must be set." \
+ -z "${CT_CUSTOM_LOCATION_ROOT_DIR}" -a -z "${custom_location}"
+
+ if [ -n "${CT_CUSTOM_LOCATION_ROOT_DIR}" \
+ -a -z "${custom_location}" ]; then
+ custom_location="${CT_CUSTOM_LOCATION_ROOT_DIR}/${custom_component}"
+ fi
+
+ CT_DoLog EXTRA "Using '${custom_name}' from custom location"
+ if [ ! -d "${custom_location}" ]; then
+ # We need to know the custom tarball extension,
+ # so we can create a properly-named symlink, which
+ # we use later on in 'extract'
+ case "${custom_location}" in
+ *.tar.xz) custom_name="${custom_name}.tar.xz";;
+ *.tar.bz2) custom_name="${custom_name}.tar.bz2";;
+ *.tar.gz|*.tgz) custom_name="${custom_name}.tar.gz";;
+ *.tar) custom_name="${custom_name}.tar";;
+ *) CT_Abort "Unknown extension for custom tarball '${custom_location}'";;
+ esac
+ CT_DoExecLog DEBUG ln -sf "${custom_location}" \
+ "${CT_TARBALLS_DIR}/${custom_name}"
+ else
+ CT_DoExecLog DEBUG ln -snf "${custom_location}" \
+ "${CT_SRC_DIR}/${custom_name}"
+ fi
+}
+
+# This function saves the specified to local storage if possible,
+# and if so, symlinks it for later usage
+# Usage: CT_SaveLocal </full/path/file.name>
+CT_SaveLocal() {
+ local file="$1"
+ local basename="${file##*/}"
+
+ if [ "${CT_SAVE_TARBALLS}" = "y" ]; then
+ CT_DoLog EXTRA "Saving '${basename}' to local storage"
+ # The file may already exist if downloads are forced: remove it first
+ CT_DoExecLog ALL rm -f "${CT_LOCAL_TARBALLS_DIR}/${basename}"
+ CT_DoExecLog ALL mv -f "${file}" "${CT_LOCAL_TARBALLS_DIR}"
+ CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}" "${file}"
+ fi
+}
+
+# Download the file from one of the URLs passed as argument
+# Usage: CT_GetFile <basename> [.extension] <url> [url ...]
+CT_GetFile() {
+ local ext
+ local -a URLS
+ local url
+ local file="$1"
+ local first_ext
+ shift
+ # If next argument starts with a dot, then this is not an URL,
+ # and we can consider that it is a preferred extension.
+ case "$1" in
+ .*) first_ext="$1"
+ shift
+ ;;
+ esac
+
+ # Does it exist localy?
+ if CT_GetLocal "${file}" ${first_ext}; then
+ return 0
+ fi
+ # No, it does not...
+
+ # If not allowed to download from the Internet, don't
+ if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
+ CT_DoLog DEBUG "Not allowed to download from the Internet, aborting ${file} download"
+ return 1
+ fi
+
+ # Try to retrieve the file
+ CT_DoLog EXTRA "Retrieving '${file}'"
+
+ # Add URLs on the LAN mirror
+ if [ "${CT_USE_MIRROR}" = "y" ]; then
+ CT_TestOrAbort "Please set the mirror base URL" -n "${CT_MIRROR_BASE_URL}"
+ URLS+=( "${CT_MIRROR_BASE_URL}/${file%-*}" )
+ URLS+=( "${CT_MIRROR_BASE_URL}" )
+ fi
+
+ if [ "${CT_FORCE_MIRROR}" != "y" ]; then
+ URLS+=( "${@}" )
+ fi
+
+ # Scan all URLs in turn, and try to grab a tarball from there
+ # Do *not* try git trees (ext=/.git), this is handled in a specific
+ # wrapper, below
+ for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
+ # Try all urls in turn
+ for url in "${URLS[@]}"; do
+ [ -n "${url}" ] || continue
+ CT_DoLog DEBUG "Trying '${url}/${file}${ext}'"
+ CT_DoGetFile "${url}/${file}${ext}"
+ if [ -f "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
+ CT_DoLog DEBUG "Got '${file}' from the Internet"
+ CT_SaveLocal "${CT_TARBALLS_DIR}/${file}${ext}"
+ return 0
+ fi
+ done
+ done
+
+ # Just return error, someone may want to catch and handle the error
+ # (eg. glibc/eglibc add-ons can be missing).
+ return 1
+}
+
+# Checkout from CVS, and build the associated tarball
+# The tarball will be called ${basename}.tar.bz2
+# Prerequisite: either the server does not require password,
+# or the user must already be logged in.
+# 'tag' is the tag to retrieve. Must be specified, but can be empty.
+# If dirname is specified, then module will be renamed to dirname
+# prior to building the tarball.
+# Usage: CT_GetCVS <basename> <url> <module> <tag> [dirname[=subdir]]
+# Note: if '=subdir' is given, then it is used instead of 'module'.
+CT_GetCVS() {
+ local basename="$1"
+ local uri="$2"
+ local module="$3"
+ local tag="${4:+-r ${4}}"
+ local dirname="$5"
+ local tmp_dir
+
+ # First try locally, then the mirror
+ if CT_GetFile "${basename}"; then
+ # Got it! Return early! :-)
+ return 0
+ fi
+
+ if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
+ CT_DoLog WARN "Downloads forbidden, not trying cvs retrieval"
+ return 1
+ fi
+
+ CT_MktempDir tmp_dir
+ CT_Pushd "${tmp_dir}"
+
+ CT_DoExecLog ALL cvs -z 9 -d "${uri}" co -P ${tag} "${module}"
+ if [ -n "${dirname}" ]; then
+ case "${dirname}" in
+ *=*)
+ CT_DoExecLog DEBUG mv "${dirname#*=}" "${dirname%%=*}"
+ CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname%%=*}"
+ ;;
+ *)
+ CT_DoExecLog ALL mv "${module}" "${dirname}"
+ CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname:-${module}}"
+ ;;
+ esac
+ fi
+ CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
+
+ CT_Popd
+ CT_DoExecLog ALL rm -rf "${tmp_dir}"
+}
+
+# Check out from SVN, and build the associated tarball
+# The tarball will be called ${basename}.tar.bz2
+# Prerequisite: either the server does not require password,
+# or the user must already be logged in.
+# 'rev' is the revision to retrieve
+# Usage: CT_GetSVN <basename> <url> [rev]
+CT_GetSVN() {
+ local basename="$1"
+ local uri="$2"
+ local rev="$3"
+
+ # First try locally, then the mirror
+ if CT_GetFile "${basename}"; then
+ # Got it! Return early! :-)
+ return 0
+ fi
+
+ if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
+ CT_DoLog WARN "Downloads forbidden, not trying svn retrieval"
+ return 1
+ fi
+
+ CT_MktempDir tmp_dir
+ CT_Pushd "${tmp_dir}"
+
+ if ! CT_DoExecLog ALL svn export ${rev:+-r ${rev}} "${uri}" "${basename}"; then
+ CT_DoLog WARN "Could not retrieve '${basename}'"
+ return 1
+ fi
+ CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${basename}"
+ CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
+
+ CT_Popd
+ CT_DoExecLog ALL rm -rf "${tmp_dir}"
+}
+
+# Clone a git tree
+# Tries the given URLs in turn until one can get cloned. No tarball will be created.
+# Prerequisites: either the server does not require password,
+# or the user has already taken any action to authenticate to the server.
+# The cloned tree will *not* be stored in the local tarballs dir!
+# Usage: CT_GetGit <basename> <cset> <url>
+CT_GetGit() {
+ local basename="${1}"
+ local cset="${2}"
+ local url="${3}"
+ local file="${basename}-${cset}.tar.gz"
+ local dir="${CT_TARBALLS_DIR}/${basename}-${cset}.git"
+ local dest="${CT_TARBALLS_DIR}/${file}"
+ local tmp="${CT_TARBALLS_DIR}/${file}.tmp-dl"
+
+ # Do we alreadyhave it?
+ if CT_GetLocal "${file}"; then
+ return 0
+ fi
+ # Nope...
+
+ if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
+ CT_DoLog WARN "Downloads forbidden, not trying git retrieval"
+ return 1
+ fi
+
+ # Add URLs on the LAN mirror
+ # We subvert the normal download method, just to look for
+ # looking at the local mirror
+ if CT_GetFile "${basename}-${cset}" .tar.gz; then
+ return 0
+ fi
+
+ CT_DoLog EXTRA "Retrieving '${basename}-${cset}' (git)"
+
+ # Remove potential left-over from a previous run
+ CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
+
+ if CT_DoExecLog ALL git clone "${url}" "${dir}"; then
+ # Yep, cloned OK
+ CT_Pushd "${dir}"
+ CT_DoExecLog ALL git archive --format=tar \
+ --prefix="${basename}-${cset}/" \
+ -o "${tmp}.tar" \
+ "${cset}"
+ CT_DoExecLog ALL gzip -9 "${tmp}.tar"
+ CT_DoExecLog ALL mv -f "${tmp}.tar.gz" "${dest}"
+ CT_SaveLocal "${dest}"
+ CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
+ CT_Popd
+ else
+ # Woops...
+ CT_DoExecLog ALL rm -rf "${dir}"
+ CT_DoLog Debug "Could not clone '${basename}'"
+ return 1
+ fi
+}
+
+# Extract a tarball
+# Some tarballs need to be extracted in specific places. Eg.: glibc addons
+# must be extracted in the glibc directory; uCLibc locales must be extracted
+# in the extra/locale sub-directory of uClibc. This is taken into account
+# by the caller, that did a 'cd' into the correct path before calling us
+# and sets nochdir to 'nochdir'.
+# Note also that this function handles the git trees!
+# Usage: CT_Extract [nochdir] <basename> [options]
+# where 'options' are dependent on the source (eg. git branch/tag...)
+CT_Extract() {
+ local nochdir="$1"
+ local basename
+ local ext
+ local lzma_prog
+ local -a tar_opts
+
+ if [ "${nochdir}" = "nochdir" ]; then
+ shift
+ nochdir="$(pwd)"
+ else
+ nochdir="${CT_SRC_DIR}"
+ fi
+
+ basename="$1"
+ shift
+
+ if ! ext="$(CT_GetFileExtension "${basename}")"; then
+ CT_DoLog WARN "'${basename}' not found in '${CT_TARBALLS_DIR}'"
+ return 1
+ fi
+ local full_file="${CT_TARBALLS_DIR}/${basename}${ext}"
+
+ # Check if already extracted
+ if [ -e "${CT_SRC_DIR}/.${basename}.extracted" ]; then
+ CT_DoLog DEBUG "Already extracted '${basename}'"
+ return 0
+ fi
+
+ # Check if previously partially extracted
+ if [ -e "${CT_SRC_DIR}/.${basename}.extracting" ]; then
+ CT_DoLog ERROR "The '${basename}' sources were partially extracted."
+ CT_DoLog ERROR "Please remove first:"
+ CT_DoLog ERROR " - the source dir for '${basename}', in '${CT_SRC_DIR}'"
+ CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${basename}.extracting'"
+ CT_Abort "I'll stop now to avoid any carnage..."
+ fi
+ CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracting"
+
+ CT_Pushd "${nochdir}"
+
+ CT_DoLog EXTRA "Extracting '${basename}'"
+ CT_DoExecLog FILE mkdir -p "${basename}"
+ tar_opts=( "--strip-components=1" )
+ tar_opts+=( "-C" "${basename}" )
+ tar_opts+=( "-xv" )
+
+ # One note here:
+ # - lzma can be handled either with 'xz' or 'lzma'
+ # - we get lzma tarball only if either or both are available
+ # - so, if we get an lzma tarball, and either 'xz' or 'lzma' is
+ # missing, we can assume the other is available
+ if [ "${CT_CONFIGURE_has_lzma}" = "y" ]; then
+ lzma_prog="lzma -fdc"
+ else
+ lzma_prog="xz -fdc"
+ fi
+ case "${ext}" in
+ .tar.xz) xz -fdc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
+ .tar.lzma) ${lzma_prog} "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
+ .tar.bz2) bzip2 -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
+ .tar.gz|.tgz) gzip -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
+ .tar) CT_DoExecLog FILE tar "${tar_opts[@]}" -f "${full_file}";;
+ .zip) CT_DoExecLog FILE unzip "${@}" "${full_file}";;
+ /.git) CT_ExtractGit "${basename}" "${@}";;
+ *) CT_DoLog WARN "Don't know how to handle '${basename}${ext}': unknown extension"
+ return 1
+ ;;
+ esac
+
+ # Don't mark as being extracted for git
+ case "${ext}" in
+ /.git) ;;
+ *) CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracted";;
+ esac
+ CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${basename}.extracting"
+
+ CT_Popd
+}
+
+# Create a working git clone of a local git repository
+# Usage: CT_ExtractGit <basename> [ref]
+# where 'ref' is the reference to use:
+# the full name of a branch, like "remotes/origin/branch_name"
+# a date as understandable by git, like "YYYY-MM-DD[ hh[:mm[:ss]]]"
+# a tag name
+# If 'ref' is not given, the current repository HEAD will be used
+CT_ExtractGit() {
+ local basename="${1}"
+ local ref="${2}"
+ local repo
+ local ref_type
+
+ # pushd now to be able to get git revlist in case ref is a date
+ repo="${CT_TARBALLS_DIR}/${basename}"
+ CT_Pushd "${repo}"
+
+ # What kind of reference is ${ref} ?
+ if [ -z "${ref}" ]; then
+ ref_type=head
+ ref=$(git rev-list -n1 HEAD)
+ elif git tag |@@CT_grep@@ -E "^${ref}$" >/dev/null 2>&1; then
+ ref_type=tag
+ elif git branch -a --no-color | @@CT_grep@@ -E "^. ${ref}$" >/dev/null 2>&1; then
+ ref_type=branch
+ elif date -d "${ref}" >/dev/null 2>&1; then
+ ref_type=date
+ ref=$(git rev-list -n1 --before="${ref}")
+ else
+ CT_Abort "Reference '${ref}' is an incorrect git reference: neither tag, branch nor date"
+ fi
+
+ CT_Popd
+
+ CT_DoExecLog FILE rmdir "${basename}"
+ case "${ref_type}" in
+ branch) CT_DoExecLog FILE git clone -b "${ref}" "${repo}" "${basename}" ;;
+ *) CT_DoExecLog FILE git clone "${repo}" "${basename}"
+ CT_Pushd "${basename}"
+ CT_DoExecLog FILE git checkout "${ref}"
+ CT_Popd
+ ;;
+ esac
+}
+
+# Patches the specified component
+# See CT_Extract, above, for explanations on 'nochdir'
+# Usage: CT_Patch [nochdir] <packagename> <packageversion>
+# If the package directory is *not* packagename-packageversion, then
+# the caller must cd into the proper directory first, and call us
+# with nochdir
+CT_Patch() {
+ local nochdir="$1"
+ local pkgname
+ local version
+ local pkgdir
+ local base_file
+ local ver_file
+ local d
+ local -a patch_dirs
+ local bundled_patch_dir
+ local local_patch_dir
+ local bundled_exp_patch_dir
+ local local_exp_patch_dir
+
+ if [ "${nochdir}" = "nochdir" ]; then
+ shift
+ pkgname="$1"
+ version="$2"
+ pkgdir="${pkgname}-${version}"
+ nochdir="$(pwd)"
+ else
+ pkgname="$1"
+ version="$2"
+ pkgdir="${pkgname}-${version}"
+ nochdir="${CT_SRC_DIR}/${pkgdir}"
+ fi
+
+ # Check if already patched
+ if [ -e "${CT_SRC_DIR}/.${pkgdir}.patched" ]; then
+ CT_DoLog DEBUG "Already patched '${pkgdir}'"
+ return 0
+ fi
+
+ # Check if already partially patched
+ if [ -e "${CT_SRC_DIR}/.${pkgdir}.patching" ]; then
+ CT_DoLog ERROR "The '${pkgdir}' sources were partially patched."
+ CT_DoLog ERROR "Please remove first:"
+ CT_DoLog ERROR " - the source dir for '${pkgdir}', in '${CT_SRC_DIR}'"
+ CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.extracted'"
+ CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.patching'"
+ CT_Abort "I'll stop now to avoid any carnage..."
+ fi
+ touch "${CT_SRC_DIR}/.${pkgdir}.patching"
+
+ CT_Pushd "${nochdir}"
+
+ CT_DoLog EXTRA "Patching '${pkgdir}'"
+
+ bundled_patch_dir="${CT_LIB_DIR}/patches/${pkgname}/${version}"
+ local_patch_dir="${CT_LOCAL_PATCH_DIR}/${pkgname}/${version}"
+
+ # Check for experimental patches, if enabled.
+ if [ "${CT_EXPERIMENTAL_PATCHES}" = "y" ]; then
+ bundled_exp_patch_dir="${CT_LIB_DIR}/patches/experimental/${pkgname}/${version}"
+ local_exp_patch_dir="${CT_LOCAL_PATCH_DIR}/experimental/${pkgname}/${version}"
+ fi
+
+ case "${CT_PATCH_ORDER}" in
+ bundled) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
+ local) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}");;
+ bundled,local) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}" "${local_patch_dir}" "${local_exp_patch_dir}");;
+ local,bundled) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}" "${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
+ none) patch_dirs=;;
+ esac
+
+ for d in "${patch_dirs[@]}"; do
+ CT_DoLog DEBUG "Looking for patches in '${d}'..."
+ if [ -n "${d}" -a -d "${d}" ]; then
+ for p in "${d}"/*.patch; do
+ if [ -f "${p}" ]; then
+ CT_DoExecLog ALL patch --no-backup-if-mismatch -g0 -F1 -p1 -f -i "${p}"
+ fi
+ done
+ if [ "${CT_PATCH_SINGLE}" = "y" ]; then
+ break
+ fi
+ fi
+ done
+
+ if [ "${CT_OVERIDE_CONFIG_GUESS_SUB}" = "y" ]; then
+ CT_DoLog ALL "Overiding config.guess and config.sub"
+ for cfg in config_guess config_sub; do
+ eval ${cfg}="${CT_LIB_DIR}/scripts/${cfg/_/.}"
+ [ -e "${CT_TOP_DIR}/scripts/${cfg/_/.}" ] && eval ${cfg}="${CT_TOP_DIR}/scripts/${cfg/_/.}"
+ # Can't use CT_DoExecLog because of the '{} \;' to be passed un-mangled to find
+ find . -type f -name "${cfg/_/.}" -exec cp -v "${!cfg}" {} \; |CT_DoLog ALL
+ done
+ fi
+
+ CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${pkgdir}.patched"
+ CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${pkgdir}.patching"
+
+ CT_Popd
+}
+
+# Two wrappers to call config.(guess|sub) either from CT_TOP_DIR or CT_LIB_DIR.
+# Those from CT_TOP_DIR, if they exist, will be be more recent than those from CT_LIB_DIR.
+CT_DoConfigGuess() {
+ if [ -x "${CT_TOP_DIR}/scripts/config.guess" ]; then
+ "${CT_TOP_DIR}/scripts/config.guess"
+ else
+ "${CT_LIB_DIR}/scripts/config.guess"
+ fi
+}
+
+CT_DoConfigSub() {
+ if [ -x "${CT_TOP_DIR}/scripts/config.sub" ]; then
+ "${CT_TOP_DIR}/scripts/config.sub" "$@"
+ else
+ "${CT_LIB_DIR}/scripts/config.sub" "$@"
+ fi
+}
+
+# Compute the target tuple from what is provided by the user
+# Usage: CT_DoBuildTargetTuple
+# In fact this function takes the environment variables to build the target
+# tuple. It is needed both by the normal build sequence, as well as the
+# sample saving sequence.
+CT_DoBuildTargetTuple() {
+ # Set the endianness suffix, and the default endianness gcc option
+ case "${CT_ARCH_ENDIAN}" in
+ big)
+ target_endian_eb=eb
+ target_endian_be=be
+ target_endian_el=
+ target_endian_le=
+ CT_ARCH_ENDIAN_CFLAG="-mbig-endian"
+ CT_ARCH_ENDIAN_LDFLAG="-Wl,-EB"
+ ;;
+ little)
+ target_endian_eb=
+ target_endian_be=
+ target_endian_el=el
+ target_endian_le=le
+ CT_ARCH_ENDIAN_CFLAG="-mlittle-endian"
+ CT_ARCH_ENDIAN_LDFLAG="-Wl,-EL"
+ ;;
+ esac
+
+ # Set the bitness suffix
+ case "${CT_ARCH_BITNESS}" in
+ 32)
+ target_bits_32=32
+ target_bits_64=
+ ;;
+ 64)
+ target_bits_32=
+ target_bits_64=64
+ ;;
+ esac
+
+ # Build the default architecture tuple part
+ CT_TARGET_ARCH="${CT_ARCH}${CT_ARCH_SUFFIX}"
+
+ # Set defaults for the system part of the tuple. Can be overriden
+ # by architecture-specific values.
+ case "${CT_LIBC}" in
+ *glibc) CT_TARGET_SYS=gnu;;
+ uClibc) CT_TARGET_SYS=uclibc;;
+ *) CT_TARGET_SYS=elf;;
+ esac
+
+ # Set the default values for ARCH, ABI, CPU, TUNE, FPU and FLOAT
+ unset CT_ARCH_ARCH_CFLAG CT_ARCH_ABI_CFLAG CT_ARCH_CPU_CFLAG CT_ARCH_TUNE_CFLAG CT_ARCH_FPU_CFLAG CT_ARCH_FLOAT_CFLAG
+ unset CT_ARCH_WITH_ARCH CT_ARCH_WITH_ABI CT_ARCH_WITH_CPU CT_ARCH_WITH_TUNE CT_ARCH_WITH_FPU CT_ARCH_WITH_FLOAT
+ [ "${CT_ARCH_ARCH}" ] && { CT_ARCH_ARCH_CFLAG="-march=${CT_ARCH_ARCH}"; CT_ARCH_WITH_ARCH="--with-arch=${CT_ARCH_ARCH}"; }
+ [ "${CT_ARCH_ABI}" ] && { CT_ARCH_ABI_CFLAG="-mabi=${CT_ARCH_ABI}"; CT_ARCH_WITH_ABI="--with-abi=${CT_ARCH_ABI}"; }
+ [ "${CT_ARCH_CPU}" ] && { CT_ARCH_CPU_CFLAG="-mcpu=${CT_ARCH_CPU}"; CT_ARCH_WITH_CPU="--with-cpu=${CT_ARCH_CPU}"; }
+ [ "${CT_ARCH_TUNE}" ] && { CT_ARCH_TUNE_CFLAG="-mtune=${CT_ARCH_TUNE}"; CT_ARCH_WITH_TUNE="--with-tune=${CT_ARCH_TUNE}"; }
+ [ "${CT_ARCH_FPU}" ] && { CT_ARCH_FPU_CFLAG="-mfpu=${CT_ARCH_FPU}"; CT_ARCH_WITH_FPU="--with-fpu=${CT_ARCH_FPU}"; }
+
+ case "${CT_ARCH_FLOAT}" in
+ hard)
+ CT_ARCH_FLOAT_CFLAG="-mhard-float"
+ CT_ARCH_WITH_FLOAT="--with-float=hard"
+ ;;
+ soft)
+ CT_ARCH_FLOAT_CFLAG="-msoft-float"
+ CT_ARCH_WITH_FLOAT="--with-float=soft"
+ ;;
+ softfp)
+ CT_ARCH_FLOAT_CFLAG="-mfloat-abi=softfp"
+ CT_ARCH_WITH_FLOAT="--with-float=softfp"
+ ;;
+ esac
+
+ # Build the default kernel tuple part
+ CT_TARGET_KERNEL="${CT_KERNEL}"
+
+ # Overide the default values with the components specific settings
+ CT_DoArchTupleValues
+ CT_DoKernelTupleValues
+
+ # Finish the target tuple construction
+ CT_TARGET="${CT_TARGET_ARCH}"
+ CT_TARGET="${CT_TARGET}${CT_TARGET_VENDOR:+-${CT_TARGET_VENDOR}}"
+ CT_TARGET="${CT_TARGET}${CT_TARGET_KERNEL:+-${CT_TARGET_KERNEL}}"
+ CT_TARGET="${CT_TARGET}${CT_TARGET_SYS:+-${CT_TARGET_SYS}}"
+
+ # Sanity checks
+ __sed_alias=""
+ if [ -n "${CT_TARGET_ALIAS_SED_EXPR}" ]; then
+ __sed_alias=$(echo "${CT_TARGET}" |@@CT_sed@@ -r -e "${CT_TARGET_ALIAS_SED_EXPR}")
+ fi
+ case ":${CT_TARGET_VENDOR}:${CT_TARGET_ALIAS}:${__sed_alias}:" in
+ :*" "*:*:*:) CT_Abort "Don't use spaces in the vendor string, it breaks things.";;
+ :*"-"*:*:*:) CT_Abort "Don't use dashes in the vendor string, it breaks things.";;
+ :*:*" "*:*:) CT_Abort "Don't use spaces in the target alias, it breaks things.";;
+ :*:*:*" "*:) CT_Abort "Don't use spaces in the target sed transform, it breaks things.";;
+ esac
+
+ # Canonicalise it
+ CT_TARGET=$(CT_DoConfigSub "${CT_TARGET}")
+ # Prepare the target CFLAGS
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ENDIAN_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ARCH_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ABI_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_CPU_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_TUNE_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FPU_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FLOAT_CFLAG}"
+
+ # Now on for the target LDFLAGS
+ CT_ARCH_TARGET_LDFLAGS="${CT_ARCH_TARGET_LDFLAGS} ${CT_ARCH_ENDIAN_LDFLAG}"
+}
+
+# This function does pause the build until the user strikes "Return"
+# Usage: CT_DoPause [optional_message]
+CT_DoPause() {
+ local foo
+ local message="${1:-Pausing for your pleasure}"
+ CT_DoLog INFO "${message}"
+ read -p "Press 'Enter' to continue, or Ctrl-C to stop..." foo >&6
+ return 0
+}
+
+# This function creates a tarball of the specified directory, but
+# only if it exists
+# Usage: CT_DoTarballIfExists <dir> <tarball_basename> [extra_tar_options [...]]
+CT_DoTarballIfExists() {
+ local dir="$1"
+ local tarball="$2"
+ shift 2
+ local -a extra_tar_opts=( "$@" )
+ local -a compress
+
+ case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
+ y) compress=( gzip -c -3 - ); tar_ext=.gz;;
+ *) compress=( cat - ); tar_ext=;;
+ esac
+
+ if [ -d "${dir}" ]; then
+ CT_DoLog DEBUG " Saving '${dir}'"
+ { tar c -C "${dir}" -v -f - "${extra_tar_opts[@]}" . \
+ |"${compress[@]}" >"${tarball}.tar${tar_ext}" ;
+ } 2>&1 |@@CT_sed@@ -r -e 's/^/ /;' |CT_DoLog STATE
+ else
+ CT_DoLog STATE " Not saving '${dir}': does not exist"
+ fi
+}
+
+# This function extracts a tarball to the specified directory, but
+# only if the tarball exists
+# Usage: CT_DoExtractTarballIfExists <tarball_basename> <dir> [extra_tar_options [...]]
+CT_DoExtractTarballIfExists() {
+ local tarball="$1"
+ local dir="$2"
+ shift 2
+ local -a extra_tar_opts=( "$@" )
+ local -a uncompress
+
+ case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
+ y) uncompress=( gzip -c -d ); tar_ext=.gz;;
+ *) uncompress=( cat ); tar_ext=;;
+ esac
+
+ if [ -f "${tarball}.tar${tar_ext}" ]; then
+ CT_DoLog DEBUG " Restoring '${dir}'"
+ CT_DoForceRmdir "${dir}"
+ CT_DoExecLog DEBUG mkdir -p "${dir}"
+ { "${uncompress[@]}" "${tarball}.tar${tar_ext}" \
+ |tar x -C "${dir}" -v -f - "${extra_tar_opts[@]}" ;
+ } 2>&1 |@@CT_sed@@ -r -e 's/^/ /;' |CT_DoLog STATE
+ else
+ CT_DoLog STATE " Not restoring '${dir}': does not exist"
+ fi
+}
+
+# This function saves the state of the toolchain to be able to restart
+# at any one point
+# Usage: CT_DoSaveState <next_step_name>
+CT_DoSaveState() {
+ [ "${CT_DEBUG_CT_SAVE_STEPS}" = "y" ] || return 0
+ local state_name="$1"
+ local state_dir="${CT_STATE_DIR}/${state_name}"
+
+ # Log this to the log level required by the user
+ CT_DoLog ${CT_LOG_LEVEL_MAX} "Saving state to restart at step '${state_name}'..."
+
+ rm -rf "${state_dir}"
+ mkdir -p "${state_dir}"
+
+ CT_DoLog STATE " Saving environment and aliases"
+ # We must omit shell functions, and some specific bash variables
+ # that break when restoring the environment, later. We could do
+ # all the processing in the awk script, but a sed is easier...
+ set |awk '
+ BEGIN { _p = 1; }
+ $0~/^[^ ]+ \(\)/ { _p = 0; }
+ _p == 1
+ $0 == "}" { _p = 1; }
+ ' |@@CT_sed@@ -r -e '/^BASH_(ARGC|ARGV|LINENO|SOURCE|VERSINFO)=/d;
+ /^(UID|EUID)=/d;
+ /^(FUNCNAME|GROUPS|PPID|SHELLOPTS)=/d;' >"${state_dir}/env.sh"
+
+ CT_DoTarballIfExists "${CT_BUILDTOOLS_PREFIX_DIR}" "${state_dir}/buildtools_dir"
+ CT_DoTarballIfExists "${CT_CONFIG_DIR}" "${state_dir}/config_dir"
+ CT_DoTarballIfExists "${CT_PREFIX_DIR}" "${state_dir}/prefix_dir" --exclude '*.log'
+
+ CT_DoLog STATE " Saving log file"
+ exec >/dev/null
+ case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
+ y) gzip -3 -c "${tmp_log_file}" >"${state_dir}/log.gz";;
+ *) cat "${tmp_log_file}" >"${state_dir}/log";;
+ esac
+ exec >>"${tmp_log_file}"
+}
+
+# This function restores a previously saved state
+# Usage: CT_DoLoadState <state_name>
+CT_DoLoadState(){
+ local state_name="$1"
+ local state_dir="${CT_STATE_DIR}/${state_name}"
+ local old_RESTART="${CT_RESTART}"
+ local old_STOP="${CT_STOP}"
+
+ CT_TestOrAbort "The previous build did not reach the point where it could be restarted at '${CT_RESTART}'" -d "${state_dir}"
+
+ # We need to do something special with the log file!
+ if [ "${CT_LOG_TO_FILE}" = "y" ]; then
+ exec >"${state_dir}/tail.log"
+ fi
+
+ # Log this to the log level required by the user
+ CT_DoLog ${CT_LOG_LEVEL_MAX} "Restoring state at step '${state_name}', as requested."
+
+ CT_DoExtractTarballIfExists "${state_dir}/prefix_dir" "${CT_PREFIX_DIR}"
+ CT_DoExtractTarballIfExists "${state_dir}/config_dir" "${CT_CONFIG_DIR}"
+ CT_DoExtractTarballIfExists "${state_dir}/buildtools_dir" "${CT_BUILDTOOLS_PREFIX_DIR}"
+
+ # Restore the environment, discarding any error message
+ # (for example, read-only bash internals)
+ CT_DoLog STATE " Restoring environment"
+ . "${state_dir}/env.sh" >/dev/null 2>&1 || true
+
+ # Restore the new RESTART and STOP steps
+ CT_RESTART="${old_RESTART}"
+ CT_STOP="${old_STOP}"
+ unset old_stop old_restart
+
+ CT_DoLog STATE " Restoring log file"
+ exec >/dev/null
+ case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
+ y) gzip -dc "${state_dir}/log.gz" >"${tmp_log_file}";;
+ *) cat "${state_dir}/log" >"${tmp_log_file}";;
+ esac
+ cat "${state_dir}/tail.log" >>"${tmp_log_file}"
+ exec >>"${tmp_log_file}"
+ rm -f "${state_dir}/tail.log"
+}
diff --git a/scripts/xldd.in b/scripts/xldd.in
index c906240..4cbe333 100755
- --- a/scripts/xldd.in
+++ b/scripts/xldd.in
@@ -159,7 +159,7 @@ fi
sysroot="$( "${gcc}" -print-sysroot 2>/dev/null )"
if [ -z "${sysroot}" ]; then
sysroot="$( "${gcc}" -print-file-name=libc.so 2>/dev/null \
- - |sed -r -e 's:/usr/lib/libc.so$::;' \
+ |"${sed}" -r -e 's:/usr/lib/libc.so$::;' \
)"
fi
if [ -z "${sysroot}" ]; then
- --
1.8.5.2 (Apple Git-48)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
Comment: GPGTools - https://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iQIcBAEBCgAGBQJT4ZKSAAoJEHYXgoVc4PRjKYUQAIqsmgvc2vZpG+TNhRhm37cw
DBSoncpD7B9eTiaKhVRVTbeS1Tx/Fh0WvstULbQYmnnF6ovdkW1XNEjBYXLP24T/
pogcxRcr8imHGVXvem+CwQ7pQq83dW/idYnvqd7gqP/Ib/CfibQrJlGxgIXDanNq
4+xLi+Hdjt3eCf2fAkDCQ7e2x0xUZwyAoY42JqgpbZAugk4uyum7c+7N38kQcera
HHve5B4/F87KEHJp+xT07DIcTschYgWYZIz/lmEkgm0ptBDtcJePinZpSUTbrZ+l
UqtbSldLpn/pV0FsnHjSGKsHSXd4ylFhZL5YsFvYteB+6q0lfPe1MkbLdx78YE8K
dITbWcpJAZFX6Ci+l3X70lf5B4wHBR2R+f+FArhCpT76Zf0V+KJFVIsL6dx6qmir
s/LZvJQB4QVzgJvlXBkTe5MTLQ6smMQDhQelQQWJ7oUjqRrgvywv4pdIMoLWLDqc
rgp3540JVVz1Y97/sSUNI+YNUkYDxvpB31RY4T9WTT1YXhP6dnzU8clYfZI9phBc
cuZDnyDPnPojio9BnBMJeqnMojDknyc9npNi5qfjWYm7jqW4bJ5mt/7YFzSMKjcn
E3O58IDdcDM7BNGFYTnaIfP0a5FxpDBYd5y4m13NSUlXMBWADLbJV0W4Y1iq+vA1
cZnevMrW531Eu1KTQUnw
=6M3V
-----END PGP SIGNATURE-----
--
For unsubscribe information see http://sourceware.org/lists.html#faq
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes
2014-08-06 2:27 ` [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes Fabian Freyer
@ 2014-08-06 2:40 ` Fabian Freyer
2014-08-26 22:26 ` Yann E. MORIN
2014-08-26 22:51 ` Yann E. MORIN
2 siblings, 0 replies; 10+ messages in thread
From: Fabian Freyer @ 2014-08-06 2:40 UTC (permalink / raw)
To: Yann E. MORIN; +Cc: crossgcc
[-- Attachment #1: Type: text/plain, Size: 112155 bytes --]
Unfortunately, my inline PGP signature seems to have corrupted the patch, so
I'll resend it as multipart/signed message. Sorry about that.
[end top-post]
From 3847ffad3f1c7757d34b7a24279f5bb3b64b4c87 Mon Sep 17 00:00:00 2001
Hi,
On 26/09/12 18:56, Yann E. MORIN wrote:
> On Wednesday 26 September 2012 17:30:12 Blair Burtan wrote:
>> That was the problem but not quite the complete solution. I had to modify
>> the grep path to point to the MacPorts verison when I built ct-ng. I also
>> had to use ginstall instead of the OSX install.
>
> ./configure --help
> [--SNIP--]
> Optional Packages:
> --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
> --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
> --with-install=PATH Specify the full PATH to a BSD-compatible install
> --with-sed=PATH Specify the full PATH to GNU sed
> --with-objcopy=PATH Specify the full PATH to GNU objcopy
> --with-objdump=PATH Specify the full PATH to GNU objdump
> --with-ranlib=PATH Specify the full PATH to GNU ranlib
> --with-readelf=PATH Specify the full PATH to GNU readelf
> --with-bash=PATH Specify the full PATH to GNU bash >= 3.1
> --with-awk=PATH Specify the full PATH to GNU awk
> --with-make=PATH Specify the full PATH to GNU make >= 3.80
> --with-libtool=PATH Specify the full PATH to GNU libtool >= 1.5.26
> --with-libtoolize=PATH Specify the full PATH to GNU libtoolize >= 1.5.26
> --with-automake=PATH Specify the full PATH to GNU automake >= 1.10
> [--SNIP--]
>
> That's how you tell crosstool-NG what tools to use if the default ones are
> not the GNU ones.
While it is possible to tell crosstool-NG to use custom GNU tools for several
tools, it is not possible for all tools, especially for grep and sed. This
causes ct-ng build to fail:
[ERROR] >>
[ERROR] >> Build failed in step '(top-level)'
[ERROR] >>
[ERROR] >> Error happened in: CT_DoForceRmdir[scripts/functions@458]
[ERROR] >> called from: main[scripts/crosstool-NG.sh@238]
[ERROR] >>
One of the problems here is also that on BSD installs, including OS X, GNU
tools are often installed with a prefixed 'g', in this case "ggrep" and "gsed".
There is no way to tell crosstool-NG to use ggrep instead of grep, and
adjusting $PATH does not help either.
I have created a small (not counting the changes due to the scripts/functions
rename) patch that adds --with-grep and substitues @@CT_sed@@ for sed in a few
places where sed from PATH is used and GNU-specific options are used. I can
confirm this works for me on Darwin using GNU tools installed via homebrew using
the following ./configure options:
./configure --prefix=$(pwd) --exec-prefix=$(pwd) \
--with-objcopy=gobjcopy \
--with-objdump=gobjdump \
--with-readelf=greadelf \
--with-libtool=glibtool \
--with-libtoolize=glibtoolize \
--with-install=ginstall \
--with-sed=gsed \
--with-awk=gawk \
--with-grep=ggrep
I have not yet tested that this patch works flawlessly on Linux using default
./configure options. I'd like to submit the following patch for testing.
Regards,
Fabian Freyer
---
Makefile.in | 5 +-
configure.ac | 6 +
scripts/crosstool-NG.sh.in | 6 +-
scripts/functions | 1395 --------------------------------------------
scripts/functions.in | 1395 ++++++++++++++++++++++++++++++++++++++++++++
scripts/xldd.in | 2 +-
6 files changed, 1409 insertions(+), 1400 deletions(-)
delete mode 100644 scripts/functions
create mode 100644 scripts/functions.in
diff --git a/Makefile.in b/Makefile.in
index 01759b6..cd68baa 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -59,7 +59,7 @@ export datarootdir := @datarootdir@
export install := @INSTALL@
export bash := @_BASH@
export awk := @_AWK@
-export grep := @GREP@
+export grep := @_GREP@
export make := @MAKE@
export sed := @SED@
export libtool := @LIBTOOL@
@@ -142,6 +142,7 @@ uninstall: real-uninstall
# Build rules
build-bin: $(PROG_NAME) \
+ scripts/functions \
scripts/crosstool-NG.sh \
scripts/saveSample.sh \
scripts/showTuple.sh
@@ -174,6 +175,8 @@ define sed_it
-e 's,@@CT_make@@,$(make),g;' \
-e 's,@@CT_bash@@,$(bash),g;' \
-e 's,@@CT_awk@@,$(awk),g;' \
+ -e 's,@@CT_grep@@,$(grep),g;' \
+ -e 's,@@CT_sed@@,$(sed),g;' \
$< >$@
endef
diff --git a/configure.ac b/configure.ac
index f8c67be..27238ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -94,6 +94,12 @@ AC_ARG_WITH([install],
[Specify the full PATH to a BSD-compatible install]),
[INSTALL=$withval])
AC_PROG_INSTALL
+AC_CACHE_VAL([ac_cv_path_GREP],
+ [AC_ARG_WITH([grep],
+ AS_HELP_STRING([--with-grep=PATH],
+ [Specify the full PATH to GNU grep]),
+ [ac_cv_path_GREP=$withval])])
+AC_SUBST([_GREP], [$ac_cv_path_GREP])
AC_PROG_GREP
AC_PROG_EGREP
AS_IF(
diff --git a/scripts/crosstool-NG.sh.in b/scripts/crosstool-NG.sh.in
index 3699500..4b9011d 100644
--- a/scripts/crosstool-NG.sh.in
+++ b/scripts/crosstool-NG.sh.in
@@ -125,7 +125,7 @@ CT_DoLog INFO "Build started ${CT_STAR_DATE_HUMAN}"
# We really need to extract from ,config and not .config.2, as we
# do want the kconfig's values, not our mangled config with arrays.
CT_DoStep DEBUG "Dumping user-supplied crosstool-NG configuration"
-CT_DoExecLog DEBUG grep -E '^(# |)CT_' .config
+CT_DoExecLog DEBUG @@CT_grep@@ -E '^(# |)CT_' .config
CT_EndStep
CT_DoLog DEBUG "Unsetting and unexporting MAKEFLAGS"
@@ -570,9 +570,9 @@ if [ -z "${CT_RESTART}" ]; then
CT_DoLog EXTRA " build = ${CT_REAL_BUILD}"
CT_DoLog EXTRA " host = ${CT_REAL_HOST}"
CT_DoLog EXTRA " target = ${CT_TARGET}"
- set |grep -E '^CT_.+=' |sort |CT_DoLog DEBUG
+ set |@@CT_grep@@ -E '^CT_.+=' |sort |CT_DoLog DEBUG
CT_DoLog DEBUG "Other environment:"
- printenv |grep -v -E '^CT_.+=' |CT_DoLog DEBUG
+ printenv |@@CT_grep@@ -v -E '^CT_.+=' |CT_DoLog DEBUG
CT_EndStep
fi
diff --git a/scripts/functions b/scripts/functions
deleted file mode 100644
index 2e4d4fa..0000000
--- a/scripts/functions
+++ /dev/null
@@ -1,1395 +0,0 @@
-# This file contains some usefull common functions -*- sh -*-
-# Copyright 2007 Yann E. MORIN
-# Licensed under the GPL v2. See COPYING in the root of this package
-
-# Prepare the fault handler
-CT_OnError() {
- local ret=$?
- local result
- local old_trap
- local intro
- local file line func
- local step step_depth
-
- # To avoid printing the backtace for each sub-shell
- # up to the top-level, just remember we've dumped it
- if [ ! -f "${CT_WORK_DIR}/backtrace" ]; then
- touch "${CT_WORK_DIR}/backtrace"
-
- # Print steps backtrace
- step_depth=${CT_STEP_COUNT}
- CT_STEP_COUNT=1 # To have a zero-indentation
- CT_DoLog ERROR ""
- CT_DoLog ERROR ">>"
- intro="Build failed"
- for((step=step_depth; step>0; step--)); do
- CT_DoLog ERROR ">> ${intro} in step '${CT_STEP_MESSAGE[${step}]}'"
- intro=" called"
- done
-
- # Print functions backtrace
- intro="Error happened in"
- CT_DoLog ERROR ">>"
- for((depth=1; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
- file="${BASH_SOURCE[${depth}]#${CT_LIB_DIR}/}"
- func="${FUNCNAME[${depth}]}"
- line="@${BASH_LINENO[${depth}-1]:-?}"
- CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
- intro=" called from"
- done
-
- # If the user asked for interactive debugging, dump him/her to a shell
- if [ "${CT_DEBUG_INTERACTIVE}" = "y" ]; then
- # We do not want this sub-shell exit status to be caught, because
- # it is absolutely legit that it exits with non-zero.
- # Save the trap handler to restore it after our debug-shell
- old_trap="$(trap -p ERR)"
- trap -- ERR
- (
- exec >&6 2>&7 <&8
- printf "\r \n\nCurrent command"
- if [ -n "${cur_cmd}" ]; then
- printf ":\n %s\n" "${cur_cmd}"
- else
- printf " (unknown), "
- fi
- printf "exited with error code: %d\n" ${ret}
- printf "Please fix it up and finish by exiting the shell with one of these values:\n"
- printf " 1 fixed, continue with next build command\n"
- if [ -n "${cur_cmd}" ]; then
- printf " 2 repeat this build command\n"
- fi
- printf " 3 abort build\n\n"
- while true; do
- ${bash} --rcfile <(printf "PS1='ct-ng:\w> '\nPROMPT_COMMAND=''\n") -i
- result=$?
- case $result in
- 1) printf "\nContinuing past the failed command.\n\n"
- break
- ;;
- 2) if [ -n "${cur_cmd}" ]; then
- printf "\nRe-trying last command.\n\n"
- break
- fi
- ;;
- 3) break;;
- esac
- printf "\nPlease exit with one of these values:\n"
- printf " 1 fixed, continue with next build command\n"
- if [ -n "${cur_cmd}" ]; then
- printf " 2 repeat this build command\n"
- fi
- printf " 3 abort build\n"
- done
- exit $result
- )
- result=$?
- # Restore the trap handler
- eval "${old_trap}"
- case "${result}" in
- 1) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/skip"; return;;
- 2) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/repeat"; return;;
- # 3 is an abort, continue...
- esac
- fi
- fi
-
- # And finally, in top-level shell, print some hints
- if [ ${BASH_SUBSHELL} -eq 0 ]; then
- # Help diagnose the error
- CT_STEP_COUNT=1 # To have a zero-indentation
- CT_DoLog ERROR ">>"
- if [ "${CT_LOG_TO_FILE}" = "y" ]; then
- CT_DoLog ERROR ">> For more info on this error, look at the file: '${tmp_log_file#${CT_TOP_DIR}/}'"
- fi
- CT_DoLog ERROR ">> There is a list of known issues, some with workarounds, in:"
- CT_DoLog ERROR ">> '${CT_DOC_DIR#${CT_TOP_DIR}/}/B - Known issues.txt'"
-
- CT_DoLog ERROR ""
- CT_DoEnd ERROR
- rm -f "${CT_WORK_DIR}/backtrace"
- fi
- exit $ret
-}
-
-# Install the fault handler
-trap CT_OnError ERR
-
-# Inherit the fault handler in subshells and functions
-set -E
-
-# Make pipes fail on the _first_ failed command
-# Not supported on bash < 3.x, but we need it, so drop the obsoleting bash-2.x
-set -o pipefail
-
-# Don't hash commands' locations, and search every time it is requested.
-# This is slow, but needed because of the static/shared core gcc which shall
-# always match to shared if it exists, and only fallback to static if the
-# shared is not found
-set +o hashall
-
-# Log policy:
-# - first of all, save stdout so we can see the live logs: fd #6
-# (also save stdin and stderr for use by CT_DEBUG_INTERACTIVE)
-exec 6>&1 7>&2 8<&0
-# - then point stdout to the log file
-tmp_log_file="${CT_TOP_DIR}/build.log"
-rm -f "${tmp_log_file}"
-exec >>"${tmp_log_file}"
-
-# The different log levels:
-CT_LOG_LEVEL_ERROR=0
-CT_LOG_LEVEL_WARN=1
-CT_LOG_LEVEL_INFO=2
-CT_LOG_LEVEL_EXTRA=3
-CT_LOG_LEVEL_CFG=4
-CT_LOG_LEVEL_FILE=5
-CT_LOG_LEVEL_STATE=6
-CT_LOG_LEVEL_ALL=7
-CT_LOG_LEVEL_DEBUG=8
-
-# Make it easy to use \n and !
-CR=$(printf "\n")
-BANG='!'
-
-# A function to log what is happening
-# Different log level are available:
-# - ERROR: A serious, fatal error occurred
-# - WARN: A non fatal, non serious error occurred, take your responsbility with the generated build
-# - INFO: Informational messages
-# - EXTRA: Extra informational messages
-# - CFG: Output of various "./configure"-type scripts
-# - FILE: File / archive unpacking.
-# - STATE: State save & restore
-# - ALL: Component's build messages
-# - DEBUG: Internal debug messages
-# Usage: CT_DoLog <level> [message]
-# If message is empty, then stdin will be logged.
-CT_DoLog() {
- local max_level LEVEL level cur_l cur_L
- local l
- eval max_level="\${CT_LOG_LEVEL_${CT_LOG_LEVEL_MAX}}"
- # Set the maximum log level to DEBUG if we have none
- [ -z "${max_level}" ] && max_level=${CT_LOG_LEVEL_DEBUG}
-
- LEVEL="$1"; shift
- eval level="\${CT_LOG_LEVEL_${LEVEL}}"
-
- if [ $# -eq 0 ]; then
- cat -
- else
- printf "%s\n" "${*}"
- fi |( IFS="${CR}" # We want the full lines, even leading spaces
- _prog_bar_cpt=0
- _prog_bar[0]='/'
- _prog_bar[1]='-'
- _prog_bar[2]='\'
- _prog_bar[3]='|'
- indent=$((2*CT_STEP_COUNT))
- while read line; do
- case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
- y,*"warning:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
- y,*"WARNING:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
- *"error:"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
- *"make["*"]: *** ["*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
- *) cur_L="${LEVEL}"; cur_l="${level}";;
- esac
- # There will always be a log file (stdout, fd #1), be it /dev/null
- printf "[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}"
- if [ ${cur_l} -le ${max_level} ]; then
- # Only print to console (fd #6) if log level is high enough.
- printf "${CT_LOG_PROGRESS_BAR:+\r}[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}" >&6
- fi
- if [ "${CT_LOG_PROGRESS_BAR}" = "y" ]; then
- printf "\r[%02d:%02d] %s " $((SECONDS/60)) $((SECONDS%60)) "${_prog_bar[$((_prog_bar_cpt/10))]}" >&6
- _prog_bar_cpt=$(((_prog_bar_cpt+1)%40))
- fi
- done
- )
-
- return 0
-}
-
-# Execute an action, and log its messages
-# It is possible to even log local variable assignments (a-la: var=val ./cmd opts)
-# Usage: CT_DoExecLog <level> [VAR=val...] <command> [parameters...]
-CT_DoExecLog() {
- local level="$1"
- local cur_cmd
- local ret
- shift
- (
- for i in "$@"; do
- cur_cmd+="'${i}' "
- done
- while true; do
- case "${1}" in
- *=*) eval export "'${1}'"; shift;;
- *) break;;
- esac
- done
- # This while-loop goes hand-in-hand with the ERR trap handler:
- # - if the command terminates successfully, then we hit the break
- # statement, and we exit the loop
- # - if the command terminates in error, then the ERR handler kicks
- # in, then:
- # - if the user did *not* ask for interactive debugging, the ERR
- # handler exits, and we hit the end of the sub-shell
- # - if the user did ask for interactive debugging, the ERR handler
- # spawns a shell. Upon termination of this shell, the ERR handler
- # examines the exit status of the shell:
- # - if 1, the ERR handler returns; then we hit the else statement,
- # then the break, and we exit the 'while' loop, to continue the
- # build;
- # - if 2, the ERR handler touches the repeat file, and returns;
- # then we hit the if statement, and we loop for one more
- # iteration;
- # - if 3, the ERR handler exits with the command's exit status,
- # and we're dead;
- # - for any other exit status of the shell, the ERR handler
- # prints an informational message, and respawns the shell
- #
- # This allows a user to get an interactive shell that has the same
- # environment (PATH and so on) that the failed command was ran with.
- while true; do
- rm -f "${CT_BUILD_DIR}/repeat"
- CT_DoLog DEBUG "==> Executing: ${cur_cmd}"
- "${@}" 2>&1 |CT_DoLog "${level}"
- ret="${?}"
- if [ -f "${CT_BUILD_DIR}/repeat" ]; then
- rm -f "${CT_BUILD_DIR}/repeat"
- continue
- elif [ -f "${CT_BUILD_DIR}/skip" ]; then
- rm -f "${CT_BUILD_DIR}/skip"
- ret=0
- break
- else
- break
- fi
- done
- exit ${ret}
- )
- # Catch failure of the sub-shell
- [ $? -eq 0 ]
-}
-
-# Tail message to be logged whatever happens
-# Usage: CT_DoEnd <level>
-CT_DoEnd()
-{
- local level="$1"
- CT_STOP_DATE=$(CT_DoDate +%s%N)
- CT_STOP_DATE_HUMAN=$(CT_DoDate +%Y%m%d.%H%M%S)
- if [ "${level}" != "ERROR" ]; then
- CT_DoLog "${level:-INFO}" "Build completed at ${CT_STOP_DATE_HUMAN}"
- fi
- elapsed=$((CT_STOP_DATE-CT_STAR_DATE))
- elapsed_min=$((elapsed/(60*1000*1000*1000)))
- elapsed_sec=$(printf "%02d" $(((elapsed%(60*1000*1000*1000))/(1000*1000*1000))))
- elapsed_csec=$(printf "%02d" $(((elapsed%(1000*1000*1000))/(10*1000*1000))))
- CT_DoLog ${level:-INFO} "(elapsed: ${elapsed_min}:${elapsed_sec}.${elapsed_csec})"
-}
-
-# Remove entries referring to . and other relative paths
-# Usage: CT_SanitizePath
-CT_SanitizePath() {
- local new
- local p
- local IFS=:
- for p in $PATH; do
- # Only accept absolute paths;
- # Note: as a special case the empty string in PATH is equivalent to .
- if [ -n "${p}" -a -z "${p%%/*}" ]; then
- new="${new}${new:+:}${p}"
- fi
- done
- PATH="${new}"
-}
-
-# Sanitise the directory name contained in the variable passed as argument:
-# - remove duplicate /
-# Usage: CT_SanitiseVarDir CT_PREFIX_DIR
-CT_SanitiseVarDir() {
- local var
- local old_dir
- local new_dir
-
- for var in "$@"; do
- eval "old_dir=\"\${${var}}\""
- new_dir="$( printf "${old_dir}" \
- |sed -r -e 's:/+:/:g;' \
- )"
- eval "${var}=\"${new_dir}\""
- CT_DoLog DEBUG "Sanitised '${var}': '${old_dir}' -> '${new_dir}'"
- done
-}
-
-# Abort the execution with an error message
-# Usage: CT_Abort <message>
-CT_Abort() {
- CT_DoLog ERROR "$1"
- false
-}
-
-# Test a condition, and print a message if satisfied
-# Usage: CT_Test <message> <tests>
-CT_Test() {
- local ret
- local m="$1"
- shift
- CT_DoLog DEBUG "Testing '! ( $* )'"
- test "$@" && CT_DoLog WARN "$m"
- return 0
-}
-
-# Test a condition, and abort with an error message if satisfied
-# Usage: CT_TestAndAbort <message> <tests>
-CT_TestAndAbort() {
- local m="$1"
- shift
- CT_DoLog DEBUG "Testing '! ( $* )'"
- test "$@" && CT_Abort "$m"
- return 0
-}
-
-# Test a condition, and abort with an error message if not satisfied
-# Usage: CT_TestAndAbort <message> <tests>
-CT_TestOrAbort() {
- local m="$1"
- shift
- CT_DoLog DEBUG "Testing '$*'"
- test "$@" || CT_Abort "$m"
- return 0
-}
-
-# Test the presence of a tool, or abort if not found
-# Usage: CT_HasOrAbort <tool>
-CT_HasOrAbort() {
- CT_TestAndAbort "'${1}' not found and needed for successful toolchain build." -z "$(CT_Which "${1}")"
- return 0
-}
-
-# Search a program: wrap "which" for those system where "which"
-# verbosely says there is no match (such as on Mandriva).
-# Usage: CT_Which <filename>
-CT_Which() {
- which "$1" 2>/dev/null || true
-}
-
-# Get current date with nanosecond precision
-# On those system not supporting nanosecond precision, faked with rounding down
-# to the highest entire second
-# Usage: CT_DoDate <fmt>
-CT_DoDate() {
- date "$1" |sed -r -e 's/%?N$/000000000/;'
-}
-
-CT_STEP_COUNT=1
-CT_STEP_MESSAGE[${CT_STEP_COUNT}]="(top-level)"
-# Memorise a step being done so that any error is caught
-# Usage: CT_DoStep <loglevel> <message>
-CT_DoStep() {
- local start=$(CT_DoDate +%s%N)
- CT_DoLog "$1" "================================================================="
- CT_DoLog "$1" "$2"
- CT_STEP_COUNT=$((CT_STEP_COUNT+1))
- CT_STEP_LEVEL[${CT_STEP_COUNT}]="$1"; shift
- CT_STEP_START[${CT_STEP_COUNT}]="${start}"
- CT_STEP_MESSAGE[${CT_STEP_COUNT}]="$1"
- return 0
-}
-
-# End the step just being done
-# Usage: CT_EndStep
-CT_EndStep() {
- local stop=$(CT_DoDate +%s%N)
- local duration=$(printf "%032d" $((stop-${CT_STEP_START[${CT_STEP_COUNT}]})) |sed -r -e 's/([[:digit:]]{2})[[:digit:]]{7}$/\.\1/; s/^0+//; s/^\./0\./;')
- local elapsed=$(printf "%02d:%02d" $((SECONDS/60)) $((SECONDS%60)))
- local level="${CT_STEP_LEVEL[${CT_STEP_COUNT}]}"
- local message="${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}"
- CT_STEP_COUNT=$((CT_STEP_COUNT-1))
- CT_DoLog "${level}" "${message}: done in ${duration}s (at ${elapsed})"
- return 0
-}
-
-# Pushes into a directory, and pops back
-CT_Pushd() {
- CT_DoLog DEBUG "Entering '$1'"
- pushd "$1" >/dev/null 2>&1
-}
-CT_Popd() {
- popd >/dev/null 2>&1
-}
-
-# Create a dir and cd or pushd into it
-# Usage: CT_mkdir_cd <dir/to/create>
-# CT_mkdir_pushd <dir/to/create>
-CT_mkdir_cd() {
- local dir="${1}"
-
- mkdir -p "${dir}"
- cd "${dir}"
-}
-CT_mkdir_pushd() {
- local dir="${1}"
-
- mkdir -p "${dir}"
- CT_Pushd "${dir}"
-}
-
-# Creates a temporary directory
-# $1: variable to assign to
-# Usage: CT_MktempDir foo
-CT_MktempDir() {
- # Some mktemp do not allow more than 6 Xs
- eval "$1"=$(mktemp -q -d "${CT_BUILD_DIR}/tmp.XXXXXX")
- CT_TestOrAbort "Could not make temporary directory" -n "${!1}" -a -d "${!1}"
- CT_DoLog DEBUG "Made temporary directory '${!1}'"
- return 0
-}
-
-# Removes one or more directories, even if it is read-only, or its parent is
-# Usage: CT_DoForceRmdir dir [...]
-CT_DoForceRmdir() {
- local dir
- local mode
- for dir in "${@}"; do
- [ -d "${dir}" ] || continue
- case "$CT_SYS_OS" in
- Linux|CYGWIN*)
- mode="$(stat -c '%a' "$(dirname "${dir}")")"
- ;;
- Darwin|*BSD)
- mode="$(stat -f '%Lp' "$(dirname "${dir}")")"
- ;;
- *)
- CT_Abort "Unhandled host OS $CT_SYS_OS"
- ;;
- esac
- CT_DoExecLog ALL chmod u+w "$(dirname "${dir}")"
- CT_DoExecLog ALL chmod -R u+w "${dir}"
- CT_DoExecLog ALL rm -rf "${dir}"
- CT_DoExecLog ALL chmod ${mode} "$(dirname "${dir}")"
- done
-}
-
-# Echoes the specified string on stdout until the pipe breaks.
-# Doesn't fail
-# $1: string to echo
-# Usage: CT_DoYes "" |make oldconfig
-CT_DoYes() {
- yes "$1" || true
-}
-
-# Add the specified directory to LD_LIBRARY_PATH, and export it
-# If the specified patch is already present, just export
-# $1: path to add
-# $2: add as 'first' or 'last' path, 'first' is assumed if $2 is empty
-# Usage CT_SetLibPath /some/where/lib [first|last]
-CT_SetLibPath() {
- local path="$1"
- local pos="$2"
-
- case ":${LD_LIBRARY_PATH}:" in
- *:"${path}":*) ;;
- *) case "${pos}" in
- last)
- CT_DoLog DEBUG "Adding '${path}' at end of LD_LIBRARY_PATH"
- LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${path}"
- ;;
- first|"")
- CT_DoLog DEBUG "Adding '${path}' at start of LD_LIBRARY_PATH"
- LD_LIBRARY_PATH="${path}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
- ;;
- *)
- CT_Abort "Incorrect position '${pos}' to add '${path}' to LD_LIBRARY_PATH"
- ;;
- esac
- ;;
- esac
- CT_DoLog DEBUG "==> LD_LIBRARY_PATH='${LD_LIBRARY_PATH}'"
- export LD_LIBRARY_PATH
-}
-
-# Build up the list of allowed tarball extensions
-# Add them in the prefered order; most preferred comes first
-CT_DoListTarballExt() {
- if [ "${CT_CONFIGURE_has_xz}" = "y" ]; then
- printf ".tar.xz\n"
- fi
- if [ "${CT_CONFIGURE_has_lzma}" = "y" \
- -o "${CT_CONFIGURE_has_xz}" = "y" ]; then
- printf ".tar.lzma\n"
- fi
- printf ".tar.bz2\n"
- printf ".tar.gz\n.tgz\n"
- printf ".tar\n"
- printf ".zip\n"
-}
-
-# Get the file name extension of a component
-# Usage: CT_GetFileExtension <component_name-component_version> [extension]
-# If found, echoes the extension to stdout, and return 0
-# If not found, echoes nothing on stdout, and return !0.
-CT_GetFileExtension() {
- local ext
- local file="$1"
- shift
- local first_ext="$1"
-
- # we need to also check for an empty extension for those very
- # peculiar components that don't have one (such as sstrip from
- # buildroot).
- for ext in ${first_ext} $(CT_DoListTarballExt) /.git ''; do
- if [ -e "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
- echo "${ext}"
- exit 0
- fi
- done
-
- exit 1
-}
-
-# Try to retrieve the specified URL (HTTP or FTP)
-# Usage: CT_DoGetFile <URL>
-# This functions always returns true (0), as it can be legitimate not
-# to find the requested URL (think about snapshots, different layouts
-# for different gcc versions, etc...).
-CT_DoGetFile() {
- local url="${1}"
- local dest="${CT_TARBALLS_DIR}/${url##*/}"
- local tmp="${dest}.tmp-dl"
-
- # Remove potential left-over from a previous run
- rm -f "${tmp}"
-
- # We also retry a few times, in case there is a transient error (eg. behind
- # a dynamic IP that changes during the transfer...)
- # With automated download as we are doing, it can be very dangerous to
- # continue the downloads. It's far better to simply overwrite the
- # destination file.
- # Some company networks have firewalls to connect to the internet, but it's
- # not easy to detect them, so force a global ${CT_CONNECT_TIMEOUT}-second
- # timeout.
- if [ ${CT_CONNECT_TIMEOUT} = -1 ]; then
- T=
- else
- T="-T ${CT_CONNECT_TIMEOUT}"
- fi
- if CT_DoExecLog ALL wget --passive-ftp --tries=3 -nc \
- --progress=dot:binary \
- ${T} \
- -O "${tmp}" \
- "${url}"
- then
- # Success, we got it, good!
- mv "${tmp}" "${dest}"
- CT_DoLog DEBUG "Got it from: \"${url}\""
- else
- # Woops...
- rm -f "${tmp}"
- CT_DoLog DEBUG "Not at this location: \"${url}\""
- fi
-}
-
-# This function tries to retrieve a tarball form a local directory
-# Usage: CT_GetLocal <basename> [.extension]
-CT_GetLocal() {
- local basename="$1"
- local first_ext="$2"
- local ext
-
- # Do we already have it in *our* tarballs dir?
- if ext="$( CT_GetFileExtension "${basename}" ${first_ext} )"; then
- CT_DoLog DEBUG "Already have '${basename}'"
- return 0
- fi
-
- if [ -n "${CT_LOCAL_TARBALLS_DIR}" ]; then
- CT_DoLog DEBUG "Trying to retrieve an already downloaded copy of '${basename}'"
- # We'd rather have a bzip2'ed tarball, then gzipped tarball, plain tarball,
- # or, as a failover, a file without extension.
- for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
- CT_DoLog DEBUG "Trying '${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}'"
- if [ -r "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" -a \
- "${CT_FORCE_DOWNLOAD}" != "y" ]; then
- CT_DoLog DEBUG "Got '${basename}' from local storage"
- CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" "${CT_TARBALLS_DIR}/${basename}${ext}"
- return 0
- fi
- done
- fi
- return 1
-}
-
-# This function gets the custom source from either a tarball or directory
-# Usage: CT_GetCustom <component> <custom_version> <custom_location>
-CT_GetCustom() {
- local custom_component="$1"
- local custom_version="$2"
- local custom_location="$3"
- local custom_name="${custom_component}-${custom_version}"
-
- CT_TestAndAbort "${custom_name}: CT_CUSTOM_LOCATION_ROOT_DIR or ${custom_component}'s CUSTOM_LOCATION must be set." \
- -z "${CT_CUSTOM_LOCATION_ROOT_DIR}" -a -z "${custom_location}"
-
- if [ -n "${CT_CUSTOM_LOCATION_ROOT_DIR}" \
- -a -z "${custom_location}" ]; then
- custom_location="${CT_CUSTOM_LOCATION_ROOT_DIR}/${custom_component}"
- fi
-
- CT_DoLog EXTRA "Using '${custom_name}' from custom location"
- if [ ! -d "${custom_location}" ]; then
- # We need to know the custom tarball extension,
- # so we can create a properly-named symlink, which
- # we use later on in 'extract'
- case "${custom_location}" in
- *.tar.xz) custom_name="${custom_name}.tar.xz";;
- *.tar.bz2) custom_name="${custom_name}.tar.bz2";;
- *.tar.gz|*.tgz) custom_name="${custom_name}.tar.gz";;
- *.tar) custom_name="${custom_name}.tar";;
- *) CT_Abort "Unknown extension for custom tarball '${custom_location}'";;
- esac
- CT_DoExecLog DEBUG ln -sf "${custom_location}" \
- "${CT_TARBALLS_DIR}/${custom_name}"
- else
- CT_DoExecLog DEBUG ln -snf "${custom_location}" \
- "${CT_SRC_DIR}/${custom_name}"
- fi
-}
-
-# This function saves the specified to local storage if possible,
-# and if so, symlinks it for later usage
-# Usage: CT_SaveLocal </full/path/file.name>
-CT_SaveLocal() {
- local file="$1"
- local basename="${file##*/}"
-
- if [ "${CT_SAVE_TARBALLS}" = "y" ]; then
- CT_DoLog EXTRA "Saving '${basename}' to local storage"
- # The file may already exist if downloads are forced: remove it first
- CT_DoExecLog ALL rm -f "${CT_LOCAL_TARBALLS_DIR}/${basename}"
- CT_DoExecLog ALL mv -f "${file}" "${CT_LOCAL_TARBALLS_DIR}"
- CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}" "${file}"
- fi
-}
-
-# Download the file from one of the URLs passed as argument
-# Usage: CT_GetFile <basename> [.extension] <url> [url ...]
-CT_GetFile() {
- local ext
- local -a URLS
- local url
- local file="$1"
- local first_ext
- shift
- # If next argument starts with a dot, then this is not an URL,
- # and we can consider that it is a preferred extension.
- case "$1" in
- .*) first_ext="$1"
- shift
- ;;
- esac
-
- # Does it exist localy?
- if CT_GetLocal "${file}" ${first_ext}; then
- return 0
- fi
- # No, it does not...
-
- # If not allowed to download from the Internet, don't
- if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
- CT_DoLog DEBUG "Not allowed to download from the Internet, aborting ${file} download"
- return 1
- fi
-
- # Try to retrieve the file
- CT_DoLog EXTRA "Retrieving '${file}'"
-
- # Add URLs on the LAN mirror
- if [ "${CT_USE_MIRROR}" = "y" ]; then
- CT_TestOrAbort "Please set the mirror base URL" -n "${CT_MIRROR_BASE_URL}"
- URLS+=( "${CT_MIRROR_BASE_URL}/${file%-*}" )
- URLS+=( "${CT_MIRROR_BASE_URL}" )
- fi
-
- if [ "${CT_FORCE_MIRROR}" != "y" ]; then
- URLS+=( "${@}" )
- fi
-
- # Scan all URLs in turn, and try to grab a tarball from there
- # Do *not* try git trees (ext=/.git), this is handled in a specific
- # wrapper, below
- for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
- # Try all urls in turn
- for url in "${URLS[@]}"; do
- [ -n "${url}" ] || continue
- CT_DoLog DEBUG "Trying '${url}/${file}${ext}'"
- CT_DoGetFile "${url}/${file}${ext}"
- if [ -f "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
- CT_DoLog DEBUG "Got '${file}' from the Internet"
- CT_SaveLocal "${CT_TARBALLS_DIR}/${file}${ext}"
- return 0
- fi
- done
- done
-
- # Just return error, someone may want to catch and handle the error
- # (eg. glibc/eglibc add-ons can be missing).
- return 1
-}
-
-# Checkout from CVS, and build the associated tarball
-# The tarball will be called ${basename}.tar.bz2
-# Prerequisite: either the server does not require password,
-# or the user must already be logged in.
-# 'tag' is the tag to retrieve. Must be specified, but can be empty.
-# If dirname is specified, then module will be renamed to dirname
-# prior to building the tarball.
-# Usage: CT_GetCVS <basename> <url> <module> <tag> [dirname[=subdir]]
-# Note: if '=subdir' is given, then it is used instead of 'module'.
-CT_GetCVS() {
- local basename="$1"
- local uri="$2"
- local module="$3"
- local tag="${4:+-r ${4}}"
- local dirname="$5"
- local tmp_dir
-
- # First try locally, then the mirror
- if CT_GetFile "${basename}"; then
- # Got it! Return early!
- return 0
- fi
-
- if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
- CT_DoLog WARN "Downloads forbidden, not trying cvs retrieval"
- return 1
- fi
-
- CT_MktempDir tmp_dir
- CT_Pushd "${tmp_dir}"
-
- CT_DoExecLog ALL cvs -z 9 -d "${uri}" co -P ${tag} "${module}"
- if [ -n "${dirname}" ]; then
- case "${dirname}" in
- *=*)
- CT_DoExecLog DEBUG mv "${dirname#*=}" "${dirname%%=*}"
- CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname%%=*}"
- ;;
- *)
- CT_DoExecLog ALL mv "${module}" "${dirname}"
- CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname:-${module}}"
- ;;
- esac
- fi
- CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
-
- CT_Popd
- CT_DoExecLog ALL rm -rf "${tmp_dir}"
-}
-
-# Check out from SVN, and build the associated tarball
-# The tarball will be called ${basename}.tar.bz2
-# Prerequisite: either the server does not require password,
-# or the user must already be logged in.
-# 'rev' is the revision to retrieve
-# Usage: CT_GetSVN <basename> <url> [rev]
-CT_GetSVN() {
- local basename="$1"
- local uri="$2"
- local rev="$3"
-
- # First try locally, then the mirror
- if CT_GetFile "${basename}"; then
- # Got it! Return early!
- return 0
- fi
-
- if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
- CT_DoLog WARN "Downloads forbidden, not trying svn retrieval"
- return 1
- fi
-
- CT_MktempDir tmp_dir
- CT_Pushd "${tmp_dir}"
-
- if ! CT_DoExecLog ALL svn export ${rev:+-r ${rev}} "${uri}" "${basename}"; then
- CT_DoLog WARN "Could not retrieve '${basename}'"
- return 1
- fi
- CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${basename}"
- CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
-
- CT_Popd
- CT_DoExecLog ALL rm -rf "${tmp_dir}"
-}
-
-# Clone a git tree
-# Tries the given URLs in turn until one can get cloned. No tarball will be created.
-# Prerequisites: either the server does not require password,
-# or the user has already taken any action to authenticate to the server.
-# The cloned tree will *not* be stored in the local tarballs dir!
-# Usage: CT_GetGit <basename> <cset> <url>
-CT_GetGit() {
- local basename="${1}"
- local cset="${2}"
- local url="${3}"
- local file="${basename}-${cset}.tar.gz"
- local dir="${CT_TARBALLS_DIR}/${basename}-${cset}.git"
- local dest="${CT_TARBALLS_DIR}/${file}"
- local tmp="${CT_TARBALLS_DIR}/${file}.tmp-dl"
-
- # Do we alreadyhave it?
- if CT_GetLocal "${file}"; then
- return 0
- fi
- # Nope...
-
- if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
- CT_DoLog WARN "Downloads forbidden, not trying git retrieval"
- return 1
- fi
-
- # Add URLs on the LAN mirror
- # We subvert the normal download method, just to look for
- # looking at the local mirror
- if CT_GetFile "${basename}-${cset}" .tar.gz; then
- return 0
- fi
-
- CT_DoLog EXTRA "Retrieving '${basename}-${cset}' (git)"
-
- # Remove potential left-over from a previous run
- CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
-
- if CT_DoExecLog ALL git clone "${url}" "${dir}"; then
- # Yep, cloned OK
- CT_Pushd "${dir}"
- CT_DoExecLog ALL git archive --format=tar \
- --prefix="${basename}-${cset}/" \
- -o "${tmp}.tar" \
- "${cset}"
- CT_DoExecLog ALL gzip -9 "${tmp}.tar"
- CT_DoExecLog ALL mv -f "${tmp}.tar.gz" "${dest}"
- CT_SaveLocal "${dest}"
- CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
- CT_Popd
- else
- # Woops...
- CT_DoExecLog ALL rm -rf "${dir}"
- CT_DoLog Debug "Could not clone '${basename}'"
- return 1
- fi
-}
-
-# Extract a tarball
-# Some tarballs need to be extracted in specific places. Eg.: glibc addons
-# must be extracted in the glibc directory; uCLibc locales must be extracted
-# in the extra/locale sub-directory of uClibc. This is taken into account
-# by the caller, that did a 'cd' into the correct path before calling us
-# and sets nochdir to 'nochdir'.
-# Note also that this function handles the git trees!
-# Usage: CT_Extract [nochdir] <basename> [options]
-# where 'options' are dependent on the source (eg. git branch/tag...)
-CT_Extract() {
- local nochdir="$1"
- local basename
- local ext
- local lzma_prog
- local -a tar_opts
-
- if [ "${nochdir}" = "nochdir" ]; then
- shift
- nochdir="$(pwd)"
- else
- nochdir="${CT_SRC_DIR}"
- fi
-
- basename="$1"
- shift
-
- if ! ext="$(CT_GetFileExtension "${basename}")"; then
- CT_DoLog WARN "'${basename}' not found in '${CT_TARBALLS_DIR}'"
- return 1
- fi
- local full_file="${CT_TARBALLS_DIR}/${basename}${ext}"
-
- # Check if already extracted
- if [ -e "${CT_SRC_DIR}/.${basename}.extracted" ]; then
- CT_DoLog DEBUG "Already extracted '${basename}'"
- return 0
- fi
-
- # Check if previously partially extracted
- if [ -e "${CT_SRC_DIR}/.${basename}.extracting" ]; then
- CT_DoLog ERROR "The '${basename}' sources were partially extracted."
- CT_DoLog ERROR "Please remove first:"
- CT_DoLog ERROR " - the source dir for '${basename}', in '${CT_SRC_DIR}'"
- CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${basename}.extracting'"
- CT_Abort "I'll stop now to avoid any carnage..."
- fi
- CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracting"
-
- CT_Pushd "${nochdir}"
-
- CT_DoLog EXTRA "Extracting '${basename}'"
- CT_DoExecLog FILE mkdir -p "${basename}"
- tar_opts=( "--strip-components=1" )
- tar_opts+=( "-C" "${basename}" )
- tar_opts+=( "-xv" )
-
- # One note here:
- # - lzma can be handled either with 'xz' or 'lzma'
- # - we get lzma tarball only if either or both are available
- # - so, if we get an lzma tarball, and either 'xz' or 'lzma' is
- # missing, we can assume the other is available
- if [ "${CT_CONFIGURE_has_lzma}" = "y" ]; then
- lzma_prog="lzma -fdc"
- else
- lzma_prog="xz -fdc"
- fi
- case "${ext}" in
- .tar.xz) xz -fdc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
- .tar.lzma) ${lzma_prog} "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
- .tar.bz2) bzip2 -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
- .tar.gz|.tgz) gzip -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
- .tar) CT_DoExecLog FILE tar "${tar_opts[@]}" -f "${full_file}";;
- .zip) CT_DoExecLog FILE unzip "${@}" "${full_file}";;
- /.git) CT_ExtractGit "${basename}" "${@}";;
- *) CT_DoLog WARN "Don't know how to handle '${basename}${ext}': unknown extension"
- return 1
- ;;
- esac
-
- # Don't mark as being extracted for git
- case "${ext}" in
- /.git) ;;
- *) CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracted";;
- esac
- CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${basename}.extracting"
-
- CT_Popd
-}
-
-# Create a working git clone of a local git repository
-# Usage: CT_ExtractGit <basename> [ref]
-# where 'ref' is the reference to use:
-# the full name of a branch, like "remotes/origin/branch_name"
-# a date as understandable by git, like "YYYY-MM-DD[ hh[:mm[:ss]]]"
-# a tag name
-# If 'ref' is not given, the current repository HEAD will be used
-CT_ExtractGit() {
- local basename="${1}"
- local ref="${2}"
- local repo
- local ref_type
-
- # pushd now to be able to get git revlist in case ref is a date
- repo="${CT_TARBALLS_DIR}/${basename}"
- CT_Pushd "${repo}"
-
- # What kind of reference is ${ref} ?
- if [ -z "${ref}" ]; then
- ref_type=head
- ref=$(git rev-list -n1 HEAD)
- elif git tag |grep -E "^${ref}$" >/dev/null 2>&1; then
- ref_type=tag
- elif git branch -a --no-color |grep -E "^. ${ref}$" >/dev/null 2>&1; then
- ref_type=branch
- elif date -d "${ref}" >/dev/null 2>&1; then
- ref_type=date
- ref=$(git rev-list -n1 --before="${ref}")
- else
- CT_Abort "Reference '${ref}' is an incorrect git reference: neither tag, branch nor date"
- fi
-
- CT_Popd
-
- CT_DoExecLog FILE rmdir "${basename}"
- case "${ref_type}" in
- branch) CT_DoExecLog FILE git clone -b "${ref}" "${repo}" "${basename}" ;;
- *) CT_DoExecLog FILE git clone "${repo}" "${basename}"
- CT_Pushd "${basename}"
- CT_DoExecLog FILE git checkout "${ref}"
- CT_Popd
- ;;
- esac
-}
-
-# Patches the specified component
-# See CT_Extract, above, for explanations on 'nochdir'
-# Usage: CT_Patch [nochdir] <packagename> <packageversion>
-# If the package directory is *not* packagename-packageversion, then
-# the caller must cd into the proper directory first, and call us
-# with nochdir
-CT_Patch() {
- local nochdir="$1"
- local pkgname
- local version
- local pkgdir
- local base_file
- local ver_file
- local d
- local -a patch_dirs
- local bundled_patch_dir
- local local_patch_dir
- local bundled_exp_patch_dir
- local local_exp_patch_dir
-
- if [ "${nochdir}" = "nochdir" ]; then
- shift
- pkgname="$1"
- version="$2"
- pkgdir="${pkgname}-${version}"
- nochdir="$(pwd)"
- else
- pkgname="$1"
- version="$2"
- pkgdir="${pkgname}-${version}"
- nochdir="${CT_SRC_DIR}/${pkgdir}"
- fi
-
- # Check if already patched
- if [ -e "${CT_SRC_DIR}/.${pkgdir}.patched" ]; then
- CT_DoLog DEBUG "Already patched '${pkgdir}'"
- return 0
- fi
-
- # Check if already partially patched
- if [ -e "${CT_SRC_DIR}/.${pkgdir}.patching" ]; then
- CT_DoLog ERROR "The '${pkgdir}' sources were partially patched."
- CT_DoLog ERROR "Please remove first:"
- CT_DoLog ERROR " - the source dir for '${pkgdir}', in '${CT_SRC_DIR}'"
- CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.extracted'"
- CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.patching'"
- CT_Abort "I'll stop now to avoid any carnage..."
- fi
- touch "${CT_SRC_DIR}/.${pkgdir}.patching"
-
- CT_Pushd "${nochdir}"
-
- CT_DoLog EXTRA "Patching '${pkgdir}'"
-
- bundled_patch_dir="${CT_LIB_DIR}/patches/${pkgname}/${version}"
- local_patch_dir="${CT_LOCAL_PATCH_DIR}/${pkgname}/${version}"
-
- # Check for experimental patches, if enabled.
- if [ "${CT_EXPERIMENTAL_PATCHES}" = "y" ]; then
- bundled_exp_patch_dir="${CT_LIB_DIR}/patches/experimental/${pkgname}/${version}"
- local_exp_patch_dir="${CT_LOCAL_PATCH_DIR}/experimental/${pkgname}/${version}"
- fi
-
- case "${CT_PATCH_ORDER}" in
- bundled) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
- local) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}");;
- bundled,local) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}" "${local_patch_dir}" "${local_exp_patch_dir}");;
- local,bundled) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}" "${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
- none) patch_dirs=;;
- esac
-
- for d in "${patch_dirs[@]}"; do
- CT_DoLog DEBUG "Looking for patches in '${d}'..."
- if [ -n "${d}" -a -d "${d}" ]; then
- for p in "${d}"/*.patch; do
- if [ -f "${p}" ]; then
- CT_DoExecLog ALL patch --no-backup-if-mismatch -g0 -F1 -p1 -f -i "${p}"
- fi
- done
- if [ "${CT_PATCH_SINGLE}" = "y" ]; then
- break
- fi
- fi
- done
-
- if [ "${CT_OVERIDE_CONFIG_GUESS_SUB}" = "y" ]; then
- CT_DoLog ALL "Overiding config.guess and config.sub"
- for cfg in config_guess config_sub; do
- eval ${cfg}="${CT_LIB_DIR}/scripts/${cfg/_/.}"
- [ -e "${CT_TOP_DIR}/scripts/${cfg/_/.}" ] && eval ${cfg}="${CT_TOP_DIR}/scripts/${cfg/_/.}"
- # Can't use CT_DoExecLog because of the '{} \;' to be passed un-mangled to find
- find . -type f -name "${cfg/_/.}" -exec cp -v "${!cfg}" {} \; |CT_DoLog ALL
- done
- fi
-
- CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${pkgdir}.patched"
- CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${pkgdir}.patching"
-
- CT_Popd
-}
-
-# Two wrappers to call config.(guess|sub) either from CT_TOP_DIR or CT_LIB_DIR.
-# Those from CT_TOP_DIR, if they exist, will be be more recent than those from CT_LIB_DIR.
-CT_DoConfigGuess() {
- if [ -x "${CT_TOP_DIR}/scripts/config.guess" ]; then
- "${CT_TOP_DIR}/scripts/config.guess"
- else
- "${CT_LIB_DIR}/scripts/config.guess"
- fi
-}
-
-CT_DoConfigSub() {
- if [ -x "${CT_TOP_DIR}/scripts/config.sub" ]; then
- "${CT_TOP_DIR}/scripts/config.sub" "$@"
- else
- "${CT_LIB_DIR}/scripts/config.sub" "$@"
- fi
-}
-
-# Compute the target tuple from what is provided by the user
-# Usage: CT_DoBuildTargetTuple
-# In fact this function takes the environment variables to build the target
-# tuple. It is needed both by the normal build sequence, as well as the
-# sample saving sequence.
-CT_DoBuildTargetTuple() {
- # Set the endianness suffix, and the default endianness gcc option
- case "${CT_ARCH_ENDIAN}" in
- big)
- target_endian_eb=eb
- target_endian_be=be
- target_endian_el=
- target_endian_le=
- CT_ARCH_ENDIAN_CFLAG="-mbig-endian"
- CT_ARCH_ENDIAN_LDFLAG="-Wl,-EB"
- ;;
- little)
- target_endian_eb=
- target_endian_be=
- target_endian_el=el
- target_endian_le=le
- CT_ARCH_ENDIAN_CFLAG="-mlittle-endian"
- CT_ARCH_ENDIAN_LDFLAG="-Wl,-EL"
- ;;
- esac
-
- # Set the bitness suffix
- case "${CT_ARCH_BITNESS}" in
- 32)
- target_bits_32=32
- target_bits_64=
- ;;
- 64)
- target_bits_32=
- target_bits_64=64
- ;;
- esac
-
- # Build the default architecture tuple part
- CT_TARGET_ARCH="${CT_ARCH}${CT_ARCH_SUFFIX}"
-
- # Set defaults for the system part of the tuple. Can be overriden
- # by architecture-specific values.
- case "${CT_LIBC}" in
- *glibc) CT_TARGET_SYS=gnu;;
- uClibc) CT_TARGET_SYS=uclibc;;
- *) CT_TARGET_SYS=elf;;
- esac
-
- # Set the default values for ARCH, ABI, CPU, TUNE, FPU and FLOAT
- unset CT_ARCH_ARCH_CFLAG CT_ARCH_ABI_CFLAG CT_ARCH_CPU_CFLAG CT_ARCH_TUNE_CFLAG CT_ARCH_FPU_CFLAG CT_ARCH_FLOAT_CFLAG
- unset CT_ARCH_WITH_ARCH CT_ARCH_WITH_ABI CT_ARCH_WITH_CPU CT_ARCH_WITH_TUNE CT_ARCH_WITH_FPU CT_ARCH_WITH_FLOAT
- [ "${CT_ARCH_ARCH}" ] && { CT_ARCH_ARCH_CFLAG="-march=${CT_ARCH_ARCH}"; CT_ARCH_WITH_ARCH="--with-arch=${CT_ARCH_ARCH}"; }
- [ "${CT_ARCH_ABI}" ] && { CT_ARCH_ABI_CFLAG="-mabi=${CT_ARCH_ABI}"; CT_ARCH_WITH_ABI="--with-abi=${CT_ARCH_ABI}"; }
- [ "${CT_ARCH_CPU}" ] && { CT_ARCH_CPU_CFLAG="-mcpu=${CT_ARCH_CPU}"; CT_ARCH_WITH_CPU="--with-cpu=${CT_ARCH_CPU}"; }
- [ "${CT_ARCH_TUNE}" ] && { CT_ARCH_TUNE_CFLAG="-mtune=${CT_ARCH_TUNE}"; CT_ARCH_WITH_TUNE="--with-tune=${CT_ARCH_TUNE}"; }
- [ "${CT_ARCH_FPU}" ] && { CT_ARCH_FPU_CFLAG="-mfpu=${CT_ARCH_FPU}"; CT_ARCH_WITH_FPU="--with-fpu=${CT_ARCH_FPU}"; }
-
- case "${CT_ARCH_FLOAT}" in
- hard)
- CT_ARCH_FLOAT_CFLAG="-mhard-float"
- CT_ARCH_WITH_FLOAT="--with-float=hard"
- ;;
- soft)
- CT_ARCH_FLOAT_CFLAG="-msoft-float"
- CT_ARCH_WITH_FLOAT="--with-float=soft"
- ;;
- softfp)
- CT_ARCH_FLOAT_CFLAG="-mfloat-abi=softfp"
- CT_ARCH_WITH_FLOAT="--with-float=softfp"
- ;;
- esac
-
- # Build the default kernel tuple part
- CT_TARGET_KERNEL="${CT_KERNEL}"
-
- # Overide the default values with the components specific settings
- CT_DoArchTupleValues
- CT_DoKernelTupleValues
-
- # Finish the target tuple construction
- CT_TARGET="${CT_TARGET_ARCH}"
- CT_TARGET="${CT_TARGET}${CT_TARGET_VENDOR:+-${CT_TARGET_VENDOR}}"
- CT_TARGET="${CT_TARGET}${CT_TARGET_KERNEL:+-${CT_TARGET_KERNEL}}"
- CT_TARGET="${CT_TARGET}${CT_TARGET_SYS:+-${CT_TARGET_SYS}}"
-
- # Sanity checks
- __sed_alias=""
- if [ -n "${CT_TARGET_ALIAS_SED_EXPR}" ]; then
- __sed_alias=$(echo "${CT_TARGET}" |sed -r -e "${CT_TARGET_ALIAS_SED_EXPR}")
- fi
- case ":${CT_TARGET_VENDOR}:${CT_TARGET_ALIAS}:${__sed_alias}:" in
- :*" "*:*:*:) CT_Abort "Don't use spaces in the vendor string, it breaks things.";;
- :*"-"*:*:*:) CT_Abort "Don't use dashes in the vendor string, it breaks things.";;
- :*:*" "*:*:) CT_Abort "Don't use spaces in the target alias, it breaks things.";;
- :*:*:*" "*:) CT_Abort "Don't use spaces in the target sed transform, it breaks things.";;
- esac
-
- # Canonicalise it
- CT_TARGET=$(CT_DoConfigSub "${CT_TARGET}")
- # Prepare the target CFLAGS
- CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ENDIAN_CFLAG}"
- CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ARCH_CFLAG}"
- CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ABI_CFLAG}"
- CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_CPU_CFLAG}"
- CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_TUNE_CFLAG}"
- CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FPU_CFLAG}"
- CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FLOAT_CFLAG}"
-
- # Now on for the target LDFLAGS
- CT_ARCH_TARGET_LDFLAGS="${CT_ARCH_TARGET_LDFLAGS} ${CT_ARCH_ENDIAN_LDFLAG}"
-}
-
-# This function does pause the build until the user strikes "Return"
-# Usage: CT_DoPause [optional_message]
-CT_DoPause() {
- local foo
- local message="${1:-Pausing for your pleasure}"
- CT_DoLog INFO "${message}"
- read -p "Press 'Enter' to continue, or Ctrl-C to stop..." foo >&6
- return 0
-}
-
-# This function creates a tarball of the specified directory, but
-# only if it exists
-# Usage: CT_DoTarballIfExists <dir> <tarball_basename> [extra_tar_options [...]]
-CT_DoTarballIfExists() {
- local dir="$1"
- local tarball="$2"
- shift 2
- local -a extra_tar_opts=( "$@" )
- local -a compress
-
- case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
- y) compress=( gzip -c -3 - ); tar_ext=.gz;;
- *) compress=( cat - ); tar_ext=;;
- esac
-
- if [ -d "${dir}" ]; then
- CT_DoLog DEBUG " Saving '${dir}'"
- { tar c -C "${dir}" -v -f - "${extra_tar_opts[@]}" . \
- |"${compress[@]}" >"${tarball}.tar${tar_ext}" ;
- } 2>&1 |sed -r -e 's/^/ /;' |CT_DoLog STATE
- else
- CT_DoLog STATE " Not saving '${dir}': does not exist"
- fi
-}
-
-# This function extracts a tarball to the specified directory, but
-# only if the tarball exists
-# Usage: CT_DoExtractTarballIfExists <tarball_basename> <dir> [extra_tar_options [...]]
-CT_DoExtractTarballIfExists() {
- local tarball="$1"
- local dir="$2"
- shift 2
- local -a extra_tar_opts=( "$@" )
- local -a uncompress
-
- case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
- y) uncompress=( gzip -c -d ); tar_ext=.gz;;
- *) uncompress=( cat ); tar_ext=;;
- esac
-
- if [ -f "${tarball}.tar${tar_ext}" ]; then
- CT_DoLog DEBUG " Restoring '${dir}'"
- CT_DoForceRmdir "${dir}"
- CT_DoExecLog DEBUG mkdir -p "${dir}"
- { "${uncompress[@]}" "${tarball}.tar${tar_ext}" \
- |tar x -C "${dir}" -v -f - "${extra_tar_opts[@]}" ;
- } 2>&1 |sed -r -e 's/^/ /;' |CT_DoLog STATE
- else
- CT_DoLog STATE " Not restoring '${dir}': does not exist"
- fi
-}
-
-# This function saves the state of the toolchain to be able to restart
-# at any one point
-# Usage: CT_DoSaveState <next_step_name>
-CT_DoSaveState() {
- [ "${CT_DEBUG_CT_SAVE_STEPS}" = "y" ] || return 0
- local state_name="$1"
- local state_dir="${CT_STATE_DIR}/${state_name}"
-
- # Log this to the log level required by the user
- CT_DoLog ${CT_LOG_LEVEL_MAX} "Saving state to restart at step '${state_name}'..."
-
- rm -rf "${state_dir}"
- mkdir -p "${state_dir}"
-
- CT_DoLog STATE " Saving environment and aliases"
- # We must omit shell functions, and some specific bash variables
- # that break when restoring the environment, later. We could do
- # all the processing in the awk script, but a sed is easier...
- set |awk '
- BEGIN { _p = 1; }
- $0~/^[^ ]+ \(\)/ { _p = 0; }
- _p == 1
- $0 == "}" { _p = 1; }
- ' |sed -r -e '/^BASH_(ARGC|ARGV|LINENO|SOURCE|VERSINFO)=/d;
- /^(UID|EUID)=/d;
- /^(FUNCNAME|GROUPS|PPID|SHELLOPTS)=/d;' >"${state_dir}/env.sh"
-
- CT_DoTarballIfExists "${CT_BUILDTOOLS_PREFIX_DIR}" "${state_dir}/buildtools_dir"
- CT_DoTarballIfExists "${CT_CONFIG_DIR}" "${state_dir}/config_dir"
- CT_DoTarballIfExists "${CT_PREFIX_DIR}" "${state_dir}/prefix_dir" --exclude '*.log'
-
- CT_DoLog STATE " Saving log file"
- exec >/dev/null
- case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
- y) gzip -3 -c "${tmp_log_file}" >"${state_dir}/log.gz";;
- *) cat "${tmp_log_file}" >"${state_dir}/log";;
- esac
- exec >>"${tmp_log_file}"
-}
-
-# This function restores a previously saved state
-# Usage: CT_DoLoadState <state_name>
-CT_DoLoadState(){
- local state_name="$1"
- local state_dir="${CT_STATE_DIR}/${state_name}"
- local old_RESTART="${CT_RESTART}"
- local old_STOP="${CT_STOP}"
-
- CT_TestOrAbort "The previous build did not reach the point where it could be restarted at '${CT_RESTART}'" -d "${state_dir}"
-
- # We need to do something special with the log file!
- if [ "${CT_LOG_TO_FILE}" = "y" ]; then
- exec >"${state_dir}/tail.log"
- fi
-
- # Log this to the log level required by the user
- CT_DoLog ${CT_LOG_LEVEL_MAX} "Restoring state at step '${state_name}', as requested."
-
- CT_DoExtractTarballIfExists "${state_dir}/prefix_dir" "${CT_PREFIX_DIR}"
- CT_DoExtractTarballIfExists "${state_dir}/config_dir" "${CT_CONFIG_DIR}"
- CT_DoExtractTarballIfExists "${state_dir}/buildtools_dir" "${CT_BUILDTOOLS_PREFIX_DIR}"
-
- # Restore the environment, discarding any error message
- # (for example, read-only bash internals)
- CT_DoLog STATE " Restoring environment"
- . "${state_dir}/env.sh" >/dev/null 2>&1 || true
-
- # Restore the new RESTART and STOP steps
- CT_RESTART="${old_RESTART}"
- CT_STOP="${old_STOP}"
- unset old_stop old_restart
-
- CT_DoLog STATE " Restoring log file"
- exec >/dev/null
- case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
- y) gzip -dc "${state_dir}/log.gz" >"${tmp_log_file}";;
- *) cat "${state_dir}/log" >"${tmp_log_file}";;
- esac
- cat "${state_dir}/tail.log" >>"${tmp_log_file}"
- exec >>"${tmp_log_file}"
- rm -f "${state_dir}/tail.log"
-}
diff --git a/scripts/functions.in b/scripts/functions.in
new file mode 100644
index 0000000..51bf4a1
--- /dev/null
+++ b/scripts/functions.in
@@ -0,0 +1,1395 @@
+# This file contains some usefull common functions -*- sh -*-
+# Copyright 2007 Yann E. MORIN
+# Licensed under the GPL v2. See COPYING in the root of this package
+
+# Prepare the fault handler
+CT_OnError() {
+ local ret=$?
+ local result
+ local old_trap
+ local intro
+ local file line func
+ local step step_depth
+
+ # To avoid printing the backtace for each sub-shell
+ # up to the top-level, just remember we've dumped it
+ if [ ! -f "${CT_WORK_DIR}/backtrace" ]; then
+ touch "${CT_WORK_DIR}/backtrace"
+
+ # Print steps backtrace
+ step_depth=${CT_STEP_COUNT}
+ CT_STEP_COUNT=1 # To have a zero-indentation
+ CT_DoLog ERROR ""
+ CT_DoLog ERROR ">>"
+ intro="Build failed"
+ for((step=step_depth; step>0; step--)); do
+ CT_DoLog ERROR ">> ${intro} in step '${CT_STEP_MESSAGE[${step}]}'"
+ intro=" called"
+ done
+
+ # Print functions backtrace
+ intro="Error happened in"
+ CT_DoLog ERROR ">>"
+ for((depth=1; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
+ file="${BASH_SOURCE[${depth}]#${CT_LIB_DIR}/}"
+ func="${FUNCNAME[${depth}]}"
+ line="@${BASH_LINENO[${depth}-1]:-?}"
+ CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
+ intro=" called from"
+ done
+
+ # If the user asked for interactive debugging, dump him/her to a shell
+ if [ "${CT_DEBUG_INTERACTIVE}" = "y" ]; then
+ # We do not want this sub-shell exit status to be caught, because
+ # it is absolutely legit that it exits with non-zero.
+ # Save the trap handler to restore it after our debug-shell
+ old_trap="$(trap -p ERR)"
+ trap -- ERR
+ (
+ exec >&6 2>&7 <&8
+ printf "\r \n\nCurrent command"
+ if [ -n "${cur_cmd}" ]; then
+ printf ":\n %s\n" "${cur_cmd}"
+ else
+ printf " (unknown), "
+ fi
+ printf "exited with error code: %d\n" ${ret}
+ printf "Please fix it up and finish by exiting the shell with one of these values:\n"
+ printf " 1 fixed, continue with next build command\n"
+ if [ -n "${cur_cmd}" ]; then
+ printf " 2 repeat this build command\n"
+ fi
+ printf " 3 abort build\n\n"
+ while true; do
+ ${bash} --rcfile <(printf "PS1='ct-ng:\w> '\nPROMPT_COMMAND=''\n") -i
+ result=$?
+ case $result in
+ 1) printf "\nContinuing past the failed command.\n\n"
+ break
+ ;;
+ 2) if [ -n "${cur_cmd}" ]; then
+ printf "\nRe-trying last command.\n\n"
+ break
+ fi
+ ;;
+ 3) break;;
+ esac
+ printf "\nPlease exit with one of these values:\n"
+ printf " 1 fixed, continue with next build command\n"
+ if [ -n "${cur_cmd}" ]; then
+ printf " 2 repeat this build command\n"
+ fi
+ printf " 3 abort build\n"
+ done
+ exit $result
+ )
+ result=$?
+ # Restore the trap handler
+ eval "${old_trap}"
+ case "${result}" in
+ 1) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/skip"; return;;
+ 2) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/repeat"; return;;
+ # 3 is an abort, continue...
+ esac
+ fi
+ fi
+
+ # And finally, in top-level shell, print some hints
+ if [ ${BASH_SUBSHELL} -eq 0 ]; then
+ # Help diagnose the error
+ CT_STEP_COUNT=1 # To have a zero-indentation
+ CT_DoLog ERROR ">>"
+ if [ "${CT_LOG_TO_FILE}" = "y" ]; then
+ CT_DoLog ERROR ">> For more info on this error, look at the file: '${tmp_log_file#${CT_TOP_DIR}/}'"
+ fi
+ CT_DoLog ERROR ">> There is a list of known issues, some with workarounds, in:"
+ CT_DoLog ERROR ">> '${CT_DOC_DIR#${CT_TOP_DIR}/}/B - Known issues.txt'"
+
+ CT_DoLog ERROR ""
+ CT_DoEnd ERROR
+ rm -f "${CT_WORK_DIR}/backtrace"
+ fi
+ exit $ret
+}
+
+# Install the fault handler
+trap CT_OnError ERR
+
+# Inherit the fault handler in subshells and functions
+set -E
+
+# Make pipes fail on the _first_ failed command
+# Not supported on bash < 3.x, but we need it, so drop the obsoleting bash-2.x
+set -o pipefail
+
+# Don't hash commands' locations, and search every time it is requested.
+# This is slow, but needed because of the static/shared core gcc which shall
+# always match to shared if it exists, and only fallback to static if the
+# shared is not found
+set +o hashall
+
+# Log policy:
+# - first of all, save stdout so we can see the live logs: fd #6
+# (also save stdin and stderr for use by CT_DEBUG_INTERACTIVE)
+exec 6>&1 7>&2 8<&0
+# - then point stdout to the log file
+tmp_log_file="${CT_TOP_DIR}/build.log"
+rm -f "${tmp_log_file}"
+exec >>"${tmp_log_file}"
+
+# The different log levels:
+CT_LOG_LEVEL_ERROR=0
+CT_LOG_LEVEL_WARN=1
+CT_LOG_LEVEL_INFO=2
+CT_LOG_LEVEL_EXTRA=3
+CT_LOG_LEVEL_CFG=4
+CT_LOG_LEVEL_FILE=5
+CT_LOG_LEVEL_STATE=6
+CT_LOG_LEVEL_ALL=7
+CT_LOG_LEVEL_DEBUG=8
+
+# Make it easy to use \n and !
+CR=$(printf "\n")
+BANG='!'
+
+# A function to log what is happening
+# Different log level are available:
+# - ERROR: A serious, fatal error occurred
+# - WARN: A non fatal, non serious error occurred, take your responsbility with the generated build
+# - INFO: Informational messages
+# - EXTRA: Extra informational messages
+# - CFG: Output of various "./configure"-type scripts
+# - FILE: File / archive unpacking.
+# - STATE: State save & restore
+# - ALL: Component's build messages
+# - DEBUG: Internal debug messages
+# Usage: CT_DoLog <level> [message]
+# If message is empty, then stdin will be logged.
+CT_DoLog() {
+ local max_level LEVEL level cur_l cur_L
+ local l
+ eval max_level="\${CT_LOG_LEVEL_${CT_LOG_LEVEL_MAX}}"
+ # Set the maximum log level to DEBUG if we have none
+ [ -z "${max_level}" ] && max_level=${CT_LOG_LEVEL_DEBUG}
+
+ LEVEL="$1"; shift
+ eval level="\${CT_LOG_LEVEL_${LEVEL}}"
+
+ if [ $# -eq 0 ]; then
+ cat -
+ else
+ printf "%s\n" "${*}"
+ fi |( IFS="${CR}" # We want the full lines, even leading spaces
+ _prog_bar_cpt=0
+ _prog_bar[0]='/'
+ _prog_bar[1]='-'
+ _prog_bar[2]='\'
+ _prog_bar[3]='|'
+ indent=$((2*CT_STEP_COUNT))
+ while read line; do
+ case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
+ y,*"warning:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
+ y,*"WARNING:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
+ *"error:"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
+ *"make["*"]: *** ["*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
+ *) cur_L="${LEVEL}"; cur_l="${level}";;
+ esac
+ # There will always be a log file (stdout, fd #1), be it /dev/null
+ printf "[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}"
+ if [ ${cur_l} -le ${max_level} ]; then
+ # Only print to console (fd #6) if log level is high enough.
+ printf "${CT_LOG_PROGRESS_BAR:+\r}[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}" >&6
+ fi
+ if [ "${CT_LOG_PROGRESS_BAR}" = "y" ]; then
+ printf "\r[%02d:%02d] %s " $((SECONDS/60)) $((SECONDS%60)) "${_prog_bar[$((_prog_bar_cpt/10))]}" >&6
+ _prog_bar_cpt=$(((_prog_bar_cpt+1)%40))
+ fi
+ done
+ )
+
+ return 0
+}
+
+# Execute an action, and log its messages
+# It is possible to even log local variable assignments (a-la: var=val ./cmd opts)
+# Usage: CT_DoExecLog <level> [VAR=val...] <command> [parameters...]
+CT_DoExecLog() {
+ local level="$1"
+ local cur_cmd
+ local ret
+ shift
+ (
+ for i in "$@"; do
+ cur_cmd+="'${i}' "
+ done
+ while true; do
+ case "${1}" in
+ *=*) eval export "'${1}'"; shift;;
+ *) break;;
+ esac
+ done
+ # This while-loop goes hand-in-hand with the ERR trap handler:
+ # - if the command terminates successfully, then we hit the break
+ # statement, and we exit the loop
+ # - if the command terminates in error, then the ERR handler kicks
+ # in, then:
+ # - if the user did *not* ask for interactive debugging, the ERR
+ # handler exits, and we hit the end of the sub-shell
+ # - if the user did ask for interactive debugging, the ERR handler
+ # spawns a shell. Upon termination of this shell, the ERR handler
+ # examines the exit status of the shell:
+ # - if 1, the ERR handler returns; then we hit the else statement,
+ # then the break, and we exit the 'while' loop, to continue the
+ # build;
+ # - if 2, the ERR handler touches the repeat file, and returns;
+ # then we hit the if statement, and we loop for one more
+ # iteration;
+ # - if 3, the ERR handler exits with the command's exit status,
+ # and we're dead;
+ # - for any other exit status of the shell, the ERR handler
+ # prints an informational message, and respawns the shell
+ #
+ # This allows a user to get an interactive shell that has the same
+ # environment (PATH and so on) that the failed command was ran with.
+ while true; do
+ rm -f "${CT_BUILD_DIR}/repeat"
+ CT_DoLog DEBUG "==> Executing: ${cur_cmd}"
+ "${@}" 2>&1 |CT_DoLog "${level}"
+ ret="${?}"
+ if [ -f "${CT_BUILD_DIR}/repeat" ]; then
+ rm -f "${CT_BUILD_DIR}/repeat"
+ continue
+ elif [ -f "${CT_BUILD_DIR}/skip" ]; then
+ rm -f "${CT_BUILD_DIR}/skip"
+ ret=0
+ break
+ else
+ break
+ fi
+ done
+ exit ${ret}
+ )
+ # Catch failure of the sub-shell
+ [ $? -eq 0 ]
+}
+
+# Tail message to be logged whatever happens
+# Usage: CT_DoEnd <level>
+CT_DoEnd()
+{
+ local level="$1"
+ CT_STOP_DATE=$(CT_DoDate +%s%N)
+ CT_STOP_DATE_HUMAN=$(CT_DoDate +%Y%m%d.%H%M%S)
+ if [ "${level}" != "ERROR" ]; then
+ CT_DoLog "${level:-INFO}" "Build completed at ${CT_STOP_DATE_HUMAN}"
+ fi
+ elapsed=$((CT_STOP_DATE-CT_STAR_DATE))
+ elapsed_min=$((elapsed/(60*1000*1000*1000)))
+ elapsed_sec=$(printf "%02d" $(((elapsed%(60*1000*1000*1000))/(1000*1000*1000))))
+ elapsed_csec=$(printf "%02d" $(((elapsed%(1000*1000*1000))/(10*1000*1000))))
+ CT_DoLog ${level:-INFO} "(elapsed: ${elapsed_min}:${elapsed_sec}.${elapsed_csec})"
+}
+
+# Remove entries referring to . and other relative paths
+# Usage: CT_SanitizePath
+CT_SanitizePath() {
+ local new
+ local p
+ local IFS=:
+ for p in $PATH; do
+ # Only accept absolute paths;
+ # Note: as a special case the empty string in PATH is equivalent to .
+ if [ -n "${p}" -a -z "${p%%/*}" ]; then
+ new="${new}${new:+:}${p}"
+ fi
+ done
+ PATH="${new}"
+}
+
+# Sanitise the directory name contained in the variable passed as argument:
+# - remove duplicate /
+# Usage: CT_SanitiseVarDir CT_PREFIX_DIR
+CT_SanitiseVarDir() {
+ local var
+ local old_dir
+ local new_dir
+
+ for var in "$@"; do
+ eval "old_dir=\"\${${var}}\""
+ new_dir="$( printf "${old_dir}" \
+ |@@CT_sed@@ -r -e 's:/+:/:g;' \
+ )"
+ eval "${var}=\"${new_dir}\""
+ CT_DoLog DEBUG "Sanitised '${var}': '${old_dir}' -> '${new_dir}'"
+ done
+}
+
+# Abort the execution with an error message
+# Usage: CT_Abort <message>
+CT_Abort() {
+ CT_DoLog ERROR "$1"
+ false
+}
+
+# Test a condition, and print a message if satisfied
+# Usage: CT_Test <message> <tests>
+CT_Test() {
+ local ret
+ local m="$1"
+ shift
+ CT_DoLog DEBUG "Testing '! ( $* )'"
+ test "$@" && CT_DoLog WARN "$m"
+ return 0
+}
+
+# Test a condition, and abort with an error message if satisfied
+# Usage: CT_TestAndAbort <message> <tests>
+CT_TestAndAbort() {
+ local m="$1"
+ shift
+ CT_DoLog DEBUG "Testing '! ( $* )'"
+ test "$@" && CT_Abort "$m"
+ return 0
+}
+
+# Test a condition, and abort with an error message if not satisfied
+# Usage: CT_TestAndAbort <message> <tests>
+CT_TestOrAbort() {
+ local m="$1"
+ shift
+ CT_DoLog DEBUG "Testing '$*'"
+ test "$@" || CT_Abort "$m"
+ return 0
+}
+
+# Test the presence of a tool, or abort if not found
+# Usage: CT_HasOrAbort <tool>
+CT_HasOrAbort() {
+ CT_TestAndAbort "'${1}' not found and needed for successful toolchain build." -z "$(CT_Which "${1}")"
+ return 0
+}
+
+# Search a program: wrap "which" for those system where "which"
+# verbosely says there is no match (such as on Mandriva).
+# Usage: CT_Which <filename>
+CT_Which() {
+ which "$1" 2>/dev/null || true
+}
+
+# Get current date with nanosecond precision
+# On those system not supporting nanosecond precision, faked with rounding down
+# to the highest entire second
+# Usage: CT_DoDate <fmt>
+CT_DoDate() {
+ date "$1" |@@CT_sed@@ -r -e 's/%?N$/000000000/;'
+}
+
+CT_STEP_COUNT=1
+CT_STEP_MESSAGE[${CT_STEP_COUNT}]="(top-level)"
+# Memorise a step being done so that any error is caught
+# Usage: CT_DoStep <loglevel> <message>
+CT_DoStep() {
+ local start=$(CT_DoDate +%s%N)
+ CT_DoLog "$1" "================================================================="
+ CT_DoLog "$1" "$2"
+ CT_STEP_COUNT=$((CT_STEP_COUNT+1))
+ CT_STEP_LEVEL[${CT_STEP_COUNT}]="$1"; shift
+ CT_STEP_START[${CT_STEP_COUNT}]="${start}"
+ CT_STEP_MESSAGE[${CT_STEP_COUNT}]="$1"
+ return 0
+}
+
+# End the step just being done
+# Usage: CT_EndStep
+CT_EndStep() {
+ local stop=$(CT_DoDate +%s%N)
+ local duration=$(printf "%032d" $((stop-${CT_STEP_START[${CT_STEP_COUNT}]})) |@@CT_sed@@ -r -e 's/([[:digit:]]{2})[[:digit:]]{7}$/\.\1/; s/^0+//; s/^\./0\./;')
+ local elapsed=$(printf "%02d:%02d" $((SECONDS/60)) $((SECONDS%60)))
+ local level="${CT_STEP_LEVEL[${CT_STEP_COUNT}]}"
+ local message="${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}"
+ CT_STEP_COUNT=$((CT_STEP_COUNT-1))
+ CT_DoLog "${level}" "${message}: done in ${duration}s (at ${elapsed})"
+ return 0
+}
+
+# Pushes into a directory, and pops back
+CT_Pushd() {
+ CT_DoLog DEBUG "Entering '$1'"
+ pushd "$1" >/dev/null 2>&1
+}
+CT_Popd() {
+ popd >/dev/null 2>&1
+}
+
+# Create a dir and cd or pushd into it
+# Usage: CT_mkdir_cd <dir/to/create>
+# CT_mkdir_pushd <dir/to/create>
+CT_mkdir_cd() {
+ local dir="${1}"
+
+ mkdir -p "${dir}"
+ cd "${dir}"
+}
+CT_mkdir_pushd() {
+ local dir="${1}"
+
+ mkdir -p "${dir}"
+ CT_Pushd "${dir}"
+}
+
+# Creates a temporary directory
+# $1: variable to assign to
+# Usage: CT_MktempDir foo
+CT_MktempDir() {
+ # Some mktemp do not allow more than 6 Xs
+ eval "$1"=$(mktemp -q -d "${CT_BUILD_DIR}/tmp.XXXXXX")
+ CT_TestOrAbort "Could not make temporary directory" -n "${!1}" -a -d "${!1}"
+ CT_DoLog DEBUG "Made temporary directory '${!1}'"
+ return 0
+}
+
+# Removes one or more directories, even if it is read-only, or its parent is
+# Usage: CT_DoForceRmdir dir [...]
+CT_DoForceRmdir() {
+ local dir
+ local mode
+ for dir in "${@}"; do
+ [ -d "${dir}" ] || continue
+ case "$CT_SYS_OS" in
+ Linux|CYGWIN*)
+ mode="$(stat -c '%a' "$(dirname "${dir}")")"
+ ;;
+ Darwin|*BSD)
+ mode="$(stat -f '%Lp' "$(dirname "${dir}")")"
+ ;;
+ *)
+ CT_Abort "Unhandled host OS $CT_SYS_OS"
+ ;;
+ esac
+ CT_DoExecLog ALL chmod u+w "$(dirname "${dir}")"
+ CT_DoExecLog ALL chmod -R u+w "${dir}"
+ CT_DoExecLog ALL rm -rf "${dir}"
+ CT_DoExecLog ALL chmod ${mode} "$(dirname "${dir}")"
+ done
+}
+
+# Echoes the specified string on stdout until the pipe breaks.
+# Doesn't fail
+# $1: string to echo
+# Usage: CT_DoYes "" |make oldconfig
+CT_DoYes() {
+ yes "$1" || true
+}
+
+# Add the specified directory to LD_LIBRARY_PATH, and export it
+# If the specified patch is already present, just export
+# $1: path to add
+# $2: add as 'first' or 'last' path, 'first' is assumed if $2 is empty
+# Usage CT_SetLibPath /some/where/lib [first|last]
+CT_SetLibPath() {
+ local path="$1"
+ local pos="$2"
+
+ case ":${LD_LIBRARY_PATH}:" in
+ *:"${path}":*) ;;
+ *) case "${pos}" in
+ last)
+ CT_DoLog DEBUG "Adding '${path}' at end of LD_LIBRARY_PATH"
+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${path}"
+ ;;
+ first|"")
+ CT_DoLog DEBUG "Adding '${path}' at start of LD_LIBRARY_PATH"
+ LD_LIBRARY_PATH="${path}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
+ ;;
+ *)
+ CT_Abort "Incorrect position '${pos}' to add '${path}' to LD_LIBRARY_PATH"
+ ;;
+ esac
+ ;;
+ esac
+ CT_DoLog DEBUG "==> LD_LIBRARY_PATH='${LD_LIBRARY_PATH}'"
+ export LD_LIBRARY_PATH
+}
+
+# Build up the list of allowed tarball extensions
+# Add them in the prefered order; most preferred comes first
+CT_DoListTarballExt() {
+ if [ "${CT_CONFIGURE_has_xz}" = "y" ]; then
+ printf ".tar.xz\n"
+ fi
+ if [ "${CT_CONFIGURE_has_lzma}" = "y" \
+ -o "${CT_CONFIGURE_has_xz}" = "y" ]; then
+ printf ".tar.lzma\n"
+ fi
+ printf ".tar.bz2\n"
+ printf ".tar.gz\n.tgz\n"
+ printf ".tar\n"
+ printf ".zip\n"
+}
+
+# Get the file name extension of a component
+# Usage: CT_GetFileExtension <component_name-component_version> [extension]
+# If found, echoes the extension to stdout, and return 0
+# If not found, echoes nothing on stdout, and return !0.
+CT_GetFileExtension() {
+ local ext
+ local file="$1"
+ shift
+ local first_ext="$1"
+
+ # we need to also check for an empty extension for those very
+ # peculiar components that don't have one (such as sstrip from
+ # buildroot).
+ for ext in ${first_ext} $(CT_DoListTarballExt) /.git ''; do
+ if [ -e "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
+ echo "${ext}"
+ exit 0
+ fi
+ done
+
+ exit 1
+}
+
+# Try to retrieve the specified URL (HTTP or FTP)
+# Usage: CT_DoGetFile <URL>
+# This functions always returns true (0), as it can be legitimate not
+# to find the requested URL (think about snapshots, different layouts
+# for different gcc versions, etc...).
+CT_DoGetFile() {
+ local url="${1}"
+ local dest="${CT_TARBALLS_DIR}/${url##*/}"
+ local tmp="${dest}.tmp-dl"
+
+ # Remove potential left-over from a previous run
+ rm -f "${tmp}"
+
+ # We also retry a few times, in case there is a transient error (eg. behind
+ # a dynamic IP that changes during the transfer...)
+ # With automated download as we are doing, it can be very dangerous to
+ # continue the downloads. It's far better to simply overwrite the
+ # destination file.
+ # Some company networks have firewalls to connect to the internet, but it's
+ # not easy to detect them, so force a global ${CT_CONNECT_TIMEOUT}-second
+ # timeout.
+ if [ ${CT_CONNECT_TIMEOUT} = -1 ]; then
+ T=
+ else
+ T="-T ${CT_CONNECT_TIMEOUT}"
+ fi
+ if CT_DoExecLog ALL wget --passive-ftp --tries=3 -nc \
+ --progress=dot:binary \
+ ${T} \
+ -O "${tmp}" \
+ "${url}"
+ then
+ # Success, we got it, good!
+ mv "${tmp}" "${dest}"
+ CT_DoLog DEBUG "Got it from: \"${url}\""
+ else
+ # Woops...
+ rm -f "${tmp}"
+ CT_DoLog DEBUG "Not at this location: \"${url}\""
+ fi
+}
+
+# This function tries to retrieve a tarball form a local directory
+# Usage: CT_GetLocal <basename> [.extension]
+CT_GetLocal() {
+ local basename="$1"
+ local first_ext="$2"
+ local ext
+
+ # Do we already have it in *our* tarballs dir?
+ if ext="$( CT_GetFileExtension "${basename}" ${first_ext} )"; then
+ CT_DoLog DEBUG "Already have '${basename}'"
+ return 0
+ fi
+
+ if [ -n "${CT_LOCAL_TARBALLS_DIR}" ]; then
+ CT_DoLog DEBUG "Trying to retrieve an already downloaded copy of '${basename}'"
+ # We'd rather have a bzip2'ed tarball, then gzipped tarball, plain tarball,
+ # or, as a failover, a file without extension.
+ for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
+ CT_DoLog DEBUG "Trying '${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}'"
+ if [ -r "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" -a \
+ "${CT_FORCE_DOWNLOAD}" != "y" ]; then
+ CT_DoLog DEBUG "Got '${basename}' from local storage"
+ CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" "${CT_TARBALLS_DIR}/${basename}${ext}"
+ return 0
+ fi
+ done
+ fi
+ return 1
+}
+
+# This function gets the custom source from either a tarball or directory
+# Usage: CT_GetCustom <component> <custom_version> <custom_location>
+CT_GetCustom() {
+ local custom_component="$1"
+ local custom_version="$2"
+ local custom_location="$3"
+ local custom_name="${custom_component}-${custom_version}"
+
+ CT_TestAndAbort "${custom_name}: CT_CUSTOM_LOCATION_ROOT_DIR or ${custom_component}'s CUSTOM_LOCATION must be set." \
+ -z "${CT_CUSTOM_LOCATION_ROOT_DIR}" -a -z "${custom_location}"
+
+ if [ -n "${CT_CUSTOM_LOCATION_ROOT_DIR}" \
+ -a -z "${custom_location}" ]; then
+ custom_location="${CT_CUSTOM_LOCATION_ROOT_DIR}/${custom_component}"
+ fi
+
+ CT_DoLog EXTRA "Using '${custom_name}' from custom location"
+ if [ ! -d "${custom_location}" ]; then
+ # We need to know the custom tarball extension,
+ # so we can create a properly-named symlink, which
+ # we use later on in 'extract'
+ case "${custom_location}" in
+ *.tar.xz) custom_name="${custom_name}.tar.xz";;
+ *.tar.bz2) custom_name="${custom_name}.tar.bz2";;
+ *.tar.gz|*.tgz) custom_name="${custom_name}.tar.gz";;
+ *.tar) custom_name="${custom_name}.tar";;
+ *) CT_Abort "Unknown extension for custom tarball '${custom_location}'";;
+ esac
+ CT_DoExecLog DEBUG ln -sf "${custom_location}" \
+ "${CT_TARBALLS_DIR}/${custom_name}"
+ else
+ CT_DoExecLog DEBUG ln -snf "${custom_location}" \
+ "${CT_SRC_DIR}/${custom_name}"
+ fi
+}
+
+# This function saves the specified to local storage if possible,
+# and if so, symlinks it for later usage
+# Usage: CT_SaveLocal </full/path/file.name>
+CT_SaveLocal() {
+ local file="$1"
+ local basename="${file##*/}"
+
+ if [ "${CT_SAVE_TARBALLS}" = "y" ]; then
+ CT_DoLog EXTRA "Saving '${basename}' to local storage"
+ # The file may already exist if downloads are forced: remove it first
+ CT_DoExecLog ALL rm -f "${CT_LOCAL_TARBALLS_DIR}/${basename}"
+ CT_DoExecLog ALL mv -f "${file}" "${CT_LOCAL_TARBALLS_DIR}"
+ CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}" "${file}"
+ fi
+}
+
+# Download the file from one of the URLs passed as argument
+# Usage: CT_GetFile <basename> [.extension] <url> [url ...]
+CT_GetFile() {
+ local ext
+ local -a URLS
+ local url
+ local file="$1"
+ local first_ext
+ shift
+ # If next argument starts with a dot, then this is not an URL,
+ # and we can consider that it is a preferred extension.
+ case "$1" in
+ .*) first_ext="$1"
+ shift
+ ;;
+ esac
+
+ # Does it exist localy?
+ if CT_GetLocal "${file}" ${first_ext}; then
+ return 0
+ fi
+ # No, it does not...
+
+ # If not allowed to download from the Internet, don't
+ if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
+ CT_DoLog DEBUG "Not allowed to download from the Internet, aborting ${file} download"
+ return 1
+ fi
+
+ # Try to retrieve the file
+ CT_DoLog EXTRA "Retrieving '${file}'"
+
+ # Add URLs on the LAN mirror
+ if [ "${CT_USE_MIRROR}" = "y" ]; then
+ CT_TestOrAbort "Please set the mirror base URL" -n "${CT_MIRROR_BASE_URL}"
+ URLS+=( "${CT_MIRROR_BASE_URL}/${file%-*}" )
+ URLS+=( "${CT_MIRROR_BASE_URL}" )
+ fi
+
+ if [ "${CT_FORCE_MIRROR}" != "y" ]; then
+ URLS+=( "${@}" )
+ fi
+
+ # Scan all URLs in turn, and try to grab a tarball from there
+ # Do *not* try git trees (ext=/.git), this is handled in a specific
+ # wrapper, below
+ for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
+ # Try all urls in turn
+ for url in "${URLS[@]}"; do
+ [ -n "${url}" ] || continue
+ CT_DoLog DEBUG "Trying '${url}/${file}${ext}'"
+ CT_DoGetFile "${url}/${file}${ext}"
+ if [ -f "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
+ CT_DoLog DEBUG "Got '${file}' from the Internet"
+ CT_SaveLocal "${CT_TARBALLS_DIR}/${file}${ext}"
+ return 0
+ fi
+ done
+ done
+
+ # Just return error, someone may want to catch and handle the error
+ # (eg. glibc/eglibc add-ons can be missing).
+ return 1
+}
+
+# Checkout from CVS, and build the associated tarball
+# The tarball will be called ${basename}.tar.bz2
+# Prerequisite: either the server does not require password,
+# or the user must already be logged in.
+# 'tag' is the tag to retrieve. Must be specified, but can be empty.
+# If dirname is specified, then module will be renamed to dirname
+# prior to building the tarball.
+# Usage: CT_GetCVS <basename> <url> <module> <tag> [dirname[=subdir]]
+# Note: if '=subdir' is given, then it is used instead of 'module'.
+CT_GetCVS() {
+ local basename="$1"
+ local uri="$2"
+ local module="$3"
+ local tag="${4:+-r ${4}}"
+ local dirname="$5"
+ local tmp_dir
+
+ # First try locally, then the mirror
+ if CT_GetFile "${basename}"; then
+ # Got it! Return early!
+ return 0
+ fi
+
+ if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
+ CT_DoLog WARN "Downloads forbidden, not trying cvs retrieval"
+ return 1
+ fi
+
+ CT_MktempDir tmp_dir
+ CT_Pushd "${tmp_dir}"
+
+ CT_DoExecLog ALL cvs -z 9 -d "${uri}" co -P ${tag} "${module}"
+ if [ -n "${dirname}" ]; then
+ case "${dirname}" in
+ *=*)
+ CT_DoExecLog DEBUG mv "${dirname#*=}" "${dirname%%=*}"
+ CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname%%=*}"
+ ;;
+ *)
+ CT_DoExecLog ALL mv "${module}" "${dirname}"
+ CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname:-${module}}"
+ ;;
+ esac
+ fi
+ CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
+
+ CT_Popd
+ CT_DoExecLog ALL rm -rf "${tmp_dir}"
+}
+
+# Check out from SVN, and build the associated tarball
+# The tarball will be called ${basename}.tar.bz2
+# Prerequisite: either the server does not require password,
+# or the user must already be logged in.
+# 'rev' is the revision to retrieve
+# Usage: CT_GetSVN <basename> <url> [rev]
+CT_GetSVN() {
+ local basename="$1"
+ local uri="$2"
+ local rev="$3"
+
+ # First try locally, then the mirror
+ if CT_GetFile "${basename}"; then
+ # Got it! Return early!
+ return 0
+ fi
+
+ if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
+ CT_DoLog WARN "Downloads forbidden, not trying svn retrieval"
+ return 1
+ fi
+
+ CT_MktempDir tmp_dir
+ CT_Pushd "${tmp_dir}"
+
+ if ! CT_DoExecLog ALL svn export ${rev:+-r ${rev}} "${uri}" "${basename}"; then
+ CT_DoLog WARN "Could not retrieve '${basename}'"
+ return 1
+ fi
+ CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${basename}"
+ CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
+
+ CT_Popd
+ CT_DoExecLog ALL rm -rf "${tmp_dir}"
+}
+
+# Clone a git tree
+# Tries the given URLs in turn until one can get cloned. No tarball will be created.
+# Prerequisites: either the server does not require password,
+# or the user has already taken any action to authenticate to the server.
+# The cloned tree will *not* be stored in the local tarballs dir!
+# Usage: CT_GetGit <basename> <cset> <url>
+CT_GetGit() {
+ local basename="${1}"
+ local cset="${2}"
+ local url="${3}"
+ local file="${basename}-${cset}.tar.gz"
+ local dir="${CT_TARBALLS_DIR}/${basename}-${cset}.git"
+ local dest="${CT_TARBALLS_DIR}/${file}"
+ local tmp="${CT_TARBALLS_DIR}/${file}.tmp-dl"
+
+ # Do we alreadyhave it?
+ if CT_GetLocal "${file}"; then
+ return 0
+ fi
+ # Nope...
+
+ if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
+ CT_DoLog WARN "Downloads forbidden, not trying git retrieval"
+ return 1
+ fi
+
+ # Add URLs on the LAN mirror
+ # We subvert the normal download method, just to look for
+ # looking at the local mirror
+ if CT_GetFile "${basename}-${cset}" .tar.gz; then
+ return 0
+ fi
+
+ CT_DoLog EXTRA "Retrieving '${basename}-${cset}' (git)"
+
+ # Remove potential left-over from a previous run
+ CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
+
+ if CT_DoExecLog ALL git clone "${url}" "${dir}"; then
+ # Yep, cloned OK
+ CT_Pushd "${dir}"
+ CT_DoExecLog ALL git archive --format=tar \
+ --prefix="${basename}-${cset}/" \
+ -o "${tmp}.tar" \
+ "${cset}"
+ CT_DoExecLog ALL gzip -9 "${tmp}.tar"
+ CT_DoExecLog ALL mv -f "${tmp}.tar.gz" "${dest}"
+ CT_SaveLocal "${dest}"
+ CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
+ CT_Popd
+ else
+ # Woops...
+ CT_DoExecLog ALL rm -rf "${dir}"
+ CT_DoLog Debug "Could not clone '${basename}'"
+ return 1
+ fi
+}
+
+# Extract a tarball
+# Some tarballs need to be extracted in specific places. Eg.: glibc addons
+# must be extracted in the glibc directory; uCLibc locales must be extracted
+# in the extra/locale sub-directory of uClibc. This is taken into account
+# by the caller, that did a 'cd' into the correct path before calling us
+# and sets nochdir to 'nochdir'.
+# Note also that this function handles the git trees!
+# Usage: CT_Extract [nochdir] <basename> [options]
+# where 'options' are dependent on the source (eg. git branch/tag...)
+CT_Extract() {
+ local nochdir="$1"
+ local basename
+ local ext
+ local lzma_prog
+ local -a tar_opts
+
+ if [ "${nochdir}" = "nochdir" ]; then
+ shift
+ nochdir="$(pwd)"
+ else
+ nochdir="${CT_SRC_DIR}"
+ fi
+
+ basename="$1"
+ shift
+
+ if ! ext="$(CT_GetFileExtension "${basename}")"; then
+ CT_DoLog WARN "'${basename}' not found in '${CT_TARBALLS_DIR}'"
+ return 1
+ fi
+ local full_file="${CT_TARBALLS_DIR}/${basename}${ext}"
+
+ # Check if already extracted
+ if [ -e "${CT_SRC_DIR}/.${basename}.extracted" ]; then
+ CT_DoLog DEBUG "Already extracted '${basename}'"
+ return 0
+ fi
+
+ # Check if previously partially extracted
+ if [ -e "${CT_SRC_DIR}/.${basename}.extracting" ]; then
+ CT_DoLog ERROR "The '${basename}' sources were partially extracted."
+ CT_DoLog ERROR "Please remove first:"
+ CT_DoLog ERROR " - the source dir for '${basename}', in '${CT_SRC_DIR}'"
+ CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${basename}.extracting'"
+ CT_Abort "I'll stop now to avoid any carnage..."
+ fi
+ CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracting"
+
+ CT_Pushd "${nochdir}"
+
+ CT_DoLog EXTRA "Extracting '${basename}'"
+ CT_DoExecLog FILE mkdir -p "${basename}"
+ tar_opts=( "--strip-components=1" )
+ tar_opts+=( "-C" "${basename}" )
+ tar_opts+=( "-xv" )
+
+ # One note here:
+ # - lzma can be handled either with 'xz' or 'lzma'
+ # - we get lzma tarball only if either or both are available
+ # - so, if we get an lzma tarball, and either 'xz' or 'lzma' is
+ # missing, we can assume the other is available
+ if [ "${CT_CONFIGURE_has_lzma}" = "y" ]; then
+ lzma_prog="lzma -fdc"
+ else
+ lzma_prog="xz -fdc"
+ fi
+ case "${ext}" in
+ .tar.xz) xz -fdc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
+ .tar.lzma) ${lzma_prog} "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
+ .tar.bz2) bzip2 -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
+ .tar.gz|.tgz) gzip -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
+ .tar) CT_DoExecLog FILE tar "${tar_opts[@]}" -f "${full_file}";;
+ .zip) CT_DoExecLog FILE unzip "${@}" "${full_file}";;
+ /.git) CT_ExtractGit "${basename}" "${@}";;
+ *) CT_DoLog WARN "Don't know how to handle '${basename}${ext}': unknown extension"
+ return 1
+ ;;
+ esac
+
+ # Don't mark as being extracted for git
+ case "${ext}" in
+ /.git) ;;
+ *) CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracted";;
+ esac
+ CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${basename}.extracting"
+
+ CT_Popd
+}
+
+# Create a working git clone of a local git repository
+# Usage: CT_ExtractGit <basename> [ref]
+# where 'ref' is the reference to use:
+# the full name of a branch, like "remotes/origin/branch_name"
+# a date as understandable by git, like "YYYY-MM-DD[ hh[:mm[:ss]]]"
+# a tag name
+# If 'ref' is not given, the current repository HEAD will be used
+CT_ExtractGit() {
+ local basename="${1}"
+ local ref="${2}"
+ local repo
+ local ref_type
+
+ # pushd now to be able to get git revlist in case ref is a date
+ repo="${CT_TARBALLS_DIR}/${basename}"
+ CT_Pushd "${repo}"
+
+ # What kind of reference is ${ref} ?
+ if [ -z "${ref}" ]; then
+ ref_type=head
+ ref=$(git rev-list -n1 HEAD)
+ elif git tag |@@CT_grep@@ -E "^${ref}$" >/dev/null 2>&1; then
+ ref_type=tag
+ elif git branch -a --no-color | @@CT_grep@@ -E "^. ${ref}$" >/dev/null 2>&1; then
+ ref_type=branch
+ elif date -d "${ref}" >/dev/null 2>&1; then
+ ref_type=date
+ ref=$(git rev-list -n1 --before="${ref}")
+ else
+ CT_Abort "Reference '${ref}' is an incorrect git reference: neither tag, branch nor date"
+ fi
+
+ CT_Popd
+
+ CT_DoExecLog FILE rmdir "${basename}"
+ case "${ref_type}" in
+ branch) CT_DoExecLog FILE git clone -b "${ref}" "${repo}" "${basename}" ;;
+ *) CT_DoExecLog FILE git clone "${repo}" "${basename}"
+ CT_Pushd "${basename}"
+ CT_DoExecLog FILE git checkout "${ref}"
+ CT_Popd
+ ;;
+ esac
+}
+
+# Patches the specified component
+# See CT_Extract, above, for explanations on 'nochdir'
+# Usage: CT_Patch [nochdir] <packagename> <packageversion>
+# If the package directory is *not* packagename-packageversion, then
+# the caller must cd into the proper directory first, and call us
+# with nochdir
+CT_Patch() {
+ local nochdir="$1"
+ local pkgname
+ local version
+ local pkgdir
+ local base_file
+ local ver_file
+ local d
+ local -a patch_dirs
+ local bundled_patch_dir
+ local local_patch_dir
+ local bundled_exp_patch_dir
+ local local_exp_patch_dir
+
+ if [ "${nochdir}" = "nochdir" ]; then
+ shift
+ pkgname="$1"
+ version="$2"
+ pkgdir="${pkgname}-${version}"
+ nochdir="$(pwd)"
+ else
+ pkgname="$1"
+ version="$2"
+ pkgdir="${pkgname}-${version}"
+ nochdir="${CT_SRC_DIR}/${pkgdir}"
+ fi
+
+ # Check if already patched
+ if [ -e "${CT_SRC_DIR}/.${pkgdir}.patched" ]; then
+ CT_DoLog DEBUG "Already patched '${pkgdir}'"
+ return 0
+ fi
+
+ # Check if already partially patched
+ if [ -e "${CT_SRC_DIR}/.${pkgdir}.patching" ]; then
+ CT_DoLog ERROR "The '${pkgdir}' sources were partially patched."
+ CT_DoLog ERROR "Please remove first:"
+ CT_DoLog ERROR " - the source dir for '${pkgdir}', in '${CT_SRC_DIR}'"
+ CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.extracted'"
+ CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.patching'"
+ CT_Abort "I'll stop now to avoid any carnage..."
+ fi
+ touch "${CT_SRC_DIR}/.${pkgdir}.patching"
+
+ CT_Pushd "${nochdir}"
+
+ CT_DoLog EXTRA "Patching '${pkgdir}'"
+
+ bundled_patch_dir="${CT_LIB_DIR}/patches/${pkgname}/${version}"
+ local_patch_dir="${CT_LOCAL_PATCH_DIR}/${pkgname}/${version}"
+
+ # Check for experimental patches, if enabled.
+ if [ "${CT_EXPERIMENTAL_PATCHES}" = "y" ]; then
+ bundled_exp_patch_dir="${CT_LIB_DIR}/patches/experimental/${pkgname}/${version}"
+ local_exp_patch_dir="${CT_LOCAL_PATCH_DIR}/experimental/${pkgname}/${version}"
+ fi
+
+ case "${CT_PATCH_ORDER}" in
+ bundled) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
+ local) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}");;
+ bundled,local) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}" "${local_patch_dir}" "${local_exp_patch_dir}");;
+ local,bundled) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}" "${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
+ none) patch_dirs=;;
+ esac
+
+ for d in "${patch_dirs[@]}"; do
+ CT_DoLog DEBUG "Looking for patches in '${d}'..."
+ if [ -n "${d}" -a -d "${d}" ]; then
+ for p in "${d}"/*.patch; do
+ if [ -f "${p}" ]; then
+ CT_DoExecLog ALL patch --no-backup-if-mismatch -g0 -F1 -p1 -f -i "${p}"
+ fi
+ done
+ if [ "${CT_PATCH_SINGLE}" = "y" ]; then
+ break
+ fi
+ fi
+ done
+
+ if [ "${CT_OVERIDE_CONFIG_GUESS_SUB}" = "y" ]; then
+ CT_DoLog ALL "Overiding config.guess and config.sub"
+ for cfg in config_guess config_sub; do
+ eval ${cfg}="${CT_LIB_DIR}/scripts/${cfg/_/.}"
+ [ -e "${CT_TOP_DIR}/scripts/${cfg/_/.}" ] && eval ${cfg}="${CT_TOP_DIR}/scripts/${cfg/_/.}"
+ # Can't use CT_DoExecLog because of the '{} \;' to be passed un-mangled to find
+ find . -type f -name "${cfg/_/.}" -exec cp -v "${!cfg}" {} \; |CT_DoLog ALL
+ done
+ fi
+
+ CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${pkgdir}.patched"
+ CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${pkgdir}.patching"
+
+ CT_Popd
+}
+
+# Two wrappers to call config.(guess|sub) either from CT_TOP_DIR or CT_LIB_DIR.
+# Those from CT_TOP_DIR, if they exist, will be be more recent than those from CT_LIB_DIR.
+CT_DoConfigGuess() {
+ if [ -x "${CT_TOP_DIR}/scripts/config.guess" ]; then
+ "${CT_TOP_DIR}/scripts/config.guess"
+ else
+ "${CT_LIB_DIR}/scripts/config.guess"
+ fi
+}
+
+CT_DoConfigSub() {
+ if [ -x "${CT_TOP_DIR}/scripts/config.sub" ]; then
+ "${CT_TOP_DIR}/scripts/config.sub" "$@"
+ else
+ "${CT_LIB_DIR}/scripts/config.sub" "$@"
+ fi
+}
+
+# Compute the target tuple from what is provided by the user
+# Usage: CT_DoBuildTargetTuple
+# In fact this function takes the environment variables to build the target
+# tuple. It is needed both by the normal build sequence, as well as the
+# sample saving sequence.
+CT_DoBuildTargetTuple() {
+ # Set the endianness suffix, and the default endianness gcc option
+ case "${CT_ARCH_ENDIAN}" in
+ big)
+ target_endian_eb=eb
+ target_endian_be=be
+ target_endian_el=
+ target_endian_le=
+ CT_ARCH_ENDIAN_CFLAG="-mbig-endian"
+ CT_ARCH_ENDIAN_LDFLAG="-Wl,-EB"
+ ;;
+ little)
+ target_endian_eb=
+ target_endian_be=
+ target_endian_el=el
+ target_endian_le=le
+ CT_ARCH_ENDIAN_CFLAG="-mlittle-endian"
+ CT_ARCH_ENDIAN_LDFLAG="-Wl,-EL"
+ ;;
+ esac
+
+ # Set the bitness suffix
+ case "${CT_ARCH_BITNESS}" in
+ 32)
+ target_bits_32=32
+ target_bits_64=
+ ;;
+ 64)
+ target_bits_32=
+ target_bits_64=64
+ ;;
+ esac
+
+ # Build the default architecture tuple part
+ CT_TARGET_ARCH="${CT_ARCH}${CT_ARCH_SUFFIX}"
+
+ # Set defaults for the system part of the tuple. Can be overriden
+ # by architecture-specific values.
+ case "${CT_LIBC}" in
+ *glibc) CT_TARGET_SYS=gnu;;
+ uClibc) CT_TARGET_SYS=uclibc;;
+ *) CT_TARGET_SYS=elf;;
+ esac
+
+ # Set the default values for ARCH, ABI, CPU, TUNE, FPU and FLOAT
+ unset CT_ARCH_ARCH_CFLAG CT_ARCH_ABI_CFLAG CT_ARCH_CPU_CFLAG CT_ARCH_TUNE_CFLAG CT_ARCH_FPU_CFLAG CT_ARCH_FLOAT_CFLAG
+ unset CT_ARCH_WITH_ARCH CT_ARCH_WITH_ABI CT_ARCH_WITH_CPU CT_ARCH_WITH_TUNE CT_ARCH_WITH_FPU CT_ARCH_WITH_FLOAT
+ [ "${CT_ARCH_ARCH}" ] && { CT_ARCH_ARCH_CFLAG="-march=${CT_ARCH_ARCH}"; CT_ARCH_WITH_ARCH="--with-arch=${CT_ARCH_ARCH}"; }
+ [ "${CT_ARCH_ABI}" ] && { CT_ARCH_ABI_CFLAG="-mabi=${CT_ARCH_ABI}"; CT_ARCH_WITH_ABI="--with-abi=${CT_ARCH_ABI}"; }
+ [ "${CT_ARCH_CPU}" ] && { CT_ARCH_CPU_CFLAG="-mcpu=${CT_ARCH_CPU}"; CT_ARCH_WITH_CPU="--with-cpu=${CT_ARCH_CPU}"; }
+ [ "${CT_ARCH_TUNE}" ] && { CT_ARCH_TUNE_CFLAG="-mtune=${CT_ARCH_TUNE}"; CT_ARCH_WITH_TUNE="--with-tune=${CT_ARCH_TUNE}"; }
+ [ "${CT_ARCH_FPU}" ] && { CT_ARCH_FPU_CFLAG="-mfpu=${CT_ARCH_FPU}"; CT_ARCH_WITH_FPU="--with-fpu=${CT_ARCH_FPU}"; }
+
+ case "${CT_ARCH_FLOAT}" in
+ hard)
+ CT_ARCH_FLOAT_CFLAG="-mhard-float"
+ CT_ARCH_WITH_FLOAT="--with-float=hard"
+ ;;
+ soft)
+ CT_ARCH_FLOAT_CFLAG="-msoft-float"
+ CT_ARCH_WITH_FLOAT="--with-float=soft"
+ ;;
+ softfp)
+ CT_ARCH_FLOAT_CFLAG="-mfloat-abi=softfp"
+ CT_ARCH_WITH_FLOAT="--with-float=softfp"
+ ;;
+ esac
+
+ # Build the default kernel tuple part
+ CT_TARGET_KERNEL="${CT_KERNEL}"
+
+ # Overide the default values with the components specific settings
+ CT_DoArchTupleValues
+ CT_DoKernelTupleValues
+
+ # Finish the target tuple construction
+ CT_TARGET="${CT_TARGET_ARCH}"
+ CT_TARGET="${CT_TARGET}${CT_TARGET_VENDOR:+-${CT_TARGET_VENDOR}}"
+ CT_TARGET="${CT_TARGET}${CT_TARGET_KERNEL:+-${CT_TARGET_KERNEL}}"
+ CT_TARGET="${CT_TARGET}${CT_TARGET_SYS:+-${CT_TARGET_SYS}}"
+
+ # Sanity checks
+ __sed_alias=""
+ if [ -n "${CT_TARGET_ALIAS_SED_EXPR}" ]; then
+ __sed_alias=$(echo "${CT_TARGET}" |@@CT_sed@@ -r -e "${CT_TARGET_ALIAS_SED_EXPR}")
+ fi
+ case ":${CT_TARGET_VENDOR}:${CT_TARGET_ALIAS}:${__sed_alias}:" in
+ :*" "*:*:*:) CT_Abort "Don't use spaces in the vendor string, it breaks things.";;
+ :*"-"*:*:*:) CT_Abort "Don't use dashes in the vendor string, it breaks things.";;
+ :*:*" "*:*:) CT_Abort "Don't use spaces in the target alias, it breaks things.";;
+ :*:*:*" "*:) CT_Abort "Don't use spaces in the target sed transform, it breaks things.";;
+ esac
+
+ # Canonicalise it
+ CT_TARGET=$(CT_DoConfigSub "${CT_TARGET}")
+ # Prepare the target CFLAGS
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ENDIAN_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ARCH_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ABI_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_CPU_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_TUNE_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FPU_CFLAG}"
+ CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FLOAT_CFLAG}"
+
+ # Now on for the target LDFLAGS
+ CT_ARCH_TARGET_LDFLAGS="${CT_ARCH_TARGET_LDFLAGS} ${CT_ARCH_ENDIAN_LDFLAG}"
+}
+
+# This function does pause the build until the user strikes "Return"
+# Usage: CT_DoPause [optional_message]
+CT_DoPause() {
+ local foo
+ local message="${1:-Pausing for your pleasure}"
+ CT_DoLog INFO "${message}"
+ read -p "Press 'Enter' to continue, or Ctrl-C to stop..." foo >&6
+ return 0
+}
+
+# This function creates a tarball of the specified directory, but
+# only if it exists
+# Usage: CT_DoTarballIfExists <dir> <tarball_basename> [extra_tar_options [...]]
+CT_DoTarballIfExists() {
+ local dir="$1"
+ local tarball="$2"
+ shift 2
+ local -a extra_tar_opts=( "$@" )
+ local -a compress
+
+ case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
+ y) compress=( gzip -c -3 - ); tar_ext=.gz;;
+ *) compress=( cat - ); tar_ext=;;
+ esac
+
+ if [ -d "${dir}" ]; then
+ CT_DoLog DEBUG " Saving '${dir}'"
+ { tar c -C "${dir}" -v -f - "${extra_tar_opts[@]}" . \
+ |"${compress[@]}" >"${tarball}.tar${tar_ext}" ;
+ } 2>&1 |@@CT_sed@@ -r -e 's/^/ /;' |CT_DoLog STATE
+ else
+ CT_DoLog STATE " Not saving '${dir}': does not exist"
+ fi
+}
+
+# This function extracts a tarball to the specified directory, but
+# only if the tarball exists
+# Usage: CT_DoExtractTarballIfExists <tarball_basename> <dir> [extra_tar_options [...]]
+CT_DoExtractTarballIfExists() {
+ local tarball="$1"
+ local dir="$2"
+ shift 2
+ local -a extra_tar_opts=( "$@" )
+ local -a uncompress
+
+ case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
+ y) uncompress=( gzip -c -d ); tar_ext=.gz;;
+ *) uncompress=( cat ); tar_ext=;;
+ esac
+
+ if [ -f "${tarball}.tar${tar_ext}" ]; then
+ CT_DoLog DEBUG " Restoring '${dir}'"
+ CT_DoForceRmdir "${dir}"
+ CT_DoExecLog DEBUG mkdir -p "${dir}"
+ { "${uncompress[@]}" "${tarball}.tar${tar_ext}" \
+ |tar x -C "${dir}" -v -f - "${extra_tar_opts[@]}" ;
+ } 2>&1 |@@CT_sed@@ -r -e 's/^/ /;' |CT_DoLog STATE
+ else
+ CT_DoLog STATE " Not restoring '${dir}': does not exist"
+ fi
+}
+
+# This function saves the state of the toolchain to be able to restart
+# at any one point
+# Usage: CT_DoSaveState <next_step_name>
+CT_DoSaveState() {
+ [ "${CT_DEBUG_CT_SAVE_STEPS}" = "y" ] || return 0
+ local state_name="$1"
+ local state_dir="${CT_STATE_DIR}/${state_name}"
+
+ # Log this to the log level required by the user
+ CT_DoLog ${CT_LOG_LEVEL_MAX} "Saving state to restart at step '${state_name}'..."
+
+ rm -rf "${state_dir}"
+ mkdir -p "${state_dir}"
+
+ CT_DoLog STATE " Saving environment and aliases"
+ # We must omit shell functions, and some specific bash variables
+ # that break when restoring the environment, later. We could do
+ # all the processing in the awk script, but a sed is easier...
+ set |awk '
+ BEGIN { _p = 1; }
+ $0~/^[^ ]+ \(\)/ { _p = 0; }
+ _p == 1
+ $0 == "}" { _p = 1; }
+ ' |@@CT_sed@@ -r -e '/^BASH_(ARGC|ARGV|LINENO|SOURCE|VERSINFO)=/d;
+ /^(UID|EUID)=/d;
+ /^(FUNCNAME|GROUPS|PPID|SHELLOPTS)=/d;' >"${state_dir}/env.sh"
+
+ CT_DoTarballIfExists "${CT_BUILDTOOLS_PREFIX_DIR}" "${state_dir}/buildtools_dir"
+ CT_DoTarballIfExists "${CT_CONFIG_DIR}" "${state_dir}/config_dir"
+ CT_DoTarballIfExists "${CT_PREFIX_DIR}" "${state_dir}/prefix_dir" --exclude '*.log'
+
+ CT_DoLog STATE " Saving log file"
+ exec >/dev/null
+ case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
+ y) gzip -3 -c "${tmp_log_file}" >"${state_dir}/log.gz";;
+ *) cat "${tmp_log_file}" >"${state_dir}/log";;
+ esac
+ exec >>"${tmp_log_file}"
+}
+
+# This function restores a previously saved state
+# Usage: CT_DoLoadState <state_name>
+CT_DoLoadState(){
+ local state_name="$1"
+ local state_dir="${CT_STATE_DIR}/${state_name}"
+ local old_RESTART="${CT_RESTART}"
+ local old_STOP="${CT_STOP}"
+
+ CT_TestOrAbort "The previous build did not reach the point where it could be restarted at '${CT_RESTART}'" -d "${state_dir}"
+
+ # We need to do something special with the log file!
+ if [ "${CT_LOG_TO_FILE}" = "y" ]; then
+ exec >"${state_dir}/tail.log"
+ fi
+
+ # Log this to the log level required by the user
+ CT_DoLog ${CT_LOG_LEVEL_MAX} "Restoring state at step '${state_name}', as requested."
+
+ CT_DoExtractTarballIfExists "${state_dir}/prefix_dir" "${CT_PREFIX_DIR}"
+ CT_DoExtractTarballIfExists "${state_dir}/config_dir" "${CT_CONFIG_DIR}"
+ CT_DoExtractTarballIfExists "${state_dir}/buildtools_dir" "${CT_BUILDTOOLS_PREFIX_DIR}"
+
+ # Restore the environment, discarding any error message
+ # (for example, read-only bash internals)
+ CT_DoLog STATE " Restoring environment"
+ . "${state_dir}/env.sh" >/dev/null 2>&1 || true
+
+ # Restore the new RESTART and STOP steps
+ CT_RESTART="${old_RESTART}"
+ CT_STOP="${old_STOP}"
+ unset old_stop old_restart
+
+ CT_DoLog STATE " Restoring log file"
+ exec >/dev/null
+ case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
+ y) gzip -dc "${state_dir}/log.gz" >"${tmp_log_file}";;
+ *) cat "${state_dir}/log" >"${tmp_log_file}";;
+ esac
+ cat "${state_dir}/tail.log" >>"${tmp_log_file}"
+ exec >>"${tmp_log_file}"
+ rm -f "${state_dir}/tail.log"
+}
diff --git a/scripts/xldd.in b/scripts/xldd.in
index c906240..4cbe333 100755
--- a/scripts/xldd.in
+++ b/scripts/xldd.in
@@ -159,7 +159,7 @@ fi
sysroot="$( "${gcc}" -print-sysroot 2>/dev/null )"
if [ -z "${sysroot}" ]; then
sysroot="$( "${gcc}" -print-file-name=libc.so 2>/dev/null \
- |sed -r -e 's:/usr/lib/libc.so$::;' \
+ |"${sed}" -r -e 's:/usr/lib/libc.so$::;' \
)"
fi
if [ -z "${sysroot}" ]; then
-- 1.8.5.2 (Apple Git-48)
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 947 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes
2014-08-06 2:27 ` [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes Fabian Freyer
2014-08-06 2:40 ` Fabian Freyer
@ 2014-08-26 22:26 ` Yann E. MORIN
2014-08-26 22:43 ` Fabian Freyer
2014-08-26 22:51 ` Yann E. MORIN
2 siblings, 1 reply; 10+ messages in thread
From: Yann E. MORIN @ 2014-08-26 22:26 UTC (permalink / raw)
To: Fabian Freyer; +Cc: crossgcc
Fabian, All,
On 2014-08-06 04:27 +0200, Fabian Freyer spake thusly:
> Hi,
>
> On 26/09/12 18:56, Yann E. MORIN wrote:
> > On Wednesday 26 September 2012 17:30:12 Blair Burtan wrote:
> >> That was the problem but not quite the complete solution. I had to modify
> >> the grep path to point to the MacPorts verison when I built ct-ng. I also
> >> had to use ginstall instead of the OSX install.
> >
> > ./configure --help
> > [--SNIP--]
> > Optional Packages:
> > --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
> > --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
> > --with-install=PATH Specify the full PATH to a BSD-compatible install
> > --with-sed=PATH Specify the full PATH to GNU sed
> > --with-objcopy=PATH Specify the full PATH to GNU objcopy
> > --with-objdump=PATH Specify the full PATH to GNU objdump
> > --with-ranlib=PATH Specify the full PATH to GNU ranlib
> > --with-readelf=PATH Specify the full PATH to GNU readelf
> > --with-bash=PATH Specify the full PATH to GNU bash >= 3.1
> > --with-awk=PATH Specify the full PATH to GNU awk
> > --with-make=PATH Specify the full PATH to GNU make >= 3.80
> > --with-libtool=PATH Specify the full PATH to GNU libtool >= 1.5.26
> > --with-libtoolize=PATH Specify the full PATH to GNU libtoolize >= 1.5.26
> > --with-automake=PATH Specify the full PATH to GNU automake >= 1.10
> > [--SNIP--]
> >
> > That's how you tell crosstool-NG what tools to use if the default ones are
> > not the GNU ones.
>
> While it is possible to tell crosstool-NG to use custom GNU tools for several
> tools, it is not possible for all tools, especially for grep and sed. This
> causes ct-ng build to fail:
>
> [ERROR] >>
> [ERROR] >> Build failed in step '(top-level)'
> [ERROR] >>
> [ERROR] >> Error happened in: CT_DoForceRmdir[scripts/functions@458]
> [ERROR] >> called from: main[scripts/crosstool-NG.sh@238]
> [ERROR] >>
>
> One of the problems here is also that on BSD installs, including OS X, GNU
> tools are often installed with a prefixed 'g', in this case "ggrep" and "gsed".
> There is no way to tell crosstool-NG to use ggrep instead of grep, and
> adjusting $PATH does not help either.
>
> I have created a small (not counting the changes due to the scripts/functions
> rename) patch that adds --with-grep and substitues @@CT_sed@@ for sed in a few
> places where sed from PATH is used and GNU-specific options are used.
The solution is not to pre-process 'functions.in' into 'functions', but
to add the new tools to the generated paths.mk and paths.sh, and then to
use ${sed} and ${grep} where needed.
Note that 'sed' is already present in those files, so only grep needs to
be added.
Is there a name which GNU grep is known as on BSD systems? For example,
we have gsed. Do we have ggrep, too?
In which case, we'd need four patches:
- use ${sed} instead of plain 'sed' where appropriate
- add --with-grep to the list of tools we can specify
- add an alternate name for when searching for grep
- use ${grep} instead of plain 'grep' where appropriate
I'll tackle this here.
Sorry for the delay, and thanks for the report.
Regards,
Yann E. MORIN.
> I can
> confirm this works for me on Darwin using GNU tools installed via homebrew using
> the following ./configure options:
>
> ./configure --prefix=$(pwd) --exec-prefix=$(pwd) \
> --with-objcopy=gobjcopy \
> --with-objdump=gobjdump \
> --with-readelf=greadelf \
> --with-libtool=glibtool \
> --with-libtoolize=glibtoolize \
> --with-install=ginstall \
> --with-sed=gsed \
> --with-awk=gawk \
> --with-grep=ggrep
>
> I have not yet tested that this patch works flawlessly on Linux using default
> ./configure options. I'd like to submit the following patch for testing.
>
> Regards,
> Fabian Freyer
>
> - ---
> Makefile.in | 5 +-
> configure.ac | 6 +
> scripts/crosstool-NG.sh.in | 6 +-
> scripts/functions | 1395 --------------------------------------------
> scripts/functions.in | 1395 ++++++++++++++++++++++++++++++++++++++++++++
> scripts/xldd.in | 2 +-
> 6 files changed, 1409 insertions(+), 1400 deletions(-)
> delete mode 100644 scripts/functions
> create mode 100644 scripts/functions.in
>
> diff --git a/Makefile.in b/Makefile.in
> index 01759b6..cd68baa 100644
> - --- a/Makefile.in
> +++ b/Makefile.in
> @@ -59,7 +59,7 @@ export datarootdir := @datarootdir@
> export install := @INSTALL@
> export bash := @_BASH@
> export awk := @_AWK@
> - -export grep := @GREP@
> +export grep := @_GREP@
> export make := @MAKE@
> export sed := @SED@
> export libtool := @LIBTOOL@
> @@ -142,6 +142,7 @@ uninstall: real-uninstall
> # Build rules
>
> build-bin: $(PROG_NAME) \
> + scripts/functions \
> scripts/crosstool-NG.sh \
> scripts/saveSample.sh \
> scripts/showTuple.sh
> @@ -174,6 +175,8 @@ define sed_it
> -e 's,@@CT_make@@,$(make),g;' \
> -e 's,@@CT_bash@@,$(bash),g;' \
> -e 's,@@CT_awk@@,$(awk),g;' \
> + -e 's,@@CT_grep@@,$(grep),g;' \
> + -e 's,@@CT_sed@@,$(sed),g;' \
> $< >$@
> endef
>
> diff --git a/configure.ac b/configure.ac
> index f8c67be..27238ab 100644
> - --- a/configure.ac
> +++ b/configure.ac
> @@ -94,6 +94,12 @@ AC_ARG_WITH([install],
> [Specify the full PATH to a BSD-compatible install]),
> [INSTALL=$withval])
> AC_PROG_INSTALL
> +AC_CACHE_VAL([ac_cv_path_GREP],
> + [AC_ARG_WITH([grep],
> + AS_HELP_STRING([--with-grep=PATH],
> + [Specify the full PATH to GNU grep]),
> + [ac_cv_path_GREP=$withval])])
> +AC_SUBST([_GREP], [$ac_cv_path_GREP])
> AC_PROG_GREP
> AC_PROG_EGREP
> AS_IF(
> diff --git a/scripts/crosstool-NG.sh.in b/scripts/crosstool-NG.sh.in
> index 3699500..4b9011d 100644
> - --- a/scripts/crosstool-NG.sh.in
> +++ b/scripts/crosstool-NG.sh.in
> @@ -125,7 +125,7 @@ CT_DoLog INFO "Build started ${CT_STAR_DATE_HUMAN}"
> # We really need to extract from ,config and not .config.2, as we
> # do want the kconfig's values, not our mangled config with arrays.
> CT_DoStep DEBUG "Dumping user-supplied crosstool-NG configuration"
> - -CT_DoExecLog DEBUG grep -E '^(# |)CT_' .config
> +CT_DoExecLog DEBUG @@CT_grep@@ -E '^(# |)CT_' .config
> CT_EndStep
>
> CT_DoLog DEBUG "Unsetting and unexporting MAKEFLAGS"
> @@ -570,9 +570,9 @@ if [ -z "${CT_RESTART}" ]; then
> CT_DoLog EXTRA " build = ${CT_REAL_BUILD}"
> CT_DoLog EXTRA " host = ${CT_REAL_HOST}"
> CT_DoLog EXTRA " target = ${CT_TARGET}"
> - - set |grep -E '^CT_.+=' |sort |CT_DoLog DEBUG
> + set |@@CT_grep@@ -E '^CT_.+=' |sort |CT_DoLog DEBUG
> CT_DoLog DEBUG "Other environment:"
> - - printenv |grep -v -E '^CT_.+=' |CT_DoLog DEBUG
> + printenv |@@CT_grep@@ -v -E '^CT_.+=' |CT_DoLog DEBUG
> CT_EndStep
> fi
>
> diff --git a/scripts/functions b/scripts/functions
> deleted file mode 100644
> index 2e4d4fa..0000000
> - --- a/scripts/functions
> +++ /dev/null
> @@ -1,1395 +0,0 @@
> - -# This file contains some usefull common functions -*- sh -*-
> - -# Copyright 2007 Yann E. MORIN
> - -# Licensed under the GPL v2. See COPYING in the root of this package
> - -
> - -# Prepare the fault handler
> - -CT_OnError() {
> - - local ret=$?
> - - local result
> - - local old_trap
> - - local intro
> - - local file line func
> - - local step step_depth
> - -
> - - # To avoid printing the backtace for each sub-shell
> - - # up to the top-level, just remember we've dumped it
> - - if [ ! -f "${CT_WORK_DIR}/backtrace" ]; then
> - - touch "${CT_WORK_DIR}/backtrace"
> - -
> - - # Print steps backtrace
> - - step_depth=${CT_STEP_COUNT}
> - - CT_STEP_COUNT=1 # To have a zero-indentation
> - - CT_DoLog ERROR ""
> - - CT_DoLog ERROR ">>"
> - - intro="Build failed"
> - - for((step=step_depth; step>0; step--)); do
> - - CT_DoLog ERROR ">> ${intro} in step '${CT_STEP_MESSAGE[${step}]}'"
> - - intro=" called"
> - - done
> - -
> - - # Print functions backtrace
> - - intro="Error happened in"
> - - CT_DoLog ERROR ">>"
> - - for((depth=1; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
> - - file="${BASH_SOURCE[${depth}]#${CT_LIB_DIR}/}"
> - - func="${FUNCNAME[${depth}]}"
> - - line="@${BASH_LINENO[${depth}-1]:-?}"
> - - CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
> - - intro=" called from"
> - - done
> - -
> - - # If the user asked for interactive debugging, dump him/her to a shell
> - - if [ "${CT_DEBUG_INTERACTIVE}" = "y" ]; then
> - - # We do not want this sub-shell exit status to be caught, because
> - - # it is absolutely legit that it exits with non-zero.
> - - # Save the trap handler to restore it after our debug-shell
> - - old_trap="$(trap -p ERR)"
> - - trap -- ERR
> - - (
> - - exec >&6 2>&7 <&8
> - - printf "\r \n\nCurrent command"
> - - if [ -n "${cur_cmd}" ]; then
> - - printf ":\n %s\n" "${cur_cmd}"
> - - else
> - - printf " (unknown), "
> - - fi
> - - printf "exited with error code: %d\n" ${ret}
> - - printf "Please fix it up and finish by exiting the shell with one of these values:\n"
> - - printf " 1 fixed, continue with next build command\n"
> - - if [ -n "${cur_cmd}" ]; then
> - - printf " 2 repeat this build command\n"
> - - fi
> - - printf " 3 abort build\n\n"
> - - while true; do
> - - ${bash} --rcfile <(printf "PS1='ct-ng:\w> '\nPROMPT_COMMAND=''\n") -i
> - - result=$?
> - - case $result in
> - - 1) printf "\nContinuing past the failed command.\n\n"
> - - break
> - - ;;
> - - 2) if [ -n "${cur_cmd}" ]; then
> - - printf "\nRe-trying last command.\n\n"
> - - break
> - - fi
> - - ;;
> - - 3) break;;
> - - esac
> - - printf "\nPlease exit with one of these values:\n"
> - - printf " 1 fixed, continue with next build command\n"
> - - if [ -n "${cur_cmd}" ]; then
> - - printf " 2 repeat this build command\n"
> - - fi
> - - printf " 3 abort build\n"
> - - done
> - - exit $result
> - - )
> - - result=$?
> - - # Restore the trap handler
> - - eval "${old_trap}"
> - - case "${result}" in
> - - 1) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/skip"; return;;
> - - 2) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/repeat"; return;;
> - - # 3 is an abort, continue...
> - - esac
> - - fi
> - - fi
> - -
> - - # And finally, in top-level shell, print some hints
> - - if [ ${BASH_SUBSHELL} -eq 0 ]; then
> - - # Help diagnose the error
> - - CT_STEP_COUNT=1 # To have a zero-indentation
> - - CT_DoLog ERROR ">>"
> - - if [ "${CT_LOG_TO_FILE}" = "y" ]; then
> - - CT_DoLog ERROR ">> For more info on this error, look at the file: '${tmp_log_file#${CT_TOP_DIR}/}'"
> - - fi
> - - CT_DoLog ERROR ">> There is a list of known issues, some with workarounds, in:"
> - - CT_DoLog ERROR ">> '${CT_DOC_DIR#${CT_TOP_DIR}/}/B - Known issues.txt'"
> - -
> - - CT_DoLog ERROR ""
> - - CT_DoEnd ERROR
> - - rm -f "${CT_WORK_DIR}/backtrace"
> - - fi
> - - exit $ret
> - -}
> - -
> - -# Install the fault handler
> - -trap CT_OnError ERR
> - -
> - -# Inherit the fault handler in subshells and functions
> - -set -E
> - -
> - -# Make pipes fail on the _first_ failed command
> - -# Not supported on bash < 3.x, but we need it, so drop the obsoleting bash-2.x
> - -set -o pipefail
> - -
> - -# Don't hash commands' locations, and search every time it is requested.
> - -# This is slow, but needed because of the static/shared core gcc which shall
> - -# always match to shared if it exists, and only fallback to static if the
> - -# shared is not found
> - -set +o hashall
> - -
> - -# Log policy:
> - -# - first of all, save stdout so we can see the live logs: fd #6
> - -# (also save stdin and stderr for use by CT_DEBUG_INTERACTIVE)
> - -exec 6>&1 7>&2 8<&0
> - -# - then point stdout to the log file
> - -tmp_log_file="${CT_TOP_DIR}/build.log"
> - -rm -f "${tmp_log_file}"
> - -exec >>"${tmp_log_file}"
> - -
> - -# The different log levels:
> - -CT_LOG_LEVEL_ERROR=0
> - -CT_LOG_LEVEL_WARN=1
> - -CT_LOG_LEVEL_INFO=2
> - -CT_LOG_LEVEL_EXTRA=3
> - -CT_LOG_LEVEL_CFG=4
> - -CT_LOG_LEVEL_FILE=5
> - -CT_LOG_LEVEL_STATE=6
> - -CT_LOG_LEVEL_ALL=7
> - -CT_LOG_LEVEL_DEBUG=8
> - -
> - -# Make it easy to use \n and !
> - -CR=$(printf "\n")
> - -BANG='!'
> - -
> - -# A function to log what is happening
> - -# Different log level are available:
> - -# - ERROR: A serious, fatal error occurred
> - -# - WARN: A non fatal, non serious error occurred, take your responsbility with the generated build
> - -# - INFO: Informational messages
> - -# - EXTRA: Extra informational messages
> - -# - CFG: Output of various "./configure"-type scripts
> - -# - FILE: File / archive unpacking.
> - -# - STATE: State save & restore
> - -# - ALL: Component's build messages
> - -# - DEBUG: Internal debug messages
> - -# Usage: CT_DoLog <level> [message]
> - -# If message is empty, then stdin will be logged.
> - -CT_DoLog() {
> - - local max_level LEVEL level cur_l cur_L
> - - local l
> - - eval max_level="\${CT_LOG_LEVEL_${CT_LOG_LEVEL_MAX}}"
> - - # Set the maximum log level to DEBUG if we have none
> - - [ -z "${max_level}" ] && max_level=${CT_LOG_LEVEL_DEBUG}
> - -
> - - LEVEL="$1"; shift
> - - eval level="\${CT_LOG_LEVEL_${LEVEL}}"
> - -
> - - if [ $# -eq 0 ]; then
> - - cat -
> - - else
> - - printf "%s\n" "${*}"
> - - fi |( IFS="${CR}" # We want the full lines, even leading spaces
> - - _prog_bar_cpt=0
> - - _prog_bar[0]='/'
> - - _prog_bar[1]='-'
> - - _prog_bar[2]='\'
> - - _prog_bar[3]='|'
> - - indent=$((2*CT_STEP_COUNT))
> - - while read line; do
> - - case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
> - - y,*"warning:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
> - - y,*"WARNING:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
> - - *"error:"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
> - - *"make["*"]: *** ["*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
> - - *) cur_L="${LEVEL}"; cur_l="${level}";;
> - - esac
> - - # There will always be a log file (stdout, fd #1), be it /dev/null
> - - printf "[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}"
> - - if [ ${cur_l} -le ${max_level} ]; then
> - - # Only print to console (fd #6) if log level is high enough.
> - - printf "${CT_LOG_PROGRESS_BAR:+\r}[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}" >&6
> - - fi
> - - if [ "${CT_LOG_PROGRESS_BAR}" = "y" ]; then
> - - printf "\r[%02d:%02d] %s " $((SECONDS/60)) $((SECONDS%60)) "${_prog_bar[$((_prog_bar_cpt/10))]}" >&6
> - - _prog_bar_cpt=$(((_prog_bar_cpt+1)%40))
> - - fi
> - - done
> - - )
> - -
> - - return 0
> - -}
> - -
> - -# Execute an action, and log its messages
> - -# It is possible to even log local variable assignments (a-la: var=val ./cmd opts)
> - -# Usage: CT_DoExecLog <level> [VAR=val...] <command> [parameters...]
> - -CT_DoExecLog() {
> - - local level="$1"
> - - local cur_cmd
> - - local ret
> - - shift
> - - (
> - - for i in "$@"; do
> - - cur_cmd+="'${i}' "
> - - done
> - - while true; do
> - - case "${1}" in
> - - *=*) eval export "'${1}'"; shift;;
> - - *) break;;
> - - esac
> - - done
> - - # This while-loop goes hand-in-hand with the ERR trap handler:
> - - # - if the command terminates successfully, then we hit the break
> - - # statement, and we exit the loop
> - - # - if the command terminates in error, then the ERR handler kicks
> - - # in, then:
> - - # - if the user did *not* ask for interactive debugging, the ERR
> - - # handler exits, and we hit the end of the sub-shell
> - - # - if the user did ask for interactive debugging, the ERR handler
> - - # spawns a shell. Upon termination of this shell, the ERR handler
> - - # examines the exit status of the shell:
> - - # - if 1, the ERR handler returns; then we hit the else statement,
> - - # then the break, and we exit the 'while' loop, to continue the
> - - # build;
> - - # - if 2, the ERR handler touches the repeat file, and returns;
> - - # then we hit the if statement, and we loop for one more
> - - # iteration;
> - - # - if 3, the ERR handler exits with the command's exit status,
> - - # and we're dead;
> - - # - for any other exit status of the shell, the ERR handler
> - - # prints an informational message, and respawns the shell
> - - #
> - - # This allows a user to get an interactive shell that has the same
> - - # environment (PATH and so on) that the failed command was ran with.
> - - while true; do
> - - rm -f "${CT_BUILD_DIR}/repeat"
> - - CT_DoLog DEBUG "==> Executing: ${cur_cmd}"
> - - "${@}" 2>&1 |CT_DoLog "${level}"
> - - ret="${?}"
> - - if [ -f "${CT_BUILD_DIR}/repeat" ]; then
> - - rm -f "${CT_BUILD_DIR}/repeat"
> - - continue
> - - elif [ -f "${CT_BUILD_DIR}/skip" ]; then
> - - rm -f "${CT_BUILD_DIR}/skip"
> - - ret=0
> - - break
> - - else
> - - break
> - - fi
> - - done
> - - exit ${ret}
> - - )
> - - # Catch failure of the sub-shell
> - - [ $? -eq 0 ]
> - -}
> - -
> - -# Tail message to be logged whatever happens
> - -# Usage: CT_DoEnd <level>
> - -CT_DoEnd()
> - -{
> - - local level="$1"
> - - CT_STOP_DATE=$(CT_DoDate +%s%N)
> - - CT_STOP_DATE_HUMAN=$(CT_DoDate +%Y%m%d.%H%M%S)
> - - if [ "${level}" != "ERROR" ]; then
> - - CT_DoLog "${level:-INFO}" "Build completed at ${CT_STOP_DATE_HUMAN}"
> - - fi
> - - elapsed=$((CT_STOP_DATE-CT_STAR_DATE))
> - - elapsed_min=$((elapsed/(60*1000*1000*1000)))
> - - elapsed_sec=$(printf "%02d" $(((elapsed%(60*1000*1000*1000))/(1000*1000*1000))))
> - - elapsed_csec=$(printf "%02d" $(((elapsed%(1000*1000*1000))/(10*1000*1000))))
> - - CT_DoLog ${level:-INFO} "(elapsed: ${elapsed_min}:${elapsed_sec}.${elapsed_csec})"
> - -}
> - -
> - -# Remove entries referring to . and other relative paths
> - -# Usage: CT_SanitizePath
> - -CT_SanitizePath() {
> - - local new
> - - local p
> - - local IFS=:
> - - for p in $PATH; do
> - - # Only accept absolute paths;
> - - # Note: as a special case the empty string in PATH is equivalent to .
> - - if [ -n "${p}" -a -z "${p%%/*}" ]; then
> - - new="${new}${new:+:}${p}"
> - - fi
> - - done
> - - PATH="${new}"
> - -}
> - -
> - -# Sanitise the directory name contained in the variable passed as argument:
> - -# - remove duplicate /
> - -# Usage: CT_SanitiseVarDir CT_PREFIX_DIR
> - -CT_SanitiseVarDir() {
> - - local var
> - - local old_dir
> - - local new_dir
> - -
> - - for var in "$@"; do
> - - eval "old_dir=\"\${${var}}\""
> - - new_dir="$( printf "${old_dir}" \
> - - |sed -r -e 's:/+:/:g;' \
> - - )"
> - - eval "${var}=\"${new_dir}\""
> - - CT_DoLog DEBUG "Sanitised '${var}': '${old_dir}' -> '${new_dir}'"
> - - done
> - -}
> - -
> - -# Abort the execution with an error message
> - -# Usage: CT_Abort <message>
> - -CT_Abort() {
> - - CT_DoLog ERROR "$1"
> - - false
> - -}
> - -
> - -# Test a condition, and print a message if satisfied
> - -# Usage: CT_Test <message> <tests>
> - -CT_Test() {
> - - local ret
> - - local m="$1"
> - - shift
> - - CT_DoLog DEBUG "Testing '! ( $* )'"
> - - test "$@" && CT_DoLog WARN "$m"
> - - return 0
> - -}
> - -
> - -# Test a condition, and abort with an error message if satisfied
> - -# Usage: CT_TestAndAbort <message> <tests>
> - -CT_TestAndAbort() {
> - - local m="$1"
> - - shift
> - - CT_DoLog DEBUG "Testing '! ( $* )'"
> - - test "$@" && CT_Abort "$m"
> - - return 0
> - -}
> - -
> - -# Test a condition, and abort with an error message if not satisfied
> - -# Usage: CT_TestAndAbort <message> <tests>
> - -CT_TestOrAbort() {
> - - local m="$1"
> - - shift
> - - CT_DoLog DEBUG "Testing '$*'"
> - - test "$@" || CT_Abort "$m"
> - - return 0
> - -}
> - -
> - -# Test the presence of a tool, or abort if not found
> - -# Usage: CT_HasOrAbort <tool>
> - -CT_HasOrAbort() {
> - - CT_TestAndAbort "'${1}' not found and needed for successful toolchain build." -z "$(CT_Which "${1}")"
> - - return 0
> - -}
> - -
> - -# Search a program: wrap "which" for those system where "which"
> - -# verbosely says there is no match (such as on Mandriva).
> - -# Usage: CT_Which <filename>
> - -CT_Which() {
> - - which "$1" 2>/dev/null || true
> - -}
> - -
> - -# Get current date with nanosecond precision
> - -# On those system not supporting nanosecond precision, faked with rounding down
> - -# to the highest entire second
> - -# Usage: CT_DoDate <fmt>
> - -CT_DoDate() {
> - - date "$1" |sed -r -e 's/%?N$/000000000/;'
> - -}
> - -
> - -CT_STEP_COUNT=1
> - -CT_STEP_MESSAGE[${CT_STEP_COUNT}]="(top-level)"
> - -# Memorise a step being done so that any error is caught
> - -# Usage: CT_DoStep <loglevel> <message>
> - -CT_DoStep() {
> - - local start=$(CT_DoDate +%s%N)
> - - CT_DoLog "$1" "================================================================="
> - - CT_DoLog "$1" "$2"
> - - CT_STEP_COUNT=$((CT_STEP_COUNT+1))
> - - CT_STEP_LEVEL[${CT_STEP_COUNT}]="$1"; shift
> - - CT_STEP_START[${CT_STEP_COUNT}]="${start}"
> - - CT_STEP_MESSAGE[${CT_STEP_COUNT}]="$1"
> - - return 0
> - -}
> - -
> - -# End the step just being done
> - -# Usage: CT_EndStep
> - -CT_EndStep() {
> - - local stop=$(CT_DoDate +%s%N)
> - - local duration=$(printf "%032d" $((stop-${CT_STEP_START[${CT_STEP_COUNT}]})) |sed -r -e 's/([[:digit:]]{2})[[:digit:]]{7}$/\.\1/; s/^0+//; s/^\./0\./;')
> - - local elapsed=$(printf "%02d:%02d" $((SECONDS/60)) $((SECONDS%60)))
> - - local level="${CT_STEP_LEVEL[${CT_STEP_COUNT}]}"
> - - local message="${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}"
> - - CT_STEP_COUNT=$((CT_STEP_COUNT-1))
> - - CT_DoLog "${level}" "${message}: done in ${duration}s (at ${elapsed})"
> - - return 0
> - -}
> - -
> - -# Pushes into a directory, and pops back
> - -CT_Pushd() {
> - - CT_DoLog DEBUG "Entering '$1'"
> - - pushd "$1" >/dev/null 2>&1
> - -}
> - -CT_Popd() {
> - - popd >/dev/null 2>&1
> - -}
> - -
> - -# Create a dir and cd or pushd into it
> - -# Usage: CT_mkdir_cd <dir/to/create>
> - -# CT_mkdir_pushd <dir/to/create>
> - -CT_mkdir_cd() {
> - - local dir="${1}"
> - -
> - - mkdir -p "${dir}"
> - - cd "${dir}"
> - -}
> - -CT_mkdir_pushd() {
> - - local dir="${1}"
> - -
> - - mkdir -p "${dir}"
> - - CT_Pushd "${dir}"
> - -}
> - -
> - -# Creates a temporary directory
> - -# $1: variable to assign to
> - -# Usage: CT_MktempDir foo
> - -CT_MktempDir() {
> - - # Some mktemp do not allow more than 6 Xs
> - - eval "$1"=$(mktemp -q -d "${CT_BUILD_DIR}/tmp.XXXXXX")
> - - CT_TestOrAbort "Could not make temporary directory" -n "${!1}" -a -d "${!1}"
> - - CT_DoLog DEBUG "Made temporary directory '${!1}'"
> - - return 0
> - -}
> - -
> - -# Removes one or more directories, even if it is read-only, or its parent is
> - -# Usage: CT_DoForceRmdir dir [...]
> - -CT_DoForceRmdir() {
> - - local dir
> - - local mode
> - - for dir in "${@}"; do
> - - [ -d "${dir}" ] || continue
> - - case "$CT_SYS_OS" in
> - - Linux|CYGWIN*)
> - - mode="$(stat -c '%a' "$(dirname "${dir}")")"
> - - ;;
> - - Darwin|*BSD)
> - - mode="$(stat -f '%Lp' "$(dirname "${dir}")")"
> - - ;;
> - - *)
> - - CT_Abort "Unhandled host OS $CT_SYS_OS"
> - - ;;
> - - esac
> - - CT_DoExecLog ALL chmod u+w "$(dirname "${dir}")"
> - - CT_DoExecLog ALL chmod -R u+w "${dir}"
> - - CT_DoExecLog ALL rm -rf "${dir}"
> - - CT_DoExecLog ALL chmod ${mode} "$(dirname "${dir}")"
> - - done
> - -}
> - -
> - -# Echoes the specified string on stdout until the pipe breaks.
> - -# Doesn't fail
> - -# $1: string to echo
> - -# Usage: CT_DoYes "" |make oldconfig
> - -CT_DoYes() {
> - - yes "$1" || true
> - -}
> - -
> - -# Add the specified directory to LD_LIBRARY_PATH, and export it
> - -# If the specified patch is already present, just export
> - -# $1: path to add
> - -# $2: add as 'first' or 'last' path, 'first' is assumed if $2 is empty
> - -# Usage CT_SetLibPath /some/where/lib [first|last]
> - -CT_SetLibPath() {
> - - local path="$1"
> - - local pos="$2"
> - -
> - - case ":${LD_LIBRARY_PATH}:" in
> - - *:"${path}":*) ;;
> - - *) case "${pos}" in
> - - last)
> - - CT_DoLog DEBUG "Adding '${path}' at end of LD_LIBRARY_PATH"
> - - LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${path}"
> - - ;;
> - - first|"")
> - - CT_DoLog DEBUG "Adding '${path}' at start of LD_LIBRARY_PATH"
> - - LD_LIBRARY_PATH="${path}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
> - - ;;
> - - *)
> - - CT_Abort "Incorrect position '${pos}' to add '${path}' to LD_LIBRARY_PATH"
> - - ;;
> - - esac
> - - ;;
> - - esac
> - - CT_DoLog DEBUG "==> LD_LIBRARY_PATH='${LD_LIBRARY_PATH}'"
> - - export LD_LIBRARY_PATH
> - -}
> - -
> - -# Build up the list of allowed tarball extensions
> - -# Add them in the prefered order; most preferred comes first
> - -CT_DoListTarballExt() {
> - - if [ "${CT_CONFIGURE_has_xz}" = "y" ]; then
> - - printf ".tar.xz\n"
> - - fi
> - - if [ "${CT_CONFIGURE_has_lzma}" = "y" \
> - - -o "${CT_CONFIGURE_has_xz}" = "y" ]; then
> - - printf ".tar.lzma\n"
> - - fi
> - - printf ".tar.bz2\n"
> - - printf ".tar.gz\n.tgz\n"
> - - printf ".tar\n"
> - - printf ".zip\n"
> - -}
> - -
> - -# Get the file name extension of a component
> - -# Usage: CT_GetFileExtension <component_name-component_version> [extension]
> - -# If found, echoes the extension to stdout, and return 0
> - -# If not found, echoes nothing on stdout, and return !0.
> - -CT_GetFileExtension() {
> - - local ext
> - - local file="$1"
> - - shift
> - - local first_ext="$1"
> - -
> - - # we need to also check for an empty extension for those very
> - - # peculiar components that don't have one (such as sstrip from
> - - # buildroot).
> - - for ext in ${first_ext} $(CT_DoListTarballExt) /.git ''; do
> - - if [ -e "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
> - - echo "${ext}"
> - - exit 0
> - - fi
> - - done
> - -
> - - exit 1
> - -}
> - -
> - -# Try to retrieve the specified URL (HTTP or FTP)
> - -# Usage: CT_DoGetFile <URL>
> - -# This functions always returns true (0), as it can be legitimate not
> - -# to find the requested URL (think about snapshots, different layouts
> - -# for different gcc versions, etc...).
> - -CT_DoGetFile() {
> - - local url="${1}"
> - - local dest="${CT_TARBALLS_DIR}/${url##*/}"
> - - local tmp="${dest}.tmp-dl"
> - -
> - - # Remove potential left-over from a previous run
> - - rm -f "${tmp}"
> - -
> - - # We also retry a few times, in case there is a transient error (eg. behind
> - - # a dynamic IP that changes during the transfer...)
> - - # With automated download as we are doing, it can be very dangerous to
> - - # continue the downloads. It's far better to simply overwrite the
> - - # destination file.
> - - # Some company networks have firewalls to connect to the internet, but it's
> - - # not easy to detect them, so force a global ${CT_CONNECT_TIMEOUT}-second
> - - # timeout.
> - - if [ ${CT_CONNECT_TIMEOUT} = -1 ]; then
> - - T=
> - - else
> - - T="-T ${CT_CONNECT_TIMEOUT}"
> - - fi
> - - if CT_DoExecLog ALL wget --passive-ftp --tries=3 -nc \
> - - --progress=dot:binary \
> - - ${T} \
> - - -O "${tmp}" \
> - - "${url}"
> - - then
> - - # Success, we got it, good!
> - - mv "${tmp}" "${dest}"
> - - CT_DoLog DEBUG "Got it from: \"${url}\""
> - - else
> - - # Woops...
> - - rm -f "${tmp}"
> - - CT_DoLog DEBUG "Not at this location: \"${url}\""
> - - fi
> - -}
> - -
> - -# This function tries to retrieve a tarball form a local directory
> - -# Usage: CT_GetLocal <basename> [.extension]
> - -CT_GetLocal() {
> - - local basename="$1"
> - - local first_ext="$2"
> - - local ext
> - -
> - - # Do we already have it in *our* tarballs dir?
> - - if ext="$( CT_GetFileExtension "${basename}" ${first_ext} )"; then
> - - CT_DoLog DEBUG "Already have '${basename}'"
> - - return 0
> - - fi
> - -
> - - if [ -n "${CT_LOCAL_TARBALLS_DIR}" ]; then
> - - CT_DoLog DEBUG "Trying to retrieve an already downloaded copy of '${basename}'"
> - - # We'd rather have a bzip2'ed tarball, then gzipped tarball, plain tarball,
> - - # or, as a failover, a file without extension.
> - - for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
> - - CT_DoLog DEBUG "Trying '${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}'"
> - - if [ -r "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" -a \
> - - "${CT_FORCE_DOWNLOAD}" != "y" ]; then
> - - CT_DoLog DEBUG "Got '${basename}' from local storage"
> - - CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" "${CT_TARBALLS_DIR}/${basename}${ext}"
> - - return 0
> - - fi
> - - done
> - - fi
> - - return 1
> - -}
> - -
> - -# This function gets the custom source from either a tarball or directory
> - -# Usage: CT_GetCustom <component> <custom_version> <custom_location>
> - -CT_GetCustom() {
> - - local custom_component="$1"
> - - local custom_version="$2"
> - - local custom_location="$3"
> - - local custom_name="${custom_component}-${custom_version}"
> - -
> - - CT_TestAndAbort "${custom_name}: CT_CUSTOM_LOCATION_ROOT_DIR or ${custom_component}'s CUSTOM_LOCATION must be set." \
> - - -z "${CT_CUSTOM_LOCATION_ROOT_DIR}" -a -z "${custom_location}"
> - -
> - - if [ -n "${CT_CUSTOM_LOCATION_ROOT_DIR}" \
> - - -a -z "${custom_location}" ]; then
> - - custom_location="${CT_CUSTOM_LOCATION_ROOT_DIR}/${custom_component}"
> - - fi
> - -
> - - CT_DoLog EXTRA "Using '${custom_name}' from custom location"
> - - if [ ! -d "${custom_location}" ]; then
> - - # We need to know the custom tarball extension,
> - - # so we can create a properly-named symlink, which
> - - # we use later on in 'extract'
> - - case "${custom_location}" in
> - - *.tar.xz) custom_name="${custom_name}.tar.xz";;
> - - *.tar.bz2) custom_name="${custom_name}.tar.bz2";;
> - - *.tar.gz|*.tgz) custom_name="${custom_name}.tar.gz";;
> - - *.tar) custom_name="${custom_name}.tar";;
> - - *) CT_Abort "Unknown extension for custom tarball '${custom_location}'";;
> - - esac
> - - CT_DoExecLog DEBUG ln -sf "${custom_location}" \
> - - "${CT_TARBALLS_DIR}/${custom_name}"
> - - else
> - - CT_DoExecLog DEBUG ln -snf "${custom_location}" \
> - - "${CT_SRC_DIR}/${custom_name}"
> - - fi
> - -}
> - -
> - -# This function saves the specified to local storage if possible,
> - -# and if so, symlinks it for later usage
> - -# Usage: CT_SaveLocal </full/path/file.name>
> - -CT_SaveLocal() {
> - - local file="$1"
> - - local basename="${file##*/}"
> - -
> - - if [ "${CT_SAVE_TARBALLS}" = "y" ]; then
> - - CT_DoLog EXTRA "Saving '${basename}' to local storage"
> - - # The file may already exist if downloads are forced: remove it first
> - - CT_DoExecLog ALL rm -f "${CT_LOCAL_TARBALLS_DIR}/${basename}"
> - - CT_DoExecLog ALL mv -f "${file}" "${CT_LOCAL_TARBALLS_DIR}"
> - - CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}" "${file}"
> - - fi
> - -}
> - -
> - -# Download the file from one of the URLs passed as argument
> - -# Usage: CT_GetFile <basename> [.extension] <url> [url ...]
> - -CT_GetFile() {
> - - local ext
> - - local -a URLS
> - - local url
> - - local file="$1"
> - - local first_ext
> - - shift
> - - # If next argument starts with a dot, then this is not an URL,
> - - # and we can consider that it is a preferred extension.
> - - case "$1" in
> - - .*) first_ext="$1"
> - - shift
> - - ;;
> - - esac
> - -
> - - # Does it exist localy?
> - - if CT_GetLocal "${file}" ${first_ext}; then
> - - return 0
> - - fi
> - - # No, it does not...
> - -
> - - # If not allowed to download from the Internet, don't
> - - if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
> - - CT_DoLog DEBUG "Not allowed to download from the Internet, aborting ${file} download"
> - - return 1
> - - fi
> - -
> - - # Try to retrieve the file
> - - CT_DoLog EXTRA "Retrieving '${file}'"
> - -
> - - # Add URLs on the LAN mirror
> - - if [ "${CT_USE_MIRROR}" = "y" ]; then
> - - CT_TestOrAbort "Please set the mirror base URL" -n "${CT_MIRROR_BASE_URL}"
> - - URLS+=( "${CT_MIRROR_BASE_URL}/${file%-*}" )
> - - URLS+=( "${CT_MIRROR_BASE_URL}" )
> - - fi
> - -
> - - if [ "${CT_FORCE_MIRROR}" != "y" ]; then
> - - URLS+=( "${@}" )
> - - fi
> - -
> - - # Scan all URLs in turn, and try to grab a tarball from there
> - - # Do *not* try git trees (ext=/.git), this is handled in a specific
> - - # wrapper, below
> - - for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
> - - # Try all urls in turn
> - - for url in "${URLS[@]}"; do
> - - [ -n "${url}" ] || continue
> - - CT_DoLog DEBUG "Trying '${url}/${file}${ext}'"
> - - CT_DoGetFile "${url}/${file}${ext}"
> - - if [ -f "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
> - - CT_DoLog DEBUG "Got '${file}' from the Internet"
> - - CT_SaveLocal "${CT_TARBALLS_DIR}/${file}${ext}"
> - - return 0
> - - fi
> - - done
> - - done
> - -
> - - # Just return error, someone may want to catch and handle the error
> - - # (eg. glibc/eglibc add-ons can be missing).
> - - return 1
> - -}
> - -
> - -# Checkout from CVS, and build the associated tarball
> - -# The tarball will be called ${basename}.tar.bz2
> - -# Prerequisite: either the server does not require password,
> - -# or the user must already be logged in.
> - -# 'tag' is the tag to retrieve. Must be specified, but can be empty.
> - -# If dirname is specified, then module will be renamed to dirname
> - -# prior to building the tarball.
> - -# Usage: CT_GetCVS <basename> <url> <module> <tag> [dirname[=subdir]]
> - -# Note: if '=subdir' is given, then it is used instead of 'module'.
> - -CT_GetCVS() {
> - - local basename="$1"
> - - local uri="$2"
> - - local module="$3"
> - - local tag="${4:+-r ${4}}"
> - - local dirname="$5"
> - - local tmp_dir
> - -
> - - # First try locally, then the mirror
> - - if CT_GetFile "${basename}"; then
> - - # Got it! Return early! :-)
> - - return 0
> - - fi
> - -
> - - if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
> - - CT_DoLog WARN "Downloads forbidden, not trying cvs retrieval"
> - - return 1
> - - fi
> - -
> - - CT_MktempDir tmp_dir
> - - CT_Pushd "${tmp_dir}"
> - -
> - - CT_DoExecLog ALL cvs -z 9 -d "${uri}" co -P ${tag} "${module}"
> - - if [ -n "${dirname}" ]; then
> - - case "${dirname}" in
> - - *=*)
> - - CT_DoExecLog DEBUG mv "${dirname#*=}" "${dirname%%=*}"
> - - CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname%%=*}"
> - - ;;
> - - *)
> - - CT_DoExecLog ALL mv "${module}" "${dirname}"
> - - CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname:-${module}}"
> - - ;;
> - - esac
> - - fi
> - - CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
> - -
> - - CT_Popd
> - - CT_DoExecLog ALL rm -rf "${tmp_dir}"
> - -}
> - -
> - -# Check out from SVN, and build the associated tarball
> - -# The tarball will be called ${basename}.tar.bz2
> - -# Prerequisite: either the server does not require password,
> - -# or the user must already be logged in.
> - -# 'rev' is the revision to retrieve
> - -# Usage: CT_GetSVN <basename> <url> [rev]
> - -CT_GetSVN() {
> - - local basename="$1"
> - - local uri="$2"
> - - local rev="$3"
> - -
> - - # First try locally, then the mirror
> - - if CT_GetFile "${basename}"; then
> - - # Got it! Return early! :-)
> - - return 0
> - - fi
> - -
> - - if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
> - - CT_DoLog WARN "Downloads forbidden, not trying svn retrieval"
> - - return 1
> - - fi
> - -
> - - CT_MktempDir tmp_dir
> - - CT_Pushd "${tmp_dir}"
> - -
> - - if ! CT_DoExecLog ALL svn export ${rev:+-r ${rev}} "${uri}" "${basename}"; then
> - - CT_DoLog WARN "Could not retrieve '${basename}'"
> - - return 1
> - - fi
> - - CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${basename}"
> - - CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
> - -
> - - CT_Popd
> - - CT_DoExecLog ALL rm -rf "${tmp_dir}"
> - -}
> - -
> - -# Clone a git tree
> - -# Tries the given URLs in turn until one can get cloned. No tarball will be created.
> - -# Prerequisites: either the server does not require password,
> - -# or the user has already taken any action to authenticate to the server.
> - -# The cloned tree will *not* be stored in the local tarballs dir!
> - -# Usage: CT_GetGit <basename> <cset> <url>
> - -CT_GetGit() {
> - - local basename="${1}"
> - - local cset="${2}"
> - - local url="${3}"
> - - local file="${basename}-${cset}.tar.gz"
> - - local dir="${CT_TARBALLS_DIR}/${basename}-${cset}.git"
> - - local dest="${CT_TARBALLS_DIR}/${file}"
> - - local tmp="${CT_TARBALLS_DIR}/${file}.tmp-dl"
> - -
> - - # Do we alreadyhave it?
> - - if CT_GetLocal "${file}"; then
> - - return 0
> - - fi
> - - # Nope...
> - -
> - - if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
> - - CT_DoLog WARN "Downloads forbidden, not trying git retrieval"
> - - return 1
> - - fi
> - -
> - - # Add URLs on the LAN mirror
> - - # We subvert the normal download method, just to look for
> - - # looking at the local mirror
> - - if CT_GetFile "${basename}-${cset}" .tar.gz; then
> - - return 0
> - - fi
> - -
> - - CT_DoLog EXTRA "Retrieving '${basename}-${cset}' (git)"
> - -
> - - # Remove potential left-over from a previous run
> - - CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
> - -
> - - if CT_DoExecLog ALL git clone "${url}" "${dir}"; then
> - - # Yep, cloned OK
> - - CT_Pushd "${dir}"
> - - CT_DoExecLog ALL git archive --format=tar \
> - - --prefix="${basename}-${cset}/" \
> - - -o "${tmp}.tar" \
> - - "${cset}"
> - - CT_DoExecLog ALL gzip -9 "${tmp}.tar"
> - - CT_DoExecLog ALL mv -f "${tmp}.tar.gz" "${dest}"
> - - CT_SaveLocal "${dest}"
> - - CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
> - - CT_Popd
> - - else
> - - # Woops...
> - - CT_DoExecLog ALL rm -rf "${dir}"
> - - CT_DoLog Debug "Could not clone '${basename}'"
> - - return 1
> - - fi
> - -}
> - -
> - -# Extract a tarball
> - -# Some tarballs need to be extracted in specific places. Eg.: glibc addons
> - -# must be extracted in the glibc directory; uCLibc locales must be extracted
> - -# in the extra/locale sub-directory of uClibc. This is taken into account
> - -# by the caller, that did a 'cd' into the correct path before calling us
> - -# and sets nochdir to 'nochdir'.
> - -# Note also that this function handles the git trees!
> - -# Usage: CT_Extract [nochdir] <basename> [options]
> - -# where 'options' are dependent on the source (eg. git branch/tag...)
> - -CT_Extract() {
> - - local nochdir="$1"
> - - local basename
> - - local ext
> - - local lzma_prog
> - - local -a tar_opts
> - -
> - - if [ "${nochdir}" = "nochdir" ]; then
> - - shift
> - - nochdir="$(pwd)"
> - - else
> - - nochdir="${CT_SRC_DIR}"
> - - fi
> - -
> - - basename="$1"
> - - shift
> - -
> - - if ! ext="$(CT_GetFileExtension "${basename}")"; then
> - - CT_DoLog WARN "'${basename}' not found in '${CT_TARBALLS_DIR}'"
> - - return 1
> - - fi
> - - local full_file="${CT_TARBALLS_DIR}/${basename}${ext}"
> - -
> - - # Check if already extracted
> - - if [ -e "${CT_SRC_DIR}/.${basename}.extracted" ]; then
> - - CT_DoLog DEBUG "Already extracted '${basename}'"
> - - return 0
> - - fi
> - -
> - - # Check if previously partially extracted
> - - if [ -e "${CT_SRC_DIR}/.${basename}.extracting" ]; then
> - - CT_DoLog ERROR "The '${basename}' sources were partially extracted."
> - - CT_DoLog ERROR "Please remove first:"
> - - CT_DoLog ERROR " - the source dir for '${basename}', in '${CT_SRC_DIR}'"
> - - CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${basename}.extracting'"
> - - CT_Abort "I'll stop now to avoid any carnage..."
> - - fi
> - - CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracting"
> - -
> - - CT_Pushd "${nochdir}"
> - -
> - - CT_DoLog EXTRA "Extracting '${basename}'"
> - - CT_DoExecLog FILE mkdir -p "${basename}"
> - - tar_opts=( "--strip-components=1" )
> - - tar_opts+=( "-C" "${basename}" )
> - - tar_opts+=( "-xv" )
> - -
> - - # One note here:
> - - # - lzma can be handled either with 'xz' or 'lzma'
> - - # - we get lzma tarball only if either or both are available
> - - # - so, if we get an lzma tarball, and either 'xz' or 'lzma' is
> - - # missing, we can assume the other is available
> - - if [ "${CT_CONFIGURE_has_lzma}" = "y" ]; then
> - - lzma_prog="lzma -fdc"
> - - else
> - - lzma_prog="xz -fdc"
> - - fi
> - - case "${ext}" in
> - - .tar.xz) xz -fdc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
> - - .tar.lzma) ${lzma_prog} "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
> - - .tar.bz2) bzip2 -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
> - - .tar.gz|.tgz) gzip -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
> - - .tar) CT_DoExecLog FILE tar "${tar_opts[@]}" -f "${full_file}";;
> - - .zip) CT_DoExecLog FILE unzip "${@}" "${full_file}";;
> - - /.git) CT_ExtractGit "${basename}" "${@}";;
> - - *) CT_DoLog WARN "Don't know how to handle '${basename}${ext}': unknown extension"
> - - return 1
> - - ;;
> - - esac
> - -
> - - # Don't mark as being extracted for git
> - - case "${ext}" in
> - - /.git) ;;
> - - *) CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracted";;
> - - esac
> - - CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${basename}.extracting"
> - -
> - - CT_Popd
> - -}
> - -
> - -# Create a working git clone of a local git repository
> - -# Usage: CT_ExtractGit <basename> [ref]
> - -# where 'ref' is the reference to use:
> - -# the full name of a branch, like "remotes/origin/branch_name"
> - -# a date as understandable by git, like "YYYY-MM-DD[ hh[:mm[:ss]]]"
> - -# a tag name
> - -# If 'ref' is not given, the current repository HEAD will be used
> - -CT_ExtractGit() {
> - - local basename="${1}"
> - - local ref="${2}"
> - - local repo
> - - local ref_type
> - -
> - - # pushd now to be able to get git revlist in case ref is a date
> - - repo="${CT_TARBALLS_DIR}/${basename}"
> - - CT_Pushd "${repo}"
> - -
> - - # What kind of reference is ${ref} ?
> - - if [ -z "${ref}" ]; then
> - - ref_type=head
> - - ref=$(git rev-list -n1 HEAD)
> - - elif git tag |grep -E "^${ref}$" >/dev/null 2>&1; then
> - - ref_type=tag
> - - elif git branch -a --no-color |grep -E "^. ${ref}$" >/dev/null 2>&1; then
> - - ref_type=branch
> - - elif date -d "${ref}" >/dev/null 2>&1; then
> - - ref_type=date
> - - ref=$(git rev-list -n1 --before="${ref}")
> - - else
> - - CT_Abort "Reference '${ref}' is an incorrect git reference: neither tag, branch nor date"
> - - fi
> - -
> - - CT_Popd
> - -
> - - CT_DoExecLog FILE rmdir "${basename}"
> - - case "${ref_type}" in
> - - branch) CT_DoExecLog FILE git clone -b "${ref}" "${repo}" "${basename}" ;;
> - - *) CT_DoExecLog FILE git clone "${repo}" "${basename}"
> - - CT_Pushd "${basename}"
> - - CT_DoExecLog FILE git checkout "${ref}"
> - - CT_Popd
> - - ;;
> - - esac
> - -}
> - -
> - -# Patches the specified component
> - -# See CT_Extract, above, for explanations on 'nochdir'
> - -# Usage: CT_Patch [nochdir] <packagename> <packageversion>
> - -# If the package directory is *not* packagename-packageversion, then
> - -# the caller must cd into the proper directory first, and call us
> - -# with nochdir
> - -CT_Patch() {
> - - local nochdir="$1"
> - - local pkgname
> - - local version
> - - local pkgdir
> - - local base_file
> - - local ver_file
> - - local d
> - - local -a patch_dirs
> - - local bundled_patch_dir
> - - local local_patch_dir
> - - local bundled_exp_patch_dir
> - - local local_exp_patch_dir
> - -
> - - if [ "${nochdir}" = "nochdir" ]; then
> - - shift
> - - pkgname="$1"
> - - version="$2"
> - - pkgdir="${pkgname}-${version}"
> - - nochdir="$(pwd)"
> - - else
> - - pkgname="$1"
> - - version="$2"
> - - pkgdir="${pkgname}-${version}"
> - - nochdir="${CT_SRC_DIR}/${pkgdir}"
> - - fi
> - -
> - - # Check if already patched
> - - if [ -e "${CT_SRC_DIR}/.${pkgdir}.patched" ]; then
> - - CT_DoLog DEBUG "Already patched '${pkgdir}'"
> - - return 0
> - - fi
> - -
> - - # Check if already partially patched
> - - if [ -e "${CT_SRC_DIR}/.${pkgdir}.patching" ]; then
> - - CT_DoLog ERROR "The '${pkgdir}' sources were partially patched."
> - - CT_DoLog ERROR "Please remove first:"
> - - CT_DoLog ERROR " - the source dir for '${pkgdir}', in '${CT_SRC_DIR}'"
> - - CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.extracted'"
> - - CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.patching'"
> - - CT_Abort "I'll stop now to avoid any carnage..."
> - - fi
> - - touch "${CT_SRC_DIR}/.${pkgdir}.patching"
> - -
> - - CT_Pushd "${nochdir}"
> - -
> - - CT_DoLog EXTRA "Patching '${pkgdir}'"
> - -
> - - bundled_patch_dir="${CT_LIB_DIR}/patches/${pkgname}/${version}"
> - - local_patch_dir="${CT_LOCAL_PATCH_DIR}/${pkgname}/${version}"
> - -
> - - # Check for experimental patches, if enabled.
> - - if [ "${CT_EXPERIMENTAL_PATCHES}" = "y" ]; then
> - - bundled_exp_patch_dir="${CT_LIB_DIR}/patches/experimental/${pkgname}/${version}"
> - - local_exp_patch_dir="${CT_LOCAL_PATCH_DIR}/experimental/${pkgname}/${version}"
> - - fi
> - -
> - - case "${CT_PATCH_ORDER}" in
> - - bundled) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
> - - local) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}");;
> - - bundled,local) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}" "${local_patch_dir}" "${local_exp_patch_dir}");;
> - - local,bundled) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}" "${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
> - - none) patch_dirs=;;
> - - esac
> - -
> - - for d in "${patch_dirs[@]}"; do
> - - CT_DoLog DEBUG "Looking for patches in '${d}'..."
> - - if [ -n "${d}" -a -d "${d}" ]; then
> - - for p in "${d}"/*.patch; do
> - - if [ -f "${p}" ]; then
> - - CT_DoExecLog ALL patch --no-backup-if-mismatch -g0 -F1 -p1 -f -i "${p}"
> - - fi
> - - done
> - - if [ "${CT_PATCH_SINGLE}" = "y" ]; then
> - - break
> - - fi
> - - fi
> - - done
> - -
> - - if [ "${CT_OVERIDE_CONFIG_GUESS_SUB}" = "y" ]; then
> - - CT_DoLog ALL "Overiding config.guess and config.sub"
> - - for cfg in config_guess config_sub; do
> - - eval ${cfg}="${CT_LIB_DIR}/scripts/${cfg/_/.}"
> - - [ -e "${CT_TOP_DIR}/scripts/${cfg/_/.}" ] && eval ${cfg}="${CT_TOP_DIR}/scripts/${cfg/_/.}"
> - - # Can't use CT_DoExecLog because of the '{} \;' to be passed un-mangled to find
> - - find . -type f -name "${cfg/_/.}" -exec cp -v "${!cfg}" {} \; |CT_DoLog ALL
> - - done
> - - fi
> - -
> - - CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${pkgdir}.patched"
> - - CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${pkgdir}.patching"
> - -
> - - CT_Popd
> - -}
> - -
> - -# Two wrappers to call config.(guess|sub) either from CT_TOP_DIR or CT_LIB_DIR.
> - -# Those from CT_TOP_DIR, if they exist, will be be more recent than those from CT_LIB_DIR.
> - -CT_DoConfigGuess() {
> - - if [ -x "${CT_TOP_DIR}/scripts/config.guess" ]; then
> - - "${CT_TOP_DIR}/scripts/config.guess"
> - - else
> - - "${CT_LIB_DIR}/scripts/config.guess"
> - - fi
> - -}
> - -
> - -CT_DoConfigSub() {
> - - if [ -x "${CT_TOP_DIR}/scripts/config.sub" ]; then
> - - "${CT_TOP_DIR}/scripts/config.sub" "$@"
> - - else
> - - "${CT_LIB_DIR}/scripts/config.sub" "$@"
> - - fi
> - -}
> - -
> - -# Compute the target tuple from what is provided by the user
> - -# Usage: CT_DoBuildTargetTuple
> - -# In fact this function takes the environment variables to build the target
> - -# tuple. It is needed both by the normal build sequence, as well as the
> - -# sample saving sequence.
> - -CT_DoBuildTargetTuple() {
> - - # Set the endianness suffix, and the default endianness gcc option
> - - case "${CT_ARCH_ENDIAN}" in
> - - big)
> - - target_endian_eb=eb
> - - target_endian_be=be
> - - target_endian_el=
> - - target_endian_le=
> - - CT_ARCH_ENDIAN_CFLAG="-mbig-endian"
> - - CT_ARCH_ENDIAN_LDFLAG="-Wl,-EB"
> - - ;;
> - - little)
> - - target_endian_eb=
> - - target_endian_be=
> - - target_endian_el=el
> - - target_endian_le=le
> - - CT_ARCH_ENDIAN_CFLAG="-mlittle-endian"
> - - CT_ARCH_ENDIAN_LDFLAG="-Wl,-EL"
> - - ;;
> - - esac
> - -
> - - # Set the bitness suffix
> - - case "${CT_ARCH_BITNESS}" in
> - - 32)
> - - target_bits_32=32
> - - target_bits_64=
> - - ;;
> - - 64)
> - - target_bits_32=
> - - target_bits_64=64
> - - ;;
> - - esac
> - -
> - - # Build the default architecture tuple part
> - - CT_TARGET_ARCH="${CT_ARCH}${CT_ARCH_SUFFIX}"
> - -
> - - # Set defaults for the system part of the tuple. Can be overriden
> - - # by architecture-specific values.
> - - case "${CT_LIBC}" in
> - - *glibc) CT_TARGET_SYS=gnu;;
> - - uClibc) CT_TARGET_SYS=uclibc;;
> - - *) CT_TARGET_SYS=elf;;
> - - esac
> - -
> - - # Set the default values for ARCH, ABI, CPU, TUNE, FPU and FLOAT
> - - unset CT_ARCH_ARCH_CFLAG CT_ARCH_ABI_CFLAG CT_ARCH_CPU_CFLAG CT_ARCH_TUNE_CFLAG CT_ARCH_FPU_CFLAG CT_ARCH_FLOAT_CFLAG
> - - unset CT_ARCH_WITH_ARCH CT_ARCH_WITH_ABI CT_ARCH_WITH_CPU CT_ARCH_WITH_TUNE CT_ARCH_WITH_FPU CT_ARCH_WITH_FLOAT
> - - [ "${CT_ARCH_ARCH}" ] && { CT_ARCH_ARCH_CFLAG="-march=${CT_ARCH_ARCH}"; CT_ARCH_WITH_ARCH="--with-arch=${CT_ARCH_ARCH}"; }
> - - [ "${CT_ARCH_ABI}" ] && { CT_ARCH_ABI_CFLAG="-mabi=${CT_ARCH_ABI}"; CT_ARCH_WITH_ABI="--with-abi=${CT_ARCH_ABI}"; }
> - - [ "${CT_ARCH_CPU}" ] && { CT_ARCH_CPU_CFLAG="-mcpu=${CT_ARCH_CPU}"; CT_ARCH_WITH_CPU="--with-cpu=${CT_ARCH_CPU}"; }
> - - [ "${CT_ARCH_TUNE}" ] && { CT_ARCH_TUNE_CFLAG="-mtune=${CT_ARCH_TUNE}"; CT_ARCH_WITH_TUNE="--with-tune=${CT_ARCH_TUNE}"; }
> - - [ "${CT_ARCH_FPU}" ] && { CT_ARCH_FPU_CFLAG="-mfpu=${CT_ARCH_FPU}"; CT_ARCH_WITH_FPU="--with-fpu=${CT_ARCH_FPU}"; }
> - -
> - - case "${CT_ARCH_FLOAT}" in
> - - hard)
> - - CT_ARCH_FLOAT_CFLAG="-mhard-float"
> - - CT_ARCH_WITH_FLOAT="--with-float=hard"
> - - ;;
> - - soft)
> - - CT_ARCH_FLOAT_CFLAG="-msoft-float"
> - - CT_ARCH_WITH_FLOAT="--with-float=soft"
> - - ;;
> - - softfp)
> - - CT_ARCH_FLOAT_CFLAG="-mfloat-abi=softfp"
> - - CT_ARCH_WITH_FLOAT="--with-float=softfp"
> - - ;;
> - - esac
> - -
> - - # Build the default kernel tuple part
> - - CT_TARGET_KERNEL="${CT_KERNEL}"
> - -
> - - # Overide the default values with the components specific settings
> - - CT_DoArchTupleValues
> - - CT_DoKernelTupleValues
> - -
> - - # Finish the target tuple construction
> - - CT_TARGET="${CT_TARGET_ARCH}"
> - - CT_TARGET="${CT_TARGET}${CT_TARGET_VENDOR:+-${CT_TARGET_VENDOR}}"
> - - CT_TARGET="${CT_TARGET}${CT_TARGET_KERNEL:+-${CT_TARGET_KERNEL}}"
> - - CT_TARGET="${CT_TARGET}${CT_TARGET_SYS:+-${CT_TARGET_SYS}}"
> - -
> - - # Sanity checks
> - - __sed_alias=""
> - - if [ -n "${CT_TARGET_ALIAS_SED_EXPR}" ]; then
> - - __sed_alias=$(echo "${CT_TARGET}" |sed -r -e "${CT_TARGET_ALIAS_SED_EXPR}")
> - - fi
> - - case ":${CT_TARGET_VENDOR}:${CT_TARGET_ALIAS}:${__sed_alias}:" in
> - - :*" "*:*:*:) CT_Abort "Don't use spaces in the vendor string, it breaks things.";;
> - - :*"-"*:*:*:) CT_Abort "Don't use dashes in the vendor string, it breaks things.";;
> - - :*:*" "*:*:) CT_Abort "Don't use spaces in the target alias, it breaks things.";;
> - - :*:*:*" "*:) CT_Abort "Don't use spaces in the target sed transform, it breaks things.";;
> - - esac
> - -
> - - # Canonicalise it
> - - CT_TARGET=$(CT_DoConfigSub "${CT_TARGET}")
> - - # Prepare the target CFLAGS
> - - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ENDIAN_CFLAG}"
> - - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ARCH_CFLAG}"
> - - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ABI_CFLAG}"
> - - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_CPU_CFLAG}"
> - - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_TUNE_CFLAG}"
> - - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FPU_CFLAG}"
> - - CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FLOAT_CFLAG}"
> - -
> - - # Now on for the target LDFLAGS
> - - CT_ARCH_TARGET_LDFLAGS="${CT_ARCH_TARGET_LDFLAGS} ${CT_ARCH_ENDIAN_LDFLAG}"
> - -}
> - -
> - -# This function does pause the build until the user strikes "Return"
> - -# Usage: CT_DoPause [optional_message]
> - -CT_DoPause() {
> - - local foo
> - - local message="${1:-Pausing for your pleasure}"
> - - CT_DoLog INFO "${message}"
> - - read -p "Press 'Enter' to continue, or Ctrl-C to stop..." foo >&6
> - - return 0
> - -}
> - -
> - -# This function creates a tarball of the specified directory, but
> - -# only if it exists
> - -# Usage: CT_DoTarballIfExists <dir> <tarball_basename> [extra_tar_options [...]]
> - -CT_DoTarballIfExists() {
> - - local dir="$1"
> - - local tarball="$2"
> - - shift 2
> - - local -a extra_tar_opts=( "$@" )
> - - local -a compress
> - -
> - - case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
> - - y) compress=( gzip -c -3 - ); tar_ext=.gz;;
> - - *) compress=( cat - ); tar_ext=;;
> - - esac
> - -
> - - if [ -d "${dir}" ]; then
> - - CT_DoLog DEBUG " Saving '${dir}'"
> - - { tar c -C "${dir}" -v -f - "${extra_tar_opts[@]}" . \
> - - |"${compress[@]}" >"${tarball}.tar${tar_ext}" ;
> - - } 2>&1 |sed -r -e 's/^/ /;' |CT_DoLog STATE
> - - else
> - - CT_DoLog STATE " Not saving '${dir}': does not exist"
> - - fi
> - -}
> - -
> - -# This function extracts a tarball to the specified directory, but
> - -# only if the tarball exists
> - -# Usage: CT_DoExtractTarballIfExists <tarball_basename> <dir> [extra_tar_options [...]]
> - -CT_DoExtractTarballIfExists() {
> - - local tarball="$1"
> - - local dir="$2"
> - - shift 2
> - - local -a extra_tar_opts=( "$@" )
> - - local -a uncompress
> - -
> - - case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
> - - y) uncompress=( gzip -c -d ); tar_ext=.gz;;
> - - *) uncompress=( cat ); tar_ext=;;
> - - esac
> - -
> - - if [ -f "${tarball}.tar${tar_ext}" ]; then
> - - CT_DoLog DEBUG " Restoring '${dir}'"
> - - CT_DoForceRmdir "${dir}"
> - - CT_DoExecLog DEBUG mkdir -p "${dir}"
> - - { "${uncompress[@]}" "${tarball}.tar${tar_ext}" \
> - - |tar x -C "${dir}" -v -f - "${extra_tar_opts[@]}" ;
> - - } 2>&1 |sed -r -e 's/^/ /;' |CT_DoLog STATE
> - - else
> - - CT_DoLog STATE " Not restoring '${dir}': does not exist"
> - - fi
> - -}
> - -
> - -# This function saves the state of the toolchain to be able to restart
> - -# at any one point
> - -# Usage: CT_DoSaveState <next_step_name>
> - -CT_DoSaveState() {
> - - [ "${CT_DEBUG_CT_SAVE_STEPS}" = "y" ] || return 0
> - - local state_name="$1"
> - - local state_dir="${CT_STATE_DIR}/${state_name}"
> - -
> - - # Log this to the log level required by the user
> - - CT_DoLog ${CT_LOG_LEVEL_MAX} "Saving state to restart at step '${state_name}'..."
> - -
> - - rm -rf "${state_dir}"
> - - mkdir -p "${state_dir}"
> - -
> - - CT_DoLog STATE " Saving environment and aliases"
> - - # We must omit shell functions, and some specific bash variables
> - - # that break when restoring the environment, later. We could do
> - - # all the processing in the awk script, but a sed is easier...
> - - set |awk '
> - - BEGIN { _p = 1; }
> - - $0~/^[^ ]+ \(\)/ { _p = 0; }
> - - _p == 1
> - - $0 == "}" { _p = 1; }
> - - ' |sed -r -e '/^BASH_(ARGC|ARGV|LINENO|SOURCE|VERSINFO)=/d;
> - - /^(UID|EUID)=/d;
> - - /^(FUNCNAME|GROUPS|PPID|SHELLOPTS)=/d;' >"${state_dir}/env.sh"
> - -
> - - CT_DoTarballIfExists "${CT_BUILDTOOLS_PREFIX_DIR}" "${state_dir}/buildtools_dir"
> - - CT_DoTarballIfExists "${CT_CONFIG_DIR}" "${state_dir}/config_dir"
> - - CT_DoTarballIfExists "${CT_PREFIX_DIR}" "${state_dir}/prefix_dir" --exclude '*.log'
> - -
> - - CT_DoLog STATE " Saving log file"
> - - exec >/dev/null
> - - case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
> - - y) gzip -3 -c "${tmp_log_file}" >"${state_dir}/log.gz";;
> - - *) cat "${tmp_log_file}" >"${state_dir}/log";;
> - - esac
> - - exec >>"${tmp_log_file}"
> - -}
> - -
> - -# This function restores a previously saved state
> - -# Usage: CT_DoLoadState <state_name>
> - -CT_DoLoadState(){
> - - local state_name="$1"
> - - local state_dir="${CT_STATE_DIR}/${state_name}"
> - - local old_RESTART="${CT_RESTART}"
> - - local old_STOP="${CT_STOP}"
> - -
> - - CT_TestOrAbort "The previous build did not reach the point where it could be restarted at '${CT_RESTART}'" -d "${state_dir}"
> - -
> - - # We need to do something special with the log file!
> - - if [ "${CT_LOG_TO_FILE}" = "y" ]; then
> - - exec >"${state_dir}/tail.log"
> - - fi
> - -
> - - # Log this to the log level required by the user
> - - CT_DoLog ${CT_LOG_LEVEL_MAX} "Restoring state at step '${state_name}', as requested."
> - -
> - - CT_DoExtractTarballIfExists "${state_dir}/prefix_dir" "${CT_PREFIX_DIR}"
> - - CT_DoExtractTarballIfExists "${state_dir}/config_dir" "${CT_CONFIG_DIR}"
> - - CT_DoExtractTarballIfExists "${state_dir}/buildtools_dir" "${CT_BUILDTOOLS_PREFIX_DIR}"
> - -
> - - # Restore the environment, discarding any error message
> - - # (for example, read-only bash internals)
> - - CT_DoLog STATE " Restoring environment"
> - - . "${state_dir}/env.sh" >/dev/null 2>&1 || true
> - -
> - - # Restore the new RESTART and STOP steps
> - - CT_RESTART="${old_RESTART}"
> - - CT_STOP="${old_STOP}"
> - - unset old_stop old_restart
> - -
> - - CT_DoLog STATE " Restoring log file"
> - - exec >/dev/null
> - - case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
> - - y) gzip -dc "${state_dir}/log.gz" >"${tmp_log_file}";;
> - - *) cat "${state_dir}/log" >"${tmp_log_file}";;
> - - esac
> - - cat "${state_dir}/tail.log" >>"${tmp_log_file}"
> - - exec >>"${tmp_log_file}"
> - - rm -f "${state_dir}/tail.log"
> - -}
> diff --git a/scripts/functions.in b/scripts/functions.in
> new file mode 100644
> index 0000000..51bf4a1
> - --- /dev/null
> +++ b/scripts/functions.in
> @@ -0,0 +1,1395 @@
> +# This file contains some usefull common functions -*- sh -*-
> +# Copyright 2007 Yann E. MORIN
> +# Licensed under the GPL v2. See COPYING in the root of this package
> +
> +# Prepare the fault handler
> +CT_OnError() {
> + local ret=$?
> + local result
> + local old_trap
> + local intro
> + local file line func
> + local step step_depth
> +
> + # To avoid printing the backtace for each sub-shell
> + # up to the top-level, just remember we've dumped it
> + if [ ! -f "${CT_WORK_DIR}/backtrace" ]; then
> + touch "${CT_WORK_DIR}/backtrace"
> +
> + # Print steps backtrace
> + step_depth=${CT_STEP_COUNT}
> + CT_STEP_COUNT=1 # To have a zero-indentation
> + CT_DoLog ERROR ""
> + CT_DoLog ERROR ">>"
> + intro="Build failed"
> + for((step=step_depth; step>0; step--)); do
> + CT_DoLog ERROR ">> ${intro} in step '${CT_STEP_MESSAGE[${step}]}'"
> + intro=" called"
> + done
> +
> + # Print functions backtrace
> + intro="Error happened in"
> + CT_DoLog ERROR ">>"
> + for((depth=1; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
> + file="${BASH_SOURCE[${depth}]#${CT_LIB_DIR}/}"
> + func="${FUNCNAME[${depth}]}"
> + line="@${BASH_LINENO[${depth}-1]:-?}"
> + CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
> + intro=" called from"
> + done
> +
> + # If the user asked for interactive debugging, dump him/her to a shell
> + if [ "${CT_DEBUG_INTERACTIVE}" = "y" ]; then
> + # We do not want this sub-shell exit status to be caught, because
> + # it is absolutely legit that it exits with non-zero.
> + # Save the trap handler to restore it after our debug-shell
> + old_trap="$(trap -p ERR)"
> + trap -- ERR
> + (
> + exec >&6 2>&7 <&8
> + printf "\r \n\nCurrent command"
> + if [ -n "${cur_cmd}" ]; then
> + printf ":\n %s\n" "${cur_cmd}"
> + else
> + printf " (unknown), "
> + fi
> + printf "exited with error code: %d\n" ${ret}
> + printf "Please fix it up and finish by exiting the shell with one of these values:\n"
> + printf " 1 fixed, continue with next build command\n"
> + if [ -n "${cur_cmd}" ]; then
> + printf " 2 repeat this build command\n"
> + fi
> + printf " 3 abort build\n\n"
> + while true; do
> + ${bash} --rcfile <(printf "PS1='ct-ng:\w> '\nPROMPT_COMMAND=''\n") -i
> + result=$?
> + case $result in
> + 1) printf "\nContinuing past the failed command.\n\n"
> + break
> + ;;
> + 2) if [ -n "${cur_cmd}" ]; then
> + printf "\nRe-trying last command.\n\n"
> + break
> + fi
> + ;;
> + 3) break;;
> + esac
> + printf "\nPlease exit with one of these values:\n"
> + printf " 1 fixed, continue with next build command\n"
> + if [ -n "${cur_cmd}" ]; then
> + printf " 2 repeat this build command\n"
> + fi
> + printf " 3 abort build\n"
> + done
> + exit $result
> + )
> + result=$?
> + # Restore the trap handler
> + eval "${old_trap}"
> + case "${result}" in
> + 1) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/skip"; return;;
> + 2) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/repeat"; return;;
> + # 3 is an abort, continue...
> + esac
> + fi
> + fi
> +
> + # And finally, in top-level shell, print some hints
> + if [ ${BASH_SUBSHELL} -eq 0 ]; then
> + # Help diagnose the error
> + CT_STEP_COUNT=1 # To have a zero-indentation
> + CT_DoLog ERROR ">>"
> + if [ "${CT_LOG_TO_FILE}" = "y" ]; then
> + CT_DoLog ERROR ">> For more info on this error, look at the file: '${tmp_log_file#${CT_TOP_DIR}/}'"
> + fi
> + CT_DoLog ERROR ">> There is a list of known issues, some with workarounds, in:"
> + CT_DoLog ERROR ">> '${CT_DOC_DIR#${CT_TOP_DIR}/}/B - Known issues.txt'"
> +
> + CT_DoLog ERROR ""
> + CT_DoEnd ERROR
> + rm -f "${CT_WORK_DIR}/backtrace"
> + fi
> + exit $ret
> +}
> +
> +# Install the fault handler
> +trap CT_OnError ERR
> +
> +# Inherit the fault handler in subshells and functions
> +set -E
> +
> +# Make pipes fail on the _first_ failed command
> +# Not supported on bash < 3.x, but we need it, so drop the obsoleting bash-2.x
> +set -o pipefail
> +
> +# Don't hash commands' locations, and search every time it is requested.
> +# This is slow, but needed because of the static/shared core gcc which shall
> +# always match to shared if it exists, and only fallback to static if the
> +# shared is not found
> +set +o hashall
> +
> +# Log policy:
> +# - first of all, save stdout so we can see the live logs: fd #6
> +# (also save stdin and stderr for use by CT_DEBUG_INTERACTIVE)
> +exec 6>&1 7>&2 8<&0
> +# - then point stdout to the log file
> +tmp_log_file="${CT_TOP_DIR}/build.log"
> +rm -f "${tmp_log_file}"
> +exec >>"${tmp_log_file}"
> +
> +# The different log levels:
> +CT_LOG_LEVEL_ERROR=0
> +CT_LOG_LEVEL_WARN=1
> +CT_LOG_LEVEL_INFO=2
> +CT_LOG_LEVEL_EXTRA=3
> +CT_LOG_LEVEL_CFG=4
> +CT_LOG_LEVEL_FILE=5
> +CT_LOG_LEVEL_STATE=6
> +CT_LOG_LEVEL_ALL=7
> +CT_LOG_LEVEL_DEBUG=8
> +
> +# Make it easy to use \n and !
> +CR=$(printf "\n")
> +BANG='!'
> +
> +# A function to log what is happening
> +# Different log level are available:
> +# - ERROR: A serious, fatal error occurred
> +# - WARN: A non fatal, non serious error occurred, take your responsbility with the generated build
> +# - INFO: Informational messages
> +# - EXTRA: Extra informational messages
> +# - CFG: Output of various "./configure"-type scripts
> +# - FILE: File / archive unpacking.
> +# - STATE: State save & restore
> +# - ALL: Component's build messages
> +# - DEBUG: Internal debug messages
> +# Usage: CT_DoLog <level> [message]
> +# If message is empty, then stdin will be logged.
> +CT_DoLog() {
> + local max_level LEVEL level cur_l cur_L
> + local l
> + eval max_level="\${CT_LOG_LEVEL_${CT_LOG_LEVEL_MAX}}"
> + # Set the maximum log level to DEBUG if we have none
> + [ -z "${max_level}" ] && max_level=${CT_LOG_LEVEL_DEBUG}
> +
> + LEVEL="$1"; shift
> + eval level="\${CT_LOG_LEVEL_${LEVEL}}"
> +
> + if [ $# -eq 0 ]; then
> + cat -
> + else
> + printf "%s\n" "${*}"
> + fi |( IFS="${CR}" # We want the full lines, even leading spaces
> + _prog_bar_cpt=0
> + _prog_bar[0]='/'
> + _prog_bar[1]='-'
> + _prog_bar[2]='\'
> + _prog_bar[3]='|'
> + indent=$((2*CT_STEP_COUNT))
> + while read line; do
> + case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
> + y,*"warning:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
> + y,*"WARNING:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
> + *"error:"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
> + *"make["*"]: *** ["*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
> + *) cur_L="${LEVEL}"; cur_l="${level}";;
> + esac
> + # There will always be a log file (stdout, fd #1), be it /dev/null
> + printf "[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}"
> + if [ ${cur_l} -le ${max_level} ]; then
> + # Only print to console (fd #6) if log level is high enough.
> + printf "${CT_LOG_PROGRESS_BAR:+\r}[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}" >&6
> + fi
> + if [ "${CT_LOG_PROGRESS_BAR}" = "y" ]; then
> + printf "\r[%02d:%02d] %s " $((SECONDS/60)) $((SECONDS%60)) "${_prog_bar[$((_prog_bar_cpt/10))]}" >&6
> + _prog_bar_cpt=$(((_prog_bar_cpt+1)%40))
> + fi
> + done
> + )
> +
> + return 0
> +}
> +
> +# Execute an action, and log its messages
> +# It is possible to even log local variable assignments (a-la: var=val ./cmd opts)
> +# Usage: CT_DoExecLog <level> [VAR=val...] <command> [parameters...]
> +CT_DoExecLog() {
> + local level="$1"
> + local cur_cmd
> + local ret
> + shift
> + (
> + for i in "$@"; do
> + cur_cmd+="'${i}' "
> + done
> + while true; do
> + case "${1}" in
> + *=*) eval export "'${1}'"; shift;;
> + *) break;;
> + esac
> + done
> + # This while-loop goes hand-in-hand with the ERR trap handler:
> + # - if the command terminates successfully, then we hit the break
> + # statement, and we exit the loop
> + # - if the command terminates in error, then the ERR handler kicks
> + # in, then:
> + # - if the user did *not* ask for interactive debugging, the ERR
> + # handler exits, and we hit the end of the sub-shell
> + # - if the user did ask for interactive debugging, the ERR handler
> + # spawns a shell. Upon termination of this shell, the ERR handler
> + # examines the exit status of the shell:
> + # - if 1, the ERR handler returns; then we hit the else statement,
> + # then the break, and we exit the 'while' loop, to continue the
> + # build;
> + # - if 2, the ERR handler touches the repeat file, and returns;
> + # then we hit the if statement, and we loop for one more
> + # iteration;
> + # - if 3, the ERR handler exits with the command's exit status,
> + # and we're dead;
> + # - for any other exit status of the shell, the ERR handler
> + # prints an informational message, and respawns the shell
> + #
> + # This allows a user to get an interactive shell that has the same
> + # environment (PATH and so on) that the failed command was ran with.
> + while true; do
> + rm -f "${CT_BUILD_DIR}/repeat"
> + CT_DoLog DEBUG "==> Executing: ${cur_cmd}"
> + "${@}" 2>&1 |CT_DoLog "${level}"
> + ret="${?}"
> + if [ -f "${CT_BUILD_DIR}/repeat" ]; then
> + rm -f "${CT_BUILD_DIR}/repeat"
> + continue
> + elif [ -f "${CT_BUILD_DIR}/skip" ]; then
> + rm -f "${CT_BUILD_DIR}/skip"
> + ret=0
> + break
> + else
> + break
> + fi
> + done
> + exit ${ret}
> + )
> + # Catch failure of the sub-shell
> + [ $? -eq 0 ]
> +}
> +
> +# Tail message to be logged whatever happens
> +# Usage: CT_DoEnd <level>
> +CT_DoEnd()
> +{
> + local level="$1"
> + CT_STOP_DATE=$(CT_DoDate +%s%N)
> + CT_STOP_DATE_HUMAN=$(CT_DoDate +%Y%m%d.%H%M%S)
> + if [ "${level}" != "ERROR" ]; then
> + CT_DoLog "${level:-INFO}" "Build completed at ${CT_STOP_DATE_HUMAN}"
> + fi
> + elapsed=$((CT_STOP_DATE-CT_STAR_DATE))
> + elapsed_min=$((elapsed/(60*1000*1000*1000)))
> + elapsed_sec=$(printf "%02d" $(((elapsed%(60*1000*1000*1000))/(1000*1000*1000))))
> + elapsed_csec=$(printf "%02d" $(((elapsed%(1000*1000*1000))/(10*1000*1000))))
> + CT_DoLog ${level:-INFO} "(elapsed: ${elapsed_min}:${elapsed_sec}.${elapsed_csec})"
> +}
> +
> +# Remove entries referring to . and other relative paths
> +# Usage: CT_SanitizePath
> +CT_SanitizePath() {
> + local new
> + local p
> + local IFS=:
> + for p in $PATH; do
> + # Only accept absolute paths;
> + # Note: as a special case the empty string in PATH is equivalent to .
> + if [ -n "${p}" -a -z "${p%%/*}" ]; then
> + new="${new}${new:+:}${p}"
> + fi
> + done
> + PATH="${new}"
> +}
> +
> +# Sanitise the directory name contained in the variable passed as argument:
> +# - remove duplicate /
> +# Usage: CT_SanitiseVarDir CT_PREFIX_DIR
> +CT_SanitiseVarDir() {
> + local var
> + local old_dir
> + local new_dir
> +
> + for var in "$@"; do
> + eval "old_dir=\"\${${var}}\""
> + new_dir="$( printf "${old_dir}" \
> + |@@CT_sed@@ -r -e 's:/+:/:g;' \
> + )"
> + eval "${var}=\"${new_dir}\""
> + CT_DoLog DEBUG "Sanitised '${var}': '${old_dir}' -> '${new_dir}'"
> + done
> +}
> +
> +# Abort the execution with an error message
> +# Usage: CT_Abort <message>
> +CT_Abort() {
> + CT_DoLog ERROR "$1"
> + false
> +}
> +
> +# Test a condition, and print a message if satisfied
> +# Usage: CT_Test <message> <tests>
> +CT_Test() {
> + local ret
> + local m="$1"
> + shift
> + CT_DoLog DEBUG "Testing '! ( $* )'"
> + test "$@" && CT_DoLog WARN "$m"
> + return 0
> +}
> +
> +# Test a condition, and abort with an error message if satisfied
> +# Usage: CT_TestAndAbort <message> <tests>
> +CT_TestAndAbort() {
> + local m="$1"
> + shift
> + CT_DoLog DEBUG "Testing '! ( $* )'"
> + test "$@" && CT_Abort "$m"
> + return 0
> +}
> +
> +# Test a condition, and abort with an error message if not satisfied
> +# Usage: CT_TestAndAbort <message> <tests>
> +CT_TestOrAbort() {
> + local m="$1"
> + shift
> + CT_DoLog DEBUG "Testing '$*'"
> + test "$@" || CT_Abort "$m"
> + return 0
> +}
> +
> +# Test the presence of a tool, or abort if not found
> +# Usage: CT_HasOrAbort <tool>
> +CT_HasOrAbort() {
> + CT_TestAndAbort "'${1}' not found and needed for successful toolchain build." -z "$(CT_Which "${1}")"
> + return 0
> +}
> +
> +# Search a program: wrap "which" for those system where "which"
> +# verbosely says there is no match (such as on Mandriva).
> +# Usage: CT_Which <filename>
> +CT_Which() {
> + which "$1" 2>/dev/null || true
> +}
> +
> +# Get current date with nanosecond precision
> +# On those system not supporting nanosecond precision, faked with rounding down
> +# to the highest entire second
> +# Usage: CT_DoDate <fmt>
> +CT_DoDate() {
> + date "$1" |@@CT_sed@@ -r -e 's/%?N$/000000000/;'
> +}
> +
> +CT_STEP_COUNT=1
> +CT_STEP_MESSAGE[${CT_STEP_COUNT}]="(top-level)"
> +# Memorise a step being done so that any error is caught
> +# Usage: CT_DoStep <loglevel> <message>
> +CT_DoStep() {
> + local start=$(CT_DoDate +%s%N)
> + CT_DoLog "$1" "================================================================="
> + CT_DoLog "$1" "$2"
> + CT_STEP_COUNT=$((CT_STEP_COUNT+1))
> + CT_STEP_LEVEL[${CT_STEP_COUNT}]="$1"; shift
> + CT_STEP_START[${CT_STEP_COUNT}]="${start}"
> + CT_STEP_MESSAGE[${CT_STEP_COUNT}]="$1"
> + return 0
> +}
> +
> +# End the step just being done
> +# Usage: CT_EndStep
> +CT_EndStep() {
> + local stop=$(CT_DoDate +%s%N)
> + local duration=$(printf "%032d" $((stop-${CT_STEP_START[${CT_STEP_COUNT}]})) |@@CT_sed@@ -r -e 's/([[:digit:]]{2})[[:digit:]]{7}$/\.\1/; s/^0+//; s/^\./0\./;')
> + local elapsed=$(printf "%02d:%02d" $((SECONDS/60)) $((SECONDS%60)))
> + local level="${CT_STEP_LEVEL[${CT_STEP_COUNT}]}"
> + local message="${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}"
> + CT_STEP_COUNT=$((CT_STEP_COUNT-1))
> + CT_DoLog "${level}" "${message}: done in ${duration}s (at ${elapsed})"
> + return 0
> +}
> +
> +# Pushes into a directory, and pops back
> +CT_Pushd() {
> + CT_DoLog DEBUG "Entering '$1'"
> + pushd "$1" >/dev/null 2>&1
> +}
> +CT_Popd() {
> + popd >/dev/null 2>&1
> +}
> +
> +# Create a dir and cd or pushd into it
> +# Usage: CT_mkdir_cd <dir/to/create>
> +# CT_mkdir_pushd <dir/to/create>
> +CT_mkdir_cd() {
> + local dir="${1}"
> +
> + mkdir -p "${dir}"
> + cd "${dir}"
> +}
> +CT_mkdir_pushd() {
> + local dir="${1}"
> +
> + mkdir -p "${dir}"
> + CT_Pushd "${dir}"
> +}
> +
> +# Creates a temporary directory
> +# $1: variable to assign to
> +# Usage: CT_MktempDir foo
> +CT_MktempDir() {
> + # Some mktemp do not allow more than 6 Xs
> + eval "$1"=$(mktemp -q -d "${CT_BUILD_DIR}/tmp.XXXXXX")
> + CT_TestOrAbort "Could not make temporary directory" -n "${!1}" -a -d "${!1}"
> + CT_DoLog DEBUG "Made temporary directory '${!1}'"
> + return 0
> +}
> +
> +# Removes one or more directories, even if it is read-only, or its parent is
> +# Usage: CT_DoForceRmdir dir [...]
> +CT_DoForceRmdir() {
> + local dir
> + local mode
> + for dir in "${@}"; do
> + [ -d "${dir}" ] || continue
> + case "$CT_SYS_OS" in
> + Linux|CYGWIN*)
> + mode="$(stat -c '%a' "$(dirname "${dir}")")"
> + ;;
> + Darwin|*BSD)
> + mode="$(stat -f '%Lp' "$(dirname "${dir}")")"
> + ;;
> + *)
> + CT_Abort "Unhandled host OS $CT_SYS_OS"
> + ;;
> + esac
> + CT_DoExecLog ALL chmod u+w "$(dirname "${dir}")"
> + CT_DoExecLog ALL chmod -R u+w "${dir}"
> + CT_DoExecLog ALL rm -rf "${dir}"
> + CT_DoExecLog ALL chmod ${mode} "$(dirname "${dir}")"
> + done
> +}
> +
> +# Echoes the specified string on stdout until the pipe breaks.
> +# Doesn't fail
> +# $1: string to echo
> +# Usage: CT_DoYes "" |make oldconfig
> +CT_DoYes() {
> + yes "$1" || true
> +}
> +
> +# Add the specified directory to LD_LIBRARY_PATH, and export it
> +# If the specified patch is already present, just export
> +# $1: path to add
> +# $2: add as 'first' or 'last' path, 'first' is assumed if $2 is empty
> +# Usage CT_SetLibPath /some/where/lib [first|last]
> +CT_SetLibPath() {
> + local path="$1"
> + local pos="$2"
> +
> + case ":${LD_LIBRARY_PATH}:" in
> + *:"${path}":*) ;;
> + *) case "${pos}" in
> + last)
> + CT_DoLog DEBUG "Adding '${path}' at end of LD_LIBRARY_PATH"
> + LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${path}"
> + ;;
> + first|"")
> + CT_DoLog DEBUG "Adding '${path}' at start of LD_LIBRARY_PATH"
> + LD_LIBRARY_PATH="${path}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
> + ;;
> + *)
> + CT_Abort "Incorrect position '${pos}' to add '${path}' to LD_LIBRARY_PATH"
> + ;;
> + esac
> + ;;
> + esac
> + CT_DoLog DEBUG "==> LD_LIBRARY_PATH='${LD_LIBRARY_PATH}'"
> + export LD_LIBRARY_PATH
> +}
> +
> +# Build up the list of allowed tarball extensions
> +# Add them in the prefered order; most preferred comes first
> +CT_DoListTarballExt() {
> + if [ "${CT_CONFIGURE_has_xz}" = "y" ]; then
> + printf ".tar.xz\n"
> + fi
> + if [ "${CT_CONFIGURE_has_lzma}" = "y" \
> + -o "${CT_CONFIGURE_has_xz}" = "y" ]; then
> + printf ".tar.lzma\n"
> + fi
> + printf ".tar.bz2\n"
> + printf ".tar.gz\n.tgz\n"
> + printf ".tar\n"
> + printf ".zip\n"
> +}
> +
> +# Get the file name extension of a component
> +# Usage: CT_GetFileExtension <component_name-component_version> [extension]
> +# If found, echoes the extension to stdout, and return 0
> +# If not found, echoes nothing on stdout, and return !0.
> +CT_GetFileExtension() {
> + local ext
> + local file="$1"
> + shift
> + local first_ext="$1"
> +
> + # we need to also check for an empty extension for those very
> + # peculiar components that don't have one (such as sstrip from
> + # buildroot).
> + for ext in ${first_ext} $(CT_DoListTarballExt) /.git ''; do
> + if [ -e "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
> + echo "${ext}"
> + exit 0
> + fi
> + done
> +
> + exit 1
> +}
> +
> +# Try to retrieve the specified URL (HTTP or FTP)
> +# Usage: CT_DoGetFile <URL>
> +# This functions always returns true (0), as it can be legitimate not
> +# to find the requested URL (think about snapshots, different layouts
> +# for different gcc versions, etc...).
> +CT_DoGetFile() {
> + local url="${1}"
> + local dest="${CT_TARBALLS_DIR}/${url##*/}"
> + local tmp="${dest}.tmp-dl"
> +
> + # Remove potential left-over from a previous run
> + rm -f "${tmp}"
> +
> + # We also retry a few times, in case there is a transient error (eg. behind
> + # a dynamic IP that changes during the transfer...)
> + # With automated download as we are doing, it can be very dangerous to
> + # continue the downloads. It's far better to simply overwrite the
> + # destination file.
> + # Some company networks have firewalls to connect to the internet, but it's
> + # not easy to detect them, so force a global ${CT_CONNECT_TIMEOUT}-second
> + # timeout.
> + if [ ${CT_CONNECT_TIMEOUT} = -1 ]; then
> + T=
> + else
> + T="-T ${CT_CONNECT_TIMEOUT}"
> + fi
> + if CT_DoExecLog ALL wget --passive-ftp --tries=3 -nc \
> + --progress=dot:binary \
> + ${T} \
> + -O "${tmp}" \
> + "${url}"
> + then
> + # Success, we got it, good!
> + mv "${tmp}" "${dest}"
> + CT_DoLog DEBUG "Got it from: \"${url}\""
> + else
> + # Woops...
> + rm -f "${tmp}"
> + CT_DoLog DEBUG "Not at this location: \"${url}\""
> + fi
> +}
> +
> +# This function tries to retrieve a tarball form a local directory
> +# Usage: CT_GetLocal <basename> [.extension]
> +CT_GetLocal() {
> + local basename="$1"
> + local first_ext="$2"
> + local ext
> +
> + # Do we already have it in *our* tarballs dir?
> + if ext="$( CT_GetFileExtension "${basename}" ${first_ext} )"; then
> + CT_DoLog DEBUG "Already have '${basename}'"
> + return 0
> + fi
> +
> + if [ -n "${CT_LOCAL_TARBALLS_DIR}" ]; then
> + CT_DoLog DEBUG "Trying to retrieve an already downloaded copy of '${basename}'"
> + # We'd rather have a bzip2'ed tarball, then gzipped tarball, plain tarball,
> + # or, as a failover, a file without extension.
> + for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
> + CT_DoLog DEBUG "Trying '${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}'"
> + if [ -r "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" -a \
> + "${CT_FORCE_DOWNLOAD}" != "y" ]; then
> + CT_DoLog DEBUG "Got '${basename}' from local storage"
> + CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" "${CT_TARBALLS_DIR}/${basename}${ext}"
> + return 0
> + fi
> + done
> + fi
> + return 1
> +}
> +
> +# This function gets the custom source from either a tarball or directory
> +# Usage: CT_GetCustom <component> <custom_version> <custom_location>
> +CT_GetCustom() {
> + local custom_component="$1"
> + local custom_version="$2"
> + local custom_location="$3"
> + local custom_name="${custom_component}-${custom_version}"
> +
> + CT_TestAndAbort "${custom_name}: CT_CUSTOM_LOCATION_ROOT_DIR or ${custom_component}'s CUSTOM_LOCATION must be set." \
> + -z "${CT_CUSTOM_LOCATION_ROOT_DIR}" -a -z "${custom_location}"
> +
> + if [ -n "${CT_CUSTOM_LOCATION_ROOT_DIR}" \
> + -a -z "${custom_location}" ]; then
> + custom_location="${CT_CUSTOM_LOCATION_ROOT_DIR}/${custom_component}"
> + fi
> +
> + CT_DoLog EXTRA "Using '${custom_name}' from custom location"
> + if [ ! -d "${custom_location}" ]; then
> + # We need to know the custom tarball extension,
> + # so we can create a properly-named symlink, which
> + # we use later on in 'extract'
> + case "${custom_location}" in
> + *.tar.xz) custom_name="${custom_name}.tar.xz";;
> + *.tar.bz2) custom_name="${custom_name}.tar.bz2";;
> + *.tar.gz|*.tgz) custom_name="${custom_name}.tar.gz";;
> + *.tar) custom_name="${custom_name}.tar";;
> + *) CT_Abort "Unknown extension for custom tarball '${custom_location}'";;
> + esac
> + CT_DoExecLog DEBUG ln -sf "${custom_location}" \
> + "${CT_TARBALLS_DIR}/${custom_name}"
> + else
> + CT_DoExecLog DEBUG ln -snf "${custom_location}" \
> + "${CT_SRC_DIR}/${custom_name}"
> + fi
> +}
> +
> +# This function saves the specified to local storage if possible,
> +# and if so, symlinks it for later usage
> +# Usage: CT_SaveLocal </full/path/file.name>
> +CT_SaveLocal() {
> + local file="$1"
> + local basename="${file##*/}"
> +
> + if [ "${CT_SAVE_TARBALLS}" = "y" ]; then
> + CT_DoLog EXTRA "Saving '${basename}' to local storage"
> + # The file may already exist if downloads are forced: remove it first
> + CT_DoExecLog ALL rm -f "${CT_LOCAL_TARBALLS_DIR}/${basename}"
> + CT_DoExecLog ALL mv -f "${file}" "${CT_LOCAL_TARBALLS_DIR}"
> + CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}" "${file}"
> + fi
> +}
> +
> +# Download the file from one of the URLs passed as argument
> +# Usage: CT_GetFile <basename> [.extension] <url> [url ...]
> +CT_GetFile() {
> + local ext
> + local -a URLS
> + local url
> + local file="$1"
> + local first_ext
> + shift
> + # If next argument starts with a dot, then this is not an URL,
> + # and we can consider that it is a preferred extension.
> + case "$1" in
> + .*) first_ext="$1"
> + shift
> + ;;
> + esac
> +
> + # Does it exist localy?
> + if CT_GetLocal "${file}" ${first_ext}; then
> + return 0
> + fi
> + # No, it does not...
> +
> + # If not allowed to download from the Internet, don't
> + if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
> + CT_DoLog DEBUG "Not allowed to download from the Internet, aborting ${file} download"
> + return 1
> + fi
> +
> + # Try to retrieve the file
> + CT_DoLog EXTRA "Retrieving '${file}'"
> +
> + # Add URLs on the LAN mirror
> + if [ "${CT_USE_MIRROR}" = "y" ]; then
> + CT_TestOrAbort "Please set the mirror base URL" -n "${CT_MIRROR_BASE_URL}"
> + URLS+=( "${CT_MIRROR_BASE_URL}/${file%-*}" )
> + URLS+=( "${CT_MIRROR_BASE_URL}" )
> + fi
> +
> + if [ "${CT_FORCE_MIRROR}" != "y" ]; then
> + URLS+=( "${@}" )
> + fi
> +
> + # Scan all URLs in turn, and try to grab a tarball from there
> + # Do *not* try git trees (ext=/.git), this is handled in a specific
> + # wrapper, below
> + for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
> + # Try all urls in turn
> + for url in "${URLS[@]}"; do
> + [ -n "${url}" ] || continue
> + CT_DoLog DEBUG "Trying '${url}/${file}${ext}'"
> + CT_DoGetFile "${url}/${file}${ext}"
> + if [ -f "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
> + CT_DoLog DEBUG "Got '${file}' from the Internet"
> + CT_SaveLocal "${CT_TARBALLS_DIR}/${file}${ext}"
> + return 0
> + fi
> + done
> + done
> +
> + # Just return error, someone may want to catch and handle the error
> + # (eg. glibc/eglibc add-ons can be missing).
> + return 1
> +}
> +
> +# Checkout from CVS, and build the associated tarball
> +# The tarball will be called ${basename}.tar.bz2
> +# Prerequisite: either the server does not require password,
> +# or the user must already be logged in.
> +# 'tag' is the tag to retrieve. Must be specified, but can be empty.
> +# If dirname is specified, then module will be renamed to dirname
> +# prior to building the tarball.
> +# Usage: CT_GetCVS <basename> <url> <module> <tag> [dirname[=subdir]]
> +# Note: if '=subdir' is given, then it is used instead of 'module'.
> +CT_GetCVS() {
> + local basename="$1"
> + local uri="$2"
> + local module="$3"
> + local tag="${4:+-r ${4}}"
> + local dirname="$5"
> + local tmp_dir
> +
> + # First try locally, then the mirror
> + if CT_GetFile "${basename}"; then
> + # Got it! Return early! :-)
> + return 0
> + fi
> +
> + if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
> + CT_DoLog WARN "Downloads forbidden, not trying cvs retrieval"
> + return 1
> + fi
> +
> + CT_MktempDir tmp_dir
> + CT_Pushd "${tmp_dir}"
> +
> + CT_DoExecLog ALL cvs -z 9 -d "${uri}" co -P ${tag} "${module}"
> + if [ -n "${dirname}" ]; then
> + case "${dirname}" in
> + *=*)
> + CT_DoExecLog DEBUG mv "${dirname#*=}" "${dirname%%=*}"
> + CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname%%=*}"
> + ;;
> + *)
> + CT_DoExecLog ALL mv "${module}" "${dirname}"
> + CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname:-${module}}"
> + ;;
> + esac
> + fi
> + CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
> +
> + CT_Popd
> + CT_DoExecLog ALL rm -rf "${tmp_dir}"
> +}
> +
> +# Check out from SVN, and build the associated tarball
> +# The tarball will be called ${basename}.tar.bz2
> +# Prerequisite: either the server does not require password,
> +# or the user must already be logged in.
> +# 'rev' is the revision to retrieve
> +# Usage: CT_GetSVN <basename> <url> [rev]
> +CT_GetSVN() {
> + local basename="$1"
> + local uri="$2"
> + local rev="$3"
> +
> + # First try locally, then the mirror
> + if CT_GetFile "${basename}"; then
> + # Got it! Return early! :-)
> + return 0
> + fi
> +
> + if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
> + CT_DoLog WARN "Downloads forbidden, not trying svn retrieval"
> + return 1
> + fi
> +
> + CT_MktempDir tmp_dir
> + CT_Pushd "${tmp_dir}"
> +
> + if ! CT_DoExecLog ALL svn export ${rev:+-r ${rev}} "${uri}" "${basename}"; then
> + CT_DoLog WARN "Could not retrieve '${basename}'"
> + return 1
> + fi
> + CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${basename}"
> + CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
> +
> + CT_Popd
> + CT_DoExecLog ALL rm -rf "${tmp_dir}"
> +}
> +
> +# Clone a git tree
> +# Tries the given URLs in turn until one can get cloned. No tarball will be created.
> +# Prerequisites: either the server does not require password,
> +# or the user has already taken any action to authenticate to the server.
> +# The cloned tree will *not* be stored in the local tarballs dir!
> +# Usage: CT_GetGit <basename> <cset> <url>
> +CT_GetGit() {
> + local basename="${1}"
> + local cset="${2}"
> + local url="${3}"
> + local file="${basename}-${cset}.tar.gz"
> + local dir="${CT_TARBALLS_DIR}/${basename}-${cset}.git"
> + local dest="${CT_TARBALLS_DIR}/${file}"
> + local tmp="${CT_TARBALLS_DIR}/${file}.tmp-dl"
> +
> + # Do we alreadyhave it?
> + if CT_GetLocal "${file}"; then
> + return 0
> + fi
> + # Nope...
> +
> + if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
> + CT_DoLog WARN "Downloads forbidden, not trying git retrieval"
> + return 1
> + fi
> +
> + # Add URLs on the LAN mirror
> + # We subvert the normal download method, just to look for
> + # looking at the local mirror
> + if CT_GetFile "${basename}-${cset}" .tar.gz; then
> + return 0
> + fi
> +
> + CT_DoLog EXTRA "Retrieving '${basename}-${cset}' (git)"
> +
> + # Remove potential left-over from a previous run
> + CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
> +
> + if CT_DoExecLog ALL git clone "${url}" "${dir}"; then
> + # Yep, cloned OK
> + CT_Pushd "${dir}"
> + CT_DoExecLog ALL git archive --format=tar \
> + --prefix="${basename}-${cset}/" \
> + -o "${tmp}.tar" \
> + "${cset}"
> + CT_DoExecLog ALL gzip -9 "${tmp}.tar"
> + CT_DoExecLog ALL mv -f "${tmp}.tar.gz" "${dest}"
> + CT_SaveLocal "${dest}"
> + CT_DoExecLog ALL rm -rf "${tmp}.tar.gz" "${tmp}.tar" "${tmp}" "${dir}"
> + CT_Popd
> + else
> + # Woops...
> + CT_DoExecLog ALL rm -rf "${dir}"
> + CT_DoLog Debug "Could not clone '${basename}'"
> + return 1
> + fi
> +}
> +
> +# Extract a tarball
> +# Some tarballs need to be extracted in specific places. Eg.: glibc addons
> +# must be extracted in the glibc directory; uCLibc locales must be extracted
> +# in the extra/locale sub-directory of uClibc. This is taken into account
> +# by the caller, that did a 'cd' into the correct path before calling us
> +# and sets nochdir to 'nochdir'.
> +# Note also that this function handles the git trees!
> +# Usage: CT_Extract [nochdir] <basename> [options]
> +# where 'options' are dependent on the source (eg. git branch/tag...)
> +CT_Extract() {
> + local nochdir="$1"
> + local basename
> + local ext
> + local lzma_prog
> + local -a tar_opts
> +
> + if [ "${nochdir}" = "nochdir" ]; then
> + shift
> + nochdir="$(pwd)"
> + else
> + nochdir="${CT_SRC_DIR}"
> + fi
> +
> + basename="$1"
> + shift
> +
> + if ! ext="$(CT_GetFileExtension "${basename}")"; then
> + CT_DoLog WARN "'${basename}' not found in '${CT_TARBALLS_DIR}'"
> + return 1
> + fi
> + local full_file="${CT_TARBALLS_DIR}/${basename}${ext}"
> +
> + # Check if already extracted
> + if [ -e "${CT_SRC_DIR}/.${basename}.extracted" ]; then
> + CT_DoLog DEBUG "Already extracted '${basename}'"
> + return 0
> + fi
> +
> + # Check if previously partially extracted
> + if [ -e "${CT_SRC_DIR}/.${basename}.extracting" ]; then
> + CT_DoLog ERROR "The '${basename}' sources were partially extracted."
> + CT_DoLog ERROR "Please remove first:"
> + CT_DoLog ERROR " - the source dir for '${basename}', in '${CT_SRC_DIR}'"
> + CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${basename}.extracting'"
> + CT_Abort "I'll stop now to avoid any carnage..."
> + fi
> + CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracting"
> +
> + CT_Pushd "${nochdir}"
> +
> + CT_DoLog EXTRA "Extracting '${basename}'"
> + CT_DoExecLog FILE mkdir -p "${basename}"
> + tar_opts=( "--strip-components=1" )
> + tar_opts+=( "-C" "${basename}" )
> + tar_opts+=( "-xv" )
> +
> + # One note here:
> + # - lzma can be handled either with 'xz' or 'lzma'
> + # - we get lzma tarball only if either or both are available
> + # - so, if we get an lzma tarball, and either 'xz' or 'lzma' is
> + # missing, we can assume the other is available
> + if [ "${CT_CONFIGURE_has_lzma}" = "y" ]; then
> + lzma_prog="lzma -fdc"
> + else
> + lzma_prog="xz -fdc"
> + fi
> + case "${ext}" in
> + .tar.xz) xz -fdc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
> + .tar.lzma) ${lzma_prog} "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
> + .tar.bz2) bzip2 -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
> + .tar.gz|.tgz) gzip -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
> + .tar) CT_DoExecLog FILE tar "${tar_opts[@]}" -f "${full_file}";;
> + .zip) CT_DoExecLog FILE unzip "${@}" "${full_file}";;
> + /.git) CT_ExtractGit "${basename}" "${@}";;
> + *) CT_DoLog WARN "Don't know how to handle '${basename}${ext}': unknown extension"
> + return 1
> + ;;
> + esac
> +
> + # Don't mark as being extracted for git
> + case "${ext}" in
> + /.git) ;;
> + *) CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracted";;
> + esac
> + CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${basename}.extracting"
> +
> + CT_Popd
> +}
> +
> +# Create a working git clone of a local git repository
> +# Usage: CT_ExtractGit <basename> [ref]
> +# where 'ref' is the reference to use:
> +# the full name of a branch, like "remotes/origin/branch_name"
> +# a date as understandable by git, like "YYYY-MM-DD[ hh[:mm[:ss]]]"
> +# a tag name
> +# If 'ref' is not given, the current repository HEAD will be used
> +CT_ExtractGit() {
> + local basename="${1}"
> + local ref="${2}"
> + local repo
> + local ref_type
> +
> + # pushd now to be able to get git revlist in case ref is a date
> + repo="${CT_TARBALLS_DIR}/${basename}"
> + CT_Pushd "${repo}"
> +
> + # What kind of reference is ${ref} ?
> + if [ -z "${ref}" ]; then
> + ref_type=head
> + ref=$(git rev-list -n1 HEAD)
> + elif git tag |@@CT_grep@@ -E "^${ref}$" >/dev/null 2>&1; then
> + ref_type=tag
> + elif git branch -a --no-color | @@CT_grep@@ -E "^. ${ref}$" >/dev/null 2>&1; then
> + ref_type=branch
> + elif date -d "${ref}" >/dev/null 2>&1; then
> + ref_type=date
> + ref=$(git rev-list -n1 --before="${ref}")
> + else
> + CT_Abort "Reference '${ref}' is an incorrect git reference: neither tag, branch nor date"
> + fi
> +
> + CT_Popd
> +
> + CT_DoExecLog FILE rmdir "${basename}"
> + case "${ref_type}" in
> + branch) CT_DoExecLog FILE git clone -b "${ref}" "${repo}" "${basename}" ;;
> + *) CT_DoExecLog FILE git clone "${repo}" "${basename}"
> + CT_Pushd "${basename}"
> + CT_DoExecLog FILE git checkout "${ref}"
> + CT_Popd
> + ;;
> + esac
> +}
> +
> +# Patches the specified component
> +# See CT_Extract, above, for explanations on 'nochdir'
> +# Usage: CT_Patch [nochdir] <packagename> <packageversion>
> +# If the package directory is *not* packagename-packageversion, then
> +# the caller must cd into the proper directory first, and call us
> +# with nochdir
> +CT_Patch() {
> + local nochdir="$1"
> + local pkgname
> + local version
> + local pkgdir
> + local base_file
> + local ver_file
> + local d
> + local -a patch_dirs
> + local bundled_patch_dir
> + local local_patch_dir
> + local bundled_exp_patch_dir
> + local local_exp_patch_dir
> +
> + if [ "${nochdir}" = "nochdir" ]; then
> + shift
> + pkgname="$1"
> + version="$2"
> + pkgdir="${pkgname}-${version}"
> + nochdir="$(pwd)"
> + else
> + pkgname="$1"
> + version="$2"
> + pkgdir="${pkgname}-${version}"
> + nochdir="${CT_SRC_DIR}/${pkgdir}"
> + fi
> +
> + # Check if already patched
> + if [ -e "${CT_SRC_DIR}/.${pkgdir}.patched" ]; then
> + CT_DoLog DEBUG "Already patched '${pkgdir}'"
> + return 0
> + fi
> +
> + # Check if already partially patched
> + if [ -e "${CT_SRC_DIR}/.${pkgdir}.patching" ]; then
> + CT_DoLog ERROR "The '${pkgdir}' sources were partially patched."
> + CT_DoLog ERROR "Please remove first:"
> + CT_DoLog ERROR " - the source dir for '${pkgdir}', in '${CT_SRC_DIR}'"
> + CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.extracted'"
> + CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.patching'"
> + CT_Abort "I'll stop now to avoid any carnage..."
> + fi
> + touch "${CT_SRC_DIR}/.${pkgdir}.patching"
> +
> + CT_Pushd "${nochdir}"
> +
> + CT_DoLog EXTRA "Patching '${pkgdir}'"
> +
> + bundled_patch_dir="${CT_LIB_DIR}/patches/${pkgname}/${version}"
> + local_patch_dir="${CT_LOCAL_PATCH_DIR}/${pkgname}/${version}"
> +
> + # Check for experimental patches, if enabled.
> + if [ "${CT_EXPERIMENTAL_PATCHES}" = "y" ]; then
> + bundled_exp_patch_dir="${CT_LIB_DIR}/patches/experimental/${pkgname}/${version}"
> + local_exp_patch_dir="${CT_LOCAL_PATCH_DIR}/experimental/${pkgname}/${version}"
> + fi
> +
> + case "${CT_PATCH_ORDER}" in
> + bundled) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
> + local) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}");;
> + bundled,local) patch_dirs=("${bundled_patch_dir}" "${bundled_exp_patch_dir}" "${local_patch_dir}" "${local_exp_patch_dir}");;
> + local,bundled) patch_dirs=("${local_patch_dir}" "${local_exp_patch_dir}" "${bundled_patch_dir}" "${bundled_exp_patch_dir}");;
> + none) patch_dirs=;;
> + esac
> +
> + for d in "${patch_dirs[@]}"; do
> + CT_DoLog DEBUG "Looking for patches in '${d}'..."
> + if [ -n "${d}" -a -d "${d}" ]; then
> + for p in "${d}"/*.patch; do
> + if [ -f "${p}" ]; then
> + CT_DoExecLog ALL patch --no-backup-if-mismatch -g0 -F1 -p1 -f -i "${p}"
> + fi
> + done
> + if [ "${CT_PATCH_SINGLE}" = "y" ]; then
> + break
> + fi
> + fi
> + done
> +
> + if [ "${CT_OVERIDE_CONFIG_GUESS_SUB}" = "y" ]; then
> + CT_DoLog ALL "Overiding config.guess and config.sub"
> + for cfg in config_guess config_sub; do
> + eval ${cfg}="${CT_LIB_DIR}/scripts/${cfg/_/.}"
> + [ -e "${CT_TOP_DIR}/scripts/${cfg/_/.}" ] && eval ${cfg}="${CT_TOP_DIR}/scripts/${cfg/_/.}"
> + # Can't use CT_DoExecLog because of the '{} \;' to be passed un-mangled to find
> + find . -type f -name "${cfg/_/.}" -exec cp -v "${!cfg}" {} \; |CT_DoLog ALL
> + done
> + fi
> +
> + CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${pkgdir}.patched"
> + CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${pkgdir}.patching"
> +
> + CT_Popd
> +}
> +
> +# Two wrappers to call config.(guess|sub) either from CT_TOP_DIR or CT_LIB_DIR.
> +# Those from CT_TOP_DIR, if they exist, will be be more recent than those from CT_LIB_DIR.
> +CT_DoConfigGuess() {
> + if [ -x "${CT_TOP_DIR}/scripts/config.guess" ]; then
> + "${CT_TOP_DIR}/scripts/config.guess"
> + else
> + "${CT_LIB_DIR}/scripts/config.guess"
> + fi
> +}
> +
> +CT_DoConfigSub() {
> + if [ -x "${CT_TOP_DIR}/scripts/config.sub" ]; then
> + "${CT_TOP_DIR}/scripts/config.sub" "$@"
> + else
> + "${CT_LIB_DIR}/scripts/config.sub" "$@"
> + fi
> +}
> +
> +# Compute the target tuple from what is provided by the user
> +# Usage: CT_DoBuildTargetTuple
> +# In fact this function takes the environment variables to build the target
> +# tuple. It is needed both by the normal build sequence, as well as the
> +# sample saving sequence.
> +CT_DoBuildTargetTuple() {
> + # Set the endianness suffix, and the default endianness gcc option
> + case "${CT_ARCH_ENDIAN}" in
> + big)
> + target_endian_eb=eb
> + target_endian_be=be
> + target_endian_el=
> + target_endian_le=
> + CT_ARCH_ENDIAN_CFLAG="-mbig-endian"
> + CT_ARCH_ENDIAN_LDFLAG="-Wl,-EB"
> + ;;
> + little)
> + target_endian_eb=
> + target_endian_be=
> + target_endian_el=el
> + target_endian_le=le
> + CT_ARCH_ENDIAN_CFLAG="-mlittle-endian"
> + CT_ARCH_ENDIAN_LDFLAG="-Wl,-EL"
> + ;;
> + esac
> +
> + # Set the bitness suffix
> + case "${CT_ARCH_BITNESS}" in
> + 32)
> + target_bits_32=32
> + target_bits_64=
> + ;;
> + 64)
> + target_bits_32=
> + target_bits_64=64
> + ;;
> + esac
> +
> + # Build the default architecture tuple part
> + CT_TARGET_ARCH="${CT_ARCH}${CT_ARCH_SUFFIX}"
> +
> + # Set defaults for the system part of the tuple. Can be overriden
> + # by architecture-specific values.
> + case "${CT_LIBC}" in
> + *glibc) CT_TARGET_SYS=gnu;;
> + uClibc) CT_TARGET_SYS=uclibc;;
> + *) CT_TARGET_SYS=elf;;
> + esac
> +
> + # Set the default values for ARCH, ABI, CPU, TUNE, FPU and FLOAT
> + unset CT_ARCH_ARCH_CFLAG CT_ARCH_ABI_CFLAG CT_ARCH_CPU_CFLAG CT_ARCH_TUNE_CFLAG CT_ARCH_FPU_CFLAG CT_ARCH_FLOAT_CFLAG
> + unset CT_ARCH_WITH_ARCH CT_ARCH_WITH_ABI CT_ARCH_WITH_CPU CT_ARCH_WITH_TUNE CT_ARCH_WITH_FPU CT_ARCH_WITH_FLOAT
> + [ "${CT_ARCH_ARCH}" ] && { CT_ARCH_ARCH_CFLAG="-march=${CT_ARCH_ARCH}"; CT_ARCH_WITH_ARCH="--with-arch=${CT_ARCH_ARCH}"; }
> + [ "${CT_ARCH_ABI}" ] && { CT_ARCH_ABI_CFLAG="-mabi=${CT_ARCH_ABI}"; CT_ARCH_WITH_ABI="--with-abi=${CT_ARCH_ABI}"; }
> + [ "${CT_ARCH_CPU}" ] && { CT_ARCH_CPU_CFLAG="-mcpu=${CT_ARCH_CPU}"; CT_ARCH_WITH_CPU="--with-cpu=${CT_ARCH_CPU}"; }
> + [ "${CT_ARCH_TUNE}" ] && { CT_ARCH_TUNE_CFLAG="-mtune=${CT_ARCH_TUNE}"; CT_ARCH_WITH_TUNE="--with-tune=${CT_ARCH_TUNE}"; }
> + [ "${CT_ARCH_FPU}" ] && { CT_ARCH_FPU_CFLAG="-mfpu=${CT_ARCH_FPU}"; CT_ARCH_WITH_FPU="--with-fpu=${CT_ARCH_FPU}"; }
> +
> + case "${CT_ARCH_FLOAT}" in
> + hard)
> + CT_ARCH_FLOAT_CFLAG="-mhard-float"
> + CT_ARCH_WITH_FLOAT="--with-float=hard"
> + ;;
> + soft)
> + CT_ARCH_FLOAT_CFLAG="-msoft-float"
> + CT_ARCH_WITH_FLOAT="--with-float=soft"
> + ;;
> + softfp)
> + CT_ARCH_FLOAT_CFLAG="-mfloat-abi=softfp"
> + CT_ARCH_WITH_FLOAT="--with-float=softfp"
> + ;;
> + esac
> +
> + # Build the default kernel tuple part
> + CT_TARGET_KERNEL="${CT_KERNEL}"
> +
> + # Overide the default values with the components specific settings
> + CT_DoArchTupleValues
> + CT_DoKernelTupleValues
> +
> + # Finish the target tuple construction
> + CT_TARGET="${CT_TARGET_ARCH}"
> + CT_TARGET="${CT_TARGET}${CT_TARGET_VENDOR:+-${CT_TARGET_VENDOR}}"
> + CT_TARGET="${CT_TARGET}${CT_TARGET_KERNEL:+-${CT_TARGET_KERNEL}}"
> + CT_TARGET="${CT_TARGET}${CT_TARGET_SYS:+-${CT_TARGET_SYS}}"
> +
> + # Sanity checks
> + __sed_alias=""
> + if [ -n "${CT_TARGET_ALIAS_SED_EXPR}" ]; then
> + __sed_alias=$(echo "${CT_TARGET}" |@@CT_sed@@ -r -e "${CT_TARGET_ALIAS_SED_EXPR}")
> + fi
> + case ":${CT_TARGET_VENDOR}:${CT_TARGET_ALIAS}:${__sed_alias}:" in
> + :*" "*:*:*:) CT_Abort "Don't use spaces in the vendor string, it breaks things.";;
> + :*"-"*:*:*:) CT_Abort "Don't use dashes in the vendor string, it breaks things.";;
> + :*:*" "*:*:) CT_Abort "Don't use spaces in the target alias, it breaks things.";;
> + :*:*:*" "*:) CT_Abort "Don't use spaces in the target sed transform, it breaks things.";;
> + esac
> +
> + # Canonicalise it
> + CT_TARGET=$(CT_DoConfigSub "${CT_TARGET}")
> + # Prepare the target CFLAGS
> + CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ENDIAN_CFLAG}"
> + CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ARCH_CFLAG}"
> + CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ABI_CFLAG}"
> + CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_CPU_CFLAG}"
> + CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_TUNE_CFLAG}"
> + CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FPU_CFLAG}"
> + CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FLOAT_CFLAG}"
> +
> + # Now on for the target LDFLAGS
> + CT_ARCH_TARGET_LDFLAGS="${CT_ARCH_TARGET_LDFLAGS} ${CT_ARCH_ENDIAN_LDFLAG}"
> +}
> +
> +# This function does pause the build until the user strikes "Return"
> +# Usage: CT_DoPause [optional_message]
> +CT_DoPause() {
> + local foo
> + local message="${1:-Pausing for your pleasure}"
> + CT_DoLog INFO "${message}"
> + read -p "Press 'Enter' to continue, or Ctrl-C to stop..." foo >&6
> + return 0
> +}
> +
> +# This function creates a tarball of the specified directory, but
> +# only if it exists
> +# Usage: CT_DoTarballIfExists <dir> <tarball_basename> [extra_tar_options [...]]
> +CT_DoTarballIfExists() {
> + local dir="$1"
> + local tarball="$2"
> + shift 2
> + local -a extra_tar_opts=( "$@" )
> + local -a compress
> +
> + case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
> + y) compress=( gzip -c -3 - ); tar_ext=.gz;;
> + *) compress=( cat - ); tar_ext=;;
> + esac
> +
> + if [ -d "${dir}" ]; then
> + CT_DoLog DEBUG " Saving '${dir}'"
> + { tar c -C "${dir}" -v -f - "${extra_tar_opts[@]}" . \
> + |"${compress[@]}" >"${tarball}.tar${tar_ext}" ;
> + } 2>&1 |@@CT_sed@@ -r -e 's/^/ /;' |CT_DoLog STATE
> + else
> + CT_DoLog STATE " Not saving '${dir}': does not exist"
> + fi
> +}
> +
> +# This function extracts a tarball to the specified directory, but
> +# only if the tarball exists
> +# Usage: CT_DoExtractTarballIfExists <tarball_basename> <dir> [extra_tar_options [...]]
> +CT_DoExtractTarballIfExists() {
> + local tarball="$1"
> + local dir="$2"
> + shift 2
> + local -a extra_tar_opts=( "$@" )
> + local -a uncompress
> +
> + case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
> + y) uncompress=( gzip -c -d ); tar_ext=.gz;;
> + *) uncompress=( cat ); tar_ext=;;
> + esac
> +
> + if [ -f "${tarball}.tar${tar_ext}" ]; then
> + CT_DoLog DEBUG " Restoring '${dir}'"
> + CT_DoForceRmdir "${dir}"
> + CT_DoExecLog DEBUG mkdir -p "${dir}"
> + { "${uncompress[@]}" "${tarball}.tar${tar_ext}" \
> + |tar x -C "${dir}" -v -f - "${extra_tar_opts[@]}" ;
> + } 2>&1 |@@CT_sed@@ -r -e 's/^/ /;' |CT_DoLog STATE
> + else
> + CT_DoLog STATE " Not restoring '${dir}': does not exist"
> + fi
> +}
> +
> +# This function saves the state of the toolchain to be able to restart
> +# at any one point
> +# Usage: CT_DoSaveState <next_step_name>
> +CT_DoSaveState() {
> + [ "${CT_DEBUG_CT_SAVE_STEPS}" = "y" ] || return 0
> + local state_name="$1"
> + local state_dir="${CT_STATE_DIR}/${state_name}"
> +
> + # Log this to the log level required by the user
> + CT_DoLog ${CT_LOG_LEVEL_MAX} "Saving state to restart at step '${state_name}'..."
> +
> + rm -rf "${state_dir}"
> + mkdir -p "${state_dir}"
> +
> + CT_DoLog STATE " Saving environment and aliases"
> + # We must omit shell functions, and some specific bash variables
> + # that break when restoring the environment, later. We could do
> + # all the processing in the awk script, but a sed is easier...
> + set |awk '
> + BEGIN { _p = 1; }
> + $0~/^[^ ]+ \(\)/ { _p = 0; }
> + _p == 1
> + $0 == "}" { _p = 1; }
> + ' |@@CT_sed@@ -r -e '/^BASH_(ARGC|ARGV|LINENO|SOURCE|VERSINFO)=/d;
> + /^(UID|EUID)=/d;
> + /^(FUNCNAME|GROUPS|PPID|SHELLOPTS)=/d;' >"${state_dir}/env.sh"
> +
> + CT_DoTarballIfExists "${CT_BUILDTOOLS_PREFIX_DIR}" "${state_dir}/buildtools_dir"
> + CT_DoTarballIfExists "${CT_CONFIG_DIR}" "${state_dir}/config_dir"
> + CT_DoTarballIfExists "${CT_PREFIX_DIR}" "${state_dir}/prefix_dir" --exclude '*.log'
> +
> + CT_DoLog STATE " Saving log file"
> + exec >/dev/null
> + case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
> + y) gzip -3 -c "${tmp_log_file}" >"${state_dir}/log.gz";;
> + *) cat "${tmp_log_file}" >"${state_dir}/log";;
> + esac
> + exec >>"${tmp_log_file}"
> +}
> +
> +# This function restores a previously saved state
> +# Usage: CT_DoLoadState <state_name>
> +CT_DoLoadState(){
> + local state_name="$1"
> + local state_dir="${CT_STATE_DIR}/${state_name}"
> + local old_RESTART="${CT_RESTART}"
> + local old_STOP="${CT_STOP}"
> +
> + CT_TestOrAbort "The previous build did not reach the point where it could be restarted at '${CT_RESTART}'" -d "${state_dir}"
> +
> + # We need to do something special with the log file!
> + if [ "${CT_LOG_TO_FILE}" = "y" ]; then
> + exec >"${state_dir}/tail.log"
> + fi
> +
> + # Log this to the log level required by the user
> + CT_DoLog ${CT_LOG_LEVEL_MAX} "Restoring state at step '${state_name}', as requested."
> +
> + CT_DoExtractTarballIfExists "${state_dir}/prefix_dir" "${CT_PREFIX_DIR}"
> + CT_DoExtractTarballIfExists "${state_dir}/config_dir" "${CT_CONFIG_DIR}"
> + CT_DoExtractTarballIfExists "${state_dir}/buildtools_dir" "${CT_BUILDTOOLS_PREFIX_DIR}"
> +
> + # Restore the environment, discarding any error message
> + # (for example, read-only bash internals)
> + CT_DoLog STATE " Restoring environment"
> + . "${state_dir}/env.sh" >/dev/null 2>&1 || true
> +
> + # Restore the new RESTART and STOP steps
> + CT_RESTART="${old_RESTART}"
> + CT_STOP="${old_STOP}"
> + unset old_stop old_restart
> +
> + CT_DoLog STATE " Restoring log file"
> + exec >/dev/null
> + case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
> + y) gzip -dc "${state_dir}/log.gz" >"${tmp_log_file}";;
> + *) cat "${state_dir}/log" >"${tmp_log_file}";;
> + esac
> + cat "${state_dir}/tail.log" >>"${tmp_log_file}"
> + exec >>"${tmp_log_file}"
> + rm -f "${state_dir}/tail.log"
> +}
> diff --git a/scripts/xldd.in b/scripts/xldd.in
> index c906240..4cbe333 100755
> - --- a/scripts/xldd.in
> +++ b/scripts/xldd.in
> @@ -159,7 +159,7 @@ fi
> sysroot="$( "${gcc}" -print-sysroot 2>/dev/null )"
> if [ -z "${sysroot}" ]; then
> sysroot="$( "${gcc}" -print-file-name=libc.so 2>/dev/null \
> - - |sed -r -e 's:/usr/lib/libc.so$::;' \
> + |"${sed}" -r -e 's:/usr/lib/libc.so$::;' \
> )"
> fi
> if [ -z "${sysroot}" ]; then
> - --
> 1.8.5.2 (Apple Git-48)
>
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
> Comment: GPGTools - https://gpgtools.org
> Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
>
> iQIcBAEBCgAGBQJT4ZKSAAoJEHYXgoVc4PRjKYUQAIqsmgvc2vZpG+TNhRhm37cw
> DBSoncpD7B9eTiaKhVRVTbeS1Tx/Fh0WvstULbQYmnnF6ovdkW1XNEjBYXLP24T/
> pogcxRcr8imHGVXvem+CwQ7pQq83dW/idYnvqd7gqP/Ib/CfibQrJlGxgIXDanNq
> 4+xLi+Hdjt3eCf2fAkDCQ7e2x0xUZwyAoY42JqgpbZAugk4uyum7c+7N38kQcera
> HHve5B4/F87KEHJp+xT07DIcTschYgWYZIz/lmEkgm0ptBDtcJePinZpSUTbrZ+l
> UqtbSldLpn/pV0FsnHjSGKsHSXd4ylFhZL5YsFvYteB+6q0lfPe1MkbLdx78YE8K
> dITbWcpJAZFX6Ci+l3X70lf5B4wHBR2R+f+FArhCpT76Zf0V+KJFVIsL6dx6qmir
> s/LZvJQB4QVzgJvlXBkTe5MTLQ6smMQDhQelQQWJ7oUjqRrgvywv4pdIMoLWLDqc
> rgp3540JVVz1Y97/sSUNI+YNUkYDxvpB31RY4T9WTT1YXhP6dnzU8clYfZI9phBc
> cuZDnyDPnPojio9BnBMJeqnMojDknyc9npNi5qfjWYm7jqW4bJ5mt/7YFzSMKjcn
> E3O58IDdcDM7BNGFYTnaIfP0a5FxpDBYd5y4m13NSUlXMBWADLbJV0W4Y1iq+vA1
> cZnevMrW531Eu1KTQUnw
> =6M3V
> -----END PGP SIGNATURE-----
--
.-----------------.--------------------.------------------.--------------------.
| Yann E. MORIN | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software Designer | \ / CAMPAIGN | ___ |
| +33 223 225 172 `------------.-------: X AGAINST | \e/ There is no |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL | v conspiracy. |
'------------------------------^-------^------------------^--------------------'
--
For unsubscribe information see http://sourceware.org/lists.html#faq
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes
2014-08-26 22:26 ` Yann E. MORIN
@ 2014-08-26 22:43 ` Fabian Freyer
2014-08-26 22:47 ` Yann E. MORIN
0 siblings, 1 reply; 10+ messages in thread
From: Fabian Freyer @ 2014-08-26 22:43 UTC (permalink / raw)
To: Yann E. MORIN; +Cc: crossgcc
[-- Attachment #1: Type: text/plain, Size: 3748 bytes --]
Yann, All,
On 27/08/14 00:26, Yann E. MORIN wrote:
> Fabian, All,
>
> On 2014-08-06 04:27 +0200, Fabian Freyer spake thusly:
>> Hi,
>>
>> On 26/09/12 18:56, Yann E. MORIN wrote:
>>> On Wednesday 26 September 2012 17:30:12 Blair Burtan wrote:
>>>> That was the problem but not quite the complete solution. I had to modify
>>>> the grep path to point to the MacPorts verison when I built ct-ng. I also
>>>> had to use ginstall instead of the OSX install.
>>>
>>> ./configure --help
>>> [--SNIP--]
>>> Optional Packages:
>>> --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
>>> --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
>>> --with-install=PATH Specify the full PATH to a BSD-compatible install
>>> --with-sed=PATH Specify the full PATH to GNU sed
>>> --with-objcopy=PATH Specify the full PATH to GNU objcopy
>>> --with-objdump=PATH Specify the full PATH to GNU objdump
>>> --with-ranlib=PATH Specify the full PATH to GNU ranlib
>>> --with-readelf=PATH Specify the full PATH to GNU readelf
>>> --with-bash=PATH Specify the full PATH to GNU bash >= 3.1
>>> --with-awk=PATH Specify the full PATH to GNU awk
>>> --with-make=PATH Specify the full PATH to GNU make >= 3.80
>>> --with-libtool=PATH Specify the full PATH to GNU libtool >= 1.5.26
>>> --with-libtoolize=PATH Specify the full PATH to GNU libtoolize >= 1.5.26
>>> --with-automake=PATH Specify the full PATH to GNU automake >= 1.10
>>> [--SNIP--]
>>>
>>> That's how you tell crosstool-NG what tools to use if the default ones are
>>> not the GNU ones.
>>
>> While it is possible to tell crosstool-NG to use custom GNU tools for several
>> tools, it is not possible for all tools, especially for grep and sed. This
>> causes ct-ng build to fail:
>>
>> [ERROR] >>
>> [ERROR] >> Build failed in step '(top-level)'
>> [ERROR] >>
>> [ERROR] >> Error happened in: CT_DoForceRmdir[scripts/functions@458]
>> [ERROR] >> called from: main[scripts/crosstool-NG.sh@238]
>> [ERROR] >>
>>
>> One of the problems here is also that on BSD installs, including OS X, GNU
>> tools are often installed with a prefixed 'g', in this case "ggrep" and "gsed".
>> There is no way to tell crosstool-NG to use ggrep instead of grep, and
>> adjusting $PATH does not help either.
>>
>> I have created a small (not counting the changes due to the scripts/functions
>> rename) patch that adds --with-grep and substitues @@CT_sed@@ for sed in a few
>> places where sed from PATH is used and GNU-specific options are used.
>
> The solution is not to pre-process 'functions.in' into 'functions', but
> to add the new tools to the generated paths.mk and paths.sh, and then to
> use ${sed} and ${grep} where needed.
>
> Note that 'sed' is already present in those files, so only grep needs to
> be added.
>
> Is there a name which GNU grep is known as on BSD systems? For example,
> we have gsed. Do we have ggrep, too?
Yes, gnu tools are usually prefixed with a g, so it would be called ggrep.
>
> In which case, we'd need four patches:
> - use ${sed} instead of plain 'sed' where appropriate
> - add --with-grep to the list of tools we can specify
> - add an alternate name for when searching for grep
> - use ${grep} instead of plain 'grep' where appropriate
>
> I'll tackle this here.
I would also offer to do this, since I have a testing environment ready. Also, I have already adressed some of these changes in my patch, so it wouldn't be too much work to alter them.
>
> Sorry for the delay, and thanks for the report.
>
> Regards,
> Yann E. MORIN.
Regards,
Fabian Freyer
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 882 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes
2014-08-26 22:43 ` Fabian Freyer
@ 2014-08-26 22:47 ` Yann E. MORIN
0 siblings, 0 replies; 10+ messages in thread
From: Yann E. MORIN @ 2014-08-26 22:47 UTC (permalink / raw)
To: Fabian Freyer; +Cc: crossgcc
Fabian, All,
On 2014-08-27 00:43 +0200, Fabian Freyer spake thusly:
> On 27/08/14 00:26, Yann E. MORIN wrote:
[--SNIP--]
> > Is there a name which GNU grep is known as on BSD systems? For example,
> > we have gsed. Do we have ggrep, too?
> Yes, gnu tools are usually prefixed with a g, so it would be called ggrep.
OK, good.
> > In which case, we'd need four patches:
> > - use ${sed} instead of plain 'sed' where appropriate
> > - add --with-grep to the list of tools we can specify
> > - add an alternate name for when searching for grep
> > - use ${grep} instead of plain 'grep' where appropriate
> >
> > I'll tackle this here.
>
> I would also offer to do this, since I have a testing environment ready.
> Also, I have already adressed some of these changes in my patch, so it
> wouldn't be too much work to alter them.
Hmm, I have all them done here. I'll post the patches on the list, so
you can grab them and tests them, and if need add the needed pieces I
forgot or missed.
Regards,
Yann E. MORIN.
--
.-----------------.--------------------.------------------.--------------------.
| Yann E. MORIN | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software Designer | \ / CAMPAIGN | ___ |
| +33 223 225 172 `------------.-------: X AGAINST | \e/ There is no |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL | v conspiracy. |
'------------------------------^-------^------------------^--------------------'
--
For unsubscribe information see http://sourceware.org/lists.html#faq
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes
2014-08-06 2:27 ` [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes Fabian Freyer
2014-08-06 2:40 ` Fabian Freyer
2014-08-26 22:26 ` Yann E. MORIN
@ 2014-08-26 22:51 ` Yann E. MORIN
2 siblings, 0 replies; 10+ messages in thread
From: Yann E. MORIN @ 2014-08-26 22:51 UTC (permalink / raw)
To: Fabian Freyer; +Cc: crossgcc
Fabian, All,
On 2014-08-06 04:27 +0200, Fabian Freyer spake thusly:
> While it is possible to tell crosstool-NG to use custom GNU tools for several
> tools, it is not possible for all tools, especially for grep and sed. This
> causes ct-ng build to fail:
[--SNIP--]
Also, you forgot to sign-off-by your patch, with something like:
Signed-off-by: Your NAME <you@somewheere.net>
Regards,
Yann E. MORIN.
--
.-----------------.--------------------.------------------.--------------------.
| Yann E. MORIN | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software Designer | \ / CAMPAIGN | ___ |
| +33 223 225 172 `------------.-------: X AGAINST | \e/ There is no |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL | v conspiracy. |
'------------------------------^-------^------------------^--------------------'
--
For unsubscribe information see http://sourceware.org/lists.html#faq
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-08-26 22:51 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-26 3:46 Build failed in step 'Dumping user-supplied crosstool-NG configuration' Blair Burtan
2012-09-26 6:54 ` Per Arnold Blaasmo
2012-09-26 15:30 ` Blair Burtan
2012-09-26 16:56 ` Yann E. MORIN
2014-08-06 2:27 ` [PATCH] Added support for AC_ARG_WITH([grep]...) and sed substitution fixes Fabian Freyer
2014-08-06 2:40 ` Fabian Freyer
2014-08-26 22:26 ` Yann E. MORIN
2014-08-26 22:43 ` Fabian Freyer
2014-08-26 22:47 ` Yann E. MORIN
2014-08-26 22:51 ` Yann E. MORIN
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).