Skip to content

Commit 025da07

Browse files
authored
Merge pull request #3 from lexming/feature-archdetect
standarize log formatting by adding logging function
2 parents 24767eb + c74bb8e commit 025da07

File tree

1 file changed

+113
-63
lines changed

1 file changed

+113
-63
lines changed

init/eessi_archdetect.sh

+113-63
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,33 @@
11
#!/usr/bin/env bash
2+
VERSION="1.0.0"
3+
4+
# Logging
5+
LOG_LEVEL="INFO"
6+
7+
timestamp () {
8+
date "+%Y-%m-%d %H:%M:%S"
9+
}
10+
11+
log () {
12+
# Simple logger function
13+
declare -A levels=([DEBUG]=0 [INFO]=1 [WARN]=2 [ERROR]=3)
14+
msg_type="${1:-INFO}"
15+
msg_body="${2:-'null'}"
16+
17+
[ ${levels[$msg_type]} ] || log "ERROR" "Unknown log level $msg_type"
18+
19+
# ignore messages below log level
20+
[ ${levels[$msg_type]} -lt ${levels[$LOG_LEVEL]} ] && return 0
21+
# print log message to standard error
22+
echo "$(timestamp) [$msg_type] $msg_body" >&2
23+
# exit after any error message
24+
[ $msg_type == "ERROR" ] && exit 1
25+
}
226

