scripts/functions
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Jan 01 17:49:44 2012 +0100 (2012-01-01)
changeset 2924 0eab838768b1
parent 2898 7e0af0188fc3
child 2931 8a72662f0815
permissions -rw-r--r--
cc/gcc: install the core compilers in the build-tools dir

There really is no good reason to install the core compilers in their
own places, one for each pass. We can install them with the other
build tools.

Also, this implies that:
- there are fewer directories to save/restore
- there are fewer symlinks to create for binutils
- the PATH is shorter

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
anthony@2155
     1
# This file contains some usefull common functions -*- sh -*-
yann@1
     2
# Copyright 2007 Yann E. MORIN
yann@1
     3
# Licensed under the GPL v2. See COPYING in the root of this package
yann@1
     4
yann@136
     5
# Prepare the fault handler
yann@1
     6
CT_OnError() {
yann@2388
     7
    local ret=$?
yann@2388
     8
    local intro
yann@2807
     9
    local file line func
yann@2807
    10
    local step step_depth
yann@2388
    11
yann@2807
    12
    # To avoid printing the backtace for each sub-shell
yann@2807
    13
    # up to the top-level, just remember we've dumped it
yann@2807
    14
    if [ ! -f "${CT_BUILD_DIR}/backtrace" ]; then
yann@2807
    15
        touch "${CT_BUILD_DIR}/backtrace"
yann@2388
    16
yann@2807
    17
        # Print steps backtrace
yann@2807
    18
        step_depth=${CT_STEP_COUNT}
yann@2807
    19
        CT_STEP_COUNT=1     # To have a zero-indentation
yann@2807
    20
        CT_DoLog ERROR ""
yann@2807
    21
        CT_DoLog ERROR ">>"
yann@2807
    22
        intro="Build failed"
yann@2807
    23
        for((step=step_depth; step>0; step--)); do
yann@2807
    24
            CT_DoLog ERROR ">>  ${intro} in step '${CT_STEP_MESSAGE[${step}]}'"
yann@2807
    25
            intro="      called"
yann@2807
    26
        done
yann@2388
    27
yann@2807
    28
        # Print functions backtrace
yann@2807
    29
        intro="Error happened in"
yann@2807
    30
        CT_DoLog ERROR ">>"
yann@2807
    31
        for((depth=1; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
yann@2807
    32
            file="${BASH_SOURCE[${depth}]#${CT_LIB_DIR}/}"
yann@2807
    33
            func="${FUNCNAME[${depth}]}"
yann@2807
    34
            line="@${BASH_LINENO[${depth}-1]:-?}"
yann@2807
    35
            CT_DoLog ERROR ">>  ${intro}: ${func}[${file}${line}]"
yann@2807
    36
            intro="      called from"
yann@2807
    37
        done
yann@2807
    38
    fi
yann@2388
    39
yann@2807
    40
    # And finally, in top-level shell, print some hints
yann@2807
    41
    if [ ${BASH_SUBSHELL} -eq 0 ]; then
yann@2807
    42
        # Help diagnose the error
yann@2807
    43
        CT_STEP_COUNT=1     # To have a zero-indentation
yann@2807
    44
        CT_DoLog ERROR ">>"
yann@2807
    45
        if [ "${CT_LOG_TO_FILE}" = "y" ]; then
yann@2807
    46
            CT_DoLog ERROR ">>  For more info on this error, look at the file: '${tmp_log_file#${CT_TOP_DIR}/}'"
yann@2807
    47
        fi
yann@2807
    48
        CT_DoLog ERROR ">>  There is a list of known issues, some with workarounds, in:"
yann@2807
    49
        CT_DoLog ERROR ">>      '${CT_DOC_DIR#${CT_TOP_DIR}/}/B - Known issues.txt'"
yann@2807
    50
yann@2807
    51
        CT_DoLog ERROR ""
yann@2807
    52
        CT_DoEnd ERROR
yann@2807
    53
        rm -f "${CT_BUILD_DIR}/backtrace"
yann@2388
    54
    fi
yann@1
    55
    exit $ret
yann@1
    56
}
yann@136
    57
yann@136
    58
# Install the fault handler
yann@1
    59
trap CT_OnError ERR
yann@1
    60
yann@136
    61
# Inherit the fault handler in subshells and functions
yann@1
    62
set -E
yann@136
    63
yann@136
    64
# Make pipes fail on the _first_ failed command
yann@136
    65
# Not supported on bash < 3.x, but we need it, so drop the obsoleting bash-2.x
yann@1
    66
set -o pipefail
yann@1
    67
yann@136
    68
# Don't hash commands' locations, and search every time it is requested.
yann@136
    69
# This is slow, but needed because of the static/shared core gcc which shall
yann@136
    70
# always match to shared if it exists, and only fallback to static if the
yann@136
    71
# shared is not found
yann@136
    72
set +o hashall
yann@136
    73
yann@165
    74
# Log policy:
yann@165
    75
#  - first of all, save stdout so we can see the live logs: fd #6
yann@165
    76
exec 6>&1
yann@2339
    77
#  - then point stdout to the log file
yann@2339
    78
tmp_log_file="${CT_TOP_DIR}/build.log"
yann@2339
    79
rm -f "${tmp_log_file}"
yann@165
    80
exec >>"${tmp_log_file}"
yann@165
    81
yann@1
    82
# The different log levels:
yann@1
    83
CT_LOG_LEVEL_ERROR=0
yann@1
    84
CT_LOG_LEVEL_WARN=1
yann@1
    85
CT_LOG_LEVEL_INFO=2
yann@1
    86
CT_LOG_LEVEL_EXTRA=3
anthony@2154
    87
CT_LOG_LEVEL_CFG=4
anthony@2154
    88
CT_LOG_LEVEL_FILE=5
anthony@2155
    89
CT_LOG_LEVEL_STATE=6
anthony@2155
    90
CT_LOG_LEVEL_ALL=7
anthony@2155
    91
CT_LOG_LEVEL_DEBUG=8
yann@1
    92
yann@1083
    93
# Make it easy to use \n and !
yann@1081
    94
CR=$(printf "\n")
yann@1083
    95
BANG='!'
yann@1081
    96
yann@1
    97
# A function to log what is happening
yann@1
    98
# Different log level are available:
yann@1
    99
#   - ERROR:   A serious, fatal error occurred
yann@1
   100
#   - WARN:    A non fatal, non serious error occurred, take your responsbility with the generated build
yann@1
   101
#   - INFO:    Informational messages
yann@1
   102
#   - EXTRA:   Extra informational messages
anthony@2154
   103
#   - CFG:     Output of various "./configure"-type scripts
anthony@2154
   104
#   - FILE:    File / archive unpacking.
anthony@2155
   105
#   - STATE:   State save & restore
yann@78
   106
#   - ALL:     Component's build messages
anthony@2155
   107
#   - DEBUG:   Internal debug messages
yann@1
   108
# Usage: CT_DoLog <level> [message]
yann@1
   109
# If message is empty, then stdin will be logged.
yann@1
   110
CT_DoLog() {
yann@47
   111
    local max_level LEVEL level cur_l cur_L
yann@47
   112
    local l
yann@1
   113
    eval max_level="\${CT_LOG_LEVEL_${CT_LOG_LEVEL_MAX}}"
yann@1
   114
    # Set the maximum log level to DEBUG if we have none
yann@78
   115
    [ -z "${max_level}" ] && max_level=${CT_LOG_LEVEL_DEBUG}
yann@1
   116
yann@47
   117
    LEVEL="$1"; shift
yann@1
   118
    eval level="\${CT_LOG_LEVEL_${LEVEL}}"
yann@1
   119
yann@1
   120
    if [ $# -eq 0 ]; then
yann@1
   121
        cat -
yann@1
   122
    else
yann@2096
   123
        printf "%s\n" "${*}"
yann@1081
   124
    fi |( IFS="${CR}" # We want the full lines, even leading spaces
yann@523
   125
          _prog_bar_cpt=0
yann@523
   126
          _prog_bar[0]='/'
yann@523
   127
          _prog_bar[1]='-'
yann@523
   128
          _prog_bar[2]='\'
yann@523
   129
          _prog_bar[3]='|'
yann@1
   130
          indent=$((2*CT_STEP_COUNT))
yann@1
   131
          while read line; do
yann@47
   132
              case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
yann@47
   133
                y,*"warning:"*)         cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
yann@112
   134
                y,*"WARNING:"*)         cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
yann@47
   135
                *"error:"*)             cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
yann@919
   136
                *"make["*"]: *** ["*)   cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
yann@47
   137
                *)                      cur_L="${LEVEL}"; cur_l="${level}";;
yann@47
   138
              esac
yann@523
   139
              # There will always be a log file (stdout, fd #1), be it /dev/null
yann@523
   140
              printf "[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}"
yann@47
   141
              if [ ${cur_l} -le ${max_level} ]; then
yann@523
   142
                  # Only print to console (fd #6) if log level is high enough.
javier@2382
   143
                  printf "${CT_LOG_PROGRESS_BAR:+\r}[%-5s]%*s%s%s\n" "${cur_L}" "${indent}" " " "${line}" >&6
yann@82
   144
              fi
yann@82
   145
              if [ "${CT_LOG_PROGRESS_BAR}" = "y" ]; then
