changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > infra / check.sh

changeset 213: a7129c8e52d1
parent: 91cb7ffc5945
child: 98abb7f50885
author: Richard Westhaver <ellis@rwest.io>
date: Tue, 30 Apr 2024 19:14:48 -0400
permissions: -rwxr-xr-x
description: profiles, host.sxp
1 #!/usr/bin/env sh
2 set -eu
3 main() {
4  need_cmd uname
5  need_cmd mktemp
6  need_cmd chmod
7  need_cmd mkdir
8  need_cmd rm
9  need_cmd rmdir
10  need_cmd tar
11  need_cmd zstd
12  need_cmd hg
13  need_cmd git
14  need_cmd clang
15  need_cmd grep
16  need_cmd awk
17  need_cmd head
18  need_cmd tail
19  host_config_file=host.sxp
20  rm $host_config_file
21  check_mem
22  check_disk
23  check_mod kvm
24  get_architecture || return 1
25  local _arch="$RETVAL"
26  assert_nz "$_arch" "arch"
27  _write ";; -*- mode:skel -*-"
28  _write ":arch \"$_arch\""
29  kernel_version
30  local _kernel_version="$RETVAL"
31  _write ":kernel \"$_kernel_version\""
32  check_cpus
33  local _num_cpus="$RETVAL"
34  _write ":cpus $_num_cpus"
35  case "$_arch" in
36  *windows*)
37  _write ":ext \"exe\""
38  ;;
39  *)
40  _write ":ext nil"
41  esac
42 }
43 
44 say() {
45  printf '%s\n' "$1"
46 }
47 
48 _write() {
49  say "$1" >> $host_config_file
50 }
51 
52 err() {
53  say "$1" >&2
54  exit 1
55 }
56 
57 assert_nz() {
58  if [ -z "$1" ]; then err "assert_nz $2"; fi
59 }
60 
61 check_cmd() {
62  command -v "$1" > /dev/null 2>&1
63 }
64 
65 need_cmd() {
66  if ! check_cmd "$1"; then
67  err "need '$1' (command not found)"
68  fi
69 }
70 
71 ensure() {
72  if ! "$@"; then err "command failed: $*"; fi
73 }
74 
75 check_proc() {
76  # Check for /proc by looking for the /proc/self/exe link
77  # This is only run on Linux
78  if ! test -L /proc/self/exe ; then
79  err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc."
80  fi
81 }
82 
83 get_bitness() {
84  # Architecture detection without dependencies beyond coreutils.
85  # ELF files start out "\x7fELF", and the following byte is
86  # 0x01 for 32-bit and
87  # 0x02 for 64-bit.
88  # The printf builtin on some shells like dash only supports octal
89  # escape sequences, so we use those.
90  local _current_exe_head
91  _current_exe_head=$(head -c 5 /proc/self/exe )
92  if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
93  echo 32
94  elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
95  echo 64
96  else
97  err "unknown platform bitness"
98  fi
99 }
100 
101 is_host_amd64_elf() {
102  # ELF e_machine detection without dependencies beyond coreutils.
103  # Two-byte field at offset 0x12 indicates the CPU,
104  # but we're interested in it being 0x3E to indicate amd64, or not that.
105  local _current_exe_machine
106  _current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1)
107  [ "$_current_exe_machine" = "$(printf '\076')" ]
108 }
109 
110 get_endianness() {
111  local cputype=$1
112  local suffix_eb=$2
113  local suffix_el=$3
114 
115  # detect endianness without od/hexdump, like get_bitness() does.
116  local _current_exe_endianness
117  _current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)"
118  if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
119  echo "${cputype}${suffix_el}"
120  elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
121  echo "${cputype}${suffix_eb}"
122  else
123  err "unknown platform endianness"
124  fi
125 }
126 
127 get_architecture() {
128  local _ostype _cputype _bitness _arch _clibtype
129  _ostype="$(uname -s)"
130  _cputype="$(uname -m)"
131  _clibtype="gnu"
132 
133  if [ "$_ostype" = Linux ]; then
134  if [ "$(uname -o)" = Android ]; then
135  _ostype=Android
136  fi
137  if ldd --version 2>&1 | grep -q 'musl'; then
138  _clibtype="musl"
139  fi
140  fi
141 
142  if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then
143  # Darwin `uname -m` lies
144  if sysctl hw.optional.x86_64 | grep -q ': 1'; then
145  _cputype=x86_64
146  fi
147  fi
148 
149  if [ "$_ostype" = SunOS ]; then
150  # Both Solaris and illumos presently announce as "SunOS" in "uname -s"
151  # so use "uname -o" to disambiguate. We use the full path to the
152  # system uname in case the user has coreutils uname first in PATH,
153  # which has historically sometimes printed the wrong value here.
154  if [ "$(/usr/bin/uname -o)" = illumos ]; then
155  _ostype=illumos
156  fi
157 
158  # illumos systems have multi-arch userlands, and "uname -m" reports the
159  # machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86
160  # systems. Check for the native (widest) instruction set on the
161  # running kernel:
162  if [ "$_cputype" = i86pc ]; then
163  _cputype="$(isainfo -n)"
164  fi
165  fi
166 
167  case "$_ostype" in
168 
169  Android)
170  _ostype=linux-android
171  ;;
172 
173  Linux)
174  check_proc
175  _ostype=unknown-linux-$_clibtype
176  _bitness=$(get_bitness)
177  ;;
178 
179  FreeBSD)
180  _ostype=unknown-freebsd
181  ;;
182 
183  NetBSD)
184  _ostype=unknown-netbsd
185  ;;
186 
187  DragonFly)
188  _ostype=unknown-dragonfly
189  ;;
190 
191  Darwin)
192  _ostype=apple-darwin
193  ;;
194 
195  illumos)
196  _ostype=unknown-illumos
197  ;;
198 
199  MINGW* | MSYS* | CYGWIN* | Windows_NT)
200  _ostype=pc-windows-gnu
201  ;;
202 
203  *)
204  err "unrecognized OS type: $_ostype"
205  ;;
206 
207  esac
208 
209  case "$_cputype" in
210 
211  i386 | i486 | i686 | i786 | x86)
212  _cputype=i686
213  ;;
214 
215  xscale | arm)
216  _cputype=arm
217  if [ "$_ostype" = "linux-android" ]; then
218  _ostype=linux-androideabi
219  fi
220  ;;
221 
222  armv6l)
223  _cputype=arm
224  if [ "$_ostype" = "linux-android" ]; then
225  _ostype=linux-androideabi
226  else
227  _ostype="${_ostype}eabihf"
228  fi
229  ;;
230 
231  armv7l | armv8l)
232  _cputype=armv7
233  if [ "$_ostype" = "linux-android" ]; then
234  _ostype=linux-androideabi
235  else
236  _ostype="${_ostype}eabihf"
237  fi
238  ;;
239 
240  aarch64 | arm64)
241  _cputype=aarch64
242  ;;
243 
244  x86_64 | x86-64 | x64 | amd64)
245  _cputype=x86_64
246  ;;
247 
248  mips)
249  _cputype=$(get_endianness mips '' el)
250  ;;
251 
252  mips64)
253  if [ "$_bitness" -eq 64 ]; then
254  # only n64 ABI is supported for now
255  _ostype="${_ostype}abi64"
256  _cputype=$(get_endianness mips64 '' el)
257  fi
258  ;;
259 
260  ppc)
261  _cputype=powerpc
262  ;;
263 
264  ppc64)
265  _cputype=powerpc64
266  ;;
267 
268  ppc64le)
269  _cputype=powerpc64le
270  ;;
271 
272  s390x)
273  _cputype=s390x
274  ;;
275  riscv64)
276  _cputype=riscv64gc
277  ;;
278  loongarch64)
279  _cputype=loongarch64
280  ;;
281  *)
282  err "unknown CPU type: $_cputype"
283 
284  esac
285 
286  # Detect 64-bit linux with 32-bit userland
287  if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then
288  case $_cputype in
289  x86_64)
290  if [ -n "${CPUTYPE:-}" ]; then
291  _cputype="$CPUTYPE"
292  else {
293  # 32-bit executable for amd64 = x32
294  if is_host_amd64_elf; then {
295  echo "This host is running an x32 userland; as it stands, x32 support is poor," 1>&2
296  echo "and there isn't a native toolchain -- you will have to install" 1>&2
297  echo "multiarch compatibility with i686 and/or amd64, then select one" 1>&2
298  echo "by re-running this script with the CPUTYPE environment variable" 1>&2
299  echo "set to i686 or x86_64, respectively." 1>&2
300  exit 1
301  }; else
302  _cputype=i686
303  fi
304  }; fi
305  ;;
306  mips64)
307  _cputype=$(get_endianness mips '' el)
308  ;;
309  powerpc64)
310  _cputype=powerpc
311  ;;
312  aarch64)
313  _cputype=armv7
314  if [ "$_ostype" = "linux-android" ]; then
315  _ostype=linux-androideabi
316  else
317  _ostype="${_ostype}eabihf"
318  fi
319  ;;
320  riscv64gc)
321  err "riscv64 with 32-bit userland unsupported"
322  ;;
323  esac
324  fi
325 
326  if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then
327  if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then
328  # At least one processor does not have NEON.
329  _cputype=arm
330  fi
331  fi
332 
333  _arch="${_cputype}-${_ostype}"
334 
335  RETVAL="$_arch"
336 }
337 
338 mem_total () {
339  local _mem_total
340  _mem_total=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
341  RETVAL="$_mem_total"
342 }
343 
344 check_mem () {
345  mem_total
346  local _mem_total="$RETVAL"
347  local _mem_min=8388608 # 8Gb in kB
348  if [ "$_mem_total" -lt "$_mem_min" ]; then
349  err "not enough memory: $_mem_total < $_mem_min";
350  fi
351 }
352 
353 disk_free () {
354  local _disk_free
355  _disk_free=$(df -kh . | tail -n1 | awk '{print $4}')
356  RETVAL="${_disk_free%?}"
357 }
358 
359 check_disk () {
360  disk_free
361  local _disk_free="$RETVAL"
362  local _disk_min=32 # in Gigabytes
363  if [ "$_disk_free" -lt "$_disk_min" ]; then
364  err "not enough disk space: $_disk_free < $_disk_min"
365  fi
366 }
367 
368 kernel_version () {
369  local _kernel_version
370  _kernel_version=$(uname -r)
371  RETVAL="$_kernel_version"
372 }
373 
374 check_mod () {
375  if ! lsmod | grep -wq "$1"; then
376  err "kernel module $1 isn't loaded"
377  fi
378 }
379 
380 num_cpus () {
381  local _num_cpus
382  _num_cpus=$(grep -c '^processor' /proc/cpuinfo 2>/dev/null)
383  RETVAL="$_num_cpus"
384  # sysctl -n hw.ncpu # nproc --all
385 }
386 
387 check_cpus () {
388  num_cpus
389  local _num_cpus="$RETVAL"
390  local _min_cpus=8
391  if [ "$_num_cpus" -lt "$_min_cpus" ]; then
392  err "not enough cpu threads ($_num_cpus < $_min_cpus)"
393  fi
394 }
395 
396 main "$@" || exit 1