327
# Supported CPU specifications
428
update_arch_specs(){
529
# Add contents of given spec file into an array
6-
# 1: array with CPU arch specs
30+
# 1: name of array with CPU arch specs
731
# 2: spec file with the additional specs
832

933
[ -z "$1" ] && echo "[ERROR] update_arch_specs: missing array in argument list" >&2 && exit 1
@@ -20,74 +44,100 @@ update_arch_specs(){
2044

2145
# CPU specification of host system
2246
get_cpuinfo(){
23-
cpuinfo_pattern="^${1}\s*:"
24-
#grep -i "$cpuinfo_pattern" /proc/cpuinfo | tail -n 1 | sed "s/$cpuinfo_pattern//"
25-
grep -i "$cpuinfo_pattern" ${EESSI_PROC_CPUINFO:-/proc/cpuinfo} | tail -n 1 | sed "s/$cpuinfo_pattern//"
47+
# Return the value from cpuinfo for the matching key
48+
# 1: string with key pattern
49+
50+
[ -z "$1" ] && log "ERROR" "get_cpuinfo: missing key pattern in argument list"
51+
cpuinfo_pattern="^${1}\s*:\s*"
52+
53+
# case insensitive match of key pattern and delete key pattern from result
54+
grep -i "$cpuinfo_pattern" ${EESSI_PROC_CPUINFO:-/proc/cpuinfo} | tail -n 1 | sed "s/$cpuinfo_pattern//i"
2655
}
2756

28-
# Find best match
29-
check_flags(){
30-
for flag in "$@"; do
31-
[[ " ${CPU_FLAGS[*]} " == *" $flag "* ]] || return 1
57+
check_allinfirst(){
58+
# Return true if all given arguments after the first are found in the first one
59+
# 1: reference string of space separated values
60+
# 2,3..: each additional argument is a single value to be found in the reference string
61+
62+
[ -z "$1" ] && log "ERROR" "check_allinfirst: missing argument with reference string"
63+
reference="$1"
64+
shift
65+
66+
for candidate in "$@"; do
67+
[[ " $reference " == *" $candidate "* ]] || return 1
3268
done
3369
return 0
3470
}
3571

36-
ARGUMENT=${1:-none}
37-
3872
cpupath(){
39-
# Return the best matching CPU architecture from a list of supported specifications for the host CPU
40-
local CPU_ARCH_SPEC=()
41-
42-
# Identify the host CPU architecture
43-
local MACHINE_TYPE=${EESSI_MACHINE_TYPE:-$(uname -m)}
44-
echo "[INFO] cpupath: Host CPU architecture identified as $MACHINE_TYPE" >&2
45-
46-
# Populate list of supported specs for this architecture
47-
case $MACHINE_TYPE in
48-
"x86_64") local spec_file="eessi_arch_x86.spec";;
49-
"aarch64") local spec_file="eessi_arch_arm.spec";;
50-
"ppc64le") local spec_file="eessi_arch_ppc.spec";;
51-
*) echo "[ERROR] cpupath: Unsupported CPU architecture $MACHINE_TYPE" >&2 && exit 1
52-
esac
53-
# spec files are located in a subfolder with this script
54-
local base_dir=$(dirname $(realpath $0))
55-
update_arch_specs CPU_ARCH_SPEC "$base_dir/arch_specs/${spec_file}"
56-
57-
#CPU_VENDOR_TAG="vendor_id"
58-
CPU_VENDOR_TAG="vendor[ _]id"
59-
CPU_VENDOR=$(get_cpuinfo "$CPU_VENDOR_TAG")
60-
CPU_VENDOR=$(echo ${CPU_VENDOR#*:} | xargs echo -n)
61-
echo "== CPU vendor of host system: $CPU_VENDOR" >&2
62-
63-
CPU_FLAG_TAG='flags'
64-
# cpuinfo systems print different line identifiers, eg features, instead of flags
65-
[ "${CPU_VENDOR}" == "ARM" ] && CPU_FLAG_TAG='flags'
66-
[ "${MACHINE_TYPE}" == "aarch64" ] && [ "${CPU_VENDOR}x" == "x" ] && CPU_FLAG_TAG='features'
67-
[ "${MACHINE_TYPE}" == "ppc64le" ] && CPU_FLAG_TAG='cpu'
68-
69-
CPU_FLAGS=$(get_cpuinfo "$CPU_FLAG_TAG")
70-
echo "== CPU flags of host system: $CPU_FLAGS" >&2
71-
72-
# Default to generic CPU
73-
BEST_MATCH="generic"
74-
75-
for arch in "${CPU_ARCH_SPEC[@]}"; do
76-
eval "arch_spec=$arch"
77-
if [ "${CPU_VENDOR}x" == "${arch_spec[1]}x" ]; then
78-
check_flags ${arch_spec[2]} && BEST_MATCH=${arch_spec[0]}
79-
echo "== got a match with $BEST_MATCH" >&2
80-
fi
81-
done
82-
83-
echo "Best match is $BEST_MATCH" >&2
84-
echo "$BEST_MATCH"
73+
# Identify the best matching CPU architecture from a list of supported specifications for the host CPU
74+
# Return the path to the installation files in EESSI of the best matching architecture
75+
local cpu_arch_spec=()
76+
77+
# Identify the host CPU architecture
78+
local machine_type=${EESSI_MACHINE_TYPE:-$(uname -m)}
79+
log "DEBUG" "cpupath: Host CPU architecture identified as '$machine_type'"
80+
81+
# Populate list of supported specs for this architecture
82+
case $machine_type in
83+
"x86_64") local spec_file="eessi_arch_x86.spec";;
84+
"aarch64") local spec_file="eessi_arch_arm.spec";;
85+
"ppc64le") local spec_file="eessi_arch_ppc.spec";;
86+
*) log "ERROR" "cpupath: Unsupported CPU architecture $machine_type"
87+
esac
88+
# spec files are located in a subfolder with this script
89+
local base_dir=$(dirname $(realpath $0))
90+
update_arch_specs cpu_arch_spec "$base_dir/arch_specs/${spec_file}"
91+
92+
# Identify the host CPU vendor
93+
local cpu_vendor_tag="vendor[ _]id"
94+
local cpu_vendor=$(get_cpuinfo "$cpu_vendor_tag")
95+
log "DEBUG" "cpupath: CPU vendor of host system: '$cpu_vendor'"
96+
97+
# Identify the host CPU flags or features
98+
local cpu_flag_tag='flags'
99+
# cpuinfo systems print different line identifiers, eg features, instead of flags
100+
[ "${cpu_vendor}" == "ARM" ] && cpu_flag_tag='flags'
101+
[ "${machine_type}" == "aarch64" ] && [ "${cpu_vendor}x" == "x" ] && cpu_flag_tag='features'
102+
[ "${machine_type}" == "ppc64le" ] && cpu_flag_tag='cpu'
103+
104+
local cpu_flags=$(get_cpuinfo "$cpu_flag_tag")
105+
log "DEBUG" "cpupath: CPU flags of host system: '$cpu_flags'"
106+
107+
# Default to generic CPU
108+
local best_arch_match="generic"
109+
110+
# Iterate over the supported CPU specifications to find the best match for host CPU
111+
# Order of the specifications matters, the last one to match will be selected
112+
for arch in "${cpu_arch_spec[@]}"; do
113+
eval "arch_spec=$arch"
114+
if [ "${cpu_vendor}x" == "${arch_spec[1]}x" ]; then
115+
# each flag in this CPU specification must be found in the list of flags of the host
116+
check_allinfirst "${cpu_flags[*]}" ${arch_spec[2]} && best_arch_match=${arch_spec[0]} && \
117+
log "DEBUG" "cpupath: host CPU best match updated to $best_arch_match"
118+
fi
119+
done
120+
121+
log "INFO" "cpupath: best match for host CPU: $best_arch_match"
122+
echo "$best_arch_match"
85123
}
86124

87-
if [ ${ARGUMENT} == "none" ]; then
88-
echo usage: $0 cpupath
89-
exit
90-
elif [ ${ARGUMENT} == "cpupath" ]; then
91-
cpupath
92-
exit
93-
fi
125+
# Parse command line arguments
126+
USAGE="Usage: eessi_archdetect.sh [-h][-d] <action>"
127+
128+
while getopts 'hdv' OPTION; do
129+
case "$OPTION" in
130+
h) echo "$USAGE"; exit 0;;
131+
d) LOG_LEVEL="DEBUG";;
132+
v) echo "eessi_archdetect.sh v$VERSION"; exit 0;;
133+
?) echo "$USAGE"; exit 1;;
134+
esac
135+
done
136+
shift "$(($OPTIND -1))"
137+
138+
ARGUMENT=${1:-none}
139+
140+
case "$ARGUMENT" in
141+
"cpupath") cpupath; exit;;
142+
*) echo "$USAGE"; log "ERROR" "Missing <action> argument";;
143+
esac

0 commit comments

Comments
 (0)