yann@523
   146
                  printf "\r[%02d:%02d] %s " $((SECONDS/60)) $((SECONDS%60)) "${_prog_bar[$((_prog_bar_cpt/10))]}" >&6
yann@523
   147
                  _prog_bar_cpt=$(((_prog_bar_cpt+1)%40))
yann@1
   148
              fi
yann@1
   149
          done
yann@1
   150
        )
yann@1
   151
yann@1
   152
    return 0
yann@1
   153
}
yann@1
   154
yann@535
   155
# Execute an action, and log its messages
yann@2340
   156
# It is possible to even log local variable assignments (a-la: var=val ./cmd opts)
yann@2340
   157
# Usage: CT_DoExecLog <level> [VAR=val...] <command> [parameters...]
yann@535
   158
CT_DoExecLog() {
yann@535
   159
    local level="$1"
yann@535
   160
    shift
yann@2340
   161
    (
yann@2340
   162
    for i in "$@"; do
yann@2340
   163
        tmp_log+="'${i}' "
yann@2340
   164
    done
yann@2340
   165
    while true; do
yann@2340
   166
        case "${1}" in
yann@2340
   167
            *=*)    eval export "'${1}'"; shift;;
yann@2340
   168
            *)      break;;
yann@2340
   169
        esac
yann@2340
   170
    done
yann@2340
   171
    CT_DoLog DEBUG "==> Executing: ${tmp_log}"
yann@668
   172
    "${@}" 2>&1 |CT_DoLog "${level}"
yann@2340
   173
    )
yann@2340
   174
    # Catch failure of the sub-shell
yann@2340
   175
    [ $? -eq 0 ]
yann@535
   176
}
yann@535
   177
yann@96
   178
# Tail message to be logged whatever happens
yann@96
   179
# Usage: CT_DoEnd <level>
yann@96
   180
CT_DoEnd()
yann@96
   181
{
yann@145
   182
    local level="$1"
yann@523
   183
    CT_STOP_DATE=$(CT_DoDate +%s%N)
yann@523
   184
    CT_STOP_DATE_HUMAN=$(CT_DoDate +%Y%m%d.%H%M%S)
yann@599
   185
    if [ "${level}" != "ERROR" ]; then
yann@582
   186
        CT_DoLog "${level:-INFO}" "Build completed at ${CT_STOP_DATE_HUMAN}"
yann@582
   187
    fi
yann@96
   188
    elapsed=$((CT_STOP_DATE-CT_STAR_DATE))
yann@96
   189
    elapsed_min=$((elapsed/(60*1000*1000*1000)))
yann@523
   190
    elapsed_sec=$(printf "%02d" $(((elapsed%(60*1000*1000*1000))/(1000*1000*1000))))
yann@523
   191
    elapsed_csec=$(printf "%02d" $(((elapsed%(1000*1000*1000))/(10*1000*1000))))
yann@145
   192
    CT_DoLog ${level:-INFO} "(elapsed: ${elapsed_min}:${elapsed_sec}.${elapsed_csec})"
yann@96
   193
}
yann@96
   194
yann@2051
   195
# Remove entries referring to . and other relative paths
js@2044
   196
# Usage: CT_SanitizePath
js@2044
   197
CT_SanitizePath() {
js@2044
   198
    local new
yann@2051
   199
    local p
js@2044
   200
    local IFS=:
js@2044
   201
    for p in $PATH; do
yann@2051
   202
        # Only accept absolute paths;
yann@2051
   203
        # Note: as a special case the empty string in PATH is equivalent to .
yann@2051
   204
        if [ -n "${p}" -a -z "${p%%/*}" ]; then
js@2044
   205
            new="${new}${new:+:}${p}"
js@2044
   206
        fi
js@2044
   207
    done
js@2044
   208
    PATH="${new}"
js@2044
   209
}
js@2044
   210
yann@2280
   211
# Sanitise the directory name contained in the variable passed as argument:
yann@2280
   212
# - remove duplicate /
yann@2280
   213
# Usage: CT_SanitiseVarDir CT_PREFIX_DIR
yann@2280
   214
CT_SanitiseVarDir() {
yann@2280
   215
    local var
yann@2280
   216
    local old_dir
yann@2280
   217
    local new_dir
yann@2280
   218
yann@2280
   219
    for var in "$@"; do
yann@2280
   220
        eval "old_dir=\"\${${var}}\""
yann@2280
   221
        new_dir="$( printf "${old_dir}"     \
yann@2280
   222
                    |sed -r -e 's:/+:/:g;'  \
yann@2280
   223
                  )"
yann@2280
   224
        eval "${var}=\"${new_dir}\""
yann@2280
   225
        CT_DoLog DEBUG "Sanitised '${var}': '${old_dir}' -> '${new_dir}'"
yann@2280
   226
    done
yann@2280
   227
}
yann@2280
   228
yann@96
   229
# Abort the execution with an error message
yann@1
   230
# Usage: CT_Abort <message>
yann@1
   231
CT_Abort() {
yann@128
   232
    CT_DoLog ERROR "$1"
yann@1
   233
    exit 1
yann@1
   234
}
yann@1
   235
yann@1
   236
# Test a condition, and print a message if satisfied
yann@1
   237
# Usage: CT_Test <message> <tests>
yann@1
   238
CT_Test() {
yann@1
   239
    local ret
yann@1
   240
    local m="$1"
yann@1
   241
    shift
yann@1909
   242
    CT_DoLog DEBUG "Testing '! ( $* )'"
yann@1
   243
    test "$@" && CT_DoLog WARN "$m"
yann@1
   244
    return 0
yann@1
   245
}
yann@1
   246
yann@1
   247
# Test a condition, and abort with an error message if satisfied
yann@1
   248
# Usage: CT_TestAndAbort <message> <tests>
yann@1
   249
CT_TestAndAbort() {
yann@1
   250
    local m="$1"
yann@1
   251
    shift
yann@1909
   252
    CT_DoLog DEBUG "Testing '! ( $* )'"
yann@1
   253
    test "$@" && CT_Abort "$m"
yann@1
   254
    return 0
yann@1
   255
}
yann@1
   256
yann@1
   257
# Test a condition, and abort with an error message if not satisfied
yann@1
   258
# Usage: CT_TestAndAbort <message> <tests>
yann@1
   259
CT_TestOrAbort() {
yann@1
   260
    local m="$1"
yann@1
   261
    shift
yann@1909
   262
    CT_DoLog DEBUG "Testing '$*'"
yann@1
   263
    test "$@" || CT_Abort "$m"
yann@1
   264
    return 0
yann@1
   265
}
yann@1
   266
yann@1
   267
# Test the presence of a tool, or abort if not found
yann@1
   268
# Usage: CT_HasOrAbort <tool>
yann@1
   269
CT_HasOrAbort() {
yann@773
   270
    CT_TestAndAbort "'${1}' not found and needed for successful toolchain build." -z "$(CT_Which "${1}")"
yann@1
   271
    return 0
yann@1
   272
}
yann@1
   273
yann@210
   274
# Search a program: wrap "which" for those system where
yann@1226
   275
# "which" verbosely says there is no match (Mandriva is
yann@1226
   276
# such a sucker...)
yann@210
   277
# Usage: CT_Which <filename>
yann@210
   278
CT_Which() {
yann@210
   279
  which "$1" 2>/dev/null || true
yann@210
   280
}
yann@210
   281
yann@1
   282
# Get current date with nanosecond precision
yann@1
   283
# On those system not supporting nanosecond precision, faked with rounding down
yann@1
   284
# to the highest entire second
yann@1
   285
# Usage: CT_DoDate <fmt>
yann@1
   286
CT_DoDate() {
yann@2383
   287
    date "$1" |sed -r -e 's/%?N$/000000000/;'
yann@1
   288
}
yann@1
   289
yann@1
   290
CT_STEP_COUNT=1
yann@2807
   291
CT_STEP_MESSAGE[${CT_STEP_COUNT}]="(top-level)"
yann@1
   292
# Memorise a step being done so that any error is caught
yann@1
   293
# Usage: CT_DoStep <loglevel> <message>
yann@1
   294
CT_DoStep() {
yann@523
   295
    local start=$(CT_DoDate +%s%N)
yann@1
   296
    CT_DoLog "$1" "================================================================="
yann@1
   297
    CT_DoLog "$1" "$2"
yann@1
   298
    CT_STEP_COUNT=$((CT_STEP_COUNT+1))
yann@1
   299
    CT_STEP_LEVEL[${CT_STEP_COUNT}]="$1"; shift
yann@1
   300
    CT_STEP_START[${CT_STEP_COUNT}]="${start}"
yann@1
   301
    CT_STEP_MESSAGE[${CT_STEP_COUNT}]="$1"
yann@1
   302
    return 0
yann@1
   303
}
yann@1
   304
yann@1
   305
# End the step just being done
yann@1
   306
# Usage: CT_EndStep
yann@1
   307
