1#!/bin/sh -e 2 3# The only purpose of the above shebang is to orient shellcheck right. 4# To make CI scripts maintenance simpler, copies of this file in the 5# libpcap, tcpdump and tcpslice git repositories should be identical. 6# Please mind that Solaris /bin/sh before 11 does not support the $() 7# command substitution syntax, hence the "-e SC2006" flag in Makefile. 8 9# A poor man's mktemp(1) for OSes that don't have one (e.g. AIX 7, Solaris 9). 10mktempdir_diy() { 11 while true; do 12 # /bin/sh implements $RANDOM in AIX 7, but not in Solaris before 11, 13 # thus use dd and od instead. 14 mktempdir_diy_suffix=`dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -t x -A n | head -1 | tr -d '\t '` 15 [ -z "$mktempdir_diy_suffix" ] && return 1 16 mktempdir_diy_path="${TMPDIR:-/tmp}/${1:?}.${mktempdir_diy_suffix}" 17 # "test -e" would be more appropriate, but it is not available in 18 # Solaris /bin/sh before 11. 19 if [ ! -d "$mktempdir_diy_path" ]; then 20 mkdir "$mktempdir_diy_path" 21 chmod go= "$mktempdir_diy_path" 22 echo "$mktempdir_diy_path" 23 break 24 fi 25 # Try again (very unlikely, just in case). 26 done 27} 28 29mktempdir() { 30 mktempdir_prefix=${1:-tmp} 31 case `os_id` in 32 Darwin-*|FreeBSD-*|NetBSD-*) 33 # In these operating systems mktemp(1) always appends an implicit 34 # ".XXXXXXXX" suffix to the requested template when creating a 35 # temporary directory. 36 mktemp -d -t "$mktempdir_prefix" 37 ;; 38 SunOS-5.10|SunOS-5.11) 39 # Although the suffix is optional, specify it for consistent results. 40 mktemp -d -t "${mktempdir_prefix}.XXXXXXXX" 41 ;; 42 SunOS-*|AIX-*) 43 mktempdir_diy "$mktempdir_prefix" 44 ;; 45 *) 46 # At least Haiku, Linux and OpenBSD implementations require explicit 47 # trailing X'es in the template, so make it the same suffix as above. 48 # XXX - is MSYS2 GNU-based, so that it would be like Linux? 49 mktemp -d -t "${mktempdir_prefix}.XXXXXXXX" 50 ;; 51 esac 52} 53 54print_sysinfo() { 55 uname -a 56 printf 'OS identification: ' 57 os_id 58 date 59} 60 61# Try to make the current C compiler print its version information (usually 62# multi-line) to stdout. 63cc_version_nocache() { 64 : "${CC:?}" 65 case `basename "$CC"` in 66 gcc*|egcc*|clang*|tcc*) 67 # GCC and Clang recognize --version, print to stdout and exit with 0. 68 "$CC" --version 69 ;; 70 xl*) 71 # XL C 12.1 and 13.1 recognize "-qversion", print to stdout and exit 72 # with 0. XL C 12.1 on an unknown command-line flag displays its man 73 # page and waits. 74 # XL C 16.1 recognizes "-qversion" and "--version", prints to stdout 75 # and exits with 0. Community Edition also prints a banner to stderr. 76 "$CC" -qversion 2>/dev/null 77 ;; 78 sun*) 79 # Sun compilers recognize -V, print to stderr and exit with an error. 80 "$CC" -V 2>&1 || : 81 ;; 82 cc) 83 case `os_id` in 84 SunOS-*) 85 # Most likely Sun C. 86 "$CC" -V 2>&1 || : 87 ;; 88 Darwin-*) 89 # Most likely Clang. 90 "$CC" --version 91 ;; 92 Linux-*|FreeBSD-*|NetBSD-*|OpenBSD-*) 93 # Most likely Clang or GCC. 94 "$CC" --version 95 ;; 96 esac 97 ;; 98 cl) 99 # Visual Studio's compiler doesn't have a "print the compiler 100 # version" option, but we can get version information by 101 # running it with no options, sending its standard error to 102 # the standard output, and throwing out the usage message; 103 # as we have MSYS2, we can just "head" it out. 104 # 105 # XXX - does it exit with an error? 106 "$CC" 2>&1 | head -2 107 ;; 108 *) 109 "$CC" --version || "$CC" -V || : 110 ;; 111 esac 112} 113 114cc_version() { 115 echo "${cc_version_cached:=`cc_version_nocache`}" 116} 117 118print_cc_version() { 119 cc_version 120 printf 'Compiler identification: ' 121 cc_id 122} 123 124# For the current C compiler try to print a short and uniform identification 125# string (such as "gcc-9.3.0") that is convenient to use in a case statement. 126cc_id_nocache() { 127 cc_id_firstline=`cc_version | head -1` 128 : "${cc_id_firstline:?}" 129 130 cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.*clang version \([0-9\.]*\).*$/clang-\1/'` 131 if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then 132 echo "$cc_id_guessed" 133 return 134 fi 135 136 cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^IBM XL C.*, V\([0-9\.]*\).*$/xlc-\1/'` 137 if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then 138 echo "$cc_id_guessed" 139 return 140 fi 141 142 cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.* Sun C \([0-9\.]*\) .*$/suncc-\1/'` 143 if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then 144 echo "$cc_id_guessed" 145 return 146 fi 147 148 cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^Microsoft (R) C\/C++ Optimizing Compiler Version \([0-9\.]*\) .*$/msvc-\1/'` 149 if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then 150 echo "$cc_id_guessed" 151 return 152 fi 153 154 # Examples of installed packages: 155 # "tcc version 0.9.27 (x86_64 Linux)" 156 # "tcc version 0.9.27 2023-07-05 mob@5b28165 (x86_64 OpenBSD)" 157 # Example of a development version: 158 # "tcc version 0.9.28rc 2024-04-28 mob@0aca8611 (x86_64 Linux)" 159 cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.*tcc version \([0-9\.rc]*\).*$/tcc-\1/'` 160 if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then 161 echo "$cc_id_guessed" 162 return 163 fi 164 165 # OpenBSD default GCC: 166 # "gcc (GCC) 4.2.1 20070719" 167 # RedHat GCC: 168 # "gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)" 169 # "gcc (GCC) 10.3.1 20210422 (Red Hat 10.3.1-1)" 170 # other GCC packages: 171 # "sparc-sun-solaris2.9-gcc (GCC) 4.2.0 (gccfss)" 172 # "gcc (GCC) 5.5.0" 173 # "gcc (nb4 20200810) 7.5.0" 174 # "gcc (OpenIndiana 7.5.0-il-0) 7.5.0" 175 # "gcc (Debian 8.3.0-6) 8.3.0" 176 # "gcc (Raspbian 8.3.0-6+rpi1) 8.3.0" 177 # "egcc (GCC) 8.4.0" 178 # "gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0" 179 # "gcc (FreeBSD Ports Collection) 10.3.0" 180 cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.* (.*) \([0-9\.]*\).*$/gcc-\1/'` 181 if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then 182 echo "$cc_id_guessed" 183 return 184 fi 185} 186 187cc_id() { 188 echo "${cc_id_cached:=`cc_id_nocache`}" 189} 190 191# Call this function each time CC has changed. 192discard_cc_cache() { 193 cc_version_cached= 194 cc_id_cached= 195} 196 197# For the current C compiler try to print CFLAGS value that tells to treat 198# warnings as errors. 199cc_werr_cflags() { 200 case `cc_id` in 201 gcc-*|clang-*|tcc-*) 202 echo '-Werror' 203 ;; 204 xlc-*) 205 # XL C 12.1 and 13.1 recognize "-qhalt=w". XL C 16.1 recognizes that 206 # and "-Werror". 207 echo '-qhalt=w' 208 ;; 209 suncc-*) 210 # GCC and Clang print an identification for every warning, which is 211 # useful for root cause analysis and bug fixing. Sun C does not do it 212 # by default, but an additional option makes the style more consistent. 213 echo '-errwarn=%all -errtags=yes' 214 ;; 215 msvc-*) 216 # XXX - what? 217 echo '' 218 ;; 219 esac 220} 221 222# Tell whether "gcc" is a symlink to Clang (this is the case on macOS). 223gcc_is_clang_in_disguise() { 224 case `cc_id`/`basename "${CC:?}"` in 225 clang-*/gcc) 226 return 0 227 ;; 228 esac 229 return 1 230} 231 232os_id() { 233 # OS does not change between builds or in the middle of a build, so it is 234 # fine to cache uname output. 235 : "${os_id_sysname:=`uname -s`}" 236 printf '%s-' "$os_id_sysname" 237 : "${os_id_release:=`uname -r`}" 238 case "$os_id_sysname" in 239 AIX) 240 : "${os_id_version:=`uname -v`}" 241 echo "${os_id_version}.${os_id_release}" 242 ;; 243 Darwin|GNU|OpenBSD|SunOS) 244 echo "$os_id_release" 245 ;; 246 FreeBSD|NetBSD|Linux) 247 # Meaningful version is usually the substring before the first dash. 248 # Or the first underscore. 249 echo "$os_id_release" | sed 's/^\([0-9\.]*\).*$/\1/' 250 ;; 251 Haiku) 252 # The complete version is a substring before the first space, e.g.: 253 # * "hrevNNNNN" for a release without updates, e.g. hrev56578 for 254 # R1/beta4, also for a clean build of master branch; 255 # * "hrevNNNNN+MM" for a release with updates; 256 # * "hrevNNNNN-MM" for a build of a branch that is ahead of the master 257 # branch; 258 # * "hrevNNNNN_MMMM_KK" for a CI build of a Gerrit review; 259 # * something else for a build of a working copy with the changes not 260 # yet committed. 261 # With this system it is not clear which version components would be 262 # meaningful to relate with the build result, so let's return the 263 # complete version and leave any interpretation to the user. 264 : "${os_id_version:=`uname -v`}" 265 echo "$os_id_version" | sed -E 's/^(hrev[^ ]+).+$/\1/' 266 ;; 267 MSYS*) 268 # uname -s produces "MSYS_NT-{NT version?}-{build?} 269 # uname -r produces MSYS2 version? 270 echo "$os_id_version", MSYS "$os_id_release" 271 ;; 272 *) 273 echo 'UNKNOWN' 274 ;; 275 esac 276} 277 278increment() { 279 # No arithmetic expansion in Solaris /bin/sh before 11. 280 # shellcheck disable=SC2003 281 expr "${1:?}" + 1 282} 283 284# Display text in magenta. 285echo_magenta() { 286 # ANSI magenta, the imploded text, ANSI reset, newline. 287 printf '\033[35;1m%s\033[0m\n' "$*" 288} 289 290# Run a command after displaying it. 291run_after_echo() { 292 : "${1:?}" # Require at least one argument. 293 printf '$ %s\n' "$*" 294 "$@" 295} 296 297print_so_deps() { 298 case `os_id` in 299 Darwin-*) 300 run_after_echo otool -L "${1:?}" 301 ;; 302 Haiku-*) 303 run_after_echo objdump -p "${1:?}" 304 ;; 305 MSYS*) 306 run_after_echo dumpbin /dependents "${1:?}" 307 ;; 308 *) 309 run_after_echo ldd "${1:?}" 310 ;; 311 esac 312} 313 314# Beware that setting MATRIX_DEBUG for tcpdump or tcpslice will produce A LOT 315# of additional output there and in any nested libpcap builds. Multiplied by 316# the matrix size, the full output log size might exceed limits of some CI 317# systems (as it had previously happened with Travis CI). Use with caution on 318# a reduced matrix. 319handle_matrix_debug() { 320 [ "$MATRIX_DEBUG" != yes ] && return 321 echo '$ cat Makefile [...]' 322 sed '/^# DO NOT DELETE THIS LINE -- mkdep uses it.$/q' <Makefile 323 run_after_echo cat config.h 324 [ "$CMAKE" = yes ] || run_after_echo cat config.log 325} 326 327purge_directory() { 328 if [ "`os_id`" = SunOS-5.11 ]; then 329 # In Solaris 11 /bin/sh the pathname expansion of "*" always includes 330 # "." and "..", so the straightforward rm would always fail. 331 ( 332 cd "${1:?}" 333 for pd_each in *; do 334 if [ "$pd_each" != . ] && [ "$pd_each" != .. ]; then 335 rm -rf "$pd_each" 336 fi 337 done 338 ) 339 else 340 rm -rf "${1:?}"/* 341 fi 342} 343 344# vi: set tabstop=4 softtabstop=0 expandtab shiftwidth=4 smarttab autoindent : 345