From b846f2b6a6b41b880785dac0eb5963dcb79ca888 Mon Sep 17 00:00:00 2001 From: Rob Davies Date: Fri, 24 Apr 2026 12:24:11 +0100 Subject: [PATCH] Add Github actions builds for Linux and Mac OS As Cirrus CI is closing down, tests need to migrate elsewhere. As Windows tests already run using Github actions, using it for Linux and Mac OS builds is the easiest solution. Adds Github actions workflows for Linux (specifically ubuntu as it's the only flavour supported natively), and Mac OS. Updates actions/checkout on the Windows build to the latest release. The reference to it is also changed from a tag name to a sha hash to reduce the risk of supply-chain attack. Adjusts HTS_PROG_CC_WARNINGS and HTS_PROG_CC_WERROR to remove a directory left behind by the Mac OS compiler, and to redirect compiler messages to the log file. Remove quotes around $CC invocations in HTS_PROG_CC_WARNINGS and HTS_PROG_CC_WERROR. AC_PROG_CC may add flags after the C compiler path to $CC, so it needs to be used unquoted so that field splitting can be done on the value. Makes test_hfile_libcurl work when --enable-plugins is used. --- .github/workflows/linux-build.yml | 132 ++++++++++++++++++++++++++++ .github/workflows/macos-build.yml | 117 ++++++++++++++++++++++++ .github/workflows/windows-build.yml | 6 +- Makefile | 6 +- m4/hts_prog_cc_warnings.m4 | 46 +++++----- 5 files changed, 282 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/linux-build.yml create mode 100644 .github/workflows/macos-build.yml diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml new file mode 100644 index 000000000..d2cf424ec --- /dev/null +++ b/.github/workflows/linux-build.yml @@ -0,0 +1,132 @@ +# Linux builds +name: linux CI +on: [push, pull_request] + +jobs: + build-ubuntu: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Fully declare each matrix entry here, as otherwise it's possible + # to get unexpected results due to the way the entries get expanded + # (See https://magmanu.github.io/blog/tech/matrices-github-actions/) + include: + # x86-64, clang, configure, libdeflate + - os: ubuntu-latest + use-configure: use-configure + compiler: clang + use-libdeflate: use-libdeflate + sanitize: no-sanitize + run-extra-checks: no-extra-checks + + # x86-64, gcc, configure, libdeflate, sanitize + - os: ubuntu-latest + use-configure: use-configure + compiler: gcc + use-libdeflate: use-libdeflate + sanitize: sanitize + run-extra-checks: no-extra-checks + + # x86-64, gcc, no configure, run extra checks + - os: ubuntu-latest + use-configure: no-configure + compiler: gcc + use-libdeflate: use-libdeflate + sanitize: no-sanitize + run-extra-checks: run-extra-checks + + # arm, gcc, configure, libdeflate + - os: ubuntu-24.04-arm + use-configure: use-configure + compiler: gcc + use-libdeflate: use-libdeflate + sanitize: no-sanitize + run-extra-checks: no-extra-checks + + # x86-64, gcc, configure, zlib only, sanitize + - os: ubuntu-latest + use-configure: use-configure + compiler: gcc + use-libdeflate: no-libdeflate + sanitize: sanitize + run-extra-checks: no-extra-checks + + env: + UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1 + + steps: + - name: Checkout + # This is actions/checkout@v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + submodules: true + persist-credentials: false + + # Linux (ubuntu-latest) build + - name: Run apt + run: | + autoconf_pkgs="" + deflate_pkgs="" + if [ '${{ matrix.use-configure }}' = 'use-configure' ] ; then + autoconf_pkgs="autoconf automake" + fi + if [ '${{ matrix.use-libdeflate }}' = 'use-libdeflate' ] ; then + deflate_pkgs="libdeflate-dev" + fi + sudo apt-get update + sudo apt-get install -y --no-install-suggests --no-install-recommends $autoconf_pkgs make ${{ matrix.compiler }} perl zlib1g-dev libbz2-dev liblzma-dev libcurl4-gnutls-dev libssl-dev $deflate_pkgs + + - name: Configure + if: ${{ matrix.use-configure == 'use-configure' }} + run: | + autoreconf -i + + # Select configure options + + libdeflate_opt='--without-libdeflate' + if [ '${{ matrix.use-libdeflate }}' = 'use-libdeflate' ] ; then + libdeflate_opt='--with-libdeflate' + fi + + config_opts='--enable-werror --enable-plugins' + cc='${{ matrix.compiler }}' + cflags='-g -O3 -std=c99 -pedantic' + ldflags='' + + if [ '${{ matrix.sanitize }}' = 'sanitize' ] ; then + config_opts='--enable-werror' + cflags='-g -Og -fsanitize=address,undefined -DHTS_ALLOW_UNALIGNED=0 -Wno-format-truncation -Wno-format-overflow' + ldflags='-fsanitize=address,undefined' + fi + + # Run configure, and ensure that it did set -Werror + + printf "\nRunning ./configure $config_opts ${libdeflate_opt}${cc:+ CC='$cc'}${cflags:+ CFLAGS='$cflags'}${ldflags:+ LDFLAGS='$ldflags'} ...\n\n" + + { ./configure $config_opts $libdeflate_opt ${cc:+CC="$cc"} ${cflags:+CFLAGS="$cflags"} ${ldflags:+LDFLAGS="$ldflags"} && + { grep -qE 'CFLAGS *=.*-Werror' config.mk || + { printf "\nStopping as -Werror was not set.\n" 1>&2 ; false ; } ; + } ; + } || { printf "\n### config.log content follows...\n\n" 1>&2 ; cat config.log ; false ; } + + - name: Compile + run: | + if [ '${{ matrix.use-configure }}' = 'use-configure' ] ; then + make -j5 + else + make -j5 CFLAGS='-g -O3 -Wall -Werror' + fi + + - name: Check + run: | + if [ '${{ matrix.use-configure }}' = 'use-configure' ] ; then + make check + else + make check CFLAGS='-g -O3 -Wall -Werror' + fi + + - name: Extra checks + if: ${{ matrix.run-extra-checks == 'run-extra-checks' }} + run: | + make test-shlib-exports check-untracked maintainer-check diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml new file mode 100644 index 000000000..ab770ac06 --- /dev/null +++ b/.github/workflows/macos-build.yml @@ -0,0 +1,117 @@ +# Mac OS builds +name: Mac CI +on: [push, pull_request] + +jobs: + build-macos: + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + # Fully declare each matrix entry here, as otherwise it's possible + # to get unexpected results due to the way the entries get expanded + # (See https://magmanu.github.io/blog/tech/matrices-github-actions/) + include: + # configure + - use-configure: use-configure + sanitize: no-sanitize + use-libdeflate: use-libdeflate + + # make only + - use-configure: no-configure + sanitize: no-sanitize + use-libdeflate: no-libdeflate + + # configure, sanitize + - use-configure: use-configure + sanitize: sanitize + use-libdeflate: use-libdeflate + + defaults: + run: + working-directory: ./htslib + + steps: + - name: Checkout + # This is actions/checkout@v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + submodules: true + persist-credentials: false + path: htslib + + # Checkout / build libdeflate if required. Unfortunately brew + # does not make fat binaries, so we have to build from source + - name: Checkout libdeflate + if: ${{ matrix.use-libdeflate == 'use-libdeflate' }} + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + repository: ebiggers/libdeflate + # Version 1.25 + ref: c8c56a20f8f621e6a966b716b31f1dedab6a41e3 + persist-credentials: false + path: libdeflate + + - name: Build libdeflate + if: ${{ matrix.use-libdeflate == 'use-libdeflate' }} + working-directory: ./libdeflate + run: | + cmake -B build -DLIBDEFLATE_BUILD_SHARED_LIB=OFF -DLIBDEFLATE_BUILD_GZIP=OFF -DCMAKE_C_FLAGS="-g -O3 -fPIC -arch arm64 -arch x86_64" + cmake --build build --verbose + + # MacOS. We validate compilation of x86_64 and arm64, but only + # test arm64. This will also be using clang by default + - name: configure + if: ${{ matrix.use-configure == 'use-configure'}} + run: | + # Get an up to date autoreconf, and run it + + brew install autoconf automake libtool + + autoreconf -i + + # Select configure options + + libdeflate_prefix='' + libdeflate_opt='--without-libdeflate' + if [ '${{ matrix.use-libdeflate }}' = 'use-libdeflate' ] ; then + libdeflate_opt='--with-libdeflate' + libdeflate_prefix="../libdeflate" + fi + + config_opts='--enable-werror --enable-plugins' + cc='clang' + cflags="-g -O3 -arch arm64 -arch x86_64${libdeflate_prefix:+ -I$libdeflate_prefix}" + ldflags="${libdeflate_prefix:+ -L$libdeflate_prefix/build}" + + if [ '${{ matrix.sanitize }}' = 'sanitize' ] ; then + config_opts='--enable-werror' + cflags="-g -Og -fsanitize=address,undefined -Wno-format-truncation -Wno-format-overflow -arch arm64 -arch x86_64 -DHTS_ALLOW_UNALIGNED=0${libdeflate_prefix:+ -I$libdeflate_prefix}" + ldflags="-fsanitize=address,undefined${libdeflate_prefix:+ -L$libdeflate_prefix/build}" + fi + + # Run configure, and ensure that it did set -Werror + + printf "\nRunning ./configure ${config_opts} ${libdeflate_opt}${cc:+ CC='$cc'}${cflags:+ CFLAGS='$cflags'}${ldflags:+ LDFLAGS='$ldflags'} ...\n\n" + + { ./configure $config_opts $libdeflate_opt ${cc:+CC="$cc"} ${cflags:+CFLAGS="$cflags"} ${ldflags:+LDFLAGS="$ldflags"} && + { grep -qE 'CFLAGS *=.*-Werror' config.mk || + { printf "\nStopping as -Werror was not set.\n" 1>&2 ; false ; } ; + } ; + } || { printf "\n### config.log content follows...\n\n" 1>&2 ; cat config.log ; false ; } + + - name: Compile + run: | + if [ '${{ matrix.use-configure }}' = 'use-configure' ] ; then + make -j5 + else + make -j5 CC=clang CFLAGS='-g -O3 -Wall -Werror' + fi + + - name: Check + run: | + if [ '${{ matrix.use-configure }}' = 'use-configure' ] ; then + make check + else + make check CC=clang CFLAGS='-g -O3 -Wall -Werror' + fi diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index bf6f5ae53..d49dc5df2 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -2,13 +2,15 @@ name: Windows/MinGW-W64 CI on: [push, pull_request] jobs: - build: + build-windows: runs-on: windows-latest steps: - name: Checkout - uses: actions/checkout@v4 + # This is actions/checkout@v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: submodules: true + persist-credentials: false - name: Set up MSYS2 MinGW-W64 uses: msys2/setup-msys2@v2 with: diff --git a/Makefile b/Makefile index a6617b8a2..6eab6ca6e 100644 --- a/Makefile +++ b/Makefile @@ -714,7 +714,11 @@ check test: all $(HTSCODECS_TEST_TARGETS) else \ REF_PATH=: ./test.pl $(REF_CACHE_TEST_OPTS) $${TEST_OPTS:-} ; \ fi - test/test_hfile_libcurl + if test "x$(BUILT_PLUGINS)" != "x"; then \ + HTS_PATH=. ./test/with-shlib.sh test/test_hfile_libcurl ; \ + else \ + test/test_hfile_libcurl ; \ + fi test/hts_endian: test/hts_endian.o $(CC) $(LDFLAGS) -o $@ test/hts_endian.o $(LIBS) diff --git a/m4/hts_prog_cc_warnings.m4 b/m4/hts_prog_cc_warnings.m4 index f2aed9328..5b2a9dd63 100644 --- a/m4/hts_prog_cc_warnings.m4 +++ b/m4/hts_prog_cc_warnings.m4 @@ -65,75 +65,76 @@ dnl an option that includes a hash sign... # Tests for flags to enable C compiler warnings # GCC compatible AS_IF([test "x$GCC" = "xyes" && - "$CC" -c -Wall conftest.c > /dev/null 2>&1 && + $CC -c -Wall conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[dnl AS_IF([test "x$ansi" = "x"], [hts_cv_prog_cc_warnings="-Wall"], [hts_cv_prog_cc_warnings="-Wall -ansi -pedantic"]) ], # Sun Studio or Solaris C compiler - ["$CC" -V 2>&1 | $GREP -i -E "WorkShop|Sun C" > /dev/null 2>&1 && - "$CC" -c -v -Xc conftest.c > /dev/null 2>&1 && + [$CC -V 2>&1 | $GREP -i -E "WorkShop|Sun C" >&AS_MESSAGE_LOG_FD 2>&1 && + $CC -c -v -Xc conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[dnl AS_IF([test "x$ansi" = "x"], [hts_cv_prog_cc_warnings="-v"], [hts_cv_prog_cc_warnings="-v -Xc"]) ], # Digital Unix C compiler - ["$CC" -V 2>&1 | $GREP -i "Digital UNIX Compiler" > /dev/null 2>&1 && - "$CC" -c -verbose -w0 -warnprotos -std1 conftest.c > /dev/null 2>&1 && + [$CC -V 2>&1 | $GREP -i "Digital UNIX Compiler" >&AS_MESSAGE_LOG_FD 2>&1 && + $CC -c -verbose -w0 -warnprotos -std1 conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o], [dnl AS_IF([test "x$ansi" = "x"], [hts_cv_prog_cc_warnings="-verbose -w0 -warnprotos"], [hts_cv_prog_cc_warnings="-verbose -w0 -warnprotos -std1"]) ], # C for AIX Compiler - ["$CC" 2>&1 | $GREP -i "C for AIX Compiler" > /dev/null 2>&1 && - "$CC" -c -qlanglvl=ansi -qinfo=all conftest.c > /dev/null 2>&1 && + [$CC 2>&1 | $GREP -i "C for AIX Compiler" >&AS_MESSAGE_LOG_FD 2>&1 && + $CC -c -qlanglvl=ansi -qinfo=all conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[dnl AS_IF([test "x$ansi" = "x"], [hts_cv_prog_cc_warnings="-qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd"], [hts_cv_prog_cc_warnings="-qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd -qlanglvl=ansi"]) ], # IRIX C compiler - ["$CC" -version 2>&1 | $GREP -i "MIPSpro Compilers" > /dev/null 2>&1 && - "$CC" -c -fullwarn -ansi -ansiE conftest.c > /dev/null 2>&1 && + [$CC -version 2>&1 | $GREP -i "MIPSpro Compilers" >&AS_MESSAGE_LOG_FD 2>&1 && + $CC -c -fullwarn -ansi -ansiE conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[dnl AS_IF([test "x$ansi" = "x"], [hts_cv_prog_cc_warnings="-fullwarn"], [hts_cv_prog_cc_warnings="-fullwarn -ansi -ansiE"]) ], # HP-UX C compiler - [what "$CC" 2>&1 | $GREP -i "HP C Compiler" > /dev/null 2>&1 && - "$CC" -c -Aa +w1 conftest.c > /dev/null 2>&1 && + [what "$CC" 2>&1 | $GREP -i "HP C Compiler" >&AS_MESSAGE_LOG_FD 2>&1 && + $CC -c -Aa +w1 conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[dnl AS_IF([test "x$ansi" = "x"], [hts_cv_prog_cc_warnings="+w1"], [hts_cv_prog_cc_warnings="+w1 -Aa"]) ], # The NEC SX series (Super-UX 10) C compiler - ["$CC" -V 2>&1 | $GREP "/SX" > /dev/null 2>&1 && - "$CC" -c -pvctl[,]fullmsg -Xc conftest.c > /dev/null 2>&1 && + [$CC -V 2>&1 | $GREP "/SX" >&AS_MESSAGE_LOG_FD 2>&1 && + $CC -c -pvctl[,]fullmsg -Xc conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[ AS_IF([test "x$ansi" = "x"], [hts_cv_prog_cc_warnings="-pvctl[,]fullmsg"], [hts_cv_prog_cc_warnings="-pvctl[,]fullmsg -Xc"]) ], # The Cray C compiler (Unicos) - ["$CC" -V 2>&1 | $GREP -i "Cray" > /dev/null 2>&1 && - "$CC" -c -h msglevel_2 conftest.c > /dev/null 2>&1 && + [$CC -V 2>&1 | $GREP -i "Cray" >&AS_MESSAGE_LOG_FD 2>&1 && + $CC -c -h msglevel_2 conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[dnl AS_IF([test "x$ansi" = "x"], [hts_cv_prog_cc_warnings="-h#msglevel_2"], [hts_cv_prog_cc_warnings="-h#msglevel_2,conform"]) ], # The Tiny C Compiler - ["$CC" -v 2>&1 | $GREP "tcc version" > /dev/null && - "$CC" -Wall -c conftest.c > /dev/null 2>&1 && + [$CC -v 2>&1 | $GREP "tcc version" >&AS_MESSAGE_LOG_FD && + $CC -Wall -c conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[dnl hts_cv_prog_cc_warnings="-Wall" ]) rm -f conftest.* + rm -rf conftest.dSYM ]) ]) @@ -183,19 +184,20 @@ EOF # Tests for flags to make the C compiler treat warnings as errors # GCC compatible [test "x$GCC" = "xyes" && - "$CC" -c -Werror conftest.c > /dev/null 2>&1 && + $CC -c -Werror conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[hts_cv_prog_cc_werror="-Werror"], # Sun Studio or Solaris C compiler - ["$CC" -V 2>&1 | $GREP -i -E "WorkShop|Sun C" > /dev/null 2>&1 && - "$CC" -c -errwarn=%all conftest.c > /dev/null 2>&1 && + [$CC -V 2>&1 | $GREP -i -E "WorkShop|Sun C" >&AS_MESSAGE_LOG_FD 2>&1 && + $CC -c -errwarn=%all conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[hts_cv_prog_cc_werror="-errwarn=%all"], # The Tiny C Compiler - ["$CC" -v 2>&1 | $GREP "tcc version" > /dev/null && - "$CC" -Wall -c conftest.c > /dev/null 2>&1 && + [$CC -v 2>&1 | $GREP "tcc version" >&AS_MESSAGE_LOG_FD && + $CC -Wall -c conftest.c >&AS_MESSAGE_LOG_FD 2>&1 && test -f conftest.o],[hts_cv_prog_cc_werror="-Werror"] dnl TODO: Add more compilers ) rm -f conftest.* + rm -rf conftest.dSYM ]) ]) AS_IF([test "x$hts_cv_prog_cc_werror" != x],[