CT_EndStep() {
yann@523
   308
    local stop=$(CT_DoDate +%s%N)
yann@523
   309
    local duration=$(printf "%032d" $((stop-${CT_STEP_START[${CT_STEP_COUNT}]})) |sed -r -e 's/([[:digit:]]{2})[[:digit:]]{7}$/\.\1/; s/^0+//; s/^\./0\./;')
yann@582
   310
    local elapsed=$(printf "%02d:%02d" $((SECONDS/60)) $((SECONDS%60)))
yann@1
   311
    local level="${CT_STEP_LEVEL[${CT_STEP_COUNT}]}"
yann@1
   312
    local message="${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}"
yann@1
   313
    CT_STEP_COUNT=$((CT_STEP_COUNT-1))
yann@582
   314
    CT_DoLog "${level}" "${message}: done in ${duration}s (at ${elapsed})"
yann@1
   315
    return 0
yann@1
   316
}
yann@1
   317
yann@1
   318
# Pushes into a directory, and pops back
yann@1
   319
CT_Pushd() {
yann@1
   320
    pushd "$1" >/dev/null 2>&1
yann@1
   321
}
yann@1
   322
CT_Popd() {
yann@1
   323
    popd >/dev/null 2>&1
yann@1
   324
}
yann@1
   325
yann@2898
   326
# Create a dir and cd or pushd into it
yann@2898
   327
# Usage: CT_mkdir_cd <dir/to/create>
yann@2898
   328
#        CT_mkdir_pushd <dir/to/create>
yann@2898
   329
CT_mkdir_cd() {
yann@2898
   330
    local dir="${1}"
yann@2898
   331
yann@2898
   332
    mkdir -p "${dir}"
yann@2898
   333
    cd "${dir}"
yann@2898
   334
}
yann@2898
   335
CT_mkdir_pushd() {
yann@2898
   336
    local dir="${1}"
yann@2898
   337
yann@2898
   338
    mkdir -p "${dir}"
yann@2898
   339
    CT_Pushd "${dir}"
yann@2898
   340
}
yann@2898
   341
yann@1
   342
# Creates a temporary directory
yann@1
   343
# $1: variable to assign to
yann@1
   344
# Usage: CT_MktempDir foo
yann@1
   345
CT_MktempDir() {
yann@1
   346
    # Some mktemp do not allow more than 6 Xs
yann@1113
   347
    eval "$1"=$(mktemp -q -d "${CT_BUILD_DIR}/tmp.XXXXXX")
yann@1
   348
    CT_TestOrAbort "Could not make temporary directory" -n "${!1}" -a -d "${!1}"
yann@787
   349
    CT_DoLog DEBUG "Made temporary directory '${!1}'"
yann@787
   350
    return 0
yann@1
   351
}
yann@1
   352
yann@1148
   353
# Removes one or more directories, even if it is read-only, or its parent is
yann@1138
   354
# Usage: CT_DoForceRmdir dir [...]
yann@1138
   355
CT_DoForceRmdir() {
yann@1148
   356
    local dir
yann@1148
   357
    local mode
yann@1148
   358
    for dir in "${@}"; do
yann@1148
   359
        [ -d "${dir}" ] || continue
titus@1956
   360
        case "$CT_SYS_OS" in
yann@2029
   361
            Linux|CYGWIN*)
titus@1956
   362
                mode="$(stat -c '%a' "$(dirname "${dir}")")"
titus@1956
   363
                ;;
titus@1956
   364
            Darwin|*BSD)
titus@1956
   365
                mode="$(stat -f '%Lp' "$(dirname "${dir}")")"
titus@1956
   366
                ;;
titus@1956
   367
            *)
titus@1956
   368
                CT_Abort "Unhandled host OS $CT_SYS_OS"
titus@1956
   369
                ;;
titus@1956
   370
        esac
yann@1185
   371
        CT_DoExecLog ALL chmod u+w "$(dirname "${dir}")"
yann@1185
   372
        CT_DoExecLog ALL chmod -R u+w "${dir}"
yann@1148
   373
        CT_DoExecLog ALL rm -rf "${dir}"
yann@1185
   374
        CT_DoExecLog ALL chmod ${mode} "$(dirname "${dir}")"
yann@1148
   375
    done
yann@1138
   376
}
yann@1138
   377
yann@1
   378
# Echoes the specified string on stdout until the pipe breaks.
yann@1
   379
# Doesn't fail
yann@1
   380
# $1: string to echo
yann@1
   381
# Usage: CT_DoYes "" |make oldconfig
yann@1
   382
CT_DoYes() {
yann@1
   383
    yes "$1" || true
yann@1
   384
}
yann@63
   385
yann@1391
   386
# Add the specified directory to LD_LIBRARY_PATH, and export it
yann@1391
   387
# If the specified patch is already present, just export
yann@1391
   388
# $1: path to add
yann@1391
   389
# $2: add as 'first' or 'last' path, 'first' is assumed if $2 is empty
yann@1391
   390
# Usage CT_SetLibPath /some/where/lib [first|last]
yann@1391
   391
CT_SetLibPath() {
yann@1391
   392
    local path="$1"
yann@1391
   393
    local pos="$2"
yann@1391
   394
yann@1391
   395
    case ":${LD_LIBRARY_PATH}:" in
yann@1391
   396
        *:"${path}":*)  ;;
yann@1391
   397
        *)  case "${pos}" in
yann@1391
   398
                last)
yann@1391
   399
                    CT_DoLog DEBUG "Adding '${path}' at end of LD_LIBRARY_PATH"
yann@1391
   400
                    LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${path}"
yann@1391
   401
                    ;;
yann@1391
   402
                first|"")
yann@1391
   403
                    CT_DoLog DEBUG "Adding '${path}' at start of LD_LIBRARY_PATH"
yann@1391
   404
                    LD_LIBRARY_PATH="${path}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
yann@1391
   405
                    ;;
yann@1391
   406
                *)
yann@1391
   407
                    CT_Abort "Incorrect position '${pos}' to add '${path}' to LD_LIBRARY_PATH"
yann@1391
   408
                    ;;
yann@1391
   409
            esac
yann@1391
   410
            ;;
yann@1391
   411
    esac
yann@1391
   412
    CT_DoLog DEBUG "==> LD_LIBRARY_PATH='${LD_LIBRARY_PATH}'"
yann@1391
   413
    export LD_LIBRARY_PATH
yann@1391
   414
}
yann@1391
   415
yann@2608
   416
# Build up the list of allowed tarball extensions
yann@2608
   417
# Add them in the prefered order; most preferred comes first
yann@2608
   418
CT_DoListTarballExt() {
yann@2840
   419
    if [ "${CT_CONFIGURE_has_xz}" = "y" ]; then
yann@2609
   420
        printf ".tar.xz\n"
yann@2609
   421
    fi
yann@2646
   422
    if [    "${CT_CONFIGURE_has_lzma}" = "y"    \
yann@2840
   423
         -o "${CT_CONFIGURE_has_xz}" = "y" ]; then
yann@2645
   424
        printf ".tar.lzma\n"
yann@2645
   425
    fi
yann@2608
   426
    printf ".tar.bz2\n"
yann@2608
   427
    printf ".tar.gz\n.tgz\n"
yann@2608
   428
    printf ".tar\n"
yann@2608
   429
}
yann@2608
   430
yann@85
   431
# Get the file name extension of a component
yann@719
   432
# Usage: CT_GetFileExtension <component_name-component_version> [extension]
yann@1690
   433
# If found, echoes the extension to stdout, and return 0
yann@1690
   434
# If not found, echoes nothing on stdout, and return !0.
yann@85
   435
