name: build on: [push, pull_request] permissions: read-all env: LIBBPF_VERSION: v1.3.0 OPENSSL1_VERSION: 1_1_1w+quic OPENSSL3_VERSION: 3.1.5+quic BORINGSSL_VERSION: fae0964b3d44e94ca2a2d21f86e61dabe683d130 AWSLC_VERSION: v1.23.0 NGHTTP3_VERSION: v1.2.0 NGTCP2_VERSION: v1.4.0 jobs: build-cache: strategy: matrix: os: [ubuntu-22.04, macos-12] runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v4 - name: Restore libbpf cache id: cache-libbpf uses: actions/cache@v4 if: runner.os == 'Linux' with: path: libbpf/build key: ${{ runner.os }}-libbpf-${{ env.LIBBPF_VERSION }} - name: Restore OpenSSL v1.1.1 cache id: cache-openssl1 uses: actions/cache@v4 with: path: openssl1/build key: ${{ runner.os }}-openssl-${{ env.OPENSSL1_VERSION }} - name: Restore OpenSSL v3.x cache id: cache-openssl3 uses: actions/cache@v4 with: path: openssl3/build key: ${{ runner.os }}-openssl-${{ env.OPENSSL3_VERSION }} - name: Restore BoringSSL cache id: cache-boringssl uses: actions/cache@v4 with: path: | boringssl/build/crypto/libcrypto.a boringssl/build/ssl/libssl.a boringssl/include key: ${{ runner.os }}-boringssl-${{ env.BORINGSSL_VERSION }} - name: Restore aws-lc cache id: cache-awslc uses: actions/cache@v4 with: path: | aws-lc/build/crypto/libcrypto.a aws-lc/build/ssl/libssl.a aws-lc/include key: ${{ runner.os }}-awslc-${{ env.AWSLC_VERSION }} - name: Restore nghttp3 cache id: cache-nghttp3 uses: actions/cache@v4 with: path: nghttp3/build key: ${{ runner.os }}-nghttp3-${{ env.NGHTTP3_VERSION }} - name: Restore ngtcp2 + quictls/openssl v1.1.1 cache id: cache-ngtcp2-openssl1 uses: actions/cache@v4 with: path: ngtcp2-openssl1/build key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }} - name: Restore ngtcp2 + quictls/openssl v3.x cache id: cache-ngtcp2-openssl3 uses: actions/cache@v4 with: path: ngtcp2-openssl3/build key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL3_VERSION }} - id: settings if: | (steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux') || steps.cache-openssl1.outputs.cache-hit != 'true' || steps.cache-openssl3.outputs.cache-hit != 'true' || steps.cache-boringssl.outputs.cache-hit != 'true' || steps.cache-awslc.outputs.cache-hit != 'true' || steps.cache-nghttp3.outputs.cache-hit != 'true' || steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true' || steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true' run: | echo 'needs-build=true' >> $GITHUB_OUTPUT - name: Linux setup if: runner.os == 'Linux' && steps.settings.outputs.needs-build == 'true' run: | sudo apt-get update sudo apt-get install \ g++-12 \ clang-15 \ autoconf \ automake \ autotools-dev \ libtool \ pkg-config \ libelf-dev \ cmake \ cmake-data - name: MacOS setup if: runner.os == 'macOS' && steps.settings.outputs.needs-build == 'true' run: | brew install \ autoconf \ automake \ pkg-config \ libtool - name: Build libbpf if: steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux' run: | git clone --recursive -b ${{ env.LIBBPF_VERSION }} https://github.com/libbpf/libbpf cd libbpf make -C src install PREFIX=$PWD/build - name: Build quictls/openssl v1.1.1 if: steps.cache-openssl1.outputs.cache-hit != 'true' run: | git clone --recursive --depth 1 -b OpenSSL_${{ env.OPENSSL1_VERSION }} https://github.com/quictls/openssl openssl1 cd openssl1 ./config --prefix=$PWD/build make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" make install_sw - name: Build quictls/openssl v3.x if: steps.cache-openssl3.outputs.cache-hit != 'true' run: | git clone --recursive --depth 1 -b openssl-${{ env.OPENSSL3_VERSION }} https://github.com/quictls/openssl openssl3 cd openssl3 ./config enable-ktls --prefix=$PWD/build --libdir=$PWD/build/lib make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" make install_sw - name: Build BoringSSL if: steps.cache-boringssl.outputs.cache-hit != 'true' run: | mkdir boringssl cd boringssl git init git remote add origin https://boringssl.googlesource.com/boringssl git fetch origin --depth 1 ${{ env.BORINGSSL_VERSION }} git checkout ${{ env.BORINGSSL_VERSION }} mkdir build cd build cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" - name: Build aws-lc if: steps.cache-awslc.outputs.cache-hit != 'true' run: | git clone --recursive --depth 1 -b "${AWSLC_VERSION}" https://github.com/aws/aws-lc cd aws-lc cmake -B build -DDISABLE_GO=ON make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" -C build - name: Build nghttp3 if: steps.cache-nghttp3.outputs.cache-hit != 'true' run: | git clone --recursive --depth 1 -b ${{ env.NGHTTP3_VERSION}} https://github.com/ngtcp2/nghttp3 cd nghttp3 autoreconf -i ./configure --prefix=$PWD/build --enable-lib-only make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check make install - name: Build ngtcp2 + quictls/openssl v1.1.1 + BoringSSL if: steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true' run: | git clone --recursive --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl1 cd ngtcp2-openssl1 autoreconf -i ./configure --prefix=$PWD/build --enable-lib-only \ PKG_CONFIG_PATH="../openssl1/build/lib/pkgconfig" \ BORINGSSL_CFLAGS="-I$PWD/../boringssl/include/" \ BORINGSSL_LIBS="-L$PWD/../boringssl/build/ssl -lssl -L$PWD/../boringssl/build/crypto -lcrypto" \ --with-boringssl make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check make install - name: Build ngtcp2 + quictls/openssl v3.x + aws-lc if: steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true' run: | git clone --recursive --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl3 cd ngtcp2-openssl3 autoreconf -i ./configure --prefix=$PWD/build --enable-lib-only \ PKG_CONFIG_PATH="../openssl3/build/lib/pkgconfig" \ BORINGSSL_CFLAGS="-I$PWD/../aws-lc/include/" \ BORINGSSL_LIBS="-L$PWD/../aws-lc/build/ssl -lssl -L$PWD/../aws-lc/build/crypto -lcrypto" \ --with-boringssl make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check make install build: needs: - build-cache strategy: matrix: os: [ubuntu-22.04, macos-12] compiler: [gcc, clang] buildtool: [autotools, cmake] http3: [http3, no-http3] openssl: [openssl1, openssl3, boringssl, awslc] exclude: - os: macos-12 openssl: openssl3 - http3: no-http3 openssl: openssl3 - os: macos-12 compiler: gcc - # disable macos cmake because of include path issue os: macos-12 buildtool: cmake - os: macos-12 openssl: boringssl - openssl: boringssl buildtool: cmake - openssl: boringssl compiler: gcc - os: macos-12 openssl: awslc - openssl: awslc buildtool: cmake - openssl: awslc compiler: gcc runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v4 with: submodules: recursive - name: Linux setup if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install \ g++-12 \ clang-15 \ autoconf \ automake \ autotools-dev \ libtool \ pkg-config \ zlib1g-dev \ libssl-dev \ libxml2-dev \ libev-dev \ libevent-dev \ libjansson-dev \ libjemalloc-dev \ libc-ares-dev \ libelf-dev \ libbrotli-dev \ cmake \ cmake-data echo 'CPPFLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined -g' >> $GITHUB_ENV echo 'LDFLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined' >> $GITHUB_ENV # https://github.com/actions/runner-images/issues/9491#issuecomment-1989718917 # Asan in llvm 14 provided in ubuntu 22.04 is incompatible with # high-entropy ASLR in much newer kernels that GitHub runners are # using leading to random crashes: https://reviews.llvm.org/D148280 sudo sysctl vm.mmap_rnd_bits=28 - name: MacOS setup if: runner.os == 'macOS' run: | brew install \ libev \ libevent \ c-ares \ libressl \ brotli \ autoconf \ automake \ pkg-config \ libtool echo 'PKG_CONFIG_PATH=/usr/local/opt/libressl/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig' >> $GITHUB_ENV - name: Setup clang (Linux) if: runner.os == 'Linux' && matrix.compiler == 'clang' run: | echo 'CC=clang-15' >> $GITHUB_ENV echo 'CXX=clang++-15' >> $GITHUB_ENV - name: Setup clang (MacOS) if: runner.os == 'macOS' && matrix.compiler == 'clang' run: | echo 'CC=clang' >> $GITHUB_ENV echo 'CXX=clang++' >> $GITHUB_ENV - name: Setup gcc (Linux) if: runner.os == 'Linux' && matrix.compiler == 'gcc' run: | echo 'CC=gcc-12' >> $GITHUB_ENV echo 'CXX=g++-12' >> $GITHUB_ENV - name: Setup gcc (MacOS) if: runner.os == 'macOS' && matrix.compiler == 'gcc' run: | echo 'CC=gcc' >> $GITHUB_ENV echo 'CXX=g++' >> $GITHUB_ENV - name: Restore libbpf cache uses: actions/cache/restore@v4 if: matrix.http3 == 'http3' && matrix.compiler == 'clang' && runner.os == 'Linux' with: path: libbpf/build key: ${{ runner.os }}-libbpf-${{ env.LIBBPF_VERSION }} fail-on-cache-miss: true - name: Set libbpf variables if: matrix.http3 == 'http3' && matrix.compiler == 'clang' && runner.os == 'Linux' run: | cd libbpf EXTRA_AUTOTOOLS_OPTS="--with-libbpf" EXTRA_CMAKE_OPTS="-DWITH_LIBBPF=1" echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV - name: Restore quictls/openssl v1.1.1 cache uses: actions/cache/restore@v4 if: matrix.http3 == 'http3' && matrix.openssl == 'openssl1' with: path: openssl1/build key: ${{ runner.os }}-openssl-${{ env.OPENSSL1_VERSION }} fail-on-cache-miss: true - name: Restore quictls/openssl v3.x cache uses: actions/cache/restore@v4 if: matrix.http3 == 'http3' && matrix.openssl == 'openssl3' with: path: openssl3/build key: ${{ runner.os }}-openssl-${{ env.OPENSSL3_VERSION }} fail-on-cache-miss: true - name: Restore BoringSSL cache uses: actions/cache/restore@v4 if: matrix.openssl == 'boringssl' with: path: | boringssl/build/crypto/libcrypto.a boringssl/build/ssl/libssl.a boringssl/include key: ${{ runner.os }}-boringssl-${{ env.BORINGSSL_VERSION }} fail-on-cache-miss: true - name: Restore aws-lc cache uses: actions/cache/restore@v4 if: matrix.openssl == 'awslc' with: path: | aws-lc/build/crypto/libcrypto.a aws-lc/build/ssl/libssl.a aws-lc/include key: ${{ runner.os }}-awslc-${{ env.AWSLC_VERSION }} fail-on-cache-miss: true - name: Set BoringSSL variables if: matrix.openssl == 'boringssl' run: | cd boringssl OPENSSL_CFLAGS="-I$PWD/include/" OPENSSL_LIBS="-L$PWD/build/ssl -lssl -L$PWD/build/crypto -lcrypto -pthread" EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --without-neverbleed --without-jemalloc --disable-examples" echo 'OPENSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV echo 'OPENSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV echo 'BORINGSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV - name: Set aws-lc variables if: matrix.openssl == 'awslc' run: | cd aws-lc OPENSSL_CFLAGS="-I$PWD/include/" OPENSSL_LIBS="-L$PWD/build/ssl -lssl -L$PWD/build/crypto -lcrypto -pthread" EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --without-neverbleed --without-jemalloc" echo 'OPENSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV echo 'OPENSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV echo 'BORINGSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV - name: Restore nghttp3 cache uses: actions/cache/restore@v4 if: matrix.http3 == 'http3' with: path: nghttp3/build key: ${{ runner.os }}-nghttp3-${{ env.NGHTTP3_VERSION }} fail-on-cache-miss: true - name: Restore ngtcp2 + quictls/openssl v1.1.1 cache + BoringSSL uses: actions/cache/restore@v4 if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl1' || matrix.openssl == 'boringssl') with: path: ngtcp2-openssl1/build key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }} fail-on-cache-miss: true - name: Restore ngtcp2 + quictls/openssl v3.x cache + aws-lc uses: actions/cache/restore@v4 if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl3' || matrix.openssl == 'awslc') with: path: ngtcp2-openssl3/build key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL3_VERSION }} fail-on-cache-miss: true - name: Setup extra environment variables for HTTP/3 if: matrix.http3 == 'http3' run: | PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib/pkgconfig:$PWD/nghttp3/build/lib/pkgconfig:$PWD/ngtcp2-openssl1/build/lib/pkgconfig:$PWD/ngtcp2-openssl3/build/lib/pkgconfig:$PWD/libbpf/build/lib64/pkgconfig:$PKG_CONFIG_PATH" LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib -Wl,-rpath,$PWD/libbpf/build/lib64" EXTRA_AUTOTOOLS_OPTS="--enable-http3 $EXTRA_AUTOTOOLS_OPTS" EXTRA_CMAKE_OPTS="-DENABLE_HTTP3=1 $EXTRA_CMAKE_OPTS" echo 'PKG_CONFIG_PATH='"$PKG_CONFIG_PATH" >> $GITHUB_ENV echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV - name: Configure autotools run: | autoreconf -i ./configure - name: Configure cmake (Linux) if: matrix.buildtool == 'cmake' && runner.os == 'Linux' run: | make dist VERSION=$(grep PACKAGE_VERSION config.h | cut -d' ' -f3 | tr -d '"') tar xf nghttp2-$VERSION.tar.gz cd nghttp2-$VERSION echo 'NGHTTP2_CMAKE_DIR='"$PWD" >> $GITHUB_ENV cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1 -DENABLE_APP=1 $EXTRA_CMAKE_OPTS -DCPPFLAGS="$CPPFLAGS" -DLDFLAGS="$LDFLAGS" -DBUILD_STATIC_LIBS=ON -DBUILD_TESTING=ON . - name: Configure cmake (MacOS) if: matrix.buildtool == 'cmake' && runner.os == 'macOS' run: | make dist VERSION=$(grep PACKAGE_VERSION config.h | cut -d' ' -f3 | tr -d '"') tar xf nghttp2-$VERSION.tar.gz cd nghttp2-$VERSION echo 'NGHTTP2_CMAKE_DIR='"$PWD" >> $GITHUB_ENV # This fixes infamous 'stdio.h not found' error. echo 'SDKROOT='"$(xcrun --sdk macosx --show-sdk-path)" >> $GITHUB_ENV cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DENABLE_APP=1 $EXTRA_CMAKE_OPTS -DCPPFLAGS="$CPPFLAGS" -DLDFLAGS="$LDFLAGS" -DBUILD_STATIC_LIBS=ON -DBUILD_TESTING=ON . - name: Build nghttp2 with autotools (Linux) if: matrix.buildtool == 'autotools' && runner.os == 'Linux' run: | make -j"$(nproc)" distcheck \ DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\"" - name: Build nghttp2 with autotools (MacOS) if: matrix.buildtool == 'autotools' && runner.os == 'macOS' run: | make -j"$(sysctl -n hw.ncpu)" distcheck \ DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\"" - name: Build nghttp2 with cmake if: matrix.buildtool == 'cmake' run: | cd $NGHTTP2_CMAKE_DIR make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check - uses: actions/setup-go@v5 if: matrix.buildtool == 'cmake' with: go-version-file: go.mod - name: Integration test # Integration tests for nghttpx; autotools erases build # artifacts. if: matrix.buildtool == 'cmake' run: | cd $NGHTTP2_CMAKE_DIR/integration-tests make it build-cross: strategy: matrix: host: [x86_64-w64-mingw32, i686-w64-mingw32] runs-on: ubuntu-22.04 env: HOST: ${{ matrix.host }} steps: - name: Checkout uses: actions/checkout@v4 with: submodules: recursive - name: Linux setup run: | sudo dpkg --add-architecture i386 sudo apt-get update sudo apt-get install \ gcc-mingw-w64 \ autoconf \ automake \ autotools-dev \ libtool \ pkg-config \ wine - name: Configure autotools run: | autoreconf -i && \ ./configure --enable-werror --enable-lib-only --host="$HOST" \ CFLAGS="-g -O2 -D_WIN32_WINNT=0x0600" LIBS="-pthread" - name: Build nghttp2 run: | make -j$(nproc) make -j$(nproc) check TESTS="" - name: Run tests if: matrix.host == 'x86_64-w64-mingw32' run: | export WINEPATH=/usr/x86_64-w64-mingw32/lib cd tests wine main.exe build-windows: strategy: matrix: arch: [x86, x64] include: - arch: x86 platform: Win32 - arch: x64 platform: x64 runs-on: windows-latest steps: - name: Checkout uses: actions/checkout@v4 with: submodules: recursive - uses: microsoft/setup-msbuild@v2 - name: Configure cmake run: cmake -B build -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_GENERATOR_PLATFORM=${{ matrix.platform }} -DVCPKG_TARGET_TRIPLET=${{ matrix.arch}}-windows -DBUILD_STATIC_LIBS=ON -DBUILD_TESTING=ON - name: Build nghttp2 run: | cmake --build build cmake --build build --target check release: if: github.ref_type == 'tag' needs: - build - build-cross - build-windows permissions: contents: write runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 submodules: recursive - name: Make artifacts run: | ver='${{ github.ref_name }}' prev_ver=$(git tag --sort v:refname | grep -v -F "${ver}" | \ grep 'v[0-9]\+\.[0-9]\+\.0' | tail -n1) echo -n "$GPG_KEY" | gpg --batch --pinentry-mode loopback --import ./makerelease.sh "${ver}" "${prev_ver}" env: GPG_KEY: ${{ secrets.GPG_KEY }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - name: Make release uses: actions/github-script@v7 with: script: | const fs = require('fs') let ver = '${{ github.ref_name }}' let {data: release} = await github.rest.repos.createRelease({ owner: context.repo.owner, repo: context.repo.repo, tag_name: ver, name: `nghttp2 ${ver}`, draft: true, generate_release_notes: true, discussion_category_name: 'Announcements', }) let v = ver.substring(1) let files = [ 'checksums.txt', `nghttp2-${v}.tar.bz2`, `nghttp2-${v}.tar.bz2.asc`, `nghttp2-${v}.tar.gz`, `nghttp2-${v}.tar.gz.asc`, `nghttp2-${v}.tar.xz`, `nghttp2-${v}.tar.xz.asc`, ] await Promise.all(files.map(elem => github.rest.repos.uploadReleaseAsset({ owner: context.repo.owner, repo: context.repo.repo, release_id: release.id, name: elem, data: fs.readFileSync(elem), }) ))