diff --git a/.drone.star b/.drone.star index 81d36457..54a6b271 100644 --- a/.drone.star +++ b/.drone.star @@ -8,27 +8,126 @@ # For Drone CI we use the Starlark scripting language to reduce duplication. # As the yaml syntax for Drone CI is rather limited. # -# + +globalenv = { + 'B2_CI_VERSION': '1', + 'B2_VARIANT': 'debug,release', + 'B2_FLAGS': 'warnings=extra warnings-as-errors=on', +} def main(ctx): - return generate( - # Compilers + # generate() provides: main compiler matrix, asan, ubsan, coverage, + # and cmake-superproject (linux/latest gcc) by default + jobs = generate( [ - 'gcc >=10.0', - 'clang >=10.0', - 'msvc >=14.1', - 'arm64-gcc latest', - 's390x-gcc latest', - # 'freebsd-gcc latest', - 'apple-clang *', - 'arm64-clang latest', - 's390x-clang latest', - 'freebsd-clang latest', - 'x86-msvc latest' + 'gcc >=13.0', + 'clang >=17.0', + # 'msvc >=14.1', + 'arm64-clang latest' + # 'x86-msvc latest' ], - # Standards '>=20', - packages=['zlib1g', 'zlib1g-dev', 'libbrotli-dev']) + cmake=False, + docs=False, + coverage=False, + asan=False, + cache_dir='cache') + # Note: liburing-dev is not added to generate()'s package list. + # generate() emits jobs on Ubuntu focal (which has no liburing-dev + # package at all) and jammy (liburing 2.1, which our probe rejects + # for being too old). Either way io_uring stays disabled, so the + # install would just fail focal. The manual jobs below that target + # noble (24.04) explicitly install liburing-dev where it works. + + # macOS: generate() skips apple-clang when cxx_range='>=20' because + # ci-automation's compiler_supports() doesn't list C++20 for apple-clang + # jobs += [ + # osx_cxx("macOS: Clang 16.2.0", "clang++", packages="", + # buildscript="drone", buildtype="boost", + # xcode_version="16.2.0", + # environment={ + # 'B2_TOOLSET': 'clang', + # 'B2_CXXSTD': '20', + # }, + # globalenv=globalenv), + # + # osx_cxx("macOS: Clang 26.2.0", "clang++", packages="", + # buildscript="drone", buildtype="boost", + # xcode_version="26.2.0", + # environment={ + # 'B2_TOOLSET': 'clang', + # 'B2_CXXSTD': '20', + # }, + # globalenv=globalenv), + # ] + + # jobs += [ + # freebsd_cxx("clang-22", "clang++-22", + # buildscript="drone", buildtype="boost", + # freebsd_version="15.0", + # environment={ + # 'B2_TOOLSET': 'clang-22', + # 'B2_CXXSTD': '20', + # }, + # globalenv=globalenv), + # ] + + # Jobs not covered by generate() + jobs += [ + # linux_cxx("Valgrind", "clang++-17", packages="clang-17 libc6-dbg libstdc++-12-dev liburing-dev", + # llvm_os="jammy", llvm_ver="17", + # buildscript="drone", buildtype="valgrind", + # image="cppalliance/droneubuntu2204:1", + # environment={ + # 'COMMENT': 'valgrind', + # 'B2_TOOLSET': 'clang-17', + # 'B2_CXXSTD': '20', + # 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', + # 'B2_VARIANT': 'debug', + # 'B2_TESTFLAGS': 'testing.launcher=valgrind', + # 'VALGRIND_OPTS': '--error-exitcode=1', + # }, + # globalenv=globalenv), + + # Note: no liburing-dev on the Drone cmake jobs even though the + # noble image has 2.5+. Docker's default seccomp profile blocks + # the io_uring_setup syscall (post-CVE hardening), so io_uring + # tests would compile in but abort at runtime with EPERM + # ('io_uring_queue_init_params: Operation not permitted'). + # Without liburing-dev the CMake probe disables the backend and + # the cmake-mainproject/subdirectory jobs exercise epoll only. + # io_uring runtime coverage is provided by the GitHub Actions + # Linux jobs, which run on unrestricted GitHub-hosted runners. + linux_cxx("cmake-mainproject", "g++-13", packages="g++-13", + image="cppalliance/droneubuntu2404:1", + buildtype="cmake-mainproject", buildscript="drone", + environment={ + 'COMMENT': 'cmake-mainproject', + 'CXX': 'g++-13', + }, + globalenv=globalenv), + + linux_cxx("cmake-subdirectory", "g++-13", packages="g++-13", + image="cppalliance/droneubuntu2404:1", + buildtype="cmake-subdirectory", buildscript="drone", + environment={ + 'COMMENT': 'cmake-subdirectory', + 'CXX': 'g++-13', + }, + globalenv=globalenv) + + # windows_cxx("msvc-14.3 cmake-superproject", "", + # image="cppalliance/dronevs2022:1", + # buildtype="cmake-superproject", buildscript="drone", + # environment={ + # 'B2_TOOLSET': 'msvc-14.3', + # 'B2_CXXSTD': '20', + # }, + # globalenv=globalenv), + ] + + return jobs + # from https://github.com/cppalliance/ci-automation load("@ci_automation//ci/drone/:functions.star", "linux_cxx", "windows_cxx", "osx_cxx", "freebsd_cxx", "generate") diff --git a/.drone/drone.bat b/.drone/drone.bat index b310d140..c5c3beb0 100644 --- a/.drone/drone.bat +++ b/.drone/drone.bat @@ -47,6 +47,9 @@ pushd !BOOST_ROOT!\libs git clone https://github.com/cppalliance/capy -b !BOOST_BRANCH! --depth 1 popd pushd !BOOST_ROOT!\libs +git clone https://github.com/cppalliance/corosio -b !BOOST_BRANCH! --depth 1 +popd +pushd !BOOST_ROOT!\libs git clone https://github.com/cppalliance/http -b !BOOST_BRANCH! --depth 1 popd diff --git a/.drone/drone.sh b/.drone/drone.sh index 2a249e5b..0d56d2b0 100644 --- a/.drone/drone.sh +++ b/.drone/drone.sh @@ -47,6 +47,12 @@ common_install () { popd fi + if [ ! -d "$BOOST_ROOT/libs/corosio" ]; then + pushd $BOOST_ROOT/libs + git clone https://github.com/cppalliance/corosio -b $BOOST_BRANCH --depth 1 + popd + fi + if [ ! -d "$BOOST_ROOT/libs/http" ]; then pushd $BOOST_ROOT/libs git clone https://github.com/cppalliance/http -b $BOOST_BRANCH --depth 1 @@ -139,6 +145,12 @@ if [ ! -d "$BOOST_ROOT/libs/capy" ]; then popd fi +if [ ! -d "$BOOST_ROOT/libs/corosio" ]; then + pushd $BOOST_ROOT/libs + git clone https://github.com/cppalliance/corosio -b $BOOST_BRANCH --depth 1 + popd +fi + if [ ! -d "$BOOST_ROOT/libs/http" ]; then pushd $BOOST_ROOT/libs git clone https://github.com/cppalliance/http -b $BOOST_BRANCH --depth 1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1110c661..ae63341f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,8 @@ name: CI on: pull_request: + branches: [ master, develop ] + workflow_dispatch: push: branches: - master @@ -34,21 +36,27 @@ env: NET_RETRY_COUNT: 5 DEFAULT_BUILD_VARIANT: debug,release UBSAN_OPTIONS: "print_stacktrace=1" - ASAN_OPTIONS: "detect_invalid_pointer_pairs=2" + DEBIAN_FRONTEND: "noninteractive" + TZ: "Europe/London" jobs: - runner-selection: - name: Runner Selection - runs-on: ${{ github.repository_owner == 'boostorg' && fromJSON('[ "self-hosted", "linux", "x64", "ubuntu-latest-aws" ]') || 'ubuntu-latest' }} - outputs: - labelmatrix: ${{ steps.aws_hosted_runners.outputs.labelmatrix }} - steps: - - name: AWS Hosted Runners - id: aws_hosted_runners - uses: cppalliance/aws-hosted-runners@v1.0.0 + # Self-hosted runner selection is disabled to allow re-running individual + # failed jobs from the GitHub Actions UI. When using dynamic runner selection, + # the runs-on value depends on this job's output, which isn't available when + # re-running a subset of jobs. + # + # runner-selection: + # name: Runner Selection + # runs-on: ${{ github.repository_owner == 'boostorg' && fromJSON('[ "self-hosted", "linux", "x64", "ubuntu-latest-aws" ]') || 'ubuntu-latest' }} + # outputs: + # labelmatrix: ${{ steps.aws_hosted_runners.outputs.labelmatrix }} + # steps: + # - name: AWS Hosted Runners + # id: aws_hosted_runners + # uses: cppalliance/aws-hosted-runners@v1.0.0 build: - needs: [ runner-selection ] + # needs: [ runner-selection ] defaults: run: shell: bash @@ -57,8 +65,7 @@ jobs: fail-fast: false matrix: include: - # Windows compilers - # + # Windows (3 configurations) - compiler: "msvc" version: "14.42" @@ -80,68 +87,14 @@ jobs: runs-on: "windows-2022" b2-toolset: "msvc-14.3" generator: "Visual Studio 17 2022" - is-latest: true - name: "MSVC 14.34: C++20" + name: "MSVC 14.34: C++20 (shared)" shared: true build-type: "Release" - build-cmake: true - - - compiler: "msvc" - version: "14.34" - cxxstd: "20" - latest-cxxstd: "20" - runs-on: "windows-2022" - b2-toolset: "msvc-14.3" - generator: "Visual Studio 17 2022" - is-latest: true - name: "MSVC 14.34: C++17-20 (x86)" - shared: false - x86: true - build-type: "Release" - - - compiler: "msvc" - version: "14.34" - cxxstd: "20" - latest-cxxstd: "20" - runs-on: "windows-2022" - b2-toolset: "msvc-14.3" - generator: "Visual Studio 17 2022" - is-latest: true - name: "MSVC 14.34: C++20" - shared: true - build-type: "Release" - build-cmake: true - - - compiler: "clang-cl" - version: "*" - cxx: "clang++-cl" - cc: "clang-cl" - runs-on: "windows-2022" - b2-toolset: "clang-win" - generator-toolset: "ClangCL" - is-latest: true - is-earliest: true - name: "Windows-Clang" - shared: false - build-type: "Release" - build-cmake: true - - - compiler: "mingw" - version: "*" - cxx: "g++" - cc: "gcc" - runs-on: "windows-2022" - b2-toolset: "gcc" - generator: "MinGW Makefiles" - is-latest: true - is-earliest: true - name: "MinGW (shared)" - shared: true - build-type: "Release" - build-cmake: true - compiler: "mingw" version: "*" + cxxstd: "20" + latest-cxxstd: "20" cxx: "g++" cc: "gcc" runs-on: "windows-2022" @@ -149,228 +102,59 @@ jobs: generator: "MinGW Makefiles" is-latest: true is-earliest: true - name: "MinGW (static)" + name: "MinGW: C++20" shared: false build-type: "Release" build-cmake: true - # OSX compilers + # macOS (1 configuration) + # TODO: Re-enable when BSD/kqueue support is implemented # - - - compiler: "apple-clang" - version: "*" - cxx: "clang++" - cc: "clang" - runs-on: "macos-26" - b2-toolset: "clang" - is-latest: true - name: "Apple-Clang (macOS 26)" - shared: true - build-type: "Release" - build-cmake: true - - - compiler: "apple-clang" - version: "*" - cxx: "clang++" - cc: "clang" - runs-on: "macos-26" - b2-toolset: "clang" - is-latest: true - name: "Apple-Clang (macOS 26, ubsan)" - shared: false - build-type: "RelWithDebInfo" - ubsan: true - - - compiler: "apple-clang" - version: "*" - cxx: "clang++" - cc: "clang" - runs-on: "macos-26" - b2-toolset: "clang" - is-latest: true - name: "Apple-Clang (macOS 26, asan)" - shared: true - build-type: "RelWithDebInfo" - asan: true - - - compiler: "apple-clang" - version: "*" - cxx: "clang++" - cc: "clang" - runs-on: "macos-15" - b2-toolset: "clang" - name: "Apple-Clang (macOS 15)" - shared: false - build-type: "Release" - build-cmake: true - - - compiler: "apple-clang" - version: "*" - cxx: "clang++" - cc: "clang" - runs-on: "macos-14" - b2-toolset: "clang" - name: "Apple-Clang (macOS 14)" - shared: true - build-type: "Release" - build-cmake: true - - # Linux compilers - # - - - compiler: "gcc" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-15" - cc: "gcc-15" - runs-on: "ubuntu-latest" - container: "ubuntu:25.04" - b2-toolset: "gcc" - is-latest: true - name: "GCC 15: C++20" - shared: false - build-type: "Release" - build-cmake: true - - - compiler: "gcc" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-15" - cc: "gcc-15" - runs-on: "ubuntu-latest" - container: "ubuntu:25.04" - b2-toolset: "gcc" - is-latest: true - name: "GCC 15: C++20 (no zlib)" - shared: true - build-type: "Release" - build-cmake: true - - - compiler: "gcc" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-15" - cc: "gcc-15" - runs-on: "ubuntu-latest" - container: "ubuntu:25.04" - b2-toolset: "gcc" - is-latest: true - name: "GCC 15: C++20 (x86)" - shared: false - x86: true - build-type: "Release" - install: "gcc-15-multilib g++-15-multilib" - - - compiler: "gcc" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-15" - cc: "gcc-15" - runs-on: "ubuntu-latest" - container: "ubuntu:25.04" - b2-toolset: "gcc" - is-latest: true - name: "GCC 15: C++20" - shared: true - build-type: "Release" - build-cmake: true - - - compiler: "gcc" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-15" - cc: "gcc-15" - runs-on: "ubuntu-latest" - container: "ubuntu:25.04" - b2-toolset: "gcc" - is-latest: true - name: "GCC 15: C++20 (x86)" - shared: false - x86: true - build-type: "Release" - install: "gcc-15-multilib g++-15-multilib" - build-cmake: true - - - compiler: "gcc" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-15" - cc: "gcc-15" - runs-on: "ubuntu-latest" - container: "ubuntu:25.04" - b2-toolset: "gcc" - is-latest: true - name: "GCC 15: C++20 (asan)" - shared: true - asan: true - build-type: "RelWithDebInfo" - - - compiler: "gcc" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-15" - cc: "gcc-15" - runs-on: "ubuntu-latest" - container: "ubuntu:25.04" - b2-toolset: "gcc" - is-latest: true - name: "GCC 15: C++20 (asan, x86)" - shared: false - asan: true - x86: true - build-type: "RelWithDebInfo" - install: "gcc-15-multilib g++-15-multilib" - - - compiler: "gcc" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-15" - cc: "gcc-15" - runs-on: "ubuntu-latest" - container: "ubuntu:25.04" - b2-toolset: "gcc" - is-latest: true - name: "GCC 15: C++20 (ubsan)" - shared: false - ubsan: true - build-type: "RelWithDebInfo" - - - compiler: "gcc" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-15" - cc: "gcc-15" - runs-on: "ubuntu-latest" - container: "ubuntu:25.04" - b2-toolset: "gcc" - is-latest: true - name: "GCC 15: C++20 (ubsan, x86)" - shared: false - ubsan: true - x86: true - build-type: "RelWithDebInfo" - install: "gcc-15-multilib g++-15-multilib" - - - compiler: "gcc" - version: "14" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-14" - cc: "gcc-14" - runs-on: "ubuntu-24.04" - b2-toolset: "gcc" - name: "GCC 14: C++20" - shared: true - build-type: "Release" + # - compiler: "apple-clang" + # version: "*" + # cxxstd: "20" + # latest-cxxstd: "20" + # cxx: "clang++" + # cc: "clang" + # runs-on: "macos-26" + # b2-toolset: "clang" + # is-latest: true + # name: "Apple-Clang (macOS 26, asan+ubsan): C++20" + # shared: true + # build-type: "RelWithDebInfo" + # asan: true + # ubsan: true + + # - compiler: "gcc" + # version: "15" + # cxxstd: "20" + # latest-cxxstd: "20" + # cxx: "g++-15" + # cc: "gcc-15" + # runs-on: "ubuntu-latest" + # container: "ubuntu:25.04" + # b2-toolset: "gcc" + # is-latest: true + # name: "GCC 15: C++20" + # shared: false # TODO + # build-type: "Release" + # build-cmake: true + + # - compiler: "gcc" + # version: "15" + # cxxstd: "20" + # latest-cxxstd: "20" + # cxx: "g++-15" + # cc: "gcc-15" + # runs-on: "ubuntu-latest" + # container: "ubuntu:25.04" + # b2-toolset: "gcc" + # is-latest: true + # name: "GCC 15: C++20 (asan+ubsan)" + # shared: true + # asan: true + # ubsan: true + # build-type: "RelWithDebInfo" - compiler: "gcc" version: "13" @@ -380,19 +164,6 @@ jobs: cc: "gcc-13" runs-on: "ubuntu-24.04" b2-toolset: "gcc" - name: "GCC 13: C++20" - shared: true - build-type: "Release" - - - compiler: "gcc" - version: "13" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-13" - cc: "gcc-13" - runs-on: "ubuntu-24.04" - b2-toolset: "gcc" - is-latest: true name: "GCC 13: C++20 (coverage)" shared: false coverage: true @@ -401,35 +172,9 @@ jobs: ccflags: "--coverage -fprofile-arcs -ftest-coverage" install: "lcov wget unzip" - - compiler: "gcc" - version: "12" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-12" - cc: "gcc-12" - runs-on: "ubuntu-latest" - container: "ubuntu:22.04" - b2-toolset: "gcc" - name: "GCC 12: C++20" - shared: true - build-type: "Release" - - - compiler: "gcc" - version: "11" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "g++-11" - cc: "gcc-11" - runs-on: "ubuntu-latest" - container: "ubuntu:22.04" - b2-toolset: "gcc" - name: "GCC 11: C++20" - shared: false - build-type: "Release" - - compiler: "clang" version: "20" - cxxstd: "23,2c" + cxxstd: "20,23" latest-cxxstd: "23" cxx: "clang++-20" cc: "clang-20" @@ -437,27 +182,11 @@ jobs: container: "ubuntu:24.04" b2-toolset: "clang" is-latest: true - name: "Clang 20: C++23-2C" - shared: true + name: "Clang 20: C++20-23" + shared: false # TODO build-type: "Release" build-cmake: true - - compiler: "clang" - version: "20" - cxxstd: "23,2c" - latest-cxxstd: "23" - cxx: "clang++-20" - cc: "clang-20" - runs-on: "ubuntu-latest" - container: "ubuntu:24.04" - b2-toolset: "clang" - is-latest: true - name: "Clang 20: C++23-2C (x86)" - shared: false - x86: true - build-type: "Release" - install: "gcc-multilib g++-multilib" - - compiler: "clang" version: "20" cxxstd: "20" @@ -468,102 +197,12 @@ jobs: container: "ubuntu:24.04" b2-toolset: "clang" is-latest: true - name: "Clang 20: C++20 (time-trace)" - shared: true - time-trace: true - build-type: "Release" - cxxflags: "-ftime-trace" - ccflags: "-ftime-trace" - install: " wget unzip" - - - compiler: "clang" - version: "20" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "clang++-20" - cc: "clang-20" - runs-on: "ubuntu-latest" - container: "ubuntu:24.04" - b2-toolset: "clang" - is-latest: true - name: "Clang 20: C++20 (asan)" + name: "Clang 20: C++20 (asan+ubsan)" shared: false asan: true - build-type: "RelWithDebInfo" - - - compiler: "clang" - version: "20" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "clang++-20" - cc: "clang-20" - runs-on: "ubuntu-latest" - container: "ubuntu:24.04" - b2-toolset: "clang" - is-latest: true - name: "Clang 20: C++20 (asan, x86)" - shared: true - asan: true - x86: true - build-type: "RelWithDebInfo" - install: "gcc-multilib g++-multilib" - - - compiler: "clang" - version: "20" - cxxstd: "23,2c" - latest-cxxstd: "23" - cxx: "clang++-20" - cc: "clang-20" - runs-on: "ubuntu-latest" - container: "ubuntu:24.04" - b2-toolset: "clang" - is-latest: true - name: "Clang 20: C++23-2C (ubsan)" - shared: false ubsan: true build-type: "RelWithDebInfo" - - compiler: "clang" - version: "20" - cxxstd: "23,2c" - latest-cxxstd: "23" - cxx: "clang++-20" - cc: "clang-20" - runs-on: "ubuntu-latest" - container: "ubuntu:24.04" - b2-toolset: "clang" - is-latest: true - name: "Clang 20: C++23-2C (ubsan, x86)" - shared: true - ubsan: true - x86: true - build-type: "RelWithDebInfo" - install: "gcc-multilib g++-multilib" - - - compiler: "clang" - version: "19" - cxxstd: "20,2b" - latest-cxxstd: "20" - cxx: "clang++-19" - cc: "clang-19" - runs-on: "ubuntu-24.04" - b2-toolset: "clang" - name: "Clang 19: C++20-2b" - shared: false - build-type: "Release" - - - compiler: "clang" - version: "18" - cxxstd: "20,2b" - latest-cxxstd: "20" - cxx: "clang++-18" - cc: "clang-18" - runs-on: "ubuntu-24.04" - b2-toolset: "clang" - name: "Clang 18: C++20-2b" - shared: true - build-type: "Release" - - compiler: "clang" version: "17" cxxstd: "20" @@ -577,184 +216,74 @@ jobs: build-type: "Release" - compiler: "clang" - version: "16" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "clang++-16" - cc: "clang-16" - runs-on: "ubuntu-24.04" - b2-toolset: "clang" - name: "Clang 16: C++20" - shared: true - build-type: "Release" - - - compiler: "clang" - version: "15" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "clang++-15" - cc: "clang-15" - runs-on: "ubuntu-latest" - container: "ubuntu:22.04" - b2-toolset: "clang" - name: "Clang 15: C++17-20" - shared: false - build-type: "Release" - - - compiler: "clang" - version: "14" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "clang++-14" - cc: "clang-14" - runs-on: "ubuntu-latest" - container: "ubuntu:22.04" - b2-toolset: "clang" - name: "Clang 14: C++17-20" - shared: true - build-type: "Release" - - - compiler: "clang" - version: "13" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "clang++-13" - cc: "clang-13" - runs-on: "ubuntu-latest" - container: "ubuntu:22.04" - b2-toolset: "clang" - name: "Clang 13: C++20" - shared: false - build-type: "Release" - - - compiler: "clang" - version: "12" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "clang++-12" - cc: "clang-12" - runs-on: "ubuntu-latest" - container: "ubuntu:22.04" - b2-toolset: "clang" - name: "Clang 12: C++20" - shared: true - build-type: "Release" - - - compiler: "clang" - version: "11" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "clang++-11" - cc: "clang-11" + version: "20" + cxxstd: "20,23" + latest-cxxstd: "23" + cxx: "clang++-20" + cc: "clang-20" runs-on: "ubuntu-latest" - container: "ubuntu:22.04" + container: "ubuntu:24.04" b2-toolset: "clang" - name: "Clang 11: C++20" + is-latest: true + name: "Clang 20: C++20-23 (x86)" shared: false + x86: true build-type: "Release" - - - compiler: "clang" - version: "10" - cxxstd: "20" - latest-cxxstd: "20" - cxx: "clang++-10" - cc: "clang-10" - runs-on: "ubuntu-latest" - container: "ubuntu:20.04" - b2-toolset: "clang" - name: "Clang 10: C++20" - shared: true - build-type: "Release" + install: "gcc-multilib g++-multilib" name: ${{ matrix.name }} - runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.runs-on] }} + # Skip self-hosted runner selection for now + # runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.runs-on] }} + runs-on: ${{ matrix.runs-on }} container: image: ${{ matrix.container }} options: --privileged - volumes: - - /node20217:/node20217:rw,rshared - - ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }} + timeout-minutes: 120 steps: - - name: install nodejs20glibc2.17 - if: ${{ startsWith( matrix.container, 'ubuntu:1' ) }} - run: | - apt-get update - apt-get -yqq install xz-utils curl - curl -LO https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz - tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217 - ldd /__e/node20/bin/node - - - name: Clone Boost.Http.Io - uses: actions/checkout@v3 + - name: Clone Boost.Beast2 + uses: actions/checkout@v4 with: - path: http-io-root - - - name: Clone Boost.Http.Proto - uses: actions/checkout@v3 - with: - repository: cppalliance/http - path: http-proto-root - ref: develop - - - name: Clone Boost.Buffers - uses: actions/checkout@v3 - with: - path: buffers-root - repository: cppalliance/buffers - ref: develop - - - name: Clone Boost.Capy - uses: actions/checkout@v3 - with: - path: capy-root - repository: cppalliance/capy - ref: develop + path: beast2-root - name: Setup C++ - uses: alandefreitas/cpp-actions/setup-cpp@v1.9.0 + uses: alandefreitas/cpp-actions/setup-cpp@v1.9.4 id: setup-cpp with: compiler: ${{ matrix.compiler }} version: ${{ matrix.version }} - check-latest: ${{ matrix.compiler != 'clang' || matrix.version != '^3.8' }} + check-latest: true trace-commands: true - name: Install packages - uses: alandefreitas/cpp-actions/package-install@v1.9.0 + uses: alandefreitas/cpp-actions/package-install@v1.9.4 id: package-install with: apt-get-add-architecture: ${{ matrix.x86 && 'i386' || '' }} apt-get: >- ${{ matrix.install }} - build-essential libssl-dev zlib1g-dev libbrotli-dev libpsl-dev - ${{ matrix.x86 && 'libssl-dev:i386 zlib1g-dev:i386 libbrotli-dev:i386 libpsl-dev:i386' || '' }} + build-essential libssl-dev zlib1g-dev libbrotli-dev libzstd-dev + ${{ matrix.x86 && 'libssl-dev:i386 zlib1g-dev:i386 libbrotli-dev:i386 libzstd-dev:i386' || '' }} - name: Clone Boost - uses: alandefreitas/cpp-actions/boost-clone@v1.9.0 + uses: alandefreitas/cpp-actions/boost-clone@v1.9.4 id: boost-clone with: branch: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }} boost-dir: boost-source - modules-exclude-paths: '' - scan-modules-dir: | - http-io-root - http-proto-root - buffers-root - capy-root - scan-modules-ignore: | - beast2 - http - buffers - capy + scan-modules-dir: beast2-root + patches: > + https://github.com/cppalliance/capy + https://github.com/cppalliance/corosio + https://github.com/cppalliance/http - name: Install Packages (Windows) - uses: alandefreitas/cpp-actions/package-install@v1.9.0 + uses: alandefreitas/cpp-actions/package-install@v1.9.4 if: ${{ startsWith(matrix.runs-on, 'windows') }} id: package-install-windows with: - vcpkg: zlib brotli openssl + vcpkg: zlib brotli zstd openssl vcpkg-dir: vcpkg-root vcpkg-triplet: ${{ matrix.x86 && 'x86-windows-static' || 'x64-windows' }} @@ -769,11 +298,12 @@ jobs: triplet=${{ matrix.x86 && 'x86-windows-static' || 'x64-windows' }} addrmdl=${{ matrix.x86 && '32' || '64' }} - # This is temporary until we move capy/build/brotli.jam to boost/tools/build - echo "import-search ${home}/boost-root/libs/capy/build ;" | sed 's/\/d\//D:\//g' >> user-config.jam + # This is temporary until we move http/build/brotli.jam to boost/tools/build + echo "import-search ${home}/boost-root/libs/http/build ;" | sed 's/\/d\//D:\//g' >> user-config.jam echo "using zlib : : \"${home}/vcpkg-root/installed/${triplet}/include\" \"${home}/vcpkg-root/installed/${triplet}/lib\" \"${home}/vcpkg-root/installed/${triplet}/bin\" zlib : ${addrmdl} ;" | sed 's/\/d\//D:\//g' >> user-config.jam echo "using brotli : : \"${home}/vcpkg-root/installed/${triplet}/include\" \"${home}/vcpkg-root/installed/${triplet}/lib\" \"${home}/vcpkg-root/installed/${triplet}/bin\" : ${addrmdl} ;" | sed 's/\/d\//D:\//g' >> user-config.jam + echo "using zstd : : \"${home}/vcpkg-root/installed/${triplet}/include\" \"${home}/vcpkg-root/installed/${triplet}/lib\" \"${home}/vcpkg-root/installed/${triplet}/bin\" : ${addrmdl} ;" | sed 's/\/d\//D:\//g' >> user-config.jam echo "using openssl : : \"${home}/vcpkg-root/installed/${triplet}/include\" \"${home}/vcpkg-root/installed/${triplet}/lib\" \"${home}/vcpkg-root/installed/${triplet}/bin\" libssl libcrypto : ${addrmdl} ;" | sed 's/\/d\//D:\//g' >> user-config.jam cat user-config.jam @@ -821,16 +351,13 @@ jobs: echo -E "boost_root=$boost_root" >> $GITHUB_OUTPUT # Patch boost-root with workspace module - cp -r "$workspace_root"/http-io-root "libs/$module" - cp -r "$workspace_root"/http-proto-root libs/http - cp -r "$workspace_root"/buffers-root libs/buffers - cp -r "$workspace_root"/capy-root libs/capy + cp -r "$workspace_root"/beast2-root "libs/$module" - name: Boost B2 Workflow - uses: alandefreitas/cpp-actions/b2-workflow@v1.9.0 - if: ${{ !matrix.coverage && !matrix.time-trace }} + uses: alandefreitas/cpp-actions/b2-workflow@v1.9.4 + if: ${{ !matrix.coverage }} env: - ASAN_OPTIONS: ${{ (startsWith(matrix.compiler, 'apple-clang') && 'detect_invalid_pointer_pairs=0') || 'detect_invalid_pointer_pairs=2' }} + ASAN_OPTIONS: ${{ ((matrix.compiler == 'apple-clang' || matrix.compiler == 'clang') && 'detect_invalid_pointer_pairs=0:strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1') || 'detect_invalid_pointer_pairs=2:strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1' }} with: source-dir: boost-root modules: beast2 @@ -842,23 +369,22 @@ jobs: asan: ${{ matrix.asan }} ubsan: ${{ matrix.ubsan }} shared: ${{ matrix.shared }} - rtti: ${{ (matrix.is-latest && 'on,off') || 'on' }} - cxxflags: ${{ (matrix.asan && '-fsanitize=pointer-subtract') || '' }} + rtti: on + cxxflags: ${{ (matrix.asan && '-fsanitize-address-use-after-scope -fsanitize=pointer-subtract') || '' }} user-config: ${{ ((startsWith(matrix.runs-on, 'windows') || startsWith(matrix.runs-on, 'macOS')) && format('{0}/user-config.jam', steps.patch.outputs.workspace_root)) || '' }} stop-on-error: true - extra-args: "libs/beast2/example" - name: Boost CMake Workflow - uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.0 - if: ${{ matrix.coverage || matrix.time-trace || matrix.build-cmake || matrix.is-earliest }} + uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.4 + if: ${{ matrix.coverage || matrix.build-cmake || matrix.is-earliest }} with: source-dir: boost-root build-dir: __build_cmake_test__ generator: ${{ matrix.generator }} generator-toolset: ${{ matrix.generator-toolset }} build-type: ${{ matrix.build-type }} - build-target: tests run-tests: true + install: true install-prefix: .local cxxstd: ${{ matrix.latest-cxxstd }} cc: ${{ steps.setup-cpp.outputs.cc || matrix.cc }} @@ -870,7 +396,6 @@ jobs: extra-args: | -D Boost_VERBOSE=ON -D BOOST_INCLUDE_LIBRARIES="${{ steps.patch.outputs.module }}" - export-compile-commands: ${{ matrix.time-trace }} package: false package-artifact: false ref-source-dir: boost-root/libs/beast2 @@ -885,9 +410,13 @@ jobs: run: | echo "LD_LIBRARY_PATH=$GITHUB_WORKSPACE/.local/lib:$LD_LIBRARY_PATH" >> "$GITHUB_ENV" + # Disabled: Boost's CMake infrastructure does not generate install rules for + # the "main" library in BOOST_INCLUDE_LIBRARIES, only for its dependencies. + # This causes find_package(Boost COMPONENTS burl) to fail because + # boost_beast2Config.cmake is never installed. - name: Find Package Integration Workflow - uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.0 - if: ${{ matrix.build-cmake || matrix.is-earliest }} + uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.4 + if: false # ${{ matrix.build-cmake || matrix.is-earliest }} with: source-dir: boost-root/libs/${{ steps.patch.outputs.module }}/test/cmake_test build-dir: __build_cmake_install_test__ @@ -901,7 +430,7 @@ jobs: cxxflags: ${{ matrix.cxxflags }} shared: ${{ matrix.shared }} install: false - cmake-version: '>=3.20' + cmake-version: '>=3.15' extra-args: | -D BOOST_CI_INSTALL_TEST=ON -D CMAKE_PREFIX_PATH=${{ steps.patch.outputs.workspace_root }}/.local @@ -910,7 +439,7 @@ jobs: toolchain: ${{ (startsWith(matrix.runs-on, 'windows') && steps.patch-user-config.outputs.toolchain) || '' }} - name: Subdirectory Integration Workflow - uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.0 + uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.4 if: ${{ matrix.build-cmake || matrix.is-earliest }} with: source-dir: boost-root/libs/${{ steps.patch.outputs.module }}/test/cmake_test @@ -925,89 +454,93 @@ jobs: cxxflags: ${{ matrix.cxxflags }} shared: ${{ matrix.shared }} install: false - cmake-version: '>=3.20' + cmake-version: '>=3.15' extra-args: -D BOOST_CI_INSTALL_TEST=OFF ref-source-dir: boost-root/libs/beast2/test/cmake_test toolchain: ${{ (startsWith(matrix.runs-on, 'windows') && steps.patch-user-config.outputs.toolchain) || '' }} - # - name: Root Project CMake Workflow - # uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.0 - # if: ${{ matrix.build-cmake || matrix.is-earliest }} - # with: - # source-dir: boost-root/libs/${{ steps.patch.outputs.module }} - # build-dir: __build_root_test__ - # run-tests: true - # generator: ${{ matrix.generator }} - # generator-toolset: ${{ matrix.generator-toolset }} - # build-type: ${{ matrix.build-type }} - # install: false - # cxxstd: ${{ matrix.latest-cxxstd }} - # cc: ${{ steps.setup-cpp.outputs.cc || matrix.cc }} - # ccflags: ${{ matrix.ccflags }} - # cxx: ${{ steps.setup-cpp.outputs.cxx || matrix.cxx }} - # cxxflags: ${{ matrix.cxxflags }} - # shared: ${{ matrix.shared }} - # cmake-version: '>=3.20' - # package: false - # package-artifact: false - # ref-source-dir: boost-root - # toolchain: ${{ (startsWith(matrix.runs-on, 'windows') && steps.patch-user-config.outputs.toolchain) || '' }} - - - name: FlameGraph - uses: alandefreitas/cpp-actions/flamegraph@v1.9.0 - if: matrix.time-trace + - name: Root Project CMake Workflow + uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.4 + if: ${{ matrix.build-cmake || matrix.is-earliest }} with: - source-dir: boost-root/libs/beast2 - build-dir: boost-root/__build_cmake_test__ - github_token: ${{ secrets.GITHUB_TOKEN }} + source-dir: boost-root/libs/${{ steps.patch.outputs.module }} + build-dir: __build_root_test__ + build-target: tests + run-tests: true + generator: ${{ matrix.generator }} + generator-toolset: ${{ matrix.generator-toolset }} + build-type: ${{ matrix.build-type }} + install: false + cxxstd: ${{ matrix.latest-cxxstd }} + cc: ${{ steps.setup-cpp.outputs.cc || matrix.cc }} + ccflags: ${{ matrix.ccflags }} + cxx: ${{ steps.setup-cpp.outputs.cxx || matrix.cxx }} + cxxflags: ${{ matrix.cxxflags }} + shared: ${{ matrix.shared }} + cmake-version: '>=3.20' + package: false + package-artifact: false + ref-source-dir: boost-root + toolchain: ${{ (startsWith(matrix.runs-on, 'windows') && steps.patch-user-config.outputs.toolchain) || '' }} - - name: Codecov + - name: Generate Coverage Report if: ${{ matrix.coverage }} run: | set -x - - # Generate report gcov_tool="gcov" - if command -v "gcov-${{ steps.setup-cpp.outputs.version-major }}.${{ steps.setup-cpp.outputs.version-minor }}" &> /dev/null; then - gcov_tool="gcov" - elif command -v "gcov-${{ steps.setup-cpp.outputs.version-major }}" &> /dev/null; then + if command -v "gcov-${{ steps.setup-cpp.outputs.version-major }}" &> /dev/null; then gcov_tool="gcov-${{ steps.setup-cpp.outputs.version-major }}" fi - lcov -c -q -o "boost-root/__build_cmake_test__/coverage.info" -d "boost-root/__build_cmake_test__" --include "$(pwd)/boost-root/libs/${{steps.patch.outputs.module}}/*" --gcov-tool "$gcov_tool" - - # Upload to codecov - bash <(curl -s https://codecov.io/bash) -f "boost-root/__build_cmake_test__/coverage.info" + lcov -c -q -o "boost-root/__build_cmake_test__/coverage.info" -d "boost-root/__build_cmake_test__" \ + --include "$(pwd)/boost-root/libs/${{ steps.patch.outputs.module }}/include/*" \ + --include "$(pwd)/boost-root/libs/${{ steps.patch.outputs.module }}/src/*" \ + --gcov-tool "$gcov_tool" - # Summary + - name: Upload to Codecov + if: ${{ matrix.coverage }} + uses: codecov/codecov-action@v5 + with: + files: boost-root/__build_cmake_test__/coverage.info + flags: linux + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false + verbose: true + disable_search: true + plugins: noop + + - name: Coverage Summary + if: ${{ matrix.coverage }} + run: | echo "# Coverage" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "[![codecov](https://codecov.io/github/$GITHUB_REPOSITORY/commit/$GITHUB_SHA/graphs/sunburst.svg)](https://codecov.io/github/$GITHUB_REPOSITORY/commit/$GITHUB_SHA)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY echo "Commit: [![codecov](https://codecov.io/github/$GITHUB_REPOSITORY/commit/$GITHUB_SHA/graph/badge.svg)](https://codecov.io/github/$GITHUB_REPOSITORY/commit/$GITHUB_SHA)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "Branch: [![codecov](https://codecov.io/github/$GITHUB_REPOSITORY/branch/$GITHUB_REF_NAME/graph/badge.svg)](https://codecov.io/github/$GITHUB_REPOSITORY/commit/$GITHUB_SHA)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY changelog: - needs: [ runner-selection ] + # needs: [ runner-selection ] defaults: run: shell: bash name: Changelog Summary - runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)['ubuntu-22.04'] }} + # Skip self-hosted runner selection for now + # runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)['ubuntu-22.04'] }} + runs-on: 'ubuntu-22.04' timeout-minutes: 120 steps: - - name: Clone Boost.Http.Io - uses: actions/checkout@v3 + - name: Clone Boost.Beast2 + uses: actions/checkout@v4 with: # Avoid the common API rate limit exceeded error in boostorg by including 100 latest commits in any case fetch-depth: 100 - name: Changelog - uses: alandefreitas/cpp-actions/create-changelog@v1.9.0 + uses: alandefreitas/cpp-actions/create-changelog@v1.9.4 with: thank-non-regular: ${{ startsWith(github.ref, 'refs/tags/') }} github-token: ${{ secrets.GITHUB_TOKEN }} @@ -1015,67 +548,36 @@ jobs: tag-pattern: 'boost-.*\..*\..*' antora: - needs: [ runner-selection ] - strategy: - matrix: - include: - - { name: Windows, os: windows-latest } - - { name: Ubuntu, os: ubuntu-latest } - - { name: MacOS, os: macos-15 } - name: Antora Docs (${{ matrix.name }}) - runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }} + # needs: [ runner-selection ] + name: Antora Docs + # Skip self-hosted runner selection for now + # runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)['ubuntu-latest'] }} + runs-on: 'ubuntu-latest' defaults: run: shell: bash steps: - name: Install packages - uses: alandefreitas/cpp-actions/package-install@v1.9.0 + uses: alandefreitas/cpp-actions/package-install@v1.9.4 with: apt-get: git cmake - - name: Clone Boost.Http.Io - uses: actions/checkout@v3 - with: - path: http-io-root - - - name: Clone Boost.Http.Proto - uses: actions/checkout@v3 - with: - repository: cppalliance/http - path: http-proto-root - ref: develop - - - name: Clone Boost.Buffers - uses: actions/checkout@v3 + - name: Clone Boost.Beast2 + uses: actions/checkout@v4 with: - path: buffers-root - repository: cppalliance/buffers - ref: develop - - - name: Clone Boost.Capy - uses: actions/checkout@v3 - with: - path: capy-root - repository: cppalliance/capy - ref: develop + path: beast2-root - name: Clone Boost - uses: alandefreitas/cpp-actions/boost-clone@v1.9.0 + uses: alandefreitas/cpp-actions/boost-clone@v1.9.4 id: boost-clone with: branch: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }} boost-dir: boost-source - modules-exclude-paths: '' - scan-modules-dir: | - http-io-root - http-proto-root - buffers-root - capy-root - scan-modules-ignore: | - beast2 - http - buffers - capy + scan-modules-dir: beast2-root + patches: > + https://github.com/cppalliance/capy + https://github.com/cppalliance/corosio + https://github.com/cppalliance/http - name: Patch Boost id: patch @@ -1107,32 +609,25 @@ jobs: echo -E "boost_root=$boost_root" >> $GITHUB_OUTPUT # Patch boost-root with workspace module - cp -r "$workspace_root"/http-io-root "libs/$module" - cp -r "$workspace_root"/http-proto-root libs/http - cp -r "$workspace_root"/buffers-root libs/buffers - cp -r "$workspace_root"/capy-root libs/capy + cp -r "$workspace_root"/beast2-root "libs/$module" - uses: actions/setup-node@v4 with: node-version: 18 - - name: Setup Ninja - if: runner.os == 'Windows' - uses: seanmiddleditch/gha-setup-ninja@v5 - - name: Build Antora Docs env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | git config --global --add safe.directory "$(pwd)" - + BOOST_SRC_DIR="$(pwd)/boost-root" export BOOST_SRC_DIR cd boost-root/libs/beast2 - + cd doc bash ./build_antora.sh - + # Antora returns zero even if it fails, so we check if the site directory exists if [ ! -d "build/site" ]; then echo "Antora build failed" @@ -1142,5 +637,5 @@ jobs: - name: Create Antora Docs Artifact uses: actions/upload-artifact@v4 with: - name: antora-docs-${{ matrix.name }} + name: antora-docs path: boost-root/libs/beast2/doc/build/site diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index 6897037d..f27803e1 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -5,12 +5,14 @@ # Distributed under the Boost Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # +# Official repository: https://github.com/cppalliance/beast2/ +# # Instructions # -# After running this workflow successfully, go to https://github.com/ORGANIZATION/REPO/settings/pages +# After running this workflow successfully, go to https://github.com/cppalliance/beast2/settings/pages # and enable github pages on the code-coverage branch. -# The pages will be hosted at https://ORGANIZATION.github.io/REPO +# The coverage will be hosted at https://cppalliance.org/beast2 # name: Code Coverage @@ -23,6 +25,7 @@ on: paths: - 'src/**' - 'include/**' + - 'test/**' - '.github/workflows/code-coverage.yml' workflow_dispatch: @@ -33,50 +36,105 @@ concurrency: env: GIT_FETCH_JOBS: 8 NET_RETRY_COUNT: 5 - # Commit title of the automatically created commits GCOVR_COMMIT_MSG: "Update coverage data" - # Should branch coverage be reported? Default to no. - BOOST_BRANCH_COVERAGE: 0 - EXTRA_BOOST_LIBRARIES: "cppalliance/buffers cppalliance/capy cppalliance/corosio cppalliance/http" jobs: - build: + build-linux: defaults: run: shell: bash - - strategy: - fail-fast: false - matrix: - include: - - runs-on: "ubuntu-24.04" - name: Coverage - cxxstd: "20" - gcovr_script: './ci-automation/scripts/lcov-jenkins-gcc-13.sh --only-gcovr' - - name: ${{ matrix.name }} - runs-on: ${{ matrix.runs-on }} + name: Coverage (Linux) + runs-on: ubuntu-24.04 timeout-minutes: 120 steps: - - name: Checkout code + - name: Clone Boost.Beast2 uses: actions/checkout@v6 + with: + path: beast2-root - - name: Check for code-coverage Branch + - name: Setup C++ + uses: alandefreitas/cpp-actions/setup-cpp@v1.9.4 + id: setup-cpp + with: + compiler: gcc + version: 13 + check-latest: true + + - name: Install packages + uses: alandefreitas/cpp-actions/package-install@v1.9.4 + with: + apt-get: >- + build-essential libssl-dev zlib1g-dev libbrotli-dev + lcov + + - name: Clone Boost + uses: alandefreitas/cpp-actions/boost-clone@v1.9.4 + id: boost-clone + with: + branch: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }} + boost-dir: boost-source + scan-modules-dir: beast2-root + patches: > + https://github.com/cppalliance/capy + https://github.com/cppalliance/corosio + https://github.com/cppalliance/http + + - name: ASLR Fix + run: sysctl vm.mmap_rnd_bits=28 + + - name: Patch Boost + id: patch run: | - set -xe - git config --global user.name cppalliance-bot - git config --global user.email cppalliance-bot@example.com - git fetch origin - if git branch -r | grep origin/code-coverage; then - echo "The code-coverage branch exists. Continuing." - else - echo "The code-coverage branch does not exist. Creating it." - git switch --orphan code-coverage - git commit --allow-empty -m "$GCOVR_COMMIT_MSG" - git push origin code-coverage - git checkout $GITHUB_REF_NAME - fi + set -xe + + # Identify boost module being tested + module=${GITHUB_REPOSITORY#*/} + echo "module=$module" >> $GITHUB_OUTPUT + + # Identify GitHub workspace root + workspace_root=$(echo "$GITHUB_WORKSPACE" | sed 's/\\/\//g') + echo -E "workspace_root=$workspace_root" >> $GITHUB_OUTPUT + + # Remove module from boost-source + rm -r "boost-source/libs/$module" || true + + # Copy cached boost-source to an isolated boost-root + cp -r boost-source boost-root + + # Set boost-root output + cd boost-root + boost_root="$(pwd)" + boost_root=$(echo "$boost_root" | sed 's/\\/\//g') + echo -E "boost_root=$boost_root" >> $GITHUB_OUTPUT + cd .. + + # Patch boost-root with workspace module + cp -r "$workspace_root"/beast2-root "boost-root/libs/$module" + + - name: Build with coverage + uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.4 + with: + source-dir: boost-root + build-dir: __build_cmake_test__ + build-type: Debug + build-target: tests + run-tests: true + install-prefix: .local + cxxstd: '20' + cc: ${{ steps.setup-cpp.outputs.cc || 'gcc-13' }} + cxx: ${{ steps.setup-cpp.outputs.cxx || 'g++-13' }} + cxxflags: '--coverage -fprofile-arcs -ftest-coverage' + ccflags: '--coverage -fprofile-arcs -ftest-coverage' + shared: false + cmake-version: '>=3.20' + extra-args: | + -D Boost_VERBOSE=ON + -D BOOST_INCLUDE_LIBRARIES="${{ steps.patch.outputs.module }}" + -D CMAKE_EXPORT_COMPILE_COMMANDS=ON + package: false + package-artifact: false + ref-source-dir: boost-root/libs/beast2 - name: Install Python uses: actions/setup-python@v6 @@ -92,14 +150,100 @@ jobs: repository: cppalliance/ci-automation path: ci-automation - - name: Build and run tests & collect coverage data + - name: Generate gcovr report + run: | + set -xe + module=$(basename ${GITHUB_REPOSITORY}) + gcov_tool="gcov-${{ steps.setup-cpp.outputs.version-major }}" + command -v "$gcov_tool" >/dev/null 2>&1 || gcov_tool="gcov" + mkdir -p gcovr + + # First pass: collect raw coverage data into JSON + gcovr \ + --root boost-root \ + --gcov-executable "$gcov_tool" \ + --merge-mode-functions separate \ + --sort uncovered-percent \ + --html-title "${module}" \ + --merge-lines \ + --exclude-unreachable-branches \ + --exclude-throw-branches \ + --exclude '.*/example/.*' \ + --exclude '.*/examples/.*' \ + --filter ".*/${module}/.*" \ + --html --output gcovr/index.html \ + --json-summary-pretty --json-summary gcovr/summary.json \ + --json gcovr/coverage-raw.json \ + boost-root/__build_cmake_test__ + + # Fix paths for repo-relative display + python3 ci-automation/scripts/fix_paths.py \ + gcovr/coverage-raw.json \ + gcovr/coverage-fixed.json \ + --repo "${module}" + + # Create symlinks so gcovr can find source files at repo-relative paths + ln -sfn "boost-root/libs/${module}/include" include 2>/dev/null || true + ln -sfn "boost-root/libs/${module}/src" src 2>/dev/null || true + + # Second pass: generate nested HTML from fixed JSON with custom templates + gcovr \ + -a gcovr/coverage-fixed.json \ + --merge-mode-functions separate \ + --sort uncovered-percent \ + --html-nested \ + --html-template-dir=ci-automation/gcovr-templates/html \ + --html-title "${module}" \ + --merge-lines \ + --exclude-unreachable-branches \ + --exclude-throw-branches \ + --exclude '(^|.*/)test/.*' \ + --exclude '.*/example/.*' \ + --exclude '.*/examples/.*' \ + --html --output gcovr/index.html \ + --json-summary-pretty --json-summary gcovr/summary.json + + - name: Generate sidebar navigation + run: python3 ci-automation/scripts/gcovr_build_tree.py gcovr + + - name: Generate badges + run: python3 ci-automation/scripts/generate_badges.py gcovr --json gcovr/summary.json + + - name: Upload coverage artifact + uses: actions/upload-artifact@v4 + with: + name: coverage-linux + path: gcovr/ + + deploy: + needs: [build-linux] + if: ${{ !cancelled() }} + defaults: + run: + shell: bash + name: Deploy Coverage + runs-on: ubuntu-24.04 + timeout-minutes: 30 + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Check for code-coverage Branch run: | set -xe - ls -al - export ORGANIZATION=${GITHUB_REPOSITORY_OWNER} - export REPONAME=$(basename ${GITHUB_REPOSITORY}) - export B2_CXXSTD=${{matrix.cxxstd}} - ${{matrix.gcovr_script}} + git config --global user.name cppalliance-bot + git config --global user.email cppalliance-bot@example.com + git fetch origin + if git branch -r | grep origin/code-coverage; then + echo "The code-coverage branch exists. Continuing." + else + echo "The code-coverage branch does not exist. Creating it." + git switch --orphan code-coverage + git commit --allow-empty -m "$GCOVR_COMMIT_MSG" + git push origin code-coverage + git checkout $GITHUB_REF_NAME + fi - name: Checkout GitHub pages branch uses: actions/checkout@v6 @@ -107,21 +251,61 @@ jobs: ref: code-coverage path: gh_pages_dir - - name: Copy gcovr results + - name: Download coverage artifacts + uses: actions/download-artifact@v4 + with: + pattern: coverage-* + path: coverage-artifacts/ + + - name: Copy coverage results run: | set -xe - pwd - ls -al - touch gh_pages_dir/.nojekyll # Prevent GH pages from treating these files as Jekyll pages. - mkdir -p gh_pages_dir/develop - mkdir -p gh_pages_dir/master + touch gh_pages_dir/.nojekyll + + mkdir -p "gh_pages_dir/develop" + mkdir -p "gh_pages_dir/master" + + # Remove old single-directory layout (migration from gcovr/ to gcovr-linux/) rm -rf "gh_pages_dir/${GITHUB_REF_NAME}/gcovr" - cp -rp gcovr "gh_pages_dir/${GITHUB_REF_NAME}/" - echo -e "\n\n\n\ndevelop
\nmaster
\n\n\n" > gh_pages_dir/index.html - # In the future: echo -e "\n\n\n\ngcovr
\n\n\n" > gh_pages_dir/develop/index.html - echo -e "\n\n\n\n\n\n\n" > gh_pages_dir/develop/index.html - cp gh_pages_dir/develop/index.html gh_pages_dir/master/index.html + + # Copy each platform's results (only if artifact exists) + for platform in linux; do + if [ -d "coverage-artifacts/coverage-${platform}" ]; then + rm -rf "gh_pages_dir/${GITHUB_REF_NAME}/gcovr-${platform}" + cp -rp "coverage-artifacts/coverage-${platform}" \ + "gh_pages_dir/${GITHUB_REF_NAME}/gcovr-${platform}" + fi + done + + # Generate branch index pages + for branch in develop master; do + cat > "gh_pages_dir/${branch}/index.html" << 'HTMLEOF' + + Code Coverage + +