CT_GetFileExtension() {
yann@85
   436
    local ext
yann@85
   437
    local file="$1"
yann@719
   438
    shift
yann@719
   439
    local first_ext="$1"
yann@85
   440
yann@160
   441
    # we need to also check for an empty extension for those very
yann@160
   442
    # peculiar components that don't have one (such as sstrip from
yann@160
   443
    # buildroot).
yann@2608
   444
    for ext in ${first_ext} $(CT_DoListTarballExt) /.git ''; do
yann@1763
   445
        if [ -e "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
yann@85
   446
            echo "${ext}"
yann@1690
   447
            exit 0
yann@85
   448
        fi
yann@85
   449
    done
yann@85
   450
yann@1690
   451
    exit 1
yann@85
   452
}
yann@85
   453
yann@2204
   454
# Try to retrieve the specified URL (HTTP or FTP)
yann@2204
   455
# Usage: CT_DoGetFile <URL>
yann@2204
   456
# This functions always returns true (0), as it can be legitimate not
yann@2204
   457
# to find the requested URL (think about snapshots, different layouts
yann@2204
   458
# for different gcc versions, etc...).
yann@2204
   459
CT_DoGetFile() {
yann@2501
   460
    local url="${1}"
yann@2501
   461
    local dest="${CT_TARBALLS_DIR}/${url##*/}"
yann@2205
   462
    local tmp="${dest}.tmp-dl"
yann@2204
   463
yann@2205
   464
    # Remove potential left-over from a previous run
yann@2205
   465
    rm -f "${tmp}"
yann@2205
   466
yann@2204
   467
    # We also retry a few times, in case there is a transient error (eg. behind
yann@2204
   468
    # a dynamic IP that changes during the transfer...)
yann@2204
   469
    # With automated download as we are doing, it can be very dangerous to
yann@2204
   470
    # continue the downloads. It's far better to simply overwrite the
yann@2204
   471
    # destination file.
yann@492
   472
    # Some company networks have firewalls to connect to the internet, but it's
yann@2660
   473
    # not easy to detect them, so force a global ${CT_CONNECT_TIMEOUT}-second
yann@2660
   474
    # timeout.
yann@2204
   475
    # For curl, no good progress indicator is available. So, be silent.
yann@2763
   476
    if CT_DoExecLog ALL wget --passive-ftp --tries=3 -nc    \
yann@2763
   477
                             --progress=dot:binary          \
yann@2763
   478
                             -T ${CT_CONNECT_TIMEOUT}       \
yann@2763
   479
                             -O "${tmp}"                    \
yann@2661
   480
                             "${url}"
yann@2661
   481
    then
yann@2661
   482
        # Success, we got it, good!
yann@2205
   483
        mv "${tmp}" "${dest}"
yann@2205
   484
    else
yann@2205
   485
        # Woops...
yann@2205
   486
        rm -f "${tmp}"
yann@2205
   487
    fi
yann@63
   488
}
yann@63
   489
yann@1113
   490
# This function tries to retrieve a tarball form a local directory
yann@1113
   491
# Usage: CT_GetLocal <basename> [.extension]
yann@1113
   492
CT_GetLocal() {
yann@1113
   493
    local basename="$1"
yann@1113
   494
    local first_ext="$2"
yann@1113
   495
    local ext
yann@1113
   496
yann@1113
   497
    # Do we already have it in *our* tarballs dir?
yann@1690
   498
    if ext="$( CT_GetFileExtension "${basename}" ${first_ext} )"; then
yann@1113
   499
        CT_DoLog DEBUG "Already have '${basename}'"
yann@1113
   500
        return 0
yann@1113
   501
    fi
yann@1113
   502
yann@1113
   503
    if [ -n "${CT_LOCAL_TARBALLS_DIR}" ]; then
yann@1113
   504
        CT_DoLog DEBUG "Trying to retrieve an already downloaded copy of '${basename}'"
yann@1113
   505
        # We'd rather have a bzip2'ed tarball, then gzipped tarball, plain tarball,
yann@1113
   506
        # or, as a failover, a file without extension.
yann@2608
   507
        for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
yann@1113
   508
            CT_DoLog DEBUG "Trying '${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}'"
yann@1113
   509
            if [ -r "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" -a \
yann@1113
   510
                 "${CT_FORCE_DOWNLOAD}" != "y" ]; then
yann@1113
   511
                CT_DoLog DEBUG "Got '${basename}' from local storage"
yann@1113
   512
                CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}${ext}" "${CT_TARBALLS_DIR}/${basename}${ext}"
yann@1113
   513
                return 0
yann@1113
   514
            fi
yann@1113
   515
        done
yann@1113
   516
    fi
yann@1113
   517
    return 1
yann@1113
   518
}
yann@1113
   519
yann@1113
   520
# This function saves the specified to local storage if possible,
yann@1113
   521
# and if so, symlinks it for later usage
yann@1113
   522
# Usage: CT_SaveLocal </full/path/file.name>
yann@1113
   523
CT_SaveLocal() {
yann@1113
   524
    local file="$1"
yann@1113
   525
    local basename="${file##*/}"
yann@1113
   526
yann@1113
   527
    if [ "${CT_SAVE_TARBALLS}" = "y" ]; then
yann@1134
   528
        CT_DoLog EXTRA "Saving '${basename}' to local storage"
yann@1113
   529
        # The file may already exist if downloads are forced: remove it first
yann@1113
   530
        CT_DoExecLog ALL rm -f "${CT_LOCAL_TARBALLS_DIR}/${basename}"
yann@1113
   531
        CT_DoExecLog ALL mv -f "${file}" "${CT_LOCAL_TARBALLS_DIR}"
yann@1113
   532
        CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}" "${file}"
yann@1113
   533
    fi
yann@1113
   534
}
yann@1113
   535
yann@63
   536
# Download the file from one of the URLs passed as argument
yann@1113
   537
# Usage: CT_GetFile <basename> [.extension] <url> [url ...]
yann@63
   538
CT_GetFile() {
yann@63
   539
    local ext
yann@2594
   540
    local -a URLS
yann@2594
   541
    local url
yann@63
   542
    local file="$1"
yann@1113
   543
    local first_ext
yann@63
   544
    shift
yann@712
   545
    # If next argument starts with a dot, then this is not an URL,
yann@712
   546
    # and we can consider that it is a preferred extension.
yann@242
   547
    case "$1" in
yann@712
   548
        .*) first_ext="$1"
yann@242
   549
            shift
yann@242
   550
            ;;
yann@242
   551
    esac
yann@63
   552
yann@1113
   553
    # Does it exist localy?
yann@2599
   554
    if CT_GetLocal "${file}" ${first_ext}; then
yann@2599
   555
        return 0
yann@2599
   556
    fi
yann@1113
   557
    # No, it does not...
yann@63
   558
yann@754
   559
    # Try to retrieve the file
yann@788
   560
    CT_DoLog EXTRA "Retrieving '${file}'"
yann@754
   561
yann@1022
   562
    # Add URLs on the LAN mirror
yann@1022
   563
    if [ "${CT_USE_MIRROR}" = "y" ]; then
yann@1294
   564
        CT_TestOrAbort "Please set the mirror base URL" -n "${CT_MIRROR_BASE_URL}"
yann@2594
   565
        URLS+=( "${CT_MIRROR_BASE_URL}/${file%-*}" )
yann@2594
   566
        URLS+=( "${CT_MIRROR_BASE_URL}" )
yann@2593
   567
    fi
yann@695
   568
yann@2595
   569
    if [ "${CT_FORBID_DOWNLOAD}" != "y" ]; then
yann@2595
   570
        URLS+=( "${@}" )
yann@2595
   571
    fi
yann@1022
   572
yann@1022
   573
    # Scan all URLs in turn, and try to grab a tarball from there
yann@1763
   574
    # Do *not* try git trees (ext=/.git), this is handled in a specific
yann@1763
   575
    # wrapper, below
yann@2608
   576
    for ext in ${first_ext} $(CT_DoListTarballExt) ''; do
yann@102
   577
        # Try all urls in turn
yann@2594
   578
        for url in "${URLS[@]}"; do
yann@2589
   579
            [ -n "${url}" ] || continue
yann@523
   580
            CT_DoLog DEBUG "Trying '${url}/${file}${ext}'"
yann@265
   581
            CT_DoGetFile "${url}/${file}${ext}"
yann@2492
   582
            if [ -f "${CT_TARBALLS_DIR}/${file}${ext}" ]; then
yann@799
   583
                CT_DoLog DEBUG "Got '${file}' from the Internet"
yann@1113
   584
                CT_SaveLocal "${CT_TARBALLS_DIR}/${file}${ext}"
yann@265
   585
                return 0
yann@265
   586
            fi
yann@102
   587
        done
yann@102
   588
    done
yann@63
   589
yann@2599
   590
    # Just return error, someone may want to catch and handle the error
yann@2492
   591
    # (eg. glibc/eglibc add-ons can be missing).
yann@2492
   592
    return 1
yann@63
   593
}
yann@63
   594
yann@1113
   595
# Checkout from CVS, and build the associated tarball
yann@1113
   596
# The tarball will be called ${basename}.tar.bz2
yann@1113
   597
# Prerequisite: either the server does not require password,
yann@1113
   598
# or the user must already be logged in.
yann@1113
   599
# 'tag' is the tag to retrieve. Must be specified, but can be empty.
yann@1113
   600
# If dirname is specified, then module will be renamed to dirname
yann@1113
   601
# prior to building the tarball.
yann@1592
   602
# Usage: CT_GetCVS <basename> <url> <module> <tag> [dirname[=subdir]]
yann@1592
   603
# Note: if '=subdir' is given, then it is used instead of 'module'.
yann@1113
   604
CT_GetCVS() {
yann@1113
   605
    local basename="$1"
yann@1113
   606
    local uri="$2"
yann@1113
   607
    local module="$3"
yann@1113
   608
    local tag="${4:+-r ${4}}"
yann@1113
   609
    local dirname="$5"
yann@1113
   610
    local tmp_dir
yann@1113
   611
yann@2592
   612
    # First try locally, then the mirror
yann@2592
   613
    if CT_GetFile "${basename}"; then
yann@2592
   614
        # Got it! Return early! :-)
yann@2592
   615
        return 0
yann@2592
   616
    fi
yann@1113
   617
yann@2595
   618
    if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
yann@2595
   619
        CT_DoLog WARN "Downloads forbidden, not trying cvs retrieval"
yann@2595
   620
        return 1
yann@2595
   621
    fi
yann@2595
   622
yann@1113
   623
    CT_MktempDir tmp_dir
yann@1113
   624
    CT_Pushd "${tmp_dir}"
yann@1113
   625
yann@1113
   626
    CT_DoExecLog ALL cvs -z 9 -d "${uri}" co -P ${tag} "${module}"
yann@1592
   627
    if [ -n "${dirname}" ]; then
yann@1592
   628
        case "${dirname}" in
yann@1592
   629
            *=*)
yann@1593
   630
                CT_DoExecLog DEBUG mv "${dirname#*=}" "${dirname%%=*}"
yann@1593
   631
                CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname%%=*}"
yann@1592
   632
                ;;
yann@1592
   633
            *)
yann@1592
   634
                CT_DoExecLog ALL mv "${module}" "${dirname}"
yann@1592
   635
                CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${dirname:-${module}}"
yann@1592
   636
                ;;
yann@1592
   637
        esac
