X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/c8e8e57d057ac6edd098ffbf11cd661099fc43c2..refs/heads/master:/build_common.sh diff --git a/build_common.sh b/build_common.sh index 50fcc388..ce9349ed 100644 --- a/build_common.sh +++ b/build_common.sh @@ -4,15 +4,14 @@ # To make CI scripts maintenance simpler, copies of this file in the # libpcap, tcpdump and tcpslice git repositories should be identical. # Please mind that Solaris /bin/sh before 11 does not support the $() -# command substitution syntax, hence the SC2006 directives. +# command substitution syntax, hence the "-e SC2006" flag in Makefile. # A poor man's mktemp(1) for OSes that don't have one (e.g. AIX 7, Solaris 9). mktempdir_diy() { while true; do # /bin/sh implements $RANDOM in AIX 7, but not in Solaris before 11, # thus use dd and od instead. - # shellcheck disable=SC2006 - mktempdir_diy_suffix=`dd if=/dev/urandom bs=1 count=4 2>/dev/null | od -t x -A n | head -1 | tr -d '\t '` + mktempdir_diy_suffix=`dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -t x -A n | head -1 | tr -d '\t '` [ -z "$mktempdir_diy_suffix" ] && return 1 mktempdir_diy_path="${TMPDIR:-/tmp}/${1:?}.${mktempdir_diy_suffix}" # "test -e" would be more appropriate, but it is not available in @@ -23,37 +22,30 @@ mktempdir_diy() { echo "$mktempdir_diy_path" break fi - # Try again (AIX /dev/urandom returns zeroes quite often). + # Try again (very unlikely, just in case). done } mktempdir() { mktempdir_prefix=${1:-tmp} - # shellcheck disable=SC2006 - case `uname -s` in - Darwin|FreeBSD|NetBSD) + case `os_id` in + Darwin-*|FreeBSD-*|NetBSD-*) # In these operating systems mktemp(1) always appends an implicit # ".XXXXXXXX" suffix to the requested template when creating a # temporary directory. mktemp -d -t "$mktempdir_prefix" ;; - AIX) - mktempdir_diy "$mktempdir_prefix" + SunOS-5.10|SunOS-5.11) + # Although the suffix is optional, specify it for consistent results. + mktemp -d -t "${mktempdir_prefix}.XXXXXXXX" ;; - SunOS) - # shellcheck disable=SC2006 - case `uname -r` in - 5.10|5.11) - mktemp -d -t "${mktempdir_prefix}.XXXXXXXX" - ;; - *) - mktempdir_diy "$mktempdir_prefix" - ;; - esac + SunOS-*|AIX-*) + mktempdir_diy "$mktempdir_prefix" ;; *) - # At least Linux and OpenBSD implementations require explicit trailing - # X'es in the template, so make it the same suffix as above. + # At least Haiku, Linux and OpenBSD implementations require explicit + # trailing X'es in the template, so make it the same suffix as above. + # XXX - is MSYS2 GNU-based, so that it would be like Linux? mktemp -d -t "${mktempdir_prefix}.XXXXXXXX" ;; esac @@ -61,34 +53,232 @@ mktempdir() { print_sysinfo() { uname -a + printf 'OS identification: ' + os_id date } -print_cc_version() { - # shellcheck disable=SC2006 +# Try to make the current C compiler print its version information (usually +# multi-line) to stdout. +cc_version_nocache() { + : "${CC:?}" case `basename "$CC"` in - gcc*|clang*) + gcc*|egcc*|clang*|tcc*) # GCC and Clang recognize --version, print to stdout and exit with 0. "$CC" --version ;; xl*) - # XL C for AIX recognizes -qversion, prints to stdout and exits with 0, - # but on an unknown command-line flag displays its man page and waits. - "$CC" -qversion + # XL C 12.1 and 13.1 recognize "-qversion", print to stdout and exit + # with 0. XL C 12.1 on an unknown command-line flag displays its man + # page and waits. + # XL C 16.1 recognizes "-qversion" and "--version", prints to stdout + # and exits with 0. Community Edition also prints a banner to stderr. + "$CC" -qversion 2>/dev/null ;; sun*) # Sun compilers recognize -V, print to stderr and exit with an error. "$CC" -V 2>&1 || : ;; + cc) + case `os_id` in + SunOS-*) + # Most likely Sun C. + "$CC" -V 2>&1 || : + ;; + Darwin-*) + # Most likely Clang. + "$CC" --version + ;; + Linux-*|FreeBSD-*|NetBSD-*|OpenBSD-*) + # Most likely Clang or GCC. + "$CC" --version + ;; + esac + ;; + cl) + # Visual Studio's compiler doesn't have a "print the compiler + # version" option, but we can get version information by + # running it with no options, sending its standard error to + # the standard output, and throwing out the usage message; + # as we have MSYS2, we can just "head" it out. + # + # XXX - does it exit with an error? + "$CC" 2>&1 | head -2 + ;; *) "$CC" --version || "$CC" -V || : ;; esac } +cc_version() { + echo "${cc_version_cached:=`cc_version_nocache`}" +} + +print_cc_version() { + cc_version + printf 'Compiler identification: ' + cc_id +} + +# For the current C compiler try to print a short and uniform identification +# string (such as "gcc-9.3.0") that is convenient to use in a case statement. +cc_id_nocache() { + cc_id_firstline=`cc_version | head -1` + : "${cc_id_firstline:?}" + + cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.*clang version \([0-9\.]*\).*$/clang-\1/'` + if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then + echo "$cc_id_guessed" + return + fi + + cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^IBM XL C.*, V\([0-9\.]*\).*$/xlc-\1/'` + if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then + echo "$cc_id_guessed" + return + fi + + cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.* Sun C \([0-9\.]*\) .*$/suncc-\1/'` + if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then + echo "$cc_id_guessed" + return + fi + + cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^Microsoft (R) C\/C++ Optimizing Compiler Version \([0-9\.]*\) .*$/msvc-\1/'` + if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then + echo "$cc_id_guessed" + return + fi + + # Examples of installed packages: + # "tcc version 0.9.27 (x86_64 Linux)" + # "tcc version 0.9.27 2023-07-05 mob@5b28165 (x86_64 OpenBSD)" + # Example of a development version: + # "tcc version 0.9.28rc 2024-04-28 mob@0aca8611 (x86_64 Linux)" + cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.*tcc version \([0-9\.rc]*\).*$/tcc-\1/'` + if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then + echo "$cc_id_guessed" + return + fi + + # OpenBSD default GCC: + # "gcc (GCC) 4.2.1 20070719" + # RedHat GCC: + # "gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)" + # "gcc (GCC) 10.3.1 20210422 (Red Hat 10.3.1-1)" + # other GCC packages: + # "sparc-sun-solaris2.9-gcc (GCC) 4.2.0 (gccfss)" + # "gcc (GCC) 5.5.0" + # "gcc (nb4 20200810) 7.5.0" + # "gcc (OpenIndiana 7.5.0-il-0) 7.5.0" + # "gcc (Debian 8.3.0-6) 8.3.0" + # "gcc (Raspbian 8.3.0-6+rpi1) 8.3.0" + # "egcc (GCC) 8.4.0" + # "gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0" + # "gcc (FreeBSD Ports Collection) 10.3.0" + cc_id_guessed=`echo "$cc_id_firstline" | sed 's/^.* (.*) \([0-9\.]*\).*$/gcc-\1/'` + if [ "$cc_id_firstline" != "$cc_id_guessed" ]; then + echo "$cc_id_guessed" + return + fi +} + +cc_id() { + echo "${cc_id_cached:=`cc_id_nocache`}" +} + +# Call this function each time CC has changed. +discard_cc_cache() { + cc_version_cached= + cc_id_cached= +} + +# For the current C compiler try to print CFLAGS value that tells to treat +# warnings as errors. +cc_werr_cflags() { + case `cc_id` in + gcc-*|clang-*|tcc-*) + echo '-Werror' + ;; + xlc-*) + # XL C 12.1 and 13.1 recognize "-qhalt=w". XL C 16.1 recognizes that + # and "-Werror". + echo '-qhalt=w' + ;; + suncc-*) + # GCC and Clang print an identification for every warning, which is + # useful for root cause analysis and bug fixing. Sun C does not do it + # by default, but an additional option makes the style more consistent. + echo '-errwarn=%all -errtags=yes' + ;; + msvc-*) + # XXX - what? + echo '' + ;; + esac +} + +# Tell whether "gcc" is a symlink to Clang (this is the case on macOS). +gcc_is_clang_in_disguise() { + case `cc_id`/`basename "${CC:?}"` in + clang-*/gcc) + return 0 + ;; + esac + return 1 +} + +os_id() { + # OS does not change between builds or in the middle of a build, so it is + # fine to cache uname output. + : "${os_id_sysname:=`uname -s`}" + printf '%s-' "$os_id_sysname" + : "${os_id_release:=`uname -r`}" + case "$os_id_sysname" in + AIX) + : "${os_id_version:=`uname -v`}" + echo "${os_id_version}.${os_id_release}" + ;; + Darwin|GNU|OpenBSD|SunOS) + echo "$os_id_release" + ;; + FreeBSD|NetBSD|Linux) + # Meaningful version is usually the substring before the first dash. + # Or the first underscore. + echo "$os_id_release" | sed 's/^\([0-9\.]*\).*$/\1/' + ;; + Haiku) + # The complete version is a substring before the first space, e.g.: + # * "hrevNNNNN" for a release without updates, e.g. hrev56578 for + # R1/beta4, also for a clean build of master branch; + # * "hrevNNNNN+MM" for a release with updates; + # * "hrevNNNNN-MM" for a build of a branch that is ahead of the master + # branch; + # * "hrevNNNNN_MMMM_KK" for a CI build of a Gerrit review; + # * something else for a build of a working copy with the changes not + # yet committed. + # With this system it is not clear which version components would be + # meaningful to relate with the build result, so let's return the + # complete version and leave any interpretation to the user. + : "${os_id_version:=`uname -v`}" + echo "$os_id_version" | sed -E 's/^(hrev[^ ]+).+$/\1/' + ;; + MSYS*) + # uname -s produces "MSYS_NT-{NT version?}-{build?} + # uname -r produces MSYS2 version? + echo "$os_id_version", MSYS "$os_id_release" + ;; + *) + echo 'UNKNOWN' + ;; + esac +} + increment() { # No arithmetic expansion in Solaris /bin/sh before 11. - echo "${1:?} + 1" | bc + # shellcheck disable=SC2003 + expr "${1:?}" + 1 } # Display text in magenta. @@ -105,11 +295,16 @@ run_after_echo() { } print_so_deps() { - # shellcheck disable=SC2006 - case `uname -s` in - Darwin) + case `os_id` in + Darwin-*) run_after_echo otool -L "${1:?}" ;; + Haiku-*) + run_after_echo objdump -p "${1:?}" + ;; + MSYS*) + run_after_echo dumpbin /dependents "${1:?}" + ;; *) run_after_echo ldd "${1:?}" ;; @@ -130,8 +325,7 @@ handle_matrix_debug() { } purge_directory() { - # shellcheck disable=SC2006 - if [ "`uname -s`" = SunOS ] && [ "`uname -r`" = 5.11 ]; then + if [ "`os_id`" = SunOS-5.11 ]; then # In Solaris 11 /bin/sh the pathname expansion of "*" always includes # "." and "..", so the straightforward rm would always fail. (