v2.0: Modernization (M1-M6, 44 tasks) #845
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: "Verify Build" | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| # The branches below must be a subset of the branches above | |
| branches: [master] | |
| schedule: | |
| - cron: '0 0 * * 0' | |
| # Restrict every job's GITHUB_TOKEN to read-only by default. | |
| # Jobs that need broader access should override at the job level. | |
| permissions: | |
| contents: read | |
| jobs: | |
| verify: | |
| name: Verify | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| DEBUG: ${{ matrix.debug }} | |
| COVERAGE: ${{ matrix.coverage }} | |
| LINKING: ${{ matrix.linking }} | |
| BUILD_TYPE: ${{ matrix.build-type }} | |
| CC: ${{ matrix.c-compiler }} | |
| CXX: ${{ matrix.cc-compiler }} | |
| defaults: | |
| run: | |
| shell: ${{ matrix.shell }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| os-type: [ubuntu, mac] | |
| test-group: [basic] | |
| compiler-family: [none] | |
| c-compiler: [gcc, clang] | |
| cc-compiler: [g++, clang++] | |
| debug: [debug, nodebug] | |
| coverage: [coverage, nocoverage] | |
| linking: [dynamic, static] | |
| build-type: [classic] | |
| shell: [bash] | |
| exclude: | |
| - os: ubuntu-latest | |
| os-type: mac | |
| - os: macos-latest | |
| os-type: ubuntu | |
| - c-compiler: gcc | |
| cc-compiler: clang++ | |
| - c-compiler: clang | |
| cc-compiler: g++ | |
| - c-compiler: clang | |
| debug: debug | |
| - debug: debug | |
| coverage: nocoverage | |
| - debug: nodebug | |
| coverage: coverage | |
| - linking: static | |
| debug: debug | |
| - linking: static | |
| coverage: coverage | |
| include: | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: asan | |
| compiler-family: clang | |
| c-compiler: clang-18 | |
| cc-compiler: clang++-18 | |
| debug: debug | |
| coverage: nocoverage | |
| shell: bash | |
| # This test gives false positives on newer versions of clang | |
| # and ubuntu-18.04 is not supported anymore on github | |
| #- test-group: extra | |
| # os: ubuntu-18.04 | |
| # os-type: ubuntu | |
| # build-type: msan | |
| # compiler-family: clang | |
| # c-compiler: clang-6.0 | |
| # cc-compiler: clang++-6.0 | |
| # debug: debug | |
| # coverage: nocoverage | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: lsan | |
| compiler-family: clang | |
| c-compiler: clang-18 | |
| cc-compiler: clang++-18 | |
| debug: debug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: tsan | |
| compiler-family: clang | |
| c-compiler: clang-18 | |
| cc-compiler: clang++-18 | |
| debug: debug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: ubsan | |
| compiler-family: clang | |
| c-compiler: clang-18 | |
| cc-compiler: clang++-18 | |
| debug: debug | |
| coverage: nocoverage | |
| shell: bash | |
| # gcc-9 and gcc-10 dropped: lack full C++20 support (no concepts library, no std::span, no <bit> features). | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: none | |
| compiler-family: gcc | |
| c-compiler: gcc-11 | |
| cc-compiler: g++-11 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: none | |
| compiler-family: gcc | |
| c-compiler: gcc-12 | |
| cc-compiler: g++-12 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: none | |
| compiler-family: gcc | |
| c-compiler: gcc-13 | |
| cc-compiler: g++-13 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: none | |
| compiler-family: gcc | |
| c-compiler: gcc-14 | |
| cc-compiler: g++-14 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| # clang-11, clang-12, clang-14, and clang-15 dropped: incomplete C++20 support (concepts/<bit>/<span> gaps). | |
| # clang-13 retained: passes the autoconf C++20 feature check on ubuntu-22.04. | |
| - test-group: extra | |
| os: ubuntu-22.04 | |
| os-type: ubuntu | |
| build-type: none | |
| compiler-family: clang | |
| c-compiler: clang-13 | |
| cc-compiler: clang++-13 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: none | |
| compiler-family: clang | |
| c-compiler: clang-16 | |
| cc-compiler: clang++-16 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: none | |
| compiler-family: clang | |
| c-compiler: clang-17 | |
| cc-compiler: clang++-17 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: valgrind | |
| compiler-family: gcc | |
| c-compiler: gcc-14 | |
| cc-compiler: g++-14 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| # Test build without digest auth support (issue #232) | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: no-dauth | |
| compiler-family: gcc | |
| c-compiler: gcc | |
| cc-compiler: g++ | |
| debug: nodebug | |
| coverage: nocoverage | |
| linking: dynamic | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: iwyu | |
| compiler-family: clang | |
| c-compiler: clang-18 | |
| cc-compiler: clang++-18 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: performance | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: select | |
| compiler-family: gcc | |
| c-compiler: gcc-14 | |
| cc-compiler: g++-14 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: performance | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: nodelay | |
| compiler-family: gcc | |
| c-compiler: gcc-14 | |
| cc-compiler: g++-14 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: performance | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: threads | |
| compiler-family: gcc | |
| c-compiler: gcc-14 | |
| cc-compiler: g++-14 | |
| debug: nodebug | |
| coverage: nocoverage | |
| shell: bash | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: lint | |
| compiler-family: gcc | |
| c-compiler: gcc-14 | |
| cc-compiler: g++-14 | |
| debug: debug | |
| coverage: nocoverage | |
| shell: bash | |
| # TASK-007: dedicated header-hygiene gate. Runs `make check-hygiene` | |
| # (preprocesses <httpserver.hpp> against the staged install and greps | |
| # for forbidden backend headers). Surfaces this gate as its own named | |
| # GitHub Actions check so reviewers see header-hygiene status | |
| # independently of the broader `make check` log. Until M5 lands the | |
| # check is informational (HEADER_HYGIENE_STRICT defaults to "no"); | |
| # TASK-020 flips it to strict. | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: header-hygiene | |
| compiler-family: gcc | |
| c-compiler: gcc-14 | |
| cc-compiler: g++-14 | |
| debug: nodebug | |
| coverage: nocoverage | |
| linking: dynamic | |
| shell: bash | |
| # TASK-037: build-flag invariance gate (HAVE_* all ON lane). | |
| # PRD-FLG-REQ-001 / arch §9 testing item 2. The consumer_fixture | |
| # binary (test/consumer_fixture.cpp) touches every public symbol | |
| # whose declaration was previously #ifdef HAVE_* gated. It MUST | |
| # compile + link in this configuration. Stock libmicrohttpd + | |
| # gnutls; isolated as its own matrix entry so the build-flag | |
| # invariance gate has a dedicated status check. | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: flag-invariance-on | |
| compiler-family: gcc | |
| c-compiler: gcc | |
| cc-compiler: g++ | |
| debug: nodebug | |
| coverage: nocoverage | |
| linking: dynamic | |
| shell: bash | |
| # TASK-037: build-flag invariance gate (HAVE_* all OFF lane). | |
| # libmicrohttpd is rebuilt with --disable-bauth --disable-dauth | |
| # --disable-websockets so libhttpserver auto-detects all three | |
| # as off. The gnutls install step is gated off for this build- | |
| # type so gnutls/gnutls.h is absent from the include search path | |
| # and HAVE_GNUTLS auto-detects to off as well. The same | |
| # consumer_fixture.cpp must compile + link without source changes, | |
| # proving every flag-gated public declaration is unconditional. | |
| - test-group: extra | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: flag-invariance-off | |
| compiler-family: gcc | |
| c-compiler: gcc | |
| cc-compiler: g++ | |
| debug: nodebug | |
| coverage: nocoverage | |
| linking: dynamic | |
| shell: bash | |
| - test-group: basic | |
| os: windows-latest | |
| os-type: windows | |
| msys-env: MINGW64 | |
| shell: 'msys2 {0}' | |
| build-type: classic | |
| compiler-family: none | |
| c-compiler: gcc | |
| cc-compiler: g++ | |
| debug: nodebug | |
| coverage: nocoverage | |
| linking: dynamic | |
| - test-group: basic | |
| os: windows-latest | |
| os-type: windows | |
| msys-env: MSYS | |
| shell: 'msys2 {0}' | |
| build-type: classic | |
| compiler-family: none | |
| c-compiler: gcc | |
| cc-compiler: g++ | |
| debug: nodebug | |
| coverage: nocoverage | |
| linking: dynamic | |
| # ARM 32-bit cross-compilation (ARMv7 hard-float) | |
| - test-group: cross-compile | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: arm32 | |
| compiler-family: arm-cross | |
| c-compiler: arm-linux-gnueabihf-gcc | |
| cc-compiler: arm-linux-gnueabihf-g++ | |
| debug: nodebug | |
| coverage: nocoverage | |
| linking: dynamic | |
| shell: bash | |
| # ARM 64-bit cross-compilation (AArch64) | |
| - test-group: cross-compile | |
| os: ubuntu-latest | |
| os-type: ubuntu | |
| build-type: arm64 | |
| compiler-family: arm-cross | |
| c-compiler: aarch64-linux-gnu-gcc | |
| cc-compiler: aarch64-linux-gnu-g++ | |
| debug: nodebug | |
| coverage: nocoverage | |
| linking: dynamic | |
| shell: bash | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| # We must fetch at least the immediate parents so that if this is | |
| # a pull request then we can checkout the head. | |
| fetch-depth: 2 | |
| # If this run was triggered by a pull request event, then checkout | |
| # the head of the pull request instead of the merge commit. | |
| - run: git checkout HEAD^2 | |
| shell: bash | |
| if: ${{ github.event_name == 'pull_request' }} | |
| - name: Setup MSYS2 | |
| if: ${{ matrix.os-type == 'windows' }} | |
| uses: msys2/setup-msys2@v2 | |
| with: | |
| msystem: ${{ matrix.msys-env }} | |
| update: true | |
| install: >- | |
| autotools | |
| base-devel | |
| - name: Install MinGW64 packages | |
| if: ${{ matrix.os-type == 'windows' && matrix.msys-env == 'MINGW64' }} | |
| run: | | |
| pacman --noconfirm -S --needed mingw-w64-x86_64-{toolchain,libtool,make,pkg-config,libsystre,doxygen,gnutls,graphviz,curl} | |
| - name: Install MSYS packages | |
| if: ${{ matrix.os-type == 'windows' && matrix.msys-env == 'MSYS' }} | |
| run: | | |
| pacman --noconfirm -S --needed msys2-devel gcc make libcurl-devel libgnutls-devel | |
| - name: Install Ubuntu test sources | |
| # ppa:ubuntu-toolchain-r/test was historically used to backport newer | |
| # gcc onto older Ubuntu LTS. With the C++20 floor (TASK-001), our matrix | |
| # only retains compilers that ship in stock ubuntu-22.04 / 24.04 repos | |
| # (gcc-11..14, clang-13/16/17/18), so the PPA is no longer needed -- and | |
| # add-apt-repository talks to launchpad, which is a flaky dependency. | |
| run: | | |
| sudo apt-get update ; | |
| if: ${{ matrix.os-type == 'ubuntu' }} | |
| - name: Install apache benchmark if needed | |
| run: sudo apt-get install apache2-utils ; | |
| if: ${{ matrix.test-group == 'performance' && matrix.os-type == 'ubuntu' }} | |
| - name: Install optional clang if needed | |
| run: sudo apt-get install ${{ matrix.c-compiler }} | |
| if: ${{ matrix.compiler-family == 'clang' && matrix.os-type == 'ubuntu' }} | |
| - name: Install optional gcc if needed | |
| run: sudo apt-get install ${{ matrix.cc-compiler }} | |
| if: ${{ matrix.compiler-family == 'gcc' && matrix.os-type == 'ubuntu' }} | |
| - name: Install ARM cross-compilation toolchain | |
| run: | | |
| sudo apt-get update | |
| if [ "${{ matrix.build-type }}" = "arm32" ]; then | |
| sudo apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf | |
| elif [ "${{ matrix.build-type }}" = "arm64" ]; then | |
| sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu | |
| fi | |
| if: ${{ matrix.compiler-family == 'arm-cross' }} | |
| - name: Install valgrind if needed | |
| run: sudo apt-get install valgrind | |
| if: ${{ matrix.build-type == 'valgrind' && matrix.os-type == 'ubuntu' }} | |
| - name: Install cpplint if needed | |
| run: sudo pip3 install cpplint ; | |
| if: ${{ matrix.build-type == 'lint' && matrix.os-type == 'ubuntu' }} | |
| - name: Install IWYU dependencies if needed | |
| run: | | |
| sudo apt-get install llvm-18-dev libclang-18-dev clang-18 ; | |
| if: ${{ matrix.build-type == 'iwyu' && matrix.os-type == 'ubuntu' }} | |
| - name: IWYU from cache (for testing) | |
| id: cache-IWYU | |
| uses: actions/cache@v4 | |
| with: | |
| path: include-what-you-use | |
| key: ${{ matrix.os }}-${{ matrix.c-compiler }}-include-what-you-use-pre-built | |
| if: ${{ matrix.build-type == 'iwyu' && matrix.os-type == 'ubuntu' }} | |
| # Installing iwyu manually because clang and iwyu paths won't match on Ubuntu otherwise. | |
| - name: Build IWYU if requested | |
| run: | | |
| CLANG_ROOT_PATH=`llvm-config-18 --prefix` ; | |
| CLANG_BIN_PATH=`llvm-config-18 --bindir` ; | |
| git clone https://github.com/include-what-you-use/include-what-you-use.git ; | |
| cd include-what-you-use ; | |
| git checkout clang_18 ; | |
| mkdir build_iwyu ; | |
| cd build_iwyu ; | |
| cmake -G "Unix Makefiles" -DCMAKE_PREFIX_PATH=$CLANG_ROOT_PATH -DCMAKE_C_COMPILER=$CLANG_BIN_PATH/clang -DCMAKE_CXX_COMPILER=$CLANG_BIN_PATH/clang++ ../ ; | |
| make ; | |
| sudo make install ; | |
| if: ${{ matrix.build-type == 'iwyu' && matrix.os-type == 'ubuntu' && steps.cache-IWYU.outputs.cache-hit != 'true' }} | |
| - name: Install IWYU if requested | |
| run: | | |
| cd include-what-you-use/build_iwyu ; | |
| sudo make install ; | |
| if: ${{ matrix.build-type == 'iwyu' && matrix.os-type == 'ubuntu' }} | |
| - name: CURL from cache (for testing) | |
| id: cache-CURL | |
| uses: actions/cache@v4 | |
| with: | |
| path: curl-7.75.0 | |
| key: ${{ matrix.os }}-CURL-pre-built-v2 | |
| if: ${{ matrix.os == 'macos-latest' }} | |
| - name: Build CURL (for testing) | |
| run: | | |
| curl https://libhttpserver.s3.amazonaws.com/travis_stuff/curl-7.75.0.tar.gz -o curl-7.75.0.tar.gz ; | |
| tar -xzf curl-7.75.0.tar.gz ; | |
| cd curl-7.75.0 ; | |
| ./configure --with-darwinssl --without-ssl ; | |
| make ; | |
| if: ${{ matrix.os == 'macos-latest' && steps.cache-CURL.outputs.cache-hit != 'true' }} | |
| - name: Install CURL (for testing on mac only) | |
| run: cd curl-7.75.0 ; sudo make install ; | |
| if: ${{ matrix.os == 'macos-latest' }} | |
| - name: Install CURL (for testing on linux) | |
| run: sudo apt-get install libcurl4-openssl-dev | |
| if: ${{ matrix.os-type == 'ubuntu' }} | |
| - name: Install autotools on mac | |
| run: brew install autoconf automake libtool | |
| if: ${{ matrix.os == 'macos-latest' }} | |
| - name: Setup dependencies (only on linux) | |
| run: | | |
| sudo apt-get install info install-info ; | |
| sudo apt-get install cppcheck ; | |
| if: ${{ matrix.os-type == 'ubuntu' }} | |
| - name: Setup coverage dependencies (only on linux) | |
| run: | | |
| sudo pip install gcovr ; | |
| if: ${{ matrix.os-type == 'ubuntu' && matrix.c-compiler == 'gcc' && matrix.debug == 'debug' && matrix.coverage == 'coverage' }} | |
| - name: Setup gnutls dependency (only on linux) | |
| run: | | |
| sudo apt-get install libgnutls28-dev gnutls-bin ; | |
| # TASK-037: skip gnutls install on the flag-invariance-off lane so | |
| # HAVE_GNUTLS auto-detects to off (the configure script just | |
| # AC_CHECK_HEADER's gnutls/gnutls.h, no header == HAVE_GNUTLS=0). | |
| if: ${{ matrix.os-type == 'ubuntu' && matrix.build-type != 'flag-invariance-off' }} | |
| - name: Fetch libmicrohttpd from cache | |
| id: cache-libmicrohttpd | |
| uses: actions/cache@v4 | |
| with: | |
| path: libmicrohttpd-1.0.3 | |
| key: ${{ matrix.os }}-${{ matrix.c-compiler }}-libmicrohttpd-1.0.3-pre-built-v2 | |
| # TASK-037: the flag-invariance-off lane rebuilds libmicrohttpd with | |
| # every sub-feature disabled, so it must skip the stock cache fetch. | |
| if: ${{ matrix.os-type != 'windows' && matrix.build-type != 'no-dauth' && matrix.build-type != 'flag-invariance-off' && matrix.compiler-family != 'arm-cross' }} | |
| - name: Build libmicrohttpd dependency (if not cached) | |
| run: | | |
| curl https://s3.amazonaws.com/libhttpserver/libmicrohttpd_releases/libmicrohttpd-1.0.3.tar.gz -o libmicrohttpd-1.0.3.tar.gz ; | |
| echo "7816b57aae199cf5c3645e8770e1be5f0a4dfafbcb24b3772173dc4ee634126a libmicrohttpd-1.0.3.tar.gz" | sha256sum -c ; | |
| tar -xzf libmicrohttpd-1.0.3.tar.gz ; | |
| cd libmicrohttpd-1.0.3 ; | |
| ./configure --disable-examples ; | |
| make ; | |
| # TASK-037: as above -- flag-invariance-off has its own dedicated | |
| # libmicrohttpd build step below. | |
| if: ${{ matrix.os-type != 'windows' && matrix.build-type != 'no-dauth' && matrix.build-type != 'flag-invariance-off' && matrix.compiler-family != 'arm-cross' && steps.cache-libmicrohttpd.outputs.cache-hit != 'true' }} | |
| - name: Build libmicrohttpd without digest auth (no-dauth test) | |
| run: | | |
| curl https://s3.amazonaws.com/libhttpserver/libmicrohttpd_releases/libmicrohttpd-1.0.3.tar.gz -o libmicrohttpd-1.0.3.tar.gz ; | |
| echo "7816b57aae199cf5c3645e8770e1be5f0a4dfafbcb24b3772173dc4ee634126a libmicrohttpd-1.0.3.tar.gz" | sha256sum -c ; | |
| tar -xzf libmicrohttpd-1.0.3.tar.gz ; | |
| cd libmicrohttpd-1.0.3 ; | |
| ./configure --disable-examples --disable-dauth ; | |
| make ; | |
| if: ${{ matrix.build-type == 'no-dauth' }} | |
| - name: Build libmicrohttpd with all features off (TASK-037 flag-invariance-off lane) | |
| run: | | |
| curl https://s3.amazonaws.com/libhttpserver/libmicrohttpd_releases/libmicrohttpd-1.0.3.tar.gz -o libmicrohttpd-1.0.3.tar.gz ; | |
| echo "7816b57aae199cf5c3645e8770e1be5f0a4dfafbcb24b3772173dc4ee634126a libmicrohttpd-1.0.3.tar.gz" | sha256sum -c ; | |
| tar -xzf libmicrohttpd-1.0.3.tar.gz ; | |
| cd libmicrohttpd-1.0.3 ; | |
| ./configure --disable-examples --disable-bauth --disable-dauth --disable-websockets ; | |
| make ; | |
| if: ${{ matrix.build-type == 'flag-invariance-off' }} | |
| - name: Install libmicrohttpd | |
| run: cd libmicrohttpd-1.0.3 ; sudo make install ; | |
| if: ${{ matrix.os-type != 'windows' && matrix.compiler-family != 'arm-cross' }} | |
| - name: Verify digest auth is disabled (no-dauth test) | |
| run: | | |
| # Verify that MHD_queue_auth_fail_response is NOT present in libmicrohttpd | |
| if nm /usr/local/lib/libmicrohttpd.so 2>/dev/null | grep -q MHD_queue_auth_fail_response; then | |
| echo "ERROR: libmicrohttpd was built WITH digest auth support" ; | |
| exit 1 ; | |
| fi | |
| echo "Verified: libmicrohttpd built without digest auth support" ; | |
| if: ${{ matrix.build-type == 'no-dauth' }} | |
| - name: Verify libmicrohttpd built without bauth/dauth/websockets (TASK-037 flag-invariance-off lane) | |
| # TASK-037 / PRD-FLG-REQ-001: belt-and-braces check that the bespoke | |
| # libmicrohttpd build above actually stripped the symbols that drive | |
| # libhttpserver's HAVE_BAUTH / HAVE_DAUTH / HAVE_WEBSOCKET | |
| # auto-detection. If any of these slipped back in, the configure | |
| # step would (correctly) flip the corresponding HAVE_* back on and | |
| # the lane would no longer be exercising the flag-off invariant. | |
| run: | | |
| fail=0 ; | |
| for sym in MHD_basic_auth_get_username_password3 MHD_digest_auth_check3 MHD_queue_auth_fail_response; do | |
| if nm /usr/local/lib/libmicrohttpd.so 2>/dev/null | grep -q "$sym"; then | |
| echo "ERROR: $sym present in libmicrohttpd (expected absent)" ; | |
| fail=1 ; | |
| else | |
| echo "Verified: $sym absent from libmicrohttpd" ; | |
| fi ; | |
| done ; | |
| if ls /usr/local/lib/libmicrohttpd_ws* >/dev/null 2>&1; then | |
| echo "ERROR: libmicrohttpd_ws present (expected absent)" ; | |
| fail=1 ; | |
| else | |
| echo "Verified: libmicrohttpd_ws not built/installed" ; | |
| fi ; | |
| if [ "$fail" -ne 0 ]; then exit 1; fi | |
| if: ${{ matrix.build-type == 'flag-invariance-off' }} | |
| - name: Build and install libmicrohttpd (Windows) | |
| if: ${{ matrix.os-type == 'windows' }} | |
| run: | | |
| curl https://s3.amazonaws.com/libhttpserver/libmicrohttpd_releases/libmicrohttpd-1.0.3.tar.gz -o libmicrohttpd-1.0.3.tar.gz | |
| echo "7816b57aae199cf5c3645e8770e1be5f0a4dfafbcb24b3772173dc4ee634126a libmicrohttpd-1.0.3.tar.gz" | sha256sum -c | |
| tar -xzf libmicrohttpd-1.0.3.tar.gz | |
| cd libmicrohttpd-1.0.3 | |
| ./configure --disable-examples --enable-poll=no | |
| make | |
| make install | |
| - name: Fetch libmicrohttpd from cache (ARM cross-compile) | |
| id: cache-libmicrohttpd-arm | |
| uses: actions/cache@v4 | |
| with: | |
| path: libmicrohttpd-1.0.3-${{ matrix.build-type }} | |
| key: ${{ matrix.os }}-${{ matrix.build-type }}-libmicrohttpd-1.0.3-cross-compiled | |
| if: ${{ matrix.compiler-family == 'arm-cross' }} | |
| - name: Cross-compile libmicrohttpd for ARM | |
| run: | | |
| curl https://s3.amazonaws.com/libhttpserver/libmicrohttpd_releases/libmicrohttpd-1.0.3.tar.gz -o libmicrohttpd-1.0.3.tar.gz | |
| echo "7816b57aae199cf5c3645e8770e1be5f0a4dfafbcb24b3772173dc4ee634126a libmicrohttpd-1.0.3.tar.gz" | sha256sum -c | |
| tar -xzf libmicrohttpd-1.0.3.tar.gz | |
| mv libmicrohttpd-1.0.3 libmicrohttpd-1.0.3-${{ matrix.build-type }} | |
| cd libmicrohttpd-1.0.3-${{ matrix.build-type }} | |
| mkdir -p ${{ github.workspace }}/arm-sysroot | |
| if [ "${{ matrix.build-type }}" = "arm32" ]; then | |
| ./configure --host=arm-linux-gnueabihf --prefix=${{ github.workspace }}/arm-sysroot --disable-examples --disable-doc | |
| else | |
| ./configure --host=aarch64-linux-gnu --prefix=${{ github.workspace }}/arm-sysroot --disable-examples --disable-doc | |
| fi | |
| make | |
| make install | |
| if: ${{ matrix.compiler-family == 'arm-cross' && steps.cache-libmicrohttpd-arm.outputs.cache-hit != 'true' }} | |
| - name: Install cross-compiled libmicrohttpd from cache | |
| run: | | |
| cd libmicrohttpd-1.0.3-${{ matrix.build-type }} | |
| mkdir -p ${{ github.workspace }}/arm-sysroot | |
| make install | |
| if: ${{ matrix.compiler-family == 'arm-cross' && steps.cache-libmicrohttpd-arm.outputs.cache-hit == 'true' }} | |
| - name: Refresh links to shared libs | |
| run: sudo ldconfig ; | |
| if: ${{ matrix.os-type == 'ubuntu' }} | |
| - name: Run cpplint on code | |
| run: cpplint --extensions=cpp,hpp --headers=hpp --recursive . ; | |
| if: ${{ matrix.build-type == 'lint' && matrix.os-type == 'ubuntu' }} | |
| - name: Run libhttpserver configure | |
| run: | | |
| # Set memory check flags. They need to stay in step as env variables don't propagate across steps. | |
| # TASK-038: CXXFLAGS (NOT CXXLAGS) is the autoconf-recognized var | |
| # that gets passed to the C++ compiler. A long-standing typo left | |
| # C++ TUs uninstrumented under asan/msan/lsan/tsan/ubsan — the | |
| # runtime libs were linked but the code itself was compiled | |
| # without -fsanitize=..., so the sanitizers were no-ops on the | |
| # library. The fix is a single missing 'F' per line. | |
| if [ "$BUILD_TYPE" = "asan" ]; then export CFLAGS='-fsanitize=address'; export CXXFLAGS='-fsanitize=address'; export LDFLAGS='-fsanitize=address'; fi | |
| if [ "$BUILD_TYPE" = "msan" ]; then export CFLAGS='-fsanitize=memory'; export CXXFLAGS='-fsanitize=memory'; export LDFLAGS='-fsanitize=memory'; fi | |
| if [ "$BUILD_TYPE" = "lsan" ]; then export CFLAGS='-fsanitize=leak'; export CXXFLAGS='-fsanitize=leak'; export LDFLAGS='-fsanitize=leak'; fi | |
| if [ "$BUILD_TYPE" = "tsan" ]; then export CFLAGS='-fsanitize=thread'; export CXXFLAGS='-fsanitize=thread'; export LDFLAGS='-fsanitize=thread'; fi | |
| if [ "$BUILD_TYPE" = "ubsan" ]; then export CFLAGS='-fsanitize=undefined'; export CXXFLAGS='-fsanitize=undefined'; export LDFLAGS='-fsanitize=undefined'; fi | |
| # Additional flags on mac. They need to stay in step as env variables don't propagate across steps. | |
| if [ "${{ matrix.os }}" = "macos-latest" ]; then | |
| export CFLAGS='-mtune=generic' ; | |
| export IPV6_TESTS_ENABLED="true" ; | |
| fi | |
| ./bootstrap ; | |
| mkdir build ; | |
| cd build ; | |
| if [ "${{ matrix.compiler-family }}" = "arm-cross" ]; then | |
| export CPPFLAGS="-I${{ github.workspace }}/arm-sysroot/include" | |
| export LDFLAGS="-L${{ github.workspace }}/arm-sysroot/lib" | |
| export PKG_CONFIG_PATH="${{ github.workspace }}/arm-sysroot/lib/pkgconfig" | |
| if [ "${{ matrix.build-type }}" = "arm32" ]; then | |
| ../configure --host=arm-linux-gnueabihf --disable-fastopen; | |
| else | |
| ../configure --host=aarch64-linux-gnu --disable-fastopen; | |
| fi | |
| elif [ "$LINKING" = "static" ]; then | |
| ../configure --enable-static --disable-fastopen; | |
| elif [ "$DEBUG" = "debug" ] && [ "$COVERAGE" = "coverage" ]; then | |
| ../configure --enable-debug --enable-coverage --disable-shared --disable-fastopen; | |
| elif [ "$DEBUG" = "debug" ]; then | |
| ../configure --enable-debug --disable-shared --disable-fastopen; | |
| elif [ "$BUILD_TYPE" = "valgrind" ]; then | |
| ../configure --enable-debug --disable-fastopen --disable-valgrind-helgrind --disable-valgrind-drd --disable-valgrind-sgcheck; | |
| elif [ "$BUILD_TYPE" = "iwyu" ]; then | |
| ../configure --disable-examples; | |
| else | |
| ../configure --disable-fastopen; | |
| fi | |
| - name: Verify libhttpserver detected no digest auth (no-dauth test) | |
| run: | | |
| cd build ; | |
| if grep -q "Digest Auth.*:.*no" config.log; then | |
| echo "Verified: libhttpserver correctly detected digest auth is disabled" ; | |
| else | |
| echo "ERROR: libhttpserver did not detect that digest auth is disabled" ; | |
| grep "Digest Auth" config.log || echo "Digest Auth line not found" ; | |
| exit 1 ; | |
| fi | |
| if: ${{ matrix.build-type == 'no-dauth' }} | |
| - name: Verify libhttpserver detected all features off (TASK-037 flag-invariance-off lane) | |
| # TASK-037 / PRD-FLG-REQ-001 / arch §9 testing item 2. Asserts that | |
| # configure auto-detected every HAVE_* feature as off in this lane; | |
| # if any of them are 'yes', the lane wouldn't actually be exercising | |
| # the flag-off invariant and we want the matrix to go red loudly. | |
| run: | | |
| cd build ; | |
| fail=0 ; | |
| for feat in "TLS Enabled" "Basic Auth" "Digest Auth" "WebSocket"; do | |
| if grep -qE "^ ${feat}[[:space:]]*:[[:space:]]*no$" config.log; then | |
| echo "Verified: ${feat} is off" ; | |
| else | |
| echo "ERROR: ${feat} is NOT off in this configuration" ; | |
| grep "${feat}" config.log || echo "${feat} line not found" ; | |
| fail=1 ; | |
| fi ; | |
| done ; | |
| if [ "$fail" -ne 0 ]; then exit 1; fi | |
| if: ${{ matrix.build-type == 'flag-invariance-off' }} | |
| - name: Print config.log | |
| shell: bash | |
| run: | | |
| cd build ; | |
| cat config.log ; | |
| if: ${{ failure() }} | |
| # Make or run iwyu. If running iwyu, check for the result code to be 2 (IWYU always returns an error code, if it is 2, no corrections are necessary). | |
| - name: Make or run IWYU | |
| run: | | |
| # IWYU always return an error code. If it returns "2" it indicates a success so we manage this within the function below. | |
| function safe_make_iwyu() { | |
| { | |
| make -k CXX='/usr/local/bin/include-what-you-use -Xiwyu --mapping_file=${top_builddir}/../custom_iwyu.imp' CXXFLAGS="-std=c++20 -DHTTPSERVER_COMPILATION -D_REENTRANT $CXXFLAGS" ; | |
| } || { | |
| if [ $? -ne 2 ]; then | |
| return 1; | |
| else | |
| return 0; | |
| fi | |
| } | |
| return 0; | |
| } | |
| cd build ; | |
| if [ "$BUILD_TYPE" = "iwyu" ]; then | |
| safe_make_iwyu ; | |
| else | |
| make ; | |
| fi | |
| - name: Build consumer fixture (TASK-037 build-flag invariance gate) | |
| # TASK-037 / PRD-FLG-REQ-001 / arch §9 testing item 2. The headline | |
| # gate: the same test/consumer_fixture.cpp (which touches every | |
| # previously HAVE_*-gated public symbol) must compile + link in | |
| # both the all-features-on and all-features-off configurations. | |
| # The matrix entries skip the broad `make check` / `cppcheck` steps | |
| # below -- this single fixture compile + link is the build-flag- | |
| # invariance assertion. | |
| run: | | |
| cd build ; | |
| make -C test consumer_fixture ; | |
| if: ${{ matrix.build-type == 'flag-invariance-on' || matrix.build-type == 'flag-invariance-off' }} | |
| - name: Run tests | |
| run: | | |
| cd build ; | |
| make check; | |
| # TASK-037: flag-invariance-{on,off} are compile/link-only gates, so | |
| # skip the full `make check` (which spins up real servers and would | |
| # crash on the OFF lane for the BAUTH/DAUTH/WS unit tests anyway). | |
| if: ${{ matrix.build-type != 'iwyu' && matrix.compiler-family != 'arm-cross' && matrix.build-type != 'header-hygiene' && matrix.build-type != 'flag-invariance-on' && matrix.build-type != 'flag-invariance-off' }} | |
| - name: Run header-hygiene check | |
| # TASK-007: dedicated public-header hygiene gate. Runs the | |
| # preprocessor-grep target (Layer 2) against a staged install and | |
| # reports any forbidden backend headers reaching <httpserver.hpp>. | |
| # Currently informational (HEADER_HYGIENE_STRICT=no) -- TASK-020 | |
| # flips this to strict when M5 closes the umbrella. | |
| run: | | |
| cd build | |
| make check-hygiene | |
| if: ${{ matrix.build-type == 'header-hygiene' }} | |
| - name: Print tests results | |
| shell: bash | |
| run: | | |
| cd build ; | |
| cat test/test-suite.log ; | |
| if: ${{ failure() && matrix.build-type != 'iwyu' && matrix.compiler-family != 'arm-cross' }} | |
| - name: Run Valgrind checks | |
| run: | | |
| cd build ; | |
| make check-valgrind ; | |
| if: ${{ matrix.build-type == 'valgrind' }} | |
| - name: Print Valgrind memcheck results | |
| shell: bash | |
| run: | | |
| cd build ; | |
| if [ -f test/test-suite-memcheck.log ]; then | |
| cat test/test-suite-memcheck.log ; | |
| fi | |
| if: ${{ always() && matrix.build-type == 'valgrind' }} | |
| - name: Run cppcheck | |
| run: | | |
| cd src/ ; | |
| cppcheck --error-exitcode=1 . ; | |
| # TASK-037: flag-invariance lanes are minimal gates -- skip cppcheck. | |
| if: ${{ matrix.os-type == 'ubuntu' && matrix.compiler-family != 'arm-cross' && matrix.build-type != 'flag-invariance-on' && matrix.build-type != 'flag-invariance-off' }} | |
| - name: Run performance tests (select) | |
| run: | | |
| cd build | |
| cd examples | |
| ./benchmark_select 8080 $(nproc) & | |
| sleep 5 && ab -n 1000000 -c 100 127.0.0.1:8080/plaintext | |
| if: ${{ matrix.build-type == 'select' }} | |
| - name: Run performance tests (nodelay) | |
| run: | | |
| cd build | |
| cd examples | |
| ./benchmark_nodelay 8080 $(nproc) & | |
| sleep 5 && ab -n 1000000 -c 100 127.0.0.1:8080/plaintext | |
| if: ${{ matrix.build-type == 'nodelay' }} | |
| - name: Run performance tests (threads) | |
| run: | | |
| cd build | |
| cd examples | |
| ./benchmark_threads 8080 & | |
| sleep 5 && ab -n 1000000 -c 100 127.0.0.1:8080/plaintext | |
| if: ${{ matrix.build-type == 'threads' }} | |
| - name: Generate coverage report | |
| run: | | |
| cd build | |
| gcovr --root .. --filter '../src/' --xml coverage.xml --xml-pretty --print-summary --gcov-ignore-parse-errors=negative_hits.warn_once_per_file | |
| if: ${{ matrix.os-type == 'ubuntu' && matrix.c-compiler == 'gcc' && matrix.debug == 'debug' && matrix.coverage == 'coverage' && success() }} | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: build/coverage.xml | |
| fail_ci_if_error: false | |
| if: ${{ matrix.os-type == 'ubuntu' && matrix.c-compiler == 'gcc' && matrix.debug == 'debug' && matrix.coverage == 'coverage' && success() }} |