yann@1592
   638
    fi
yann@1113
   639
    CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
yann@1113
   640
yann@1113
   641
    CT_Popd
yann@1113
   642
    CT_DoExecLog ALL rm -rf "${tmp_dir}"
yann@1113
   643
}
yann@1113
   644
yann@1244
   645
# Check out from SVN, and build the associated tarball
yann@1244
   646
# The tarball will be called ${basename}.tar.bz2
yann@1244
   647
# Prerequisite: either the server does not require password,
yann@1244
   648
# or the user must already be logged in.
yann@1244
   649
# 'rev' is the revision to retrieve
yann@1244
   650
# Usage: CT_GetSVN <basename> <url> [rev]
yann@1244
   651
CT_GetSVN() {
yann@1244
   652
    local basename="$1"
yann@1244
   653
    local uri="$2"
yann@1244
   654
    local rev="$3"
yann@1244
   655
yann@2590
   656
    # First try locally, then the mirror
yann@2590
   657
    if CT_GetFile "${basename}"; then
yann@2590
   658
        # Got it! Return early! :-)
yann@2590
   659
        return 0
yann@2590
   660
    fi
yann@1244
   661
yann@2595
   662
    if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
yann@2595
   663
        CT_DoLog WARN "Downloads forbidden, not trying svn retrieval"
yann@2595
   664
        return 1
yann@2595
   665
    fi
yann@2595
   666
yann@1244
   667
    CT_MktempDir tmp_dir
yann@1244
   668
    CT_Pushd "${tmp_dir}"
yann@1244
   669
yann@2494
   670
    if ! CT_DoExecLog ALL svn export ${rev:+-r ${rev}} "${uri}" "${basename}"; then
yann@2494
   671
        CT_DoLog WARN "Could not retrieve '${basename}'"
yann@2494
   672
        return 1
yann@2494
   673
    fi
yann@1244
   674
    CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${basename}"
yann@1244
   675
    CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"
yann@1244
   676
yann@1244
   677
    CT_Popd
yann@1244
   678
    CT_DoExecLog ALL rm -rf "${tmp_dir}"
yann@1244
   679
}
yann@1244
   680
yann@1763
   681
# Clone a git tree
yann@1763
   682
# Tries the given URLs in turn until one can get cloned. No tarball will be created.
yann@1763
   683
# Prerequisites: either the server does not require password,
yann@1763
   684
# or the user has already taken any action to authenticate to the server.
yann@1763
   685
# The cloned tree will *not* be stored in the local tarballs dir!
yann@1763
   686
# Usage: CT_GetGit <basename> <url [url ...]>
yann@1763
   687
CT_GetGit() {
yann@1763
   688
    local basename="$1"; shift
yann@1763
   689
    local url
yann@1763
   690
    local cloned=0
yann@1763
   691
yann@2595
   692
    if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then
yann@2595
   693
        CT_DoLog WARN "Downloads forbidden, not trying git retrieval"
yann@2595
   694
        return 1
yann@2595
   695
    fi
yann@2595
   696
yann@1763
   697
    # Do we have it in our tarballs dir?
yann@1763
   698
    if [ -d "${CT_TARBALLS_DIR}/${basename}/.git" ]; then
yann@1763
   699
        CT_DoLog EXTRA "Updating git tree '${basename}'"
yann@1763
   700
        CT_Pushd "${CT_TARBALLS_DIR}/${basename}"
yann@1763
   701
        CT_DoExecLog ALL git pull
yann@1763
   702
        CT_Popd
yann@1763
   703
    else
yann@1763
   704
        CT_DoLog EXTRA "Retrieving git tree '${basename}'"
yann@1763
   705
        for url in "${@}"; do
yann@1763
   706
            CT_DoLog ALL "Trying to clone from '${url}'"
yann@1763
   707
            CT_DoForceRmdir "${CT_TARBALLS_DIR}/${basename}"
yann@1763
   708
            if git clone "${url}" "${CT_TARBALLS_DIR}/${basename}" 2>&1 |CT_DoLog ALL; then
yann@1763
   709
                cloned=1
yann@1763
   710
                break
yann@1763
   711
            fi
yann@1763
   712
        done
yann@1763
   713
        CT_TestOrAbort "Could not clone '${basename}'" ${cloned} -ne 0
yann@1763
   714
    fi
yann@1763
   715
}
yann@1763
   716
yann@1126
   717
# Extract a tarball
yann@63
   718
# Some tarballs need to be extracted in specific places. Eg.: glibc addons
yann@63
   719
# must be extracted in the glibc directory; uCLibc locales must be extracted
yann@1123
   720
# in the extra/locale sub-directory of uClibc. This is taken into account
yann@1123
   721
# by the caller, that did a 'cd' into the correct path before calling us
yann@1123
   722
# and sets nochdir to 'nochdir'.
yann@1763
   723
# Note also that this function handles the git trees!
yann@1763
   724
# Usage: CT_Extract <basename> [nochdir] [options]
yann@1763
   725
# where 'options' are dependent on the source (eg. git branch/tag...)
yann@1126
   726
CT_Extract() {
yann@1761
   727
    local nochdir="$1"
yann@1761
   728
    local basename
yann@1690
   729
    local ext
yann@2646
   730
    local lzma_prog
yann@2605
   731
    local -a tar_opts
yann@1690
   732
yann@1761
   733
    if [ "${nochdir}" = "nochdir" ]; then
yann@1761
   734
        shift
yann@1761
   735
        nochdir="$(pwd)"
yann@1761
   736
    else
yann@1761
   737
        nochdir="${CT_SRC_DIR}"
yann@1761
   738
    fi
yann@1761
   739
yann@1761
   740
    basename="$1"
yann@1761
   741
    shift
yann@1761
   742
yann@1690
   743
    if ! ext="$(CT_GetFileExtension "${basename}")"; then
yann@2493
   744
        CT_DoLog WARN "'${basename}' not found in '${CT_TARBALLS_DIR}'"
yann@2493
   745
        return 1
yann@1690
   746
    fi
yann@1126
   747
    local full_file="${CT_TARBALLS_DIR}/${basename}${ext}"
yann@1126
   748
yann@1718
   749
    # Check if already extracted
yann@1718
   750
    if [ -e "${CT_SRC_DIR}/.${basename}.extracted" ]; then
yann@1718
   751
        CT_DoLog DEBUG "Already extracted '${basename}'"
yann@1718
   752
        return 0
yann@1718
   753
    fi
yann@1718
   754
yann@1691
   755
    # Check if previously partially extracted
yann@1691
   756
    if [ -e "${CT_SRC_DIR}/.${basename}.extracting" ]; then
yann@1691
   757
        CT_DoLog ERROR "The '${basename}' sources were partially extracted."
yann@1691
   758
        CT_DoLog ERROR "Please remove first:"
yann@1691
   759
        CT_DoLog ERROR " - the source dir for '${basename}', in '${CT_SRC_DIR}'"
yann@1691
   760
        CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${basename}.extracting'"
yann@1691
   761
        CT_Abort "I'll stop now to avoid any carnage..."
yann@1691
   762
    fi
yann@1691
   763
    CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracting"
yann@1691
   764
yann@1761
   765
    CT_Pushd "${nochdir}"
yann@63
   766
yann@1126
   767
    CT_DoLog EXTRA "Extracting '${basename}'"
benoit@2574
   768
    CT_DoExecLog FILE mkdir -p "${basename}"
yann@2605
   769
    tar_opts=( "--strip-components=1" )
yann@2605
   770
    tar_opts+=( "-C" "${basename}" )
yann@2605
   771
    tar_opts+=( "-xv" )
yann@2646
   772
yann@2646
   773
    # One note here:
yann@2646
   774
    # - lzma can be handled either with 'xz' or 'lzma'
yann@2646
   775
    # - we get lzma tarball only if either or both are available
yann@2646
   776
    # - so, if we get an lzma tarball, and either 'xz' or 'lzma' is
yann@2646
   777
    #   missing, we can assume the other is available
yann@2646
   778
    if [ "${CT_CONFIGURE_has_lzma}" = "y" ]; then
titus@2785
   779
        lzma_prog="lzma -fdc"
yann@2646
   780
    else
titus@2785
   781
        lzma_prog="xz -fdc"
yann@2646
   782
    fi
yann@63
   783
    case "${ext}" in
titus@2785
   784
        .tar.xz)      xz -fdc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
titus@2785
   785
        .tar.lzma)    ${lzma_prog} "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
titus@2785
   786
        .tar.bz2)     bzip2 -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
titus@2785
   787
        .tar.gz|.tgz) gzip -dc "${full_file}" | CT_DoExecLog FILE tar "${tar_opts[@]}" -f -;;
yann@2608
   788
        .tar)         CT_DoExecLog FILE tar "${tar_opts[@]}" -f "${full_file}";;
yann@1763
   789
        /.git)        CT_ExtractGit "${basename}" "${@}";;
yann@2493
   790
        *)            CT_DoLog WARN "Don't know how to handle '${basename}${ext}': unknown extension"
yann@2493
   791
                      return 1
yann@2493
   792
                      ;;
yann@63
   793
    esac
yann@63
   794
yann@1763
   795
    # Don't mark as being extracted for git
yann@1763
   796
    case "${ext}" in
yann@1763
   797
        /.git)  ;;
