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