Code Coverage Reports

+ + + + HTMLEOF + done + + # Root index + cat > gh_pages_dir/index.html << 'HTMLEOF' + + + + develop
+ master
+ + + HTMLEOF + cd gh_pages_dir + git config --global user.name cppalliance-bot + git config --global user.email cppalliance-bot@example.com git add . git commit --amend -m "$GCOVR_COMMIT_MSG" git push -f origin code-coverage diff --git a/CMakeLists.txt b/CMakeLists.txt index b1ae3901..27ea1b3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,6 @@ set(BOOST_BEAST2_DEPENDENCIES Boost::http Boost::json Boost::mp11 - Boost::static_assert Boost::system Boost::throw_exception Boost::url @@ -153,6 +152,7 @@ function(boost_beast2_setup_properties target) PUBLIC "${PROJECT_SOURCE_DIR}/include" PRIVATE "${PROJECT_SOURCE_DIR}") target_link_libraries(${target} PUBLIC ${BOOST_BEAST2_DEPENDENCIES}) + target_link_libraries(${target} PUBLIC Boost::corosio_openssl) find_package(Threads REQUIRED) target_link_libraries(${target} PUBLIC Threads::Threads) if (MINGW) diff --git a/build/Jamfile b/build/Jamfile index bf1ff920..fe4840bf 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -39,11 +39,13 @@ lib boost_beast2 : beast2_sources : requirements /boost//corosio + /boost/corosio//boost_corosio_openssl /boost//http ../ BOOST_BEAST2_SOURCE : usage-requirements /boost//corosio + /boost/corosio//boost_corosio_openssl /boost//http ; diff --git a/example/server/certificate.cpp b/example/server/certificate.cpp index 58ce35c9..6b1fcf17 100644 --- a/example/server/certificate.cpp +++ b/example/server/certificate.cpp @@ -9,6 +9,7 @@ #include "certificate.hpp" #include +#include #include namespace boost { @@ -124,12 +125,12 @@ load_server_certificate( for(auto const& t : certs) { - ctx.use_certificate_chain(t.first); + std::ignore = ctx.use_certificate_chain(t.first); // use_private_key applies to the last inserted certificate, // see: https://linux.die.net/man/3/ssl_ctx_use_privatekey // - ctx.use_private_key(t.second, + std::ignore = ctx.use_private_key(t.second, corosio::tls_file_format::pem); } diff --git a/example/server/main.cpp b/example/server/main.cpp index 4999a6cc..7d7ba710 100644 --- a/example/server/main.cpp +++ b/example/server/main.cpp @@ -14,9 +14,8 @@ #include #include #include -#include #include -#include +#include #include #include #include @@ -34,6 +33,7 @@ #include #include #include +#include namespace boost { namespace beast2 { @@ -172,7 +172,7 @@ int server_main( int argc, char* argv[] ) if(rp.req.method() != http::method::post) co_return http::route_next; http::json_sink js; - auto [ec, n] = co_await capy::push_to(rp.req_body, js); + auto [ec, n] = co_await http::push_to(rp.req_body, js); if(ec) co_return http::route_error(ec); json::value jv = js.release(); @@ -217,7 +217,7 @@ int server_main( int argc, char* argv[] ) #endif corosio::signal_set sigs(ioc); - sigs.add(SIGINT); + std::ignore = sigs.add(SIGINT); capy::run_async(ioc.get_executor())( [&]() -> capy::task { diff --git a/example/server/serve_log_admin.cpp b/example/server/serve_log_admin.cpp index 9980c008..0de5cb0b 100644 --- a/example/server/serve_log_admin.cpp +++ b/example/server/serve_log_admin.cpp @@ -27,7 +27,7 @@ class serve_log_page { } - system::error_code + std::error_code operator()( http::route_params&) const { @@ -95,7 +95,7 @@ class handle_submit { } - system::error_code + std::error_code operator()( http::route_params&) const { diff --git a/include/boost/beast2.hpp b/include/boost/beast2.hpp index 6affa4df..cf35279e 100644 --- a/include/boost/beast2.hpp +++ b/include/boost/beast2.hpp @@ -16,7 +16,5 @@ #include #include #include -#include -#include #endif diff --git a/include/boost/beast2/detail/config.hpp b/include/boost/beast2/detail/config.hpp index 0a5f9a88..ac4af049 100644 --- a/include/boost/beast2/detail/config.hpp +++ b/include/boost/beast2/detail/config.hpp @@ -29,31 +29,13 @@ namespace beast2 { # define BOOST_BEAST2_DECL # endif # if !defined(BOOST_BEAST2_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_BEAST2_NO_LIB) -# define BOOST_LIB_NAME boost_json +# define BOOST_LIB_NAME boost_beast2 # if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_BEAST2_DYN_LINK) # define BOOST_DYN_LINK # endif # include # endif -//------------------------------------------------ - -// Add source location to error codes -#ifdef BOOST_BEAST2_NO_SOURCE_LOCATION -# define BOOST_BEAST2_ERR(ev) (::boost::system::error_code(ev)) -# define BOOST_BEAST2_RETURN_EC(ev) return (ev) -#else -# define BOOST_BEAST2_ERR(ev) ( \ - ::boost::system::error_code( (ev), [] { \ - static constexpr auto loc((BOOST_CURRENT_LOCATION)); \ - return &loc; }())) -# define BOOST_BEAST2_RETURN_EC(ev) \ - do { \ - static constexpr auto loc ## __LINE__((BOOST_CURRENT_LOCATION)); \ - return ::boost::system::error_code((ev), &loc ## __LINE__); \ - } while(0) -#endif - } // beast2 namespace http {} diff --git a/include/boost/beast2/error.hpp b/include/boost/beast2/error.hpp index ed0cd9ef..beabcb51 100644 --- a/include/boost/beast2/error.hpp +++ b/include/boost/beast2/error.hpp @@ -11,9 +11,7 @@ #define BOOST_BEAST2_ERROR_HPP #include -#include -#include -#include +#include #include namespace boost { @@ -27,45 +25,38 @@ enum class error }; } // beast2 +} // boost -namespace system { +namespace std { template<> struct is_error_code_enum< ::boost::beast2::error> -{ - static bool const value = true; -}; -} // system + : std::true_type {}; +} // std +namespace boost { namespace beast2 { namespace detail { struct BOOST_SYMBOL_VISIBLE error_cat_type - : system::error_category + : std::error_category { BOOST_BEAST2_DECL const char* name( ) const noexcept override; BOOST_BEAST2_DECL std::string message( int) const override; - BOOST_BEAST2_DECL char const* message( - int, char*, std::size_t - ) const noexcept override; - BOOST_SYSTEM_CONSTEXPR error_cat_type() - : error_category(0x515eb9dbd1314d96 ) - { - } + constexpr error_cat_type() noexcept = default; }; BOOST_BEAST2_DECL extern error_cat_type error_cat; } // detail inline -BOOST_SYSTEM_CONSTEXPR -system::error_code +std::error_code make_error_code( error ev) noexcept { - return system::error_code{ + return std::error_code{ static_cast::type>(ev), detail::error_cat}; diff --git a/include/boost/beast2/http_worker.hpp b/include/boost/beast2/http_worker.hpp index c7a51fa2..c7242bcd 100644 --- a/include/boost/beast2/http_worker.hpp +++ b/include/boost/beast2/http_worker.hpp @@ -57,8 +57,8 @@ namespace beast2 { , sock(ctx) { sock.open(); - rp.req_body = capy::any_buffer_source(parser.source_for(sock)); - rp.res_body = capy::any_buffer_sink(serializer.sink_for(sock)); + rp.req_body = http::any_buffer_source(parser.source_for(sock)); + rp.res_body = http::any_buffer_sink(serializer.sink_for(sock)); stream = capy::any_read_stream(&sock); } diff --git a/include/boost/beast2/test/impl/error.hpp b/include/boost/beast2/test/impl/error.hpp index 4a410663..abc96f56 100644 --- a/include/boost/beast2/test/impl/error.hpp +++ b/include/boost/beast2/test/impl/error.hpp @@ -10,19 +10,15 @@ #ifndef BOOST_BEAST2_TEST_IMPL_ERROR_HPP #define BOOST_BEAST2_TEST_IMPL_ERROR_HPP -#include -#include +#include +#include -namespace boost { -namespace system { +namespace std { template<> struct is_error_code_enum< - boost::beast2::test::error> - : std::true_type -{ -}; -} // system -} // boost + ::boost::beast2::test::error> + : std::true_type {}; +} // std namespace boost { namespace beast2 { @@ -31,7 +27,7 @@ namespace test { namespace detail { class error_cat_type : - public system::error_category + public std::error_category { public: const char* @@ -40,8 +36,8 @@ class error_cat_type : return "boost.beast2.test"; } - char const* - message(int ev, char*, std::size_t) const noexcept override + std::string + message(int ev) const override { switch(static_cast(ev)) { @@ -50,18 +46,12 @@ class error_cat_type : "An automatic unit test failure occurred"; } } - - std::string - message(int ev) const override - { - return message(ev, nullptr, 0); - } }; } // detail inline -system::error_code +std::error_code make_error_code(error e) noexcept { static detail::error_cat_type const cat{}; diff --git a/src/error.cpp b/src/error.cpp index d49d9d5b..ba95276f 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -8,8 +8,6 @@ // #include -#include -#include namespace boost { namespace beast2 { @@ -26,22 +24,12 @@ name() const noexcept std::string error_cat_type:: message(int code) const -{ - return message(code, nullptr, 0); -} - -char const* -error_cat_type:: -message( - int code, - char*, - std::size_t) const noexcept { switch(static_cast(code)) { - case error::success: return "http::error::success"; + case error::success: return "beast2::error::success"; default: - return "http::error::?"; + return "beast2::error::?"; } } diff --git a/src/http_server.cpp b/src/http_server.cpp index bd76b4e3..2b23b0c1 100644 --- a/src/http_server.cpp +++ b/src/http_server.cpp @@ -12,9 +12,9 @@ #include #include #include -#include #include -#include +#include +#include #include #include #include @@ -23,6 +23,7 @@ #include #include #include +#include namespace boost { namespace beast2 { @@ -61,10 +62,10 @@ struct http_server:: , strand(ctx_.get_executor()) , sock(ctx_) { - sock.open(); + std::ignore = sock.open(); - rp.req_body = capy::any_buffer_source(parser.source_for(sock)); - rp.res_body = capy::any_buffer_sink(serializer.sink_for(sock)); + rp.req_body = http::any_buffer_source(parser.source_for(sock)); + rp.res_body = http::any_buffer_sink(serializer.sink_for(sock)); stream = capy::any_read_stream(&sock); } @@ -83,7 +84,7 @@ struct http_server:: { co_await do_http_session(); - sock.shutdown(corosio::tcp_socket::shutdown_both); // VFALCO too wordy + std::ignore = sock.shutdown(corosio::tcp_socket::shutdown_both); // VFALCO too wordy } }; diff --git a/src/https_server.cpp b/src/https_server.cpp index 42f5b019..f898940b 100644 --- a/src/https_server.cpp +++ b/src/https_server.cpp @@ -12,10 +12,10 @@ #include #include #include -#include #include -#include #include +#include +#include #include #include #include @@ -25,6 +25,7 @@ #include #include #include +#include namespace boost { namespace beast2 { @@ -68,7 +69,7 @@ struct https_server:: , sock(ctx_) , tls_ctx(srv_->impl_->tls_ctx) { - sock.open(); + std::ignore = sock.open(); } corosio::tcp_socket& socket() override @@ -88,18 +89,18 @@ struct https_server:: ssl = std::make_unique(&sock, tls_ctx); // Perform TLS handshake as server - auto [hs_ec] = co_await ssl->handshake(corosio::tls_stream::server); + auto [hs_ec] = co_await ssl->handshake(corosio::tls_role::server); if(hs_ec) { std::cerr << "TLS handshake error: " << hs_ec.message() << "\n"; - sock.shutdown(corosio::tcp_socket::shutdown_both); + std::ignore = sock.shutdown(corosio::tcp_socket::shutdown_both); ssl.reset(); co_return; } // Wire parser and serializer to the TLS stream - rp.req_body = capy::any_buffer_source(parser.source_for(*ssl)); - rp.res_body = capy::any_buffer_sink(serializer.sink_for(*ssl)); + rp.req_body = http::any_buffer_source(parser.source_for(*ssl)); + rp.res_body = http::any_buffer_sink(serializer.sink_for(*ssl)); stream = capy::any_read_stream(ssl.get()); // Process HTTP requests over TLS @@ -115,7 +116,7 @@ struct https_server:: // Clean up TLS stream before TCP shutdown ssl.reset(); - sock.shutdown(corosio::tcp_socket::shutdown_both); + std::ignore = sock.shutdown(corosio::tcp_socket::shutdown_both); } }; diff --git a/src/route_rule.hpp b/src/route_rule.hpp index 3c5e2f03..5773a66a 100644 --- a/src/route_rule.hpp +++ b/src/route_rule.hpp @@ -199,8 +199,7 @@ constexpr struct if(it == end || *it != '(') return ""; if(it == end) - BOOST_BEAST2_RETURN_EC( - grammar::error::syntax); + return grammar::error::syntax; auto it0 = it; it = grammar::find_if_not( it, end, constraint_char{}); @@ -208,20 +207,17 @@ constexpr struct { // too small it = it0; - BOOST_BEAST2_RETURN_EC( - grammar::error::syntax); + return grammar::error::syntax; } if(it == end) { it = it0; - BOOST_BEAST2_RETURN_EC( - grammar::error::syntax); + return grammar::error::syntax; } if(*it != ')') { it0 = it; - BOOST_BEAST2_RETURN_EC( - grammar::error::syntax); + return grammar::error::syntax; } return core::string_view(++it0, it++); } @@ -238,11 +234,9 @@ constexpr struct system::result { if(it == end) - BOOST_BEAST2_RETURN_EC( - grammar::error::syntax); + return grammar::error::syntax; if(! grammar::alpha_chars(*it)) - BOOST_BEAST2_RETURN_EC( - grammar::error::syntax); + return grammar::error::syntax; auto it0 = it++; it = grammar::find_if_not( it, end, ident_char{}); @@ -276,11 +270,9 @@ struct param_segment_rule_t system::result { if(it == end) - BOOST_BEAST2_RETURN_EC( - grammar::error::syntax); + return grammar::error::syntax; if(*it != ':' && *it != '*') - BOOST_BEAST2_RETURN_EC( - grammar::error::mismatch); + return grammar::error::mismatch; value_type v; v.ptype = *it++; { diff --git a/test/unit/Jamfile b/test/unit/Jamfile index 0ba0832e..fefce4a9 100644 --- a/test/unit/Jamfile +++ b/test/unit/Jamfile @@ -20,7 +20,7 @@ project ../../../url/extra/test_suite ../../example/include extra - on + # on norecover:static clang-win:"-Wno-unused-private-field" ; diff --git a/test/unit/server/logger.cpp b/test/unit/server/logger.cpp deleted file mode 100644 index d229f7ec..00000000 --- a/test/unit/server/logger.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/cppalliance/beast2 -// - -// Test that header file is self-contained. -#include diff --git a/test/unit/server/route_rule.cpp b/test/unit/server/route_rule.cpp index b8237dfc..59774bc1 100644 --- a/test/unit/server/route_rule.cpp +++ b/test/unit/server/route_rule.cpp @@ -52,7 +52,7 @@ struct route_rule_test auto rv = grammar::parse(s, t); if(! BOOST_TEST_EQ(rv.has_error(), true)) return; - BOOST_TEST_EQ(rv.useor(), ec); + BOOST_TEST_EQ(rv.error(), ec); }; static void lit(core::string_view s)