yann@1763
   798
        *)      CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${basename}.extracted";;
yann@1763
   799
    esac
yann@1691
   800
    CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${basename}.extracting"
yann@1126
   801
yann@1761
   802
    CT_Popd
yann@1126
   803
}
yann@1126
   804
esben@2721
   805
# Create a working git clone of a local git repository
yann@1763
   806
# Usage: CT_ExtractGit <basename> [ref]
yann@1763
   807
# where 'ref' is the reference to use:
yann@1763
   808
#   the full name of a branch, like "remotes/origin/branch_name"
yann@1763
   809
#   a date as understandable by git, like "YYYY-MM-DD[ hh[:mm[:ss]]]"
yann@1763
   810
#   a tag name
esben@2721
   811
# If 'ref' is not given, the current repository HEAD will be used
yann@1763
   812
CT_ExtractGit() {
yann@1763
   813
    local basename="${1}"
yann@1763
   814
    local ref="${2}"
esben@2721
   815
    local repo
yann@1763
   816
    local ref_type
yann@1763
   817
yann@1763
   818
    # pushd now to be able to get git revlist in case ref is a date
esben@2721
   819
    repo="${CT_TARBALLS_DIR}/${basename}"
esben@2721
   820
    CT_Pushd "${repo}"
yann@1763
   821
yann@1763
   822
    # What kind of reference is ${ref} ?
yann@1763
   823
    if [ -z "${ref}" ]; then
esben@2721
   824
        ref_type=head
esben@2721
   825
        ref=$(git rev-list -n1 HEAD)
yann@1763
   826
    elif git tag |grep -E "^${ref}$" >/dev/null 2>&1; then
yann@1763
   827
        ref_type=tag
yann@1763
   828
    elif git branch -a --no-color |grep -E "^. ${ref}$" >/dev/null 2>&1; then
yann@1763
   829
        ref_type=branch
yann@1763
   830
    elif date -d "${ref}" >/dev/null 2>&1; then
yann@1763
   831
        ref_type=date
yann@1763
   832
        ref=$(git rev-list -n1 --before="${ref}")
yann@1763
   833
    else
yann@1763
   834
        CT_Abort "Reference '${ref}' is an incorrect git reference: neither tag, branch nor date"
yann@1763
   835
    fi
yann@1763
   836
esben@2721
   837
    CT_Popd
yann@1763
   838
esben@2721
   839
    CT_DoExecLog FILE rmdir "${basename}"
yann@1763
   840
    case "${ref_type}" in
esben@2721
   841
        branch) CT_DoExecLog FILE git clone -b "${ref}" "${repo}" "${basename}" ;;
esben@2721
   842
        *)      CT_DoExecLog FILE git clone "${repo}" "${basename}"
esben@2721
   843
                CT_Pushd "${basename}"
esben@2721
   844
                CT_DoExecLog FILE git checkout "${ref}"
esben@2721
   845
                CT_Popd
esben@2721
   846
                ;;
yann@1763
   847
    esac
yann@1763
   848
}
yann@1763
   849
yann@1126
   850
# Patches the specified component
yann@1761
   851
# See CT_Extract, above, for explanations on 'nochdir'
yann@1901
   852
# Usage: CT_Patch [nochdir] <packagename> <packageversion>
yann@1901
   853
# If the package directory is *not* packagename-packageversion, then
yann@1901
   854
# the caller must cd into the proper directory first, and call us
yann@1901
   855
# with nochdir
yann@1126
   856
CT_Patch() {
yann@1761
   857
    local nochdir="$1"
yann@1901
   858
    local pkgname
yann@1901
   859
    local version
yann@1901
   860
    local pkgdir
yann@1761
   861
    local base_file
yann@1761
   862
    local ver_file
yann@1507
   863
    local d
yann@1507
   864
    local -a patch_dirs
yann@1507
   865
    local bundled_patch_dir
yann@1507
   866
    local local_patch_dir
yann@1126
   867
yann@1761
   868
    if [ "${nochdir}" = "nochdir" ]; then
yann@1761
   869
        shift
yann@1906
   870
        pkgname="$1"
yann@1906
   871
        version="$2"
yann@1906
   872
        pkgdir="${pkgname}-${version}"
yann@1761
   873
        nochdir="$(pwd)"
yann@1761
   874
    else
yann@1906
   875
        pkgname="$1"
yann@1906
   876
        version="$2"
yann@1906
   877
        pkgdir="${pkgname}-${version}"
yann@1901
   878
        nochdir="${CT_SRC_DIR}/${pkgdir}"
yann@1761
   879
    fi
yann@1761
   880
yann@1126
   881
    # Check if already patched
yann@1901
   882
    if [ -e "${CT_SRC_DIR}/.${pkgdir}.patched" ]; then
yann@1901
   883
        CT_DoLog DEBUG "Already patched '${pkgdir}'"
yann@1126
   884
        return 0
yann@63
   885
    fi
yann@63
   886
yann@1271
   887
    # Check if already partially patched
yann@1901
   888
    if [ -e "${CT_SRC_DIR}/.${pkgdir}.patching" ]; then
yann@1901
   889
        CT_DoLog ERROR "The '${pkgdir}' sources were partially patched."
yann@1271
   890
        CT_DoLog ERROR "Please remove first:"
yann@1901
   891
        CT_DoLog ERROR " - the source dir for '${pkgdir}', in '${CT_SRC_DIR}'"
yann@1901
   892
        CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.extracted'"
yann@1901
   893
        CT_DoLog ERROR " - the file '${CT_SRC_DIR}/.${pkgdir}.patching'"
yann@1271
   894
        CT_Abort "I'll stop now to avoid any carnage..."
yann@1271
   895
    fi
yann@1901
   896
    touch "${CT_SRC_DIR}/.${pkgdir}.patching"
yann@1271
   897
yann@1761
   898
    CT_Pushd "${nochdir}"
yann@1123
   899
yann@1901
   900
    CT_DoLog EXTRA "Patching '${pkgdir}'"
yann@63
   901
yann@1901
   902
    bundled_patch_dir="${CT_LIB_DIR}/patches/${pkgname}/${version}"
yann@1901
   903
    local_patch_dir="${CT_LOCAL_PATCH_DIR}/${pkgname}/${version}"
yann@1507
   904
yann@1507
   905
    case "${CT_PATCH_ORDER}" in
yann@1507
   906
        bundled)        patch_dirs=("${bundled_patch_dir}");;
yann@1507
   907
        local)          patch_dirs=("${local_patch_dir}");;
yann@1507
   908
        bundled,local)  patch_dirs=("${bundled_patch_dir}" "${local_patch_dir}");;
yann@1508
   909
        local,bundled)  patch_dirs=("${local_patch_dir}" "${bundled_patch_dir}");;
yann@1630
   910
        none)           patch_dirs=;;
yann@1507
   911
    esac
yann@1507
   912
yann@1507
   913
    for d in "${patch_dirs[@]}"; do
yann@1507
   914
        CT_DoLog DEBUG "Looking for patches in '${d}'..."
yann@1507
   915
        if [ -n "${d}" -a -d "${d}" ]; then
yann@1507
   916
            for p in "${d}"/*.patch; do
yann@63
   917
                if [ -f "${p}" ]; then
yann@523
   918
                    CT_DoLog DEBUG "Applying patch '${p}'"
yann@1765
   919
                    CT_DoExecLog ALL patch --no-backup-if-mismatch -g0 -F1 -p1 -f <"${p}"
yann@63
   920
                fi
yann@63
   921
            done
yann@1509
   922
            if [ "${CT_PATCH_SINGLE}" = "y" ]; then
yann@1509
   923
                break
yann@1509
   924
            fi
yann@63
   925
        fi
yann@63
   926
    done
yann@63
   927
yann@508
   928
    if [ "${CT_OVERIDE_CONFIG_GUESS_SUB}" = "y" ]; then
yann@508
   929
        CT_DoLog ALL "Overiding config.guess and config.sub"
yann@508
   930
        for cfg in config_guess config_sub; do
yann@1101
   931
            eval ${cfg}="${CT_LIB_DIR}/scripts/${cfg/_/.}"
yann@1101
   932
            [ -e "${CT_TOP_DIR}/scripts/${cfg/_/.}" ] && eval ${cfg}="${CT_TOP_DIR}/scripts/${cfg/_/.}"
yann@776
   933
            # Can't use CT_DoExecLog because of the '{} \;' to be passed un-mangled to find
yann@508
   934
            find . -type f -name "${cfg/_/.}" -exec cp -v "${!cfg}" {} \; |CT_DoLog ALL
yann@508
   935
        done
yann@508
   936
    fi
yann@508
   937
yann@1903
   938
    CT_DoExecLog DEBUG touch "${CT_SRC_DIR}/.${pkgdir}.patched"
yann@1903
   939
    CT_DoExecLog DEBUG rm -f "${CT_SRC_DIR}/.${pkgdir}.patching"
yann@1126
   940
yann@1761
   941
    CT_Popd
yann@63
   942
}
yann@63
   943
yann@182
   944
# Two wrappers to call config.(guess|sub) either from CT_TOP_DIR or CT_LIB_DIR.
yann@182
   945
# Those from CT_TOP_DIR, if they exist, will be be more recent than those from CT_LIB_DIR.
yann@182
   946
CT_DoConfigGuess() {
yann@1101
   947
    if [ -x "${CT_TOP_DIR}/scripts/config.guess" ]; then
yann@1101
   948
        "${CT_TOP_DIR}/scripts/config.guess"
yann@182
   949
    else
yann@1101
   950
        "${CT_LIB_DIR}/scripts/config.guess"
yann@182
   951
    fi
yann@182
   952
}
yann@182
   953
yann@182
   954
CT_DoConfigSub() {
yann@1101
   955
    if [ -x "${CT_TOP_DIR}/scripts/config.sub" ]; then
yann@1101
   956
        "${CT_TOP_DIR}/scripts/config.sub" "$@"
yann@182
   957
    else
yann@1101
   958
        "${CT_LIB_DIR}/scripts/config.sub" "$@"
yann@182
   959
    fi
yann@182
   960
}
yann@182
   961
yann@335
   962
# Compute the target tuple from what is provided by the user
yann@335
   963
# Usage: CT_DoBuildTargetTuple
yann@63
   964
# In fact this function takes the environment variables to build the target
yann@335
   965
# tuple. It is needed both by the normal build sequence, as well as the
yann@63
   966
# sample saving sequence.
yann@335
   967
CT_DoBuildTargetTuple() {
yann@383
   968
    # Set the endianness suffix, and the default endianness gcc option
yann@2773
   969
    case "${CT_ARCH_ENDIAN}" in
yann@2773
   970
        big)
yann@2773
   971
            target_endian_eb=eb
yann@383
   972
            target_endian_el=
yann@391
   973
            CT_ARCH_ENDIAN_CFLAG="-mbig-endian"
yann@527
   974
            CT_ARCH_ENDIAN_LDFLAG="-EB"
yann@383
   975
            ;;
yann@2773
   976
        little)
yann@2773
   977
            target_endian_eb=
yann@383
   978
            target_endian_el=el
yann@391
   979
            CT_ARCH_ENDIAN_CFLAG="-mlittle-endian"
yann@527
   980
            CT_ARCH_ENDIAN_LDFLAG="-EL"
yann@383
   981
            ;;
yann@63
   982
    esac
yann@383
   983
yann@965
   984
    # Build the default architecture tuple part
yann@965
   985
    CT_TARGET_ARCH="${CT_ARCH}"
yann@965
   986
yann@383
   987
    # Set defaults for the system part of the tuple. Can be overriden
yann@383
   988
    # by architecture-specific values.
yann@383
   989
    case "${CT_LIBC}" in
yann@787
   990
        *glibc) CT_TARGET_SYS=gnu;;
yann@383
   991
        uClibc) CT_TARGET_SYS=uclibc;;
yann@1591
   992
        *)      CT_TARGET_SYS=elf;;
yann@63
   993
    esac
yann@383
   994
yann@391
   995
    # Set the default values for ARCH, ABI, CPU, TUNE, FPU and FLOAT
yann@497
   996
    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
yann@497
   997
    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
yann@391
   998
    [ "${CT_ARCH_ARCH}"     ] && { CT_ARCH_ARCH_CFLAG="-march=${CT_ARCH_ARCH}";  CT_ARCH_WITH_ARCH="--with-arch=${CT_ARCH_ARCH}"; }
yann@391
   999
    [ "${CT_ARCH_ABI}"      ] && { CT_ARCH_ABI_CFLAG="-mabi=${CT_ARCH_ABI}";     CT_ARCH_WITH_ABI="--with-abi=${CT_ARCH_ABI}";    }
yann@391
  1000
    [ "${CT_ARCH_CPU}"      ] && { CT_ARCH_CPU_CFLAG="-mcpu=${CT_ARCH_CPU}";     CT_ARCH_WITH_CPU="--with-cpu=${CT_ARCH_CPU}";    }
yann@405
  1001
    [ "${CT_ARCH_TUNE}"     ] && { CT_ARCH_TUNE_CFLAG="-mtune=${CT_ARCH_TUNE}";  CT_ARCH_WITH_TUNE="--with-tune=${CT_ARCH_TUNE}"; }
yann@391
  1002
    [ "${CT_ARCH_FPU}"      ] && { CT_ARCH_FPU_CFLAG="-mfpu=${CT_ARCH_FPU}";     CT_ARCH_WITH_FPU="--with-fpu=${CT_ARCH_FPU}";    }
michael@2737
  1003
michael@2737
  1004
    case "${CT_ARCH_FLOAT}" in
michael@2738
  1005
        hard)
michael@2738
  1006
            CT_ARCH_FLOAT_CFLAG="-mhard-float"
michael@2738
  1007
            CT_ARCH_WITH_FLOAT="--with-float=hard"
michael@2738
  1008
            ;;
michael@2737
  1009
        soft)
michael@2737
  1010
            CT_ARCH_FLOAT_CFLAG="-msoft-float"
michael@2737
  1011
            CT_ARCH_WITH_FLOAT="--with-float=soft"
michael@2737
  1012
            ;;
michael@2739
  1013
        softfp)
michael@2739
  1014
            CT_ARCH_FLOAT_CFLAG="-mfloat-abi=softfp"
michael@2739
  1015
            CT_ARCH_WITH_FLOAT="--with-float=softfp"
michael@2739
  1016
            ;;
michael@2737
  1017
    esac
yann@391
  1018
yann@965
  1019
    # Build the default kernel tuple part
yann@965
  1020
    CT_TARGET_KERNEL="${CT_KERNEL}"
yann@964
  1021
yann@965
  1022
    # Overide the default values with the components specific settings
yann@964
  1023
    CT_DoArchTupleValues
yann@965
  1024
    CT_DoKernelTupleValues
yann@383
  1025
yann@391
  1026
    # Finish the target tuple construction
bartvdrmeulen@1896
  1027
    CT_TARGET="${CT_TARGET_ARCH}"
bartvdrmeulen@1896
  1028
    CT_TARGET="${CT_TARGET}${CT_TARGET_VENDOR:+-${CT_TARGET_VENDOR}}"
bartvdrmeulen@1896
  1029
    CT_TARGET="${CT_TARGET}${CT_TARGET_KERNEL:+-${CT_TARGET_KERNEL}}"
bartvdrmeulen@1896
  1030
    CT_TARGET="${CT_TARGET}${CT_TARGET_SYS:+-${CT_TARGET_SYS}}"
yann@1094
  1031
yann@1094
  1032
    # Sanity checks
yann@1094
  1033
    __sed_alias=""
yann@1094
  1034
    if [ -n "${CT_TARGET_ALIAS_SED_EXPR}" ]; then
yann@1094
  1035
        __sed_alias=$(echo "${CT_TARGET}" |sed -r -e "${CT_TARGET_ALIAS_SED_EXPR}")
yann@1094
  1036
    fi
yann@1094
  1037
    case ":${CT_TARGET_VENDOR}:${CT_TARGET_ALIAS}:${__sed_alias}:" in
yann@1094
  1038
      :*" "*:*:*:) CT_Abort "Don't use spaces in the vendor string, it breaks things.";;
yann@1094
  1039
      :*"-"*:*:*:) CT_Abort "Don't use dashes in the vendor string, it breaks things.";;
yann@1094
  1040
      :*:*" "*:*:) CT_Abort "Don't use spaces in the target alias, it breaks things.";;
yann@1094
  1041
      :*:*:*" "*:) CT_Abort "Don't use spaces in the target sed transform, it breaks things.";;
yann@1094
  1042
    esac
yann@1094
  1043
yann@1094
  1044
    # Canonicalise it
yann@1094
  1045
    CT_TARGET=$(CT_DoConfigSub "${CT_TARGET}")
yann@391
  1046
    # Prepare the target CFLAGS
yann@767
  1047
    CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ENDIAN_CFLAG}"
yann@527
  1048
    CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ARCH_CFLAG}"
yann@397
  1049
    CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_ABI_CFLAG}"
yann@397
  1050
    CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_CPU_CFLAG}"
yann@397
  1051
    CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_TUNE_CFLAG}"
yann@397
  1052
    CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FPU_CFLAG}"
yann@397
  1053
    CT_ARCH_TARGET_CFLAGS="${CT_ARCH_TARGET_CFLAGS} ${CT_ARCH_FLOAT_CFLAG}"
yann@527
  1054
yann@527
  1055
    # Now on for the target LDFLAGS
yann@767
  1056
    CT_ARCH_TARGET_LDFLAGS="${CT_ARCH_TARGET_LDFLAGS} ${CT_ARCH_ENDIAN_LDFLAG}"
yann@63
  1057
}
yann@121
  1058
yann@121
  1059
# This function does pause the build until the user strikes "Return"
yann@121
  1060
# Usage: CT_DoPause [optional_message]
yann@121
  1061
CT_DoPause() {
yann@121
  1062
    local foo
yann@121
  1063
    local message="${1:-Pausing for your pleasure}"
yann@121
  1064
    CT_DoLog INFO "${message}"
yann@523
  1065
    read -p "Press 'Enter' to continue, or Ctrl-C to stop..." foo >&6
yann@121
  1066
    return 0
yann@121
  1067
}
yann@121
  1068
yann@1907
  1069
# This function creates a tarball of the specified directory, but
yann@1907
  1070
# only if it exists
yann@1907
  1071
# Usage: CT_DoTarballIfExists <dir> <tarball_basename> [extra_tar_options [...]]
yann@1907
  1072
CT_DoTarballIfExists() {
yann@1907
  1073
    local dir="$1"
yann@1907
  1074
    local tarball="$2"
yann@1907
  1075
    shift 2
yann@1907
  1076
    local -a extra_tar_opts=( "$@" )
yann@1908
  1077
    local -a compress
yann@1907
  1078
yann@1907
  1079
    case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
yann@1908
  1080
        y)  compress=( gzip -c -3 - ); tar_ext=.gz;;
yann@1908
  1081
        *)  compress=( cat - );        tar_ext=;;
yann@1907
  1082
    esac
yann@1907
  1083
yann@1907
  1084
    if [ -d "${dir}" ]; then
yann@1907
  1085
        CT_DoLog DEBUG "  Saving '${dir}'"
yann@1908
  1086
        { tar c -C "${dir}" -v -f - "${extra_tar_opts[@]}" .    \
yann@1908
  1087
          |"${compress[@]}" >"${tarball}.tar${tar_ext}"         ;
anthony@2155
  1088
        } 2>&1 |sed -r -e 's/^/    /;' |CT_DoLog STATE
yann@1907
  1089
    else
anthony@2155
  1090
        CT_DoLog STATE "  Not saving '${dir}': does not exist"
yann@1907
  1091
    fi
yann@1907
  1092
}
yann@1907
  1093
yann@1907
  1094
# This function extracts a tarball to the specified directory, but
yann@1907
  1095
# only if the tarball exists
anthony@2155
  1096
# Usage: CT_DoExtractTarballIfExists <tarball_basename> <dir> [extra_tar_options [...]]
yann@1907
  1097
CT_DoExtractTarballIfExists() {
yann@1907
  1098
    local tarball="$1"
yann@1907
  1099
    local dir="$2"
yann@1907
  1100
    shift 2
yann@1907
  1101
    local -a extra_tar_opts=( "$@" )
yann@1908
  1102
    local -a uncompress
yann@1907
  1103
yann@1907
  1104
    case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
yann@1908
  1105
        y)  uncompress=( gzip -c -d ); tar_ext=.gz;;
yann@1908
  1106
        *)  uncompress=( cat );        tar_ext=;;
yann@1907
  1107
    esac
yann@1907
  1108
yann@1907
  1109
    if [ -f "${tarball}.tar${tar_ext}" ]; then
yann@1907
  1110
        CT_DoLog DEBUG "  Restoring '${dir}'"
yann@1907
  1111
        CT_DoForceRmdir "${dir}"
yann@1907
  1112
        CT_DoExecLog DEBUG mkdir -p "${dir}"
yann@1908
  1113
        { "${uncompress[@]}" "${tarball}.tar${tar_ext}"     \
yann@1908
  1114
          |tar x -C "${dir}" -v -f - "${extra_tar_opts[@]}" ;
anthony@2155
  1115
        } 2>&1 |sed -r -e 's/^/    /;' |CT_DoLog STATE
yann@1907
  1116
    else
anthony@2155
  1117
        CT_DoLog STATE "  Not restoring '${dir}': does not exist"
yann@1907
  1118
    fi
yann@1907
  1119
}
yann@1907
  1120
yann@121
  1121
# This function saves the state of the toolchain to be able to restart
yann@121
  1122
# at any one point
yann@121
  1123
# Usage: CT_DoSaveState <next_step_name>
yann@121
  1124
CT_DoSaveState() {
yann@121
  1125
	[ "${CT_DEBUG_CT_SAVE_STEPS}" = "y" ] || return 0
yann@121
  1126
    local state_name="$1"
yann@121
  1127
    local state_dir="${CT_STATE_DIR}/${state_name}"
yann@121
  1128
yann@1266
  1129
    # Log this to the log level required by the user
yann@1266
  1130
    CT_DoLog ${CT_LOG_LEVEL_MAX} "Saving state to restart at step '${state_name}'..."
yann@1134
  1131
yann@121
  1132
    rm -rf "${state_dir}"
yann@121
  1133
    mkdir -p "${state_dir}"
yann@121
  1134
anthony@2155
  1135
    CT_DoLog STATE "  Saving environment and aliases"
yann@738
  1136
    # We must omit shell functions, and some specific bash variables
yann@738
  1137
    # that break when restoring the environment, later. We could do
yann@1299
  1138
    # all the processing in the awk script, but a sed is easier...
yann@1299
  1139
    set |awk '
yann@1017
  1140
              BEGIN { _p = 1; }
yann@1017
  1141
              $0~/^[^ ]+ \(\)/ { _p = 0; }
yann@1017
  1142
              _p == 1
yann@1017
  1143
              $0 == "}" { _p = 1; }
yann@1017
  1144
              ' |sed -r -e '/^BASH_(ARGC|ARGV|LINENO|SOURCE|VERSINFO)=/d;
yann@738
  1145
                           /^(UID|EUID)=/d;
yann@738
  1146
                           /^(FUNCNAME|GROUPS|PPID|SHELLOPTS)=/d;' >"${state_dir}/env.sh"
yann@121
  1147
yann@2308
  1148
    CT_DoTarballIfExists "${CT_BUILDTOOLS_PREFIX_DIR}" "${state_dir}/buildtools_dir"
yann@2502
  1149
    CT_DoTarballIfExists "${CT_COMPLIBS_DIR}" "${state_dir}/complibs_dir"
yann@1907
  1150
    CT_DoTarballIfExists "${CT_CONFIG_DIR}" "${state_dir}/config_dir"
yann@1907
  1151
    CT_DoTarballIfExists "${CT_PREFIX_DIR}" "${state_dir}/prefix_dir" --exclude '*.log'
yann@121
  1152
yann@2339
  1153
    CT_DoLog STATE "  Saving log file"
yann@2339
  1154
    exec >/dev/null
yann@2339
  1155
    case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
yann@2339
  1156
        y)  gzip -3 -c "${tmp_log_file}"  >"${state_dir}/log.gz";;
yann@2339
  1157
        *)  cat "${tmp_log_file}" >"${state_dir}/log";;
yann@2339
  1158
    esac
yann@2339
  1159
    exec >>"${tmp_log_file}"
yann@121
  1160
}
yann@121
  1161
yann@136
  1162
# This function restores a previously saved state
yann@121
  1163
# Usage: CT_DoLoadState <state_name>
yann@121
  1164
CT_DoLoadState(){
yann@121
  1165
    local state_name="$1"
yann@121
  1166
    local state_dir="${CT_STATE_DIR}/${state_name}"
yann@135
  1167
    local old_RESTART="${CT_RESTART}"
yann@135
  1168
    local old_STOP="${CT_STOP}"
yann@121
  1169
yann@523
  1170
    CT_TestOrAbort "The previous build did not reach the point where it could be restarted at '${CT_RESTART}'" -d "${state_dir}"
yann@141
  1171
yann@121
  1172
    # We need to do something special with the log file!
yann@121
  1173
    if [ "${CT_LOG_TO_FILE}" = "y" ]; then
yann@121
  1174
        exec >"${state_dir}/tail.log"
yann@121
  1175
    fi
yann@1266
  1176
yann@1266
  1177
    # Log this to the log level required by the user
yann@1266
  1178
    CT_DoLog ${CT_LOG_LEVEL_MAX} "Restoring state at step '${state_name}', as requested."
yann@121
  1179
yann@1907
  1180
    CT_DoExtractTarballIfExists "${state_dir}/prefix_dir" "${CT_PREFIX_DIR}"
yann@1907
  1181
    CT_DoExtractTarballIfExists "${state_dir}/config_dir" "${CT_CONFIG_DIR}"
yann@2502
  1182
    CT_DoExtractTarballIfExists "${state_dir}/complibs_dir" "${CT_COMPLIBS_DIR}"
yann@2308
  1183
    CT_DoExtractTarballIfExists "${state_dir}/buildtools_dir" "${CT_BUILDTOOLS_PREFIX_DIR}"
yann@1894
  1184
yann@121
  1185
    # Restore the environment, discarding any error message
yann@121
  1186
    # (for example, read-only bash internals)
anthony@2155
  1187
    CT_DoLog STATE "  Restoring environment"
yann@121
  1188
    . "${state_dir}/env.sh" >/dev/null 2>&1 || true
yann@121
  1189
yann@135
  1190
    # Restore the new RESTART and STOP steps
yann@135
  1191
    CT_RESTART="${old_RESTART}"
yann@135
  1192
    CT_STOP="${old_STOP}"
yann@135
  1193
    unset old_stop old_restart
yann@135
  1194
yann@2339
  1195
    CT_DoLog STATE "  Restoring log file"
yann@2339
  1196
    exec >/dev/null
yann@2339
  1197
    case "${CT_DEBUG_CT_SAVE_STEPS_GZIP}" in
yann@2339
  1198
        y)  zcat "${state_dir}/log.gz" >"${tmp_log_file}";;
yann@2339
  1199
        *)  cat "${state_dir}/log" >"${tmp_log_file}";;
yann@2339
  1200
    esac
yann@2339
  1201
    cat "${state_dir}/tail.log" >>"${tmp_log_file}"
yann@2339
  1202
    exec >>"${tmp_log_file}"
yann@2339
  1203
    rm -f "${state_dir}/tail.log"
yann@121
  1204
}