-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathdetect-environment
More file actions
420 lines (381 loc) · 12.2 KB
/
detect-environment
File metadata and controls
420 lines (381 loc) · 12.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
#!/bin/sh
#
# Always *source* this file, not execute! Always after you first
# sourced "functions". Like that:
# . `dirname "$0"`/functions
# . detect-environment
#
if [ "$_IS_FUNCTIONS_SOURCED" != yes ]; then
echo 'FATAL: You must source "functions" script before "detect-environment"!'
exit 100
fi
# Detects and sets the CROSS_TARGET environment variable based on patterns
# in the label variable (see labels.txt), specifically for MinGW cross-
# compilation targets. However, if CROSS_TARGET is already set in the
# environment it will take precedence.
detect_cross_target() {
# shellcheck disable=SC2154
# > label is referenced but not assigned.
# This file is sourced by other scripts. label is assigned elsewhere.
case "$label" in
*_x86_64_mingw*)
CROSS_TARGET=${CROSS_TARGET:-x64-mingw}
export CROSS_TARGET
;;
*_i386_mingw*)
CROSS_TARGET=${CROSS_TARGET:-x86-mingw}
export CROSS_TARGET
;;
esac
}
# This function exports operating system specific variables:
# - OS usually contains a specific distribution (e.g. Debian)
# - OS_VERSION operating system version (but is not always defined)
# - OS_VERSION_MAJOR the major (first part of) operating system version (defined if OS_VERSION is)
#
# Furthermore, the following variable is set, but it's not exported:
# - OS_FAMILY usually contains the kernel name (e.g. Linux)
detect_os() {
case "$CROSS_TARGET" in
'')
# The UNAME_S, UNAME_R and UNAME_V variables are set in the "functions"
# script from the command substitution of `uname -s`, `uname -r` and
# `uname -v` which outputs the kernel name, the kernel release and the
# kernel version respectively.
case "$UNAME_S" in
Linux)
OS_FAMILY=linux
detect_distribution
;;
SunOS)
OS_FAMILY=solaris
OS=solaris
OS_VERSION=$(echo "$UNAME_R" | sed -e 's/^5\.//')
;;
AIX)
OS_FAMILY=aix
OS_VERSION=$(uname -v).$UNAME_R
OS=aix
# LIBPATH on AIX serves the same function as LD_LIBRARY_PATH on
# Linux. However, Java also uses this environment variable, and it
# apparently messes with the library look-ups during packaging. This
# line definitely doesn't belong here. But I'll leave it for now.
unset LIBPATH
;;
Darwin)
OS_FAMILY=darwin
OS=darwin
;;
FreeBSD)
OS_FAMILY=freebsd
OS=freebsd
OS_VERSION=$UNAME_R
;;
NetBSD)
OS_FAMILY=netbsd
OS=netbsd
;;
HP-UX)
OS_FAMILY=hpux
OS=hpux
OS_VERSION=$UNAME_R
;;
*)
log_error "Unable to detect operating system: $UNAME_S"
exit 42
;;
esac
;;
*-mingw)
OS_FAMILY=mingw
OS=mingw
;;
*)
log_error "Unknown cross-compilation target: $CROSS_TARGET"
exit 42
;;
esac
# Extract major version from OS_VERSION (e.g. 16.04 -> 16, 7.0 -> 7, 10.2.3 -> 10)
if [ -n "$OS_VERSION" ]; then
OS_VERSION_MAJOR="${OS_VERSION%%.*}"
fi
export OS OS_VERSION OS_VERSION_MAJOR
}
# The uname command does not reveal the specific distribution on Linux. Hence,
# we'll need to parse it from different files located in the /etc/ directory.
# Unfortunately, there is no standard across the existing distributions. Thus,
# this is going to be a bit messy.
detect_distribution() {
if [ -f /etc/redhat-release ]; then
REL=$(cat /etc/redhat-release)
case "$REL" in
"CentOS "*)
# Example output for CentOS:
# CentOS Linux release 7.6.1810 (Core)
OS=centos
;;
"Red Hat Enterprise Linux "* | "Rocky Linux release "*)
# Example output for RHEL:
# Red Hat Enterprise Linux release 8.10 (Ootpa)
OS=rhel
;;
*)
log_error "Could not determine Linux distro from /etc/redhat-release: $REL"
exit 42
;;
esac
# Common for all of these is that the version number starts just after the
# substring 'release '. Hence we reset the match (with \K) just after
# substring and extract the major and minor version.
version_string=$(echo "$REL" | grep -oP 'release \K\d+\.\d+')
# Make sure we actually found a match
if [ -z "$version_string" ]; then
log_error "Could not determine version number from /etc/redhat-release: $REL"
exit 42
fi
OS_VERSION=$version_string
elif [ -f /etc/lsb-release ] && grep -q Ubuntu /etc/lsb-release; then
# This file was introduced by Linux Standard Base (LSB) which an attempt to
# standardize the Linux ecosystem. Unfortunately it was not adopted by many
# Linux distributions. Ubuntu dropped the support for LSB in 2015. However,
# the /etc/lsb-release file is still available as of Ubuntu 24.
#
# It might be naive to assume the file will continue to exist and that the
# existence of the file is only present in Ubuntu. Hence, if this breaks in
# the future, you'll know why.
#
# Example output of /etc/lsb-release:
#
# DISTRIB_ID=Ubuntu
# DISTRIB_RELEASE=24.04
# DISTRIB_CODENAME=noble
# DISTRIB_DESCRIPTION="Ubuntu 24.04.2 LTS"
# Get the line containing 'DISTRIB_RELEASE='
REL=$(grep DISTRIB_RELEASE= /etc/lsb-release)
# Remove the 'DISTRIB_RELEASE=' part
REL=${REL#DISTRIB_RELEASE=}
# Verify that we can find a valid version number
case "$REL" in
[0-9][0-9].[0-9][0-9]) ;;
*)
log_error "Unknown Ubuntu release: $REL"
exit 42
;;
esac
OS=ubuntu
OS_VERSION="$REL"
elif [ -f /etc/debian_version ]; then
# This file contains only the version number.
#
# Example output of /etc/debian_version
# 12.11
REL=$(cat /etc/debian_version)
if ! echo "$REL" | grep -E '^[0-9]+\.[0-9]+(\.[0-9]+)?$' >/dev/null; then
log_error "Unable to detect version of Debian: $REL"
exit 42
fi
OS=debian
OS_VERSION="$REL"
elif [ -f /etc/os-release ]; then
# see https://en.opensuse.org/SDB:Find_openSUSE_version for rules of
# parsing this file
# Example output for /etc/os-release:
#
# NAME="SLES"
# VERSION="12-SP5"
# VERSION_ID="12.5"
# PRETTY_NAME="SUSE Linux Enterprise Server 12 SP5"
# ID="sles"
# ANSI_COLOR="0;32"
# CPE_NAME="cpe:/o:suse:sles:12:sp5"
os="$(sh -c ". /etc/os-release; echo \$ID")"
ver="$(sh -c ". /etc/os-release; echo \$VERSION_ID")"
if [ "$os" = "sles" ]; then
OS=sles
OS_VERSION="$ver"
elif expr "$os" : "opensuse" >/dev/null; then
# If the string begins with "opensuse", then strip the remaining part. It
# can be "opensuse-leap" or "opensuse-tumbleweed"
OS=opensuse
OS_VERSION="$ver"
fi
fi
if [ -z "$OS" ]; then
log_error "Failed to detect Linux distribution"
exit 42
fi
if [ -z "$OS_VERSION" ]; then
log_error "Failed to detect Linux distribution version"
exit 42
fi
}
# This function determines which dependency packaging scripts shall be used
# based on the operating system and available packaging tools. E.g., if rpm is
# detected, then the "pkg-build-rpm" script will be called from the
# "install-dependencies" script.
detect_packaging() {
if [ -f /bin/rpm ]; then
DEP_PACKAGING=rpm
elif [ -f /usr/bin/dpkg ]; then
DEP_PACKAGING=deb
elif [ -f /usr/sbin/pkgadd ]; then
DEP_PACKAGING=solaris
elif [ -f /usr/sbin/pkg_add ]; then
case "$UNAME_S" in
FreeBSD)
DEP_PACKAGING=freebsd
;;
esac
elif [ -f /usr/sbin/swinstall ]; then
DEP_PACKAGING=hpux
else
log_error "Unknown packaging system"
exit 42
fi
case "$OS" in
aix)
PACKAGING=lpp
;;
mingw)
PACKAGING=msi
;;
*)
PACKAGING=$DEP_PACKAGING
;;
esac
export DEP_PACKAGING PACKAGING
}
# This function determines which architecture to build for based on the system
# we're building on. Unless we are cross compiling, then it's determined by the
# CROSS_TARGET variable.
detect_arch() {
case "$DEP_PACKAGING" in
deb)
ARCH=$(dpkg --print-architecture)
;;
rpm)
ARCH=$(rpm --eval '%{_arch}')
;;
solaris)
case $UNAME_M in
sun*)
ARCH=sparc
;;
i86pc)
ARCH=i86pc
;;
*)
log_error "Unknown Solaris architecture: $UNAME_M"
exit 42
;;
esac
;;
freebsd)
ARCH=$UNAME_M
;;
hpux)
ARCH=$UNAME_M
;;
*)
log_error "Unknown packaging system"
exit 42
;;
esac
# We need to determine the architecture based on the 'CROSS_TARGET' variable
# which is derived from the 'label' variable instead of the system that we
# are building on.
case "$CROSS_TARGET" in
'') ;;
x86-*)
ARCH=x86
;;
x64-*)
ARCH=x64
;;
*)
log_error "Unknown cross-compilation target: $CROSS_TARGET"
exit 42
;;
esac
export ARCH
}
# This function detects the path to various tools needed by the build system.
# It's useful if the specified tool is not in PATH, or if the PATH resolution
# picks up the wrong tool, or if e.g. gmake is preferred over make.
detect_tools() {
# We look for GNU Make because
# various dependencies have various requirements
MAKE=$(func_whereis gmake make)
if $MAKE -v | grep -q GNU; then
export MAKE
else
log_error "GNU Make not found"
exit 42
fi
export RPMBUILD_CMD=rpmbuild
# fuser displays the PIDs of processes using specified files or file
# systems. We use it to kill processes that can mess with the build process.
FUSER=$(func_whereis fuser)
export FUSER
# We use patch to apply patches to the dependencies.
PATCH=$(func_whereis gpatch patch)
export PATCH
}
# This function appends the -j/--jobs option to the MAKEFLAGS environment
# variable based on the number of cores. However, the variable is overwritten in
# the "install-dependencies" script. I created a ticket fix this (see
# ENT-13041).
detect_cores() {
case "$OS_FAMILY" in
aix)
NUM_CORES="$(lscfg | grep -c proc)"
;;
solaris)
NUM_CORES="$(psrinfo | wc -l)"
;;
linux)
NUM_CORES="$(grep -c '^processor' /proc/cpuinfo)"
;;
hpux)
NUM_CORES="$(ioscan -k -C processor | grep -c processor)"
;;
*)
log_debug "Detected OS family is UNKNOWN, defaulting amount of CPU cores to 1"
NUM_CORES=1
;;
esac
# Make number of jobs one higher than core count, to account for I/O, network, etc.
MAKEFLAGS="${MAKEFLAGS:--j$((NUM_CORES + 1))}"
export MAKEFLAGS
}
detect_environment() {
detect_cross_target
detect_os
detect_packaging
detect_arch
detect_tools
detect_cores
}
# The env before detecting environment (to be compared with env after)
env | sort >"env_before"
#
# We need to detect the following pieces of data:
# - distribution
# - version
# - architecture
# - packaging tool (dpkg, rpm, solaris pkg, ...)
#
detect_environment
# Print the environment variables so that the log can be used to debug problems
# stemming from wrong environment.
env_diff="$(env | sort | diff env_before - | grep '^>' | sed 's/^> //')"
unlink env_before
if [ -n "$env_diff" ]; then
echo
echo
echo "======= Changes to environment after sourcing this script ======="
echo "$env_diff"
echo "================================================================="
echo
echo
fi