changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > infra / check.sh

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