scripts/functions
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Tue May 01 16:49:15 2007 +0000 (2007-05-01)
changeset 56 07a6a48962b7
parent 1 eeea35fbf182
child 63 89b41dbffe8d
permissions -rw-r--r--
Merge patches sent by Robert P. J. Day <rpjday@mindspring.com>.
Warning: the buildroot folks purposedly removed the skip-comment patch but didn't really said why. Keeping it for the sake of having it in svn just in case (removing it will be easier thant not having it at all).
     1 # This file contains some usefull common functions
     2 # Copyright 2007 Yann E. MORIN
     3 # Licensed under the GPL v2. See COPYING in the root of this package
     4 
     5 CT_OnError() {
     6     ret=$?
     7     CT_DoLog ERROR "Build failed in step \"${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}\""
     8     for((step=(CT_STEP_COUNT-1); step>1; step--)); do
     9         CT_DoLog ERROR "      called in step \"${CT_STEP_MESSAGE[${step}]}\""
    10     done
    11     CT_DoLog ERROR "Error happened in \"${BASH_SOURCE[1]}\" in function \"${FUNCNAME[1]}\" (line unknown, sorry)"
    12     for((depth=2; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
    13         CT_DoLog ERROR "      called from \"${BASH_SOURCE[${depth}]}\" at line # ${BASH_LINENO[${depth}-1]} in function \"${FUNCNAME[${depth}]}\""
    14     done
    15     CT_DoLog ERROR "Look at \"${CT_ACTUAL_LOG_FILE}\" for more info on this error."
    16     exit $ret
    17 }
    18 trap CT_OnError ERR
    19 
    20 set -E
    21 set -o pipefail
    22 
    23 # This is crosstool-ng-0.0.1
    24 CT_VERSION=ng-0.0.1
    25 
    26 # The different log levels:
    27 CT_LOG_LEVEL_ERROR=0
    28 CT_LOG_LEVEL_WARN=1
    29 CT_LOG_LEVEL_INFO=2
    30 CT_LOG_LEVEL_EXTRA=3
    31 CT_LOG_LEVEL_DEBUG=4
    32 
    33 # Attributes
    34 _A_NOR="\\033[0m"
    35 _A_BRI="\\033[1m"
    36 _A_DIM="\\033[2m"
    37 _A_UND="\\033[4m"
    38 _A_BRB="\\033[5m"
    39 _A_REV="\\033[7m"
    40 _A_HID="\\033[8m"
    41 
    42 # Fore colors
    43 _F_BLK="\\033[30m"
    44 _F_RED="\\033[31m"
    45 _F_GRN="\\033[32m"
    46 _F_YEL="\\033[33m"
    47 _F_BLU="\\033[34m"
    48 _F_MAG="\\033[35m"
    49 _F_CYA="\\033[36m"
    50 _F_WHI="\\033[37m"
    51 
    52 # A function to log what is happening
    53 # Different log level are available:
    54 #   - ERROR:   A serious, fatal error occurred
    55 #   - WARN:    A non fatal, non serious error occurred, take your responsbility with the generated build
    56 #   - INFO:    Informational messages
    57 #   - EXTRA:   Extra informational messages
    58 #   - DEBUG:   Debug messages
    59 # Usage: CT_DoLog <level> [message]
    60 # If message is empty, then stdin will be logged.
    61 CT_DoLog() {
    62     local max_level LEVEL level cur_l cur_L
    63     local l
    64     eval max_level="\${CT_LOG_LEVEL_${CT_LOG_LEVEL_MAX}}"
    65     # Set the maximum log level to DEBUG if we have none
    66     [ -z ${max_level} ] && max_level=${CT_LOG_LEVEL_DEBUG}
    67 
    68     LEVEL="$1"; shift
    69     eval level="\${CT_LOG_LEVEL_${LEVEL}}"
    70 
    71     if [ $# -eq 0 ]; then
    72         cat -
    73     else
    74         echo "${1}"
    75     fi |( IFS="\n" # We want the full lines, even leading spaces
    76           cpt=0
    77           indent=$((2*CT_STEP_COUNT))
    78           while read line; do
    79               case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
    80                 y,*"warning:"*)         cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
    81                 *"error:"*)             cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
    82                 "make["?*"]:"*"Stop.")  cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
    83                 *)                      cur_L="${LEVEL}"; cur_l="${level}";;
    84               esac
    85               l="`printf \"[%-5s]%*s%s%s\" \"${cur_L}\" \"${indent}\" \" \" \"${line}\"`"
    86               # There will always be a log file, be it /dev/null
    87               echo -e "${l}" >>"${CT_ACTUAL_LOG_FILE}"
    88               color="CT_${cur_L}_COLOR"
    89               normal="CT_NORMAL_COLOR"
    90               if [ ${cur_l} -le ${max_level} ]; then
    91                   echo -e "${!color}${l}${!normal}"
    92               else
    93                   ${CT_PROG_BAR}
    94               fi
    95           done
    96         )
    97 
    98     return 0
    99 }
   100 
   101 # Abort the execution with a error message
   102 # Usage: CT_Abort <message>
   103 CT_Abort() {
   104     CT_DoLog ERROR "$1" >&2
   105     exit 1
   106 }
   107 
   108 # Test a condition, and print a message if satisfied
   109 # Usage: CT_Test <message> <tests>
   110 CT_Test() {
   111     local ret
   112     local m="$1"
   113     shift
   114     test "$@" && CT_DoLog WARN "$m"
   115     return 0
   116 }
   117 
   118 # Test a condition, and abort with an error message if satisfied
   119 # Usage: CT_TestAndAbort <message> <tests>
   120 CT_TestAndAbort() {
   121     local m="$1"
   122     shift
   123     test "$@" && CT_Abort "$m"
   124     return 0
   125 }
   126 
   127 # Test a condition, and abort with an error message if not satisfied
   128 # Usage: CT_TestAndAbort <message> <tests>
   129 CT_TestOrAbort() {
   130     local m="$1"
   131     shift
   132     test "$@" || CT_Abort "$m"
   133     return 0
   134 }
   135 
   136 # Test the presence of a tool, or abort if not found
   137 # Usage: CT_HasOrAbort <tool>
   138 CT_HasOrAbort() {
   139     CT_TestAndAbort "\"${1}\" not found and needed for successfull toolchain build." -z "`which \"${1}\"`"
   140     return 0
   141 }
   142 
   143 # Get current date with nanosecond precision
   144 # On those system not supporting nanosecond precision, faked with rounding down
   145 # to the highest entire second
   146 # Usage: CT_DoDate <fmt>
   147 CT_DoDate() {
   148     date "$1" |sed -r -e 's/%N$/000000000/;'
   149 }
   150 
   151 CT_STEP_COUNT=1
   152 CT_STEP_MESSAGE[${CT_STEP_COUNT}]="<none>"
   153 # Memorise a step being done so that any error is caught
   154 # Usage: CT_DoStep <loglevel> <message>
   155 CT_DoStep() {
   156     local start=`CT_DoDate +%s%N`
   157     CT_DoLog "$1" "================================================================="
   158     CT_DoLog "$1" "$2"
   159     CT_STEP_COUNT=$((CT_STEP_COUNT+1))
   160     CT_STEP_LEVEL[${CT_STEP_COUNT}]="$1"; shift
   161     CT_STEP_START[${CT_STEP_COUNT}]="${start}"
   162     CT_STEP_MESSAGE[${CT_STEP_COUNT}]="$1"
   163     return 0
   164 }
   165 
   166 # End the step just being done
   167 # Usage: CT_EndStep
   168 CT_EndStep() {
   169     local stop=`CT_DoDate +%s%N`
   170     local duration=`printf "%032d" $((stop-${CT_STEP_START[${CT_STEP_COUNT}]})) |sed -r -e 's/([[:digit:]]{2})[[:digit:]]{7}$/\.\1/; s/^0+//; s/^\./0\./;'`
   171     local level="${CT_STEP_LEVEL[${CT_STEP_COUNT}]}"
   172     local message="${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}"
   173     CT_STEP_COUNT=$((CT_STEP_COUNT-1))
   174     CT_DoLog "${level}" "${message}: done in ${duration}s"
   175     return 0
   176 }
   177 
   178 # Pushes into a directory, and pops back
   179 CT_Pushd() {
   180     pushd "$1" >/dev/null 2>&1
   181 }
   182 CT_Popd() {
   183     popd >/dev/null 2>&1
   184 }
   185 
   186 # Makes a path absolute
   187 # Usage: CT_MakeAbsolutePath path
   188 CT_MakeAbsolutePath() {
   189     # Try to cd in that directory
   190     if [ -d "$1" ]; then
   191         CT_Pushd "$1"
   192         pwd
   193         CT_Popd
   194     else
   195         # No such directory, fail back to guessing
   196         case "$1" in
   197             /*)  echo "$1";;
   198             *)   echo "`pwd`/$1";;
   199         esac
   200     fi
   201     
   202     return 0
   203 }
   204 
   205 # Creates a temporary directory
   206 # $1: variable to assign to
   207 # Usage: CT_MktempDir foo
   208 CT_MktempDir() {
   209     # Some mktemp do not allow more than 6 Xs
   210     eval "$1"="`mktemp -q -d \"${CT_BUILD_DIR}/.XXXXXX\"`"
   211     CT_TestOrAbort "Could not make temporary directory" -n "${!1}" -a -d "${!1}"
   212 }
   213 
   214 # Echoes the specified string on stdout until the pipe breaks.
   215 # Doesn't fail
   216 # $1: string to echo
   217 # Usage: CT_DoYes "" |make oldconfig
   218 CT_DoYes() {
   219     yes "$1" || true
   220 }