mirror of
https://github.com/XRPLF/clio.git
synced 2026-06-19 16:46:55 +00:00
ci: Use Nix-based images for all workflows except pre-commit (#3098)
This commit is contained in:
@@ -17,3 +17,6 @@ endfunction()
|
||||
|
||||
function(append_coverage_compiler_flags_to_target name mode)
|
||||
endfunction()
|
||||
|
||||
function(patch_nix_binary target)
|
||||
endfunction()
|
||||
|
||||
53
.github/actions/build-identifier/action.yml
vendored
Normal file
53
.github/actions/build-identifier/action.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
name: Build identifier
|
||||
description: Generate a unique build identifier and the ccache key derived from it
|
||||
|
||||
inputs:
|
||||
build_type:
|
||||
description: Current build type (e.g. Release, Debug)
|
||||
required: true
|
||||
compiler:
|
||||
description: Compiler used for the build (e.g. gcc, clang)
|
||||
required: true
|
||||
code_coverage:
|
||||
description: Whether code coverage is on
|
||||
required: true
|
||||
sanitizers:
|
||||
description: Sanitizer to enable, read by the 'sanitizers' conan profile (e.g. 'address', 'thread', 'undefinedbehavior')
|
||||
required: true
|
||||
|
||||
outputs:
|
||||
build_identifier:
|
||||
description: Unique identifier for the build configuration (without commit)
|
||||
value: ${{ steps.build_identifier.outputs.build_identifier }}
|
||||
cache_key:
|
||||
description: ccache key, the build identifier suffixed with the common ancestor commit
|
||||
value: ${{ steps.build_identifier.outputs.build_identifier }}-${{ steps.git_common_ancestor.outputs.commit }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Find common commit
|
||||
id: git_common_ancestor
|
||||
uses: ./.github/actions/git-common-ancestor
|
||||
|
||||
- name: Build identifier
|
||||
id: build_identifier
|
||||
shell: bash
|
||||
env:
|
||||
RUNNER_OS: ${{ runner.os }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
COMPILER: ${{ inputs.compiler }}
|
||||
CODE_COVERAGE: ${{ inputs.code_coverage }}
|
||||
SANITIZERS: ${{ inputs.sanitizers }}
|
||||
run: |
|
||||
# Keep the legacy "<os>_<build_type>_<compiler>" layout so standard artifact
|
||||
# names (e.g. clio_server_Linux_Release_gcc) stay backwards compatible.
|
||||
# Sanitizer/coverage builds get extra suffixes and may differ from old names.
|
||||
BUILD_IDENTIFIER="${RUNNER_OS}_${BUILD_TYPE}_${COMPILER}"
|
||||
if [ "${CODE_COVERAGE}" == "true" ]; then
|
||||
BUILD_IDENTIFIER+="_code_coverage"
|
||||
fi
|
||||
if [ -n "${SANITIZERS}" ]; then
|
||||
BUILD_IDENTIFIER+="_${SANITIZERS}"
|
||||
fi
|
||||
echo "build_identifier=${BUILD_IDENTIFIER}" >>"${GITHUB_OUTPUT}"
|
||||
41
.github/actions/cache-key/action.yml
vendored
41
.github/actions/cache-key/action.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Cache key
|
||||
description: Generate cache key for ccache
|
||||
|
||||
inputs:
|
||||
conan_profile:
|
||||
description: Conan profile name
|
||||
required: true
|
||||
build_type:
|
||||
description: Current build type (e.g. Release, Debug)
|
||||
required: true
|
||||
default: Release
|
||||
code_coverage:
|
||||
description: Whether code coverage is on
|
||||
required: true
|
||||
default: "false"
|
||||
|
||||
outputs:
|
||||
key:
|
||||
description: Generated cache key for ccache
|
||||
value: ${{ steps.key_without_commit.outputs.key }}-${{ steps.git_common_ancestor.outputs.commit }}
|
||||
restore_keys:
|
||||
description: Cache restore keys for fallback
|
||||
value: ${{ steps.key_without_commit.outputs.key }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Find common commit
|
||||
id: git_common_ancestor
|
||||
uses: ./.github/actions/git-common-ancestor
|
||||
|
||||
- name: Set cache key without commit
|
||||
id: key_without_commit
|
||||
shell: bash
|
||||
env:
|
||||
RUNNER_OS: ${{ runner.os }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CODE_COVERAGE: ${{ inputs.code_coverage == 'true' && '-code_coverage' || '' }}
|
||||
CONAN_PROFILE: ${{ inputs.conan_profile }}
|
||||
run: |
|
||||
echo "key=clio-ccache-${RUNNER_OS}-${BUILD_TYPE}${CODE_COVERAGE}-${CONAN_PROFILE}-develop" >>"${GITHUB_OUTPUT}"
|
||||
15
.github/actions/cmake/action.yml
vendored
15
.github/actions/cmake/action.yml
vendored
@@ -6,9 +6,6 @@ inputs:
|
||||
description: Build directory
|
||||
required: false
|
||||
default: "build"
|
||||
conan_profile:
|
||||
description: Conan profile name
|
||||
required: true
|
||||
build_type:
|
||||
description: Build type for third-party libraries and clio. Could be 'Release', 'Debug'
|
||||
required: true
|
||||
@@ -25,10 +22,6 @@ inputs:
|
||||
description: Whether to enable code coverage
|
||||
required: true
|
||||
default: "false"
|
||||
static:
|
||||
description: Whether Clio is to be statically linked
|
||||
required: true
|
||||
default: "false"
|
||||
time_trace:
|
||||
description: Whether to enable compiler trace reports
|
||||
required: true
|
||||
@@ -50,15 +43,9 @@ runs:
|
||||
env:
|
||||
BUILD_DIR: "${{ inputs.build_dir }}"
|
||||
BUILD_TYPE: "${{ inputs.build_type }}"
|
||||
SANITIZER_OPTION: |-
|
||||
${{ endsWith(inputs.conan_profile, '.asan') && '-Dsan=address' ||
|
||||
endsWith(inputs.conan_profile, '.tsan') && '-Dsan=thread' ||
|
||||
endsWith(inputs.conan_profile, '.ubsan') && '-Dsan=undefined' ||
|
||||
'' }}
|
||||
INTEGRATION_TESTS: "${{ inputs.integration_tests == 'true' && 'ON' || 'OFF' }}"
|
||||
BENCHMARK: "${{ inputs.benchmark == 'true' && 'ON' || 'OFF' }}"
|
||||
COVERAGE: "${{ inputs.code_coverage == 'true' && 'ON' || 'OFF' }}"
|
||||
STATIC: "${{ inputs.static == 'true' && 'ON' || 'OFF' }}"
|
||||
TIME_TRACE: "${{ inputs.time_trace == 'true' && 'ON' || 'OFF' }}"
|
||||
PACKAGE: "${{ inputs.package == 'true' && 'ON' || 'OFF' }}"
|
||||
# GitHub creates a merge commit for a PR
|
||||
@@ -81,11 +68,9 @@ runs:
|
||||
-G Ninja \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||
"${SANITIZER_OPTION}" \
|
||||
-Dtests=ON \
|
||||
-Dintegration_tests="${INTEGRATION_TESTS}" \
|
||||
-Dbenchmark="${BENCHMARK}" \
|
||||
-Dcoverage="${COVERAGE}" \
|
||||
-Dstatic="${STATIC}" \
|
||||
-Dtime_trace="${TIME_TRACE}" \
|
||||
-Dpackage="${PACKAGE}"
|
||||
|
||||
11
.github/actions/conan/action.yml
vendored
11
.github/actions/conan/action.yml
vendored
@@ -6,9 +6,6 @@ inputs:
|
||||
description: Build directory
|
||||
required: false
|
||||
default: "build"
|
||||
conan_profile:
|
||||
description: Conan profile name
|
||||
required: true
|
||||
force_conan_source_build:
|
||||
description: Whether conan should build all dependencies from source
|
||||
required: true
|
||||
@@ -17,6 +14,10 @@ inputs:
|
||||
description: Build type for third-party libraries and clio. Could be 'Release', 'Debug'
|
||||
required: true
|
||||
default: "Release"
|
||||
sanitizers:
|
||||
description: Sanitizer to enable, read by the 'sanitizers' conan profile (e.g. 'address', 'thread', 'undefinedbehavior')
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
@@ -27,11 +28,11 @@ runs:
|
||||
BUILD_DIR: "${{ inputs.build_dir }}"
|
||||
CONAN_BUILD_OPTION: "${{ inputs.force_conan_source_build == 'true' && '*' || 'missing' }}"
|
||||
BUILD_TYPE: "${{ inputs.build_type }}"
|
||||
CONAN_PROFILE: "${{ inputs.conan_profile }}"
|
||||
SANITIZERS: "${{ inputs.sanitizers }}"
|
||||
run: |
|
||||
conan \
|
||||
install . \
|
||||
-of "${BUILD_DIR}" \
|
||||
-b "${CONAN_BUILD_OPTION}" \
|
||||
-s "build_type=${BUILD_TYPE}" \
|
||||
--profile:all "${CONAN_PROFILE}"
|
||||
--profile:all ci
|
||||
|
||||
34
.github/actions/set-compiler-env/action.yml
vendored
Normal file
34
.github/actions/set-compiler-env/action.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Set compiler environment
|
||||
description: "Set CC and CXX environment variables for the given compiler."
|
||||
|
||||
inputs:
|
||||
compiler:
|
||||
description: 'The compiler to use ("gcc" or "clang").'
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Set CC and CXX for gcc
|
||||
if: ${{ inputs.compiler == 'gcc' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "CC=gcc" >>"${GITHUB_ENV}"
|
||||
echo "CXX=g++" >>"${GITHUB_ENV}"
|
||||
|
||||
- name: Set CC and CXX for clang
|
||||
if: ${{ inputs.compiler == 'clang' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "CC=clang" >>"${GITHUB_ENV}"
|
||||
echo "CXX=clang++" >>"${GITHUB_ENV}"
|
||||
|
||||
- name: Fail on unknown compiler
|
||||
if: ${{ inputs.compiler != 'gcc' && inputs.compiler != 'clang' }}
|
||||
shell: bash
|
||||
env:
|
||||
COMPILER: ${{ inputs.compiler }}
|
||||
run: |
|
||||
echo "Unknown compiler: $COMPILER" >&2
|
||||
exit 1
|
||||
102
.github/dependabot.yml
vendored
102
.github/dependabot.yml
vendored
@@ -1,98 +1,16 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
reviewers:
|
||||
- XRPLF/clio-dev-team
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/build-clio/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
reviewers:
|
||||
- XRPLF/clio-dev-team
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/build-docker-image/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
reviewers:
|
||||
- XRPLF/clio-dev-team
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/cmake/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
reviewers:
|
||||
- XRPLF/clio-dev-team
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/code-coverage/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
reviewers:
|
||||
- XRPLF/clio-dev-team
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/conan/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
reviewers:
|
||||
- XRPLF/clio-dev-team
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/git-common-ancestor/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
reviewers:
|
||||
- XRPLF/clio-dev-team
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: .github/actions/cache-key/
|
||||
directories:
|
||||
- /
|
||||
- .github/actions/build-clio/
|
||||
- .github/actions/build-docker-image/
|
||||
- .github/actions/build-identifier/
|
||||
- .github/actions/cmake/
|
||||
- .github/actions/code-coverage/
|
||||
- .github/actions/conan/
|
||||
- .github/actions/git-common-ancestor/
|
||||
- .github/actions/set-compiler-env/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
|
||||
13
.github/scripts/conan/generate_matrix.py
vendored
13
.github/scripts/conan/generate_matrix.py
vendored
@@ -3,9 +3,7 @@ import itertools
|
||||
import json
|
||||
|
||||
LINUX_OS = ["heavy", "heavy-arm64"]
|
||||
LINUX_CONTAINERS = [
|
||||
'{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
]
|
||||
LINUX_CONTAINERS = ['{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }']
|
||||
LINUX_COMPILERS = ["gcc", "clang"]
|
||||
|
||||
MACOS_OS = ["macos15"]
|
||||
@@ -13,7 +11,10 @@ MACOS_CONTAINERS = [""]
|
||||
MACOS_COMPILERS = ["apple-clang"]
|
||||
|
||||
BUILD_TYPES = ["Release", "Debug"]
|
||||
SANITIZER_EXT = [".asan", ".tsan", ".ubsan", ""]
|
||||
|
||||
# Values of the `SANITIZERS` environment variable read by the `sanitizers` conan
|
||||
# profile. An empty string builds without any sanitizers.
|
||||
SANITIZERS = ["address", "thread", "undefinedbehavior", ""]
|
||||
|
||||
|
||||
def generate_matrix():
|
||||
@@ -23,13 +24,13 @@ def generate_matrix():
|
||||
itertools.product(LINUX_OS, LINUX_CONTAINERS, LINUX_COMPILERS),
|
||||
itertools.product(MACOS_OS, MACOS_CONTAINERS, MACOS_COMPILERS),
|
||||
):
|
||||
for sanitizer_ext, build_type in itertools.product(SANITIZER_EXT, BUILD_TYPES):
|
||||
for sanitizers, build_type in itertools.product(SANITIZERS, BUILD_TYPES):
|
||||
configurations.append(
|
||||
{
|
||||
"os": os,
|
||||
"container": container,
|
||||
"compiler": compiler,
|
||||
"sanitizer_ext": sanitizer_ext,
|
||||
"sanitizers": sanitizers,
|
||||
"build_type": build_type,
|
||||
}
|
||||
)
|
||||
|
||||
48
.github/scripts/conan/init.sh
vendored
48
.github/scripts/conan/init.sh
vendored
@@ -1,48 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
REPO_DIR="$(cd "$CURRENT_DIR/../../../" && pwd)"
|
||||
|
||||
CONAN_DIR="${CONAN_HOME:-$HOME/.conan2}"
|
||||
PROFILES_DIR="$CONAN_DIR/profiles"
|
||||
|
||||
# When developers' compilers are updated, these profiles might be different
|
||||
if [[ -z "$CI" ]]; then
|
||||
APPLE_CLANG_PROFILE="$CURRENT_DIR/apple-clang-17.profile"
|
||||
else
|
||||
APPLE_CLANG_PROFILE="$CURRENT_DIR/apple-clang-17.profile"
|
||||
fi
|
||||
|
||||
GCC_PROFILE="$REPO_DIR/docker/ci/conan/gcc.profile"
|
||||
CLANG_PROFILE="$REPO_DIR/docker/ci/conan/clang.profile"
|
||||
|
||||
SANITIZER_TEMPLATE_FILE="$REPO_DIR/docker/ci/conan/sanitizer_template.profile"
|
||||
|
||||
rm -rf "$CONAN_DIR"
|
||||
|
||||
conan remote add --index 0 xrplf https://conan.ripplex.io
|
||||
|
||||
cp "$REPO_DIR/docker/ci/conan/global.conf" "$CONAN_DIR/global.conf"
|
||||
|
||||
create_profile_with_sanitizers() {
|
||||
profile_name="$1"
|
||||
profile_source="$2"
|
||||
|
||||
cp "$profile_source" "$PROFILES_DIR/$profile_name"
|
||||
cp "$SANITIZER_TEMPLATE_FILE" "$PROFILES_DIR/$profile_name.asan"
|
||||
cp "$SANITIZER_TEMPLATE_FILE" "$PROFILES_DIR/$profile_name.tsan"
|
||||
cp "$SANITIZER_TEMPLATE_FILE" "$PROFILES_DIR/$profile_name.ubsan"
|
||||
}
|
||||
|
||||
mkdir -p "$PROFILES_DIR"
|
||||
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
create_profile_with_sanitizers "apple-clang" "$APPLE_CLANG_PROFILE"
|
||||
echo "include(apple-clang)" >"$PROFILES_DIR/default"
|
||||
else
|
||||
create_profile_with_sanitizers "clang" "$CLANG_PROFILE"
|
||||
create_profile_with_sanitizers "gcc" "$GCC_PROFILE"
|
||||
echo "include(gcc)" >"$PROFILES_DIR/default"
|
||||
fi
|
||||
2
.github/scripts/conan/regenerate_lockfile.sh
vendored
2
.github/scripts/conan/regenerate_lockfile.sh
vendored
@@ -22,4 +22,4 @@ rm -f conan.lock
|
||||
# Create a new lockfile that is compatible with macOS.
|
||||
# It should also work on Linux.
|
||||
conan lock create . \
|
||||
--profile:all=.github/scripts/conan/apple-clang-17.profile
|
||||
--profile:all=./conan/profiles/apple-clang-17.profile
|
||||
|
||||
21
.github/workflows/build.yml
vendored
21
.github/workflows/build.yml
vendored
@@ -45,30 +45,24 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [heavy]
|
||||
conan_profile: [gcc, clang]
|
||||
compiler: [gcc, clang]
|
||||
build_type: [Release, Debug]
|
||||
container:
|
||||
[
|
||||
'{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }',
|
||||
]
|
||||
static: [true]
|
||||
container: ['{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }']
|
||||
|
||||
include:
|
||||
- os: macos15
|
||||
conan_profile: apple-clang
|
||||
compiler: apple-clang
|
||||
build_type: Release
|
||||
container: ""
|
||||
static: false
|
||||
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
with:
|
||||
runs_on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
conan_profile: ${{ matrix.conan_profile }}
|
||||
compiler: ${{ matrix.compiler }}
|
||||
build_type: ${{ matrix.build_type }}
|
||||
download_ccache: true
|
||||
upload_ccache: true
|
||||
static: ${{ matrix.static }}
|
||||
run_unit_tests: true
|
||||
run_integration_tests: false
|
||||
upload_clio_server: true
|
||||
@@ -79,13 +73,12 @@ jobs:
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
conan_profile: gcc
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
|
||||
compiler: gcc
|
||||
build_type: Debug
|
||||
download_ccache: true
|
||||
upload_ccache: true
|
||||
code_coverage: true
|
||||
static: true
|
||||
upload_clio_server: false
|
||||
targets: all
|
||||
analyze_build_time: false
|
||||
@@ -97,7 +90,7 @@ jobs:
|
||||
needs: build-and-test
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
20
.github/workflows/check-libxrpl.yml
vendored
20
.github/workflows/check-libxrpl.yml
vendored
@@ -10,7 +10,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
CONAN_PROFILE: gcc
|
||||
COMPILER: gcc
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
name: Build Clio / `libXRPL ${{ github.event.client_payload.version }}`
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -36,6 +36,14 @@ jobs:
|
||||
- name: Print build environment
|
||||
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
|
||||
|
||||
- name: Set compiler environment
|
||||
uses: ./.github/actions/set-compiler-env
|
||||
with:
|
||||
compiler: ${{ env.COMPILER }}
|
||||
|
||||
- name: Setup conan
|
||||
run: conan/init.sh
|
||||
|
||||
- name: Update libXRPL version requirement
|
||||
run: |
|
||||
sed -i.bak -E "s|'xrpl/[a-zA-Z0-9\\.\\-]+'|'xrpl/${{ github.event.client_payload.conan_ref }}'|g" conanfile.py
|
||||
@@ -43,17 +51,13 @@ jobs:
|
||||
|
||||
- name: Update conan lockfile
|
||||
run: |
|
||||
conan lock create . --profile:all ${{ env.CONAN_PROFILE }}
|
||||
conan lock create . --profile:all ci
|
||||
|
||||
- name: Run conan
|
||||
uses: ./.github/actions/conan
|
||||
with:
|
||||
conan_profile: ${{ env.CONAN_PROFILE }}
|
||||
|
||||
- name: Run CMake
|
||||
uses: ./.github/actions/cmake
|
||||
with:
|
||||
conan_profile: ${{ env.CONAN_PROFILE }}
|
||||
|
||||
- name: Build Clio
|
||||
uses: ./.github/actions/build-clio
|
||||
@@ -72,7 +76,7 @@ jobs:
|
||||
needs: build
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
|
||||
17
.github/workflows/clang-tidy.yml
vendored
17
.github/workflows/clang-tidy.yml
vendored
@@ -32,8 +32,7 @@ env:
|
||||
DIFF_FILE: clang-tidy-git-diff.txt
|
||||
ISSUE_FILE: clang-tidy-issue.md
|
||||
|
||||
CONAN_PROFILE: clang
|
||||
LLVM_TOOLS_VERSION: 21
|
||||
COMPILER: clang
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -52,7 +51,7 @@ jobs:
|
||||
if: ${{ always() && !cancelled() && (github.event_name != 'pull_request' || needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:f174b47f4909ae41b80406d836ab52adc39eacc6
|
||||
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -70,18 +69,24 @@ jobs:
|
||||
- name: Print build environment
|
||||
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
|
||||
|
||||
- name: Set compiler environment
|
||||
uses: ./.github/actions/set-compiler-env
|
||||
with:
|
||||
compiler: ${{ env.COMPILER }}
|
||||
|
||||
- name: Setup conan
|
||||
run: conan/init.sh
|
||||
|
||||
- name: Run conan
|
||||
uses: ./.github/actions/conan
|
||||
with:
|
||||
build_dir: ${{ env.BUILD_DIR }}
|
||||
conan_profile: ${{ env.CONAN_PROFILE }}
|
||||
build_type: ${{ env.BUILD_TYPE }}
|
||||
|
||||
- name: Run CMake
|
||||
uses: ./.github/actions/cmake
|
||||
with:
|
||||
build_dir: ${{ env.BUILD_DIR }}
|
||||
conan_profile: ${{ env.CONAN_PROFILE }}
|
||||
build_type: ${{ env.BUILD_TYPE }}
|
||||
|
||||
- name: Get number of processors
|
||||
@@ -95,7 +100,7 @@ jobs:
|
||||
TARGETS: ${{ (needs.determine-files.outputs.clang_tidy_config_changed != 'true' && github.event_name == 'pull_request') && needs.determine-files.outputs.cpp_changed_files || 'benchmarks src tests' }}
|
||||
run: |
|
||||
set -o pipefail
|
||||
run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
|
||||
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
|
||||
|
||||
- name: Print errors
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
|
||||
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
39
.github/workflows/nightly.yml
vendored
39
.github/workflows/nightly.yml
vendored
@@ -48,32 +48,29 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- os: macos15
|
||||
conan_profile: apple-clang
|
||||
compiler: apple-clang
|
||||
build_type: Release
|
||||
static: false
|
||||
- os: heavy
|
||||
conan_profile: gcc
|
||||
compiler: gcc
|
||||
build_type: Release
|
||||
static: true
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
|
||||
- os: heavy
|
||||
conan_profile: gcc
|
||||
compiler: gcc
|
||||
build_type: Debug
|
||||
static: true
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
|
||||
- os: heavy
|
||||
conan_profile: gcc.ubsan
|
||||
compiler: gcc
|
||||
sanitizers: undefinedbehavior
|
||||
build_type: Release
|
||||
static: false
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
|
||||
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
with:
|
||||
runs_on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
conan_profile: ${{ matrix.conan_profile }}
|
||||
compiler: ${{ matrix.compiler }}
|
||||
sanitizers: ${{ matrix.sanitizers }}
|
||||
build_type: ${{ matrix.build_type }}
|
||||
static: ${{ matrix.static }}
|
||||
run_unit_tests: true
|
||||
run_integration_tests: true
|
||||
upload_clio_server: true
|
||||
@@ -88,13 +85,12 @@ jobs:
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
conan_profile: gcc
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
|
||||
compiler: gcc
|
||||
build_type: Release
|
||||
download_ccache: false
|
||||
upload_ccache: false
|
||||
code_coverage: false
|
||||
static: true
|
||||
upload_clio_server: false
|
||||
package: true
|
||||
version: nightly-${{ needs.get_date.outputs.date }}
|
||||
@@ -110,23 +106,20 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- os: heavy
|
||||
conan_profile: clang
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
static: true
|
||||
compiler: clang
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
|
||||
- os: macos15
|
||||
conan_profile: apple-clang
|
||||
compiler: apple-clang
|
||||
container: ""
|
||||
static: false
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
runs_on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
conan_profile: ${{ matrix.conan_profile }}
|
||||
compiler: ${{ matrix.compiler }}
|
||||
build_type: Release
|
||||
download_ccache: false
|
||||
upload_ccache: false
|
||||
code_coverage: false
|
||||
static: ${{ matrix.static }}
|
||||
upload_clio_server: false
|
||||
targets: all
|
||||
analyze_build_time: true
|
||||
|
||||
16
.github/workflows/release.yml
vendored
16
.github/workflows/release.yml
vendored
@@ -22,22 +22,19 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- os: macos15
|
||||
conan_profile: apple-clang
|
||||
compiler: apple-clang
|
||||
build_type: Release
|
||||
static: false
|
||||
- os: heavy
|
||||
conan_profile: gcc
|
||||
compiler: gcc
|
||||
build_type: Release
|
||||
static: true
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
|
||||
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
with:
|
||||
runs_on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
conan_profile: ${{ matrix.conan_profile }}
|
||||
compiler: ${{ matrix.compiler }}
|
||||
build_type: ${{ matrix.build_type }}
|
||||
static: ${{ matrix.static }}
|
||||
run_unit_tests: true
|
||||
run_integration_tests: true
|
||||
upload_clio_server: true
|
||||
@@ -51,13 +48,12 @@ jobs:
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
conan_profile: gcc
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
|
||||
compiler: gcc
|
||||
build_type: Release
|
||||
download_ccache: false
|
||||
upload_ccache: false
|
||||
code_coverage: false
|
||||
static: true
|
||||
upload_clio_server: false
|
||||
package: true
|
||||
version: ${{ github.event_name == 'push' && github.ref_name || '' }}
|
||||
|
||||
23
.github/workflows/reusable-build-test.yml
vendored
23
.github/workflows/reusable-build-test.yml
vendored
@@ -13,11 +13,17 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
conan_profile:
|
||||
description: Conan profile to use
|
||||
compiler:
|
||||
description: 'Compiler to build with ("gcc", "clang" or "apple-clang")'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
sanitizers:
|
||||
description: 'Sanitizers to enable ("address", "thread", "undefinedbehavior" or empty)'
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
build_type:
|
||||
description: Build type
|
||||
required: true
|
||||
@@ -35,12 +41,6 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
static:
|
||||
description: Whether to build static binaries
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
run_unit_tests:
|
||||
description: Whether to run unit tests
|
||||
required: true
|
||||
@@ -81,12 +81,12 @@ jobs:
|
||||
with:
|
||||
runs_on: ${{ inputs.runs_on }}
|
||||
container: ${{ inputs.container }}
|
||||
conan_profile: ${{ inputs.conan_profile }}
|
||||
compiler: ${{ inputs.compiler }}
|
||||
sanitizers: ${{ inputs.sanitizers }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
download_ccache: ${{ inputs.download_ccache }}
|
||||
upload_ccache: ${{ inputs.upload_ccache }}
|
||||
code_coverage: false
|
||||
static: ${{ inputs.static }}
|
||||
upload_clio_server: ${{ inputs.upload_clio_server }}
|
||||
targets: ${{ inputs.targets }}
|
||||
analyze_build_time: false
|
||||
@@ -99,7 +99,8 @@ jobs:
|
||||
with:
|
||||
runs_on: ${{ inputs.runs_on }}
|
||||
container: ${{ inputs.container }}
|
||||
conan_profile: ${{ inputs.conan_profile }}
|
||||
compiler: ${{ inputs.compiler }}
|
||||
sanitizers: ${{ inputs.sanitizers }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
run_unit_tests: ${{ inputs.run_unit_tests }}
|
||||
run_integration_tests: ${{ inputs.run_integration_tests }}
|
||||
|
||||
61
.github/workflows/reusable-build.yml
vendored
61
.github/workflows/reusable-build.yml
vendored
@@ -13,11 +13,17 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
conan_profile:
|
||||
description: Conan profile to use
|
||||
compiler:
|
||||
description: 'Compiler to build with ("gcc", "clang" or "apple-clang")'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
sanitizers:
|
||||
description: 'Sanitizers to enable ("address", "thread", "undefinedbehavior" or empty)'
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
build_type:
|
||||
description: Build type
|
||||
required: true
|
||||
@@ -40,11 +46,6 @@ on:
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
static:
|
||||
description: Whether to build static binaries
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
upload_clio_server:
|
||||
description: Whether to upload clio_server
|
||||
required: true
|
||||
@@ -102,40 +103,44 @@ jobs:
|
||||
- name: Print build environment
|
||||
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
|
||||
|
||||
- name: Setup conan on macOS
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
run: ./.github/scripts/conan/init.sh
|
||||
|
||||
- name: Generate cache key
|
||||
uses: ./.github/actions/cache-key
|
||||
id: cache_key
|
||||
- name: Set compiler environment
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
uses: ./.github/actions/set-compiler-env
|
||||
with:
|
||||
compiler: ${{ inputs.compiler }}
|
||||
|
||||
- name: Setup conan
|
||||
run: conan/init.sh
|
||||
|
||||
- name: Generate build identifier
|
||||
uses: ./.github/actions/build-identifier
|
||||
id: build_identifier
|
||||
with:
|
||||
conan_profile: ${{ inputs.conan_profile }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
compiler: ${{ inputs.compiler }}
|
||||
code_coverage: ${{ inputs.code_coverage }}
|
||||
sanitizers: ${{ inputs.sanitizers }}
|
||||
|
||||
- name: Restore ccache cache
|
||||
if: ${{ inputs.download_ccache && github.ref != 'refs/heads/develop' }}
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: ${{ steps.cache_key.outputs.key }}
|
||||
key: ${{ steps.build_identifier.outputs.cache_key }}
|
||||
restore-keys: |
|
||||
${{ steps.cache_key.outputs.restore_keys }}
|
||||
${{ steps.build_identifier.outputs.build_identifier }}
|
||||
|
||||
- name: Run conan
|
||||
uses: ./.github/actions/conan
|
||||
with:
|
||||
conan_profile: ${{ inputs.conan_profile }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
sanitizers: ${{ inputs.sanitizers }}
|
||||
|
||||
- name: Run CMake
|
||||
uses: ./.github/actions/cmake
|
||||
with:
|
||||
conan_profile: ${{ inputs.conan_profile }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
code_coverage: ${{ inputs.code_coverage }}
|
||||
static: ${{ inputs.static }}
|
||||
time_trace: ${{ inputs.analyze_build_time }}
|
||||
package: ${{ inputs.package }}
|
||||
version: ${{ inputs.version }}
|
||||
@@ -156,7 +161,7 @@ jobs:
|
||||
if: ${{ inputs.analyze_build_time }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: build_time_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
name: build_time_report_${{ steps.build_identifier.outputs.build_identifier }}
|
||||
path: build_time_report.txt
|
||||
|
||||
- name: Show ccache's statistics and zero it
|
||||
@@ -170,42 +175,42 @@ jobs:
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: ${{ steps.cache_key.outputs.key }}
|
||||
key: ${{ steps.build_identifier.outputs.cache_key }}
|
||||
|
||||
- name: Strip unit_tests
|
||||
if: ${{ !endsWith(inputs.conan_profile, 'san') && !inputs.code_coverage && !inputs.analyze_build_time }}
|
||||
if: ${{ inputs.sanitizers == '' && !inputs.code_coverage && !inputs.analyze_build_time }}
|
||||
run: strip build/clio_tests
|
||||
|
||||
- name: Strip integration_tests
|
||||
if: ${{ !endsWith(inputs.conan_profile, 'san') && !inputs.code_coverage && !inputs.analyze_build_time }}
|
||||
if: ${{ inputs.sanitizers == '' && !inputs.code_coverage && !inputs.analyze_build_time }}
|
||||
run: strip build/clio_integration_tests
|
||||
|
||||
- name: Upload clio_server
|
||||
if: ${{ inputs.upload_clio_server && !inputs.code_coverage && !inputs.analyze_build_time }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: clio_server_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
name: clio_server_${{ steps.build_identifier.outputs.build_identifier }}
|
||||
path: build/clio_server
|
||||
|
||||
- name: Upload clio_tests
|
||||
if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
name: clio_tests_${{ steps.build_identifier.outputs.build_identifier }}
|
||||
path: build/clio_tests
|
||||
|
||||
- name: Upload clio_integration_tests
|
||||
if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
name: clio_integration_tests_${{ steps.build_identifier.outputs.build_identifier }}
|
||||
path: build/clio_integration_tests
|
||||
|
||||
- name: Upload Clio Linux package
|
||||
if: ${{ inputs.package }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: clio_deb_package_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
name: clio_deb_package_${{ steps.build_identifier.outputs.build_identifier }}
|
||||
path: build/*.deb
|
||||
|
||||
# This is run as part of the build job, because it requires the following:
|
||||
|
||||
2
.github/workflows/reusable-release.yml
vendored
2
.github/workflows/reusable-release.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
||||
release:
|
||||
runs-on: heavy
|
||||
container:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
|
||||
env:
|
||||
GH_REPO: ${{ github.repository }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
50
.github/workflows/reusable-test.yml
vendored
50
.github/workflows/reusable-test.yml
vendored
@@ -13,11 +13,17 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
conan_profile:
|
||||
description: Conan profile to use
|
||||
compiler:
|
||||
description: 'Compiler the binaries were built with ("gcc", "clang" or "apple-clang")'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
sanitizers:
|
||||
description: 'Sanitizers the binaries were built with ("address", "thread", "undefinedbehavior" or empty)'
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
build_type:
|
||||
description: Build type
|
||||
required: true
|
||||
@@ -54,9 +60,19 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate build identifier
|
||||
uses: ./.github/actions/build-identifier
|
||||
id: build_identifier
|
||||
with:
|
||||
build_type: ${{ inputs.build_type }}
|
||||
compiler: ${{ inputs.compiler }}
|
||||
# code_coverage is run inside build environment
|
||||
code_coverage: false
|
||||
sanitizers: ${{ inputs.sanitizers }}
|
||||
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
name: clio_tests_${{ steps.build_identifier.outputs.build_identifier }}
|
||||
|
||||
- name: Make clio_tests executable
|
||||
run: chmod +x ./clio_tests
|
||||
@@ -67,11 +83,11 @@ jobs:
|
||||
run: ./clio_tests
|
||||
|
||||
- name: Create an issue
|
||||
if: ${{ steps.run_clio_tests.outcome == 'failure' && endsWith(inputs.conan_profile, 'san') }}
|
||||
if: ${{ steps.run_clio_tests.outcome == 'failure' && inputs.sanitizers != '' }}
|
||||
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
|
||||
with:
|
||||
title: "[${{ inputs.conan_profile }}] reported issues"
|
||||
body: "Clio tests failed one or more sanitizer checks when built with `${{ inputs.conan_profile }}`."
|
||||
title: "[${{ inputs.compiler }} ${{ inputs.sanitizers }}] reported issues"
|
||||
body: "Clio tests failed one or more sanitizers checks when built with `${{ inputs.compiler }}` and the `${{ inputs.sanitizers }}` sanitizers."
|
||||
labels: "bug"
|
||||
assignees: "godexsoft,kuznetsss,mathbunnyru"
|
||||
|
||||
@@ -100,6 +116,20 @@ jobs:
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
|
||||
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate build identifier
|
||||
uses: ./.github/actions/build-identifier
|
||||
id: build_identifier
|
||||
with:
|
||||
build_type: ${{ inputs.build_type }}
|
||||
compiler: ${{ inputs.compiler }}
|
||||
# code_coverage is run inside build environment
|
||||
code_coverage: false
|
||||
sanitizers: ${{ inputs.sanitizers }}
|
||||
|
||||
- name: Delete and start colima (macOS)
|
||||
# This is a temporary workaround for colima issues on macOS runners
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
@@ -107,6 +137,12 @@ jobs:
|
||||
colima delete --force
|
||||
colima start
|
||||
|
||||
- name: Remove leftover scylladb container (macOS)
|
||||
# A previous run that didn't clean up (e.g. a cancelled job) can leave the
|
||||
# container behind, otherwise the name is still taken on the persistent runner.
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
run: docker rm --force scylladb || true
|
||||
|
||||
- name: Spin up scylladb (macOS)
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
timeout-minutes: 1
|
||||
@@ -132,7 +168,7 @@ jobs:
|
||||
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
|
||||
name: clio_integration_tests_${{ steps.build_identifier.outputs.build_identifier }}
|
||||
|
||||
- name: Run clio_integration_tests
|
||||
run: |
|
||||
|
||||
10
.github/workflows/sanitizers.yml
vendored
10
.github/workflows/sanitizers.yml
vendored
@@ -19,7 +19,7 @@ on:
|
||||
- conanfile.py
|
||||
- conan.lock
|
||||
- "cmake/**"
|
||||
# We don't run sanitizer on code change, because it takes too long
|
||||
# We don't run sanitizers on code change, because it takes too long
|
||||
# - "src/**"
|
||||
# - "tests/**"
|
||||
|
||||
@@ -36,18 +36,18 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
compiler: [gcc, clang]
|
||||
sanitizer_ext: [.asan, .tsan, .ubsan]
|
||||
sanitizers: [address, thread, undefinedbehavior]
|
||||
build_type: [Release, Debug]
|
||||
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
with:
|
||||
runs_on: heavy
|
||||
container: '{ "image": "ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
|
||||
download_ccache: false
|
||||
upload_ccache: false
|
||||
conan_profile: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
|
||||
compiler: ${{ matrix.compiler }}
|
||||
sanitizers: ${{ matrix.sanitizers }}
|
||||
build_type: ${{ matrix.build_type }}
|
||||
static: false
|
||||
run_unit_tests: true
|
||||
run_integration_tests: false
|
||||
upload_clio_server: false
|
||||
|
||||
364
.github/workflows/update-docker-ci.yml
vendored
364
.github/workflows/update-docker-ci.yml
vendored
@@ -1,364 +0,0 @@
|
||||
name: Update CI docker image
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/update-docker-ci.yml
|
||||
|
||||
- ".github/actions/build-docker-image/**"
|
||||
|
||||
- "docker/**"
|
||||
- "!docker/clio/**"
|
||||
- "!docker/develop/**"
|
||||
push:
|
||||
branches: [develop]
|
||||
paths:
|
||||
- .github/workflows/update-docker-ci.yml
|
||||
|
||||
- ".github/actions/build-docker-image/**"
|
||||
|
||||
- "docker/**"
|
||||
- "!docker/clio/**"
|
||||
- "!docker/develop/**"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
# Only matches runs for the current workflow - matches against branch & tags
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
# We want to execute all builds sequentially in develop
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
CLANG_MAJOR_VERSION: 19
|
||||
GCC_MAJOR_VERSION: 15
|
||||
GCC_VERSION: 15.2.0
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
repo:
|
||||
name: Calculate repo name
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
GHCR_REPO: ${{ steps.set-ghcr-repo.outputs.GHCR_REPO }}
|
||||
|
||||
steps:
|
||||
- name: Set GHCR_REPO
|
||||
id: set-ghcr-repo
|
||||
run: |
|
||||
echo "GHCR_REPO=$(echo ghcr.io/${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >>${GITHUB_OUTPUT}
|
||||
|
||||
gcc-amd64:
|
||||
name: Build and push GCC docker image (amd64)
|
||||
runs-on: heavy
|
||||
needs: repo
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
with:
|
||||
files: "docker/compilers/gcc/**"
|
||||
|
||||
- uses: ./.github/actions/build-docker-image
|
||||
if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_PW: ${{ secrets.DOCKERHUB_PW }}
|
||||
with:
|
||||
images: |
|
||||
${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
|
||||
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
|
||||
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
|
||||
directory: docker/compilers/gcc
|
||||
tags: |
|
||||
type=raw,value=amd64-latest
|
||||
type=raw,value=amd64-${{ env.GCC_MAJOR_VERSION }}
|
||||
type=raw,value=amd64-${{ env.GCC_VERSION }}
|
||||
type=raw,value=amd64-${{ github.sha }}
|
||||
platforms: linux/amd64
|
||||
build_args: |
|
||||
GCC_MAJOR_VERSION=${{ env.GCC_MAJOR_VERSION }}
|
||||
GCC_VERSION=${{ env.GCC_VERSION }}
|
||||
dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
|
||||
dockerhub_description: GCC compiler for XRPLF/clio.
|
||||
|
||||
gcc-arm64:
|
||||
name: Build and push GCC docker image (arm64)
|
||||
runs-on: heavy-arm64
|
||||
needs: repo
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
with:
|
||||
files: "docker/compilers/gcc/**"
|
||||
|
||||
- uses: ./.github/actions/build-docker-image
|
||||
if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_PW: ${{ secrets.DOCKERHUB_PW }}
|
||||
with:
|
||||
images: |
|
||||
${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
|
||||
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
|
||||
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
|
||||
directory: docker/compilers/gcc
|
||||
tags: |
|
||||
type=raw,value=arm64-latest
|
||||
type=raw,value=arm64-${{ env.GCC_MAJOR_VERSION }}
|
||||
type=raw,value=arm64-${{ env.GCC_VERSION }}
|
||||
type=raw,value=arm64-${{ github.sha }}
|
||||
platforms: linux/arm64
|
||||
build_args: |
|
||||
GCC_MAJOR_VERSION=${{ env.GCC_MAJOR_VERSION }}
|
||||
GCC_VERSION=${{ env.GCC_VERSION }}
|
||||
dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
|
||||
dockerhub_description: GCC compiler for XRPLF/clio.
|
||||
|
||||
gcc-merge:
|
||||
name: Merge and push multi-arch GCC docker image
|
||||
runs-on: heavy
|
||||
needs: [repo, gcc-amd64, gcc-arm64]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
with:
|
||||
files: "docker/compilers/gcc/**"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USER }}
|
||||
password: ${{ secrets.DOCKERHUB_PW }}
|
||||
|
||||
- name: Create and push multi-arch manifest
|
||||
if: ${{ github.event_name != 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
|
||||
run: |
|
||||
push_image() {
|
||||
image=$1
|
||||
|
||||
docker buildx imagetools create \
|
||||
-t $image:latest \
|
||||
-t $image:${{ env.GCC_MAJOR_VERSION }} \
|
||||
-t $image:${{ env.GCC_VERSION }} \
|
||||
-t $image:${{ github.sha }} \
|
||||
$image:arm64-latest \
|
||||
$image:amd64-latest
|
||||
}
|
||||
push_image ${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
|
||||
if [[ ${{ github.repository }} == 'XRPLF/clio' ]]; then
|
||||
push_image rippleci/clio_clang
|
||||
fi
|
||||
|
||||
clang:
|
||||
name: Build and push Clang docker image
|
||||
runs-on: heavy
|
||||
needs: repo
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
with:
|
||||
files: "docker/compilers/clang/**"
|
||||
|
||||
- uses: ./.github/actions/build-docker-image
|
||||
if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_PW: ${{ secrets.DOCKERHUB_PW }}
|
||||
with:
|
||||
images: |
|
||||
${{ needs.repo.outputs.GHCR_REPO }}/clio-clang
|
||||
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_clang' || '' }}
|
||||
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
|
||||
directory: docker/compilers/clang
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=raw,value=${{ env.CLANG_MAJOR_VERSION }}
|
||||
type=raw,value=${{ github.sha }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build_args: |
|
||||
CLANG_MAJOR_VERSION=${{ env.CLANG_MAJOR_VERSION }}
|
||||
dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_clang' || '' }}
|
||||
dockerhub_description: Clang compiler for XRPLF/clio.
|
||||
|
||||
tools-amd64:
|
||||
name: Build and push tools docker image (amd64)
|
||||
runs-on: heavy
|
||||
needs: [repo, gcc-merge]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
with:
|
||||
files: "docker/tools/**"
|
||||
|
||||
- uses: ./.github/actions/build-docker-image
|
||||
if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
images: |
|
||||
${{ needs.repo.outputs.GHCR_REPO }}/clio-tools
|
||||
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
|
||||
directory: docker/tools
|
||||
tags: |
|
||||
type=raw,value=amd64-latest
|
||||
type=raw,value=amd64-${{ github.sha }}
|
||||
platforms: linux/amd64
|
||||
build_args: |
|
||||
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
|
||||
GCC_VERSION=${{ env.GCC_VERSION }}
|
||||
|
||||
tools-arm64:
|
||||
name: Build and push tools docker image (arm64)
|
||||
runs-on: heavy-arm64
|
||||
needs: [repo, gcc-merge]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
with:
|
||||
files: "docker/tools/**"
|
||||
|
||||
- uses: ./.github/actions/build-docker-image
|
||||
if: ${{ steps.changed-files.outputs.any_changed == 'true' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
images: |
|
||||
${{ needs.repo.outputs.GHCR_REPO }}/clio-tools
|
||||
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
|
||||
directory: docker/tools
|
||||
tags: |
|
||||
type=raw,value=arm64-latest
|
||||
type=raw,value=arm64-${{ github.sha }}
|
||||
platforms: linux/arm64
|
||||
build_args: |
|
||||
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
|
||||
GCC_VERSION=${{ env.GCC_VERSION }}
|
||||
|
||||
tools-merge:
|
||||
name: Merge and push multi-arch tools docker image
|
||||
runs-on: heavy
|
||||
needs: [repo, tools-amd64, tools-arm64]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
with:
|
||||
files: "docker/tools/**"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create and push multi-arch manifest
|
||||
if: ${{ github.event_name != 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
|
||||
run: |
|
||||
image=${{ needs.repo.outputs.GHCR_REPO }}/clio-tools
|
||||
docker buildx imagetools create \
|
||||
-t $image:latest \
|
||||
-t $image:${{ github.sha }} \
|
||||
$image:arm64-latest \
|
||||
$image:amd64-latest
|
||||
|
||||
pre-commit:
|
||||
name: Build and push pre-commit docker image
|
||||
runs-on: heavy
|
||||
needs: [repo, tools-merge]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
- uses: ./.github/actions/build-docker-image
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
images: |
|
||||
${{ needs.repo.outputs.GHCR_REPO }}/clio-pre-commit
|
||||
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
|
||||
directory: docker/pre-commit
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=raw,value=${{ github.sha }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build_args: |
|
||||
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
|
||||
|
||||
ci:
|
||||
name: Build and push CI docker image
|
||||
runs-on: heavy
|
||||
needs: [repo, gcc-merge, clang, tools-merge]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
- uses: ./.github/actions/build-docker-image
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_PW: ${{ secrets.DOCKERHUB_PW }}
|
||||
with:
|
||||
images: |
|
||||
${{ needs.repo.outputs.GHCR_REPO }}/clio-ci
|
||||
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_ci' || '' }}
|
||||
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
|
||||
directory: docker/ci
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=raw,value=gcc_${{ env.GCC_MAJOR_VERSION }}_clang_${{ env.CLANG_MAJOR_VERSION }}
|
||||
type=raw,value=${{ github.sha }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build_args: |
|
||||
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
|
||||
CLANG_MAJOR_VERSION=${{ env.CLANG_MAJOR_VERSION }}
|
||||
GCC_MAJOR_VERSION=${{ env.GCC_MAJOR_VERSION }}
|
||||
GCC_VERSION=${{ env.GCC_VERSION }}
|
||||
dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_ci' || '' }}
|
||||
dockerhub_description: CI image for XRPLF/clio.
|
||||
22
.github/workflows/upload-conan-deps.yml
vendored
22
.github/workflows/upload-conan-deps.yml
vendored
@@ -59,7 +59,7 @@ jobs:
|
||||
run: .github/scripts/conan/generate_matrix.py >>"${GITHUB_OUTPUT}"
|
||||
|
||||
upload-conan-deps:
|
||||
name: Build ${{ matrix.compiler }}${{ matrix.sanitizer_ext }} ${{ matrix.build_type }}
|
||||
name: Build ${{ matrix.compiler }} ${{ matrix.sanitizers }} ${{ matrix.build_type }}
|
||||
|
||||
needs: generate-matrix
|
||||
|
||||
@@ -71,9 +71,6 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container != '' && fromJson(matrix.container) || null }}
|
||||
|
||||
env:
|
||||
CONAN_PROFILE: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
@@ -85,17 +82,24 @@ jobs:
|
||||
- name: Print build environment
|
||||
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
|
||||
|
||||
- name: Setup conan on macOS
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
run: ./.github/scripts/conan/init.sh
|
||||
- name: Set compiler environment
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
uses: ./.github/actions/set-compiler-env
|
||||
with:
|
||||
compiler: ${{ matrix.compiler }}
|
||||
|
||||
- name: Setup conan
|
||||
run: conan/init.sh
|
||||
|
||||
- name: Show conan profile
|
||||
run: conan profile show --profile:all ${{ env.CONAN_PROFILE }}
|
||||
env:
|
||||
SANITIZERS: ${{ matrix.sanitizers }}
|
||||
run: conan profile show --profile:all ci
|
||||
|
||||
- name: Run conan
|
||||
uses: ./.github/actions/conan
|
||||
with:
|
||||
conan_profile: ${{ env.CONAN_PROFILE }}
|
||||
sanitizers: ${{ matrix.sanitizers }}
|
||||
# We check that everything builds fine from source on scheduled runs
|
||||
# But we do build and upload packages with build=missing by default
|
||||
force_conan_source_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }}
|
||||
|
||||
@@ -16,7 +16,6 @@ option(docs "Generate doxygen docs" FALSE)
|
||||
option(coverage "Build test coverage report" FALSE)
|
||||
option(package "Create distribution packages" FALSE)
|
||||
option(lint "Run clang-tidy checks during compilation" FALSE)
|
||||
option(static "Statically linked Clio" FALSE)
|
||||
option(snapshot "Build snapshot tool" FALSE)
|
||||
option(
|
||||
time_trace
|
||||
@@ -25,10 +24,7 @@ option(
|
||||
)
|
||||
|
||||
# ========================================================================== #
|
||||
set(san "" CACHE STRING "Add sanitizer instrumentation")
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
|
||||
set_property(CACHE san PROPERTY STRINGS ";undefined;memory;address;thread")
|
||||
# ========================================================================== #
|
||||
|
||||
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
|
||||
@@ -42,6 +38,21 @@ add_library(clio_options INTERFACE)
|
||||
target_compile_features(clio_options INTERFACE cxx_std_23) # Clio needs c++23 but deps can remain c++20 for now
|
||||
target_include_directories(clio_options INTERFACE ${CMAKE_SOURCE_DIR}/src)
|
||||
|
||||
if(
|
||||
CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
|
||||
OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
|
||||
)
|
||||
# Note: -static-libstdc++ can statically link both libstdc++ and libc++
|
||||
target_link_libraries(
|
||||
clio_options
|
||||
INTERFACE -static-libstdc++ -static-libgcc
|
||||
)
|
||||
endif()
|
||||
|
||||
# Apply sanitizer instrumentation if requested and define SANITIZERS_ENABLED.
|
||||
# Must come before the modules and subdirectories below that key off it.
|
||||
include(Sanitizers)
|
||||
|
||||
if(verbose)
|
||||
set(CMAKE_VERBOSE_MAKEFILE TRUE)
|
||||
endif()
|
||||
@@ -50,6 +61,7 @@ endif()
|
||||
include(CheckCompiler)
|
||||
include(Settings)
|
||||
include(SourceLocation)
|
||||
include(PatchNixBinary)
|
||||
|
||||
# Clio deps
|
||||
include(deps/libxrpl)
|
||||
@@ -68,29 +80,6 @@ if(benchmark)
|
||||
add_subdirectory(benchmarks)
|
||||
endif()
|
||||
|
||||
# Enable selected sanitizer if enabled via `san`
|
||||
if(san)
|
||||
set(SUPPORTED_SANITIZERS "address" "thread" "memory" "undefined")
|
||||
if(NOT san IN_LIST SUPPORTED_SANITIZERS)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Error: Unsupported sanitizer '${san}'. Supported values are: ${SUPPORTED_SANITIZERS}."
|
||||
)
|
||||
endif()
|
||||
|
||||
# Sanitizers recommend minimum of -O1 for reasonable performance so we enable it for debug builds
|
||||
set(SAN_OPTIMIZATION_FLAG "")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(SAN_OPTIMIZATION_FLAG -O1)
|
||||
endif()
|
||||
target_compile_options(
|
||||
clio_options
|
||||
INTERFACE ${SAN_OPTIMIZATION_FLAG} ${SAN_FLAG} -fno-omit-frame-pointer
|
||||
)
|
||||
|
||||
target_link_libraries(clio_options INTERFACE ${SAN_FLAG} ${SAN_LIB})
|
||||
endif()
|
||||
|
||||
# Generate `docs` target for doxygen documentation if enabled Note: use `make docs` to generate the documentation
|
||||
if(docs)
|
||||
add_subdirectory(docs)
|
||||
|
||||
@@ -19,30 +19,3 @@ else()
|
||||
"Supported compilers: AppleClang 15+, Clang 16+, GCC 12+"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(san)
|
||||
string(TOLOWER ${san} san)
|
||||
set(SAN_FLAG "-fsanitize=${san}")
|
||||
set(SAN_LIB "")
|
||||
if(is_gcc)
|
||||
if(san STREQUAL "address")
|
||||
set(SAN_LIB "asan")
|
||||
elseif(san STREQUAL "thread")
|
||||
set(SAN_LIB "tsan")
|
||||
elseif(san STREQUAL "memory")
|
||||
set(SAN_LIB "msan")
|
||||
elseif(san STREQUAL "undefined")
|
||||
set(SAN_LIB "ubsan")
|
||||
endif()
|
||||
endif()
|
||||
set(_saved_CRL ${CMAKE_REQUIRED_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${SAN_FLAG};${SAN_LIB}")
|
||||
check_cxx_compiler_flag(${SAN_FLAG} COMPILER_SUPPORTS_SAN)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${_saved_CRL})
|
||||
if(NOT COMPILER_SUPPORTS_SAN)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"${san} sanitizer does not seem to be supported by your compiler"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
55
cmake/PatchNixBinary.cmake
Normal file
55
cmake/PatchNixBinary.cmake
Normal file
@@ -0,0 +1,55 @@
|
||||
#[===================================================================[
|
||||
Patch executables to run in non-Nix environments.
|
||||
|
||||
The Nix-based CI image links binaries against an ELF interpreter (loader)
|
||||
that lives in the Nix store, so the resulting binaries don't run elsewhere
|
||||
(including once installed from the .deb package). `patch_nix_binary` adds a
|
||||
POST_BUILD step that resets the interpreter to the system default loader and
|
||||
drops the rpath.
|
||||
|
||||
This is only active inside the Nix-based image, detected by the presence of
|
||||
/tmp/loader-path.sh (shipped by that image, resolves the default loader). It
|
||||
is skipped for sanitizer builds, whose runtime libraries are resolved through
|
||||
the rpath. Everywhere else `patch_nix_binary` is a no-op.
|
||||
#]===================================================================]
|
||||
|
||||
include_guard(GLOBAL)
|
||||
|
||||
# Provided by the Nix-based CI image; prints the system default ELF loader path.
|
||||
set(_loader_path_script "/tmp/loader-path.sh")
|
||||
|
||||
if(
|
||||
CMAKE_SYSTEM_NAME STREQUAL "Linux"
|
||||
AND NOT SANITIZERS_ENABLED
|
||||
AND EXISTS "${_loader_path_script}"
|
||||
)
|
||||
execute_process(
|
||||
COMMAND "${_loader_path_script}"
|
||||
OUTPUT_VARIABLE DEFAULT_LOADER_PATH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
find_program(PATCHELF_COMMAND patchelf REQUIRED)
|
||||
set(PATCH_NIX_BINARIES TRUE)
|
||||
message(
|
||||
STATUS
|
||||
"Binaries will be patched to use loader '${DEFAULT_LOADER_PATH}'"
|
||||
)
|
||||
else()
|
||||
set(PATCH_NIX_BINARIES FALSE)
|
||||
endif()
|
||||
|
||||
function(patch_nix_binary target)
|
||||
if(NOT PATCH_NIX_BINARIES)
|
||||
return()
|
||||
endif()
|
||||
add_custom_command(
|
||||
TARGET ${target}
|
||||
POST_BUILD
|
||||
COMMAND
|
||||
"${PATCHELF_COMMAND}" --set-interpreter "${DEFAULT_LOADER_PATH}"
|
||||
--remove-rpath "$<TARGET_FILE:${target}>"
|
||||
COMMENT "Patching ${target}: set default loader, remove rpath"
|
||||
VERBATIM
|
||||
)
|
||||
endfunction()
|
||||
47
cmake/Sanitizers.cmake
Normal file
47
cmake/Sanitizers.cmake
Normal file
@@ -0,0 +1,47 @@
|
||||
#[===================================================================[
|
||||
Apply sanitizer flags built by the Conan profile.
|
||||
|
||||
Parsing, validation, and flag construction are performed in
|
||||
conan/profiles/sanitizers. This module reads the following CMake variables
|
||||
injected by the Conan toolchain via extra_variables:
|
||||
|
||||
- SANITIZERS: The active sanitizers (e.g. "address").
|
||||
- SANITIZERS_COMPILER_FLAGS: Space-separated compiler flags.
|
||||
- SANITIZERS_LINKER_FLAGS: Space-separated linker flags.
|
||||
|
||||
It defines SANITIZERS_ENABLED for the rest of the build to key off, and
|
||||
applies the flags to the 'clio_options' interface library.
|
||||
#]===================================================================]
|
||||
|
||||
include_guard(GLOBAL)
|
||||
|
||||
if(NOT DEFINED SANITIZERS)
|
||||
set(SANITIZERS_ENABLED FALSE)
|
||||
return()
|
||||
endif()
|
||||
set(SANITIZERS_ENABLED TRUE)
|
||||
|
||||
message(STATUS "=== Configuring sanitizers ===")
|
||||
message(STATUS " SANITIZERS: ${SANITIZERS}")
|
||||
message(STATUS " Compile flags: ${SANITIZERS_COMPILER_FLAGS}")
|
||||
message(STATUS " Link flags: ${SANITIZERS_LINKER_FLAGS}")
|
||||
|
||||
# Flags arrive as space-separated strings; split into CMake lists before use
|
||||
separate_arguments(
|
||||
sanitizers_compiler_flags
|
||||
UNIX_COMMAND
|
||||
"${SANITIZERS_COMPILER_FLAGS}"
|
||||
)
|
||||
separate_arguments(
|
||||
sanitizers_linker_flags
|
||||
UNIX_COMMAND
|
||||
"${SANITIZERS_LINKER_FLAGS}"
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
clio_options
|
||||
INTERFACE
|
||||
$<$<COMPILE_LANGUAGE:CXX>:${sanitizers_compiler_flags}>
|
||||
$<$<COMPILE_LANGUAGE:C>:${sanitizers_compiler_flags}>
|
||||
)
|
||||
target_link_options(clio_options INTERFACE ${sanitizers_linker_flags})
|
||||
@@ -40,7 +40,7 @@ if(is_appleclang)
|
||||
list(APPEND COMPILER_FLAGS -Wreorder-init-list)
|
||||
endif()
|
||||
|
||||
if(san)
|
||||
if(SANITIZERS_ENABLED)
|
||||
# When building with sanitizers some compilers will actually produce extra warnings/errors. We don't want this yet,
|
||||
# at least not until we have fixed all runtime issues reported by the sanitizers. Once that is done we can start
|
||||
# removing some of these and trying to fix it in our codebase. We can never remove all of below because most of them
|
||||
@@ -85,3 +85,22 @@ target_compile_options(clio_options INTERFACE ${COMPILER_FLAGS})
|
||||
|
||||
# Add debug symbols for all builds, including Release. This is needed to get useful stack traces in production.
|
||||
target_compile_options(clio_options INTERFACE -g)
|
||||
|
||||
# Keep -stdlib=libstdc++ off the compile commands, but preserve it for linking.
|
||||
#
|
||||
# Conan turns `compiler.libcxx=libstdc++` into `-stdlib=libstdc++` and puts it in CMAKE_CXX_FLAGS, which CMake passes to
|
||||
# BOTH compile and link steps. On a normal Clang the compile step consumes it while choosing the C++ stdlib include
|
||||
# paths. The Nixpkgs Clang wrapper (used by our CI image) supplies those paths itself (via -nostdinc++), so at compile
|
||||
# time the flag is unused -> Clang errors under our -Werror. At link time the flag IS consumed (it selects the C++
|
||||
# runtime), so we move it there instead of dropping it entirely.
|
||||
get_filename_component(_cxx_real "${CMAKE_CXX_COMPILER}" REALPATH)
|
||||
if(
|
||||
_cxx_real MATCHES "^/nix/store/"
|
||||
AND CMAKE_SYSTEM_NAME STREQUAL "Linux"
|
||||
AND is_clang
|
||||
AND CMAKE_CXX_FLAGS MATCHES "stdlib=libstdc"
|
||||
)
|
||||
string(REPLACE "-stdlib=libstdc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(STRIP "${CMAKE_CXX_FLAGS}" CMAKE_CXX_FLAGS)
|
||||
add_link_options($<$<LINK_LANGUAGE:CXX>:-stdlib=libstdc++>)
|
||||
endif()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if("${san}" STREQUAL "")
|
||||
if(NOT SANITIZERS_ENABLED)
|
||||
target_compile_definitions(clio_options INTERFACE BOOST_STACKTRACE_LINK)
|
||||
target_compile_definitions(
|
||||
clio_options
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
|
||||
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
|
||||
"boost/1.83.0#91d8b1572534d2c334d6790e3c34d0c1%1764175359.61",
|
||||
"benchmark/1.9.4#ce4403f7a24d3e1f907cd9da4b678be4%1754578869.672",
|
||||
"benchmark/1.9.5#b885dc73ad67b40a55d45684d1c88ad1%1774363287.434",
|
||||
"abseil/20230802.1#90ba607d4ee8fb5fb157c3db540671fc%1764175359.429"
|
||||
],
|
||||
"build_requires": [
|
||||
|
||||
7
conan/global.conf
Normal file
7
conan/global.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
# Global configuration for Conan. This is used to set the number of parallel
|
||||
# downloads and uploads.
|
||||
core:non_interactive=True
|
||||
core.download:parallel={{ os.cpu_count() }}
|
||||
core.upload:parallel={{ os.cpu_count() }}
|
||||
tools.files.download:retry=5
|
||||
tools.files.download:retry_wait=10
|
||||
30
conan/init.sh
Executable file
30
conan/init.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROFILES_SRC_DIR="$CURRENT_DIR/profiles"
|
||||
|
||||
CONAN_DIR="${CONAN_HOME:-$HOME/.conan2}"
|
||||
PROFILES_DIR="$CONAN_DIR/profiles"
|
||||
|
||||
rm -rf "$CONAN_DIR"
|
||||
|
||||
conan remote add --index 0 --force xrplf https://conan.ripplex.io
|
||||
|
||||
cp "$CURRENT_DIR/global.conf" "$CONAN_DIR/global.conf"
|
||||
|
||||
mkdir -p "$PROFILES_DIR"
|
||||
|
||||
# The compiler is selected via the `CC`/`CXX` environment variables (see
|
||||
# `.github/actions/set-compiler-env`) and the sanitizers via the `SANITIZERS`
|
||||
# environment variable. Builds always use the `ci` profile, which includes
|
||||
# `sanitizers` and `default`.
|
||||
cp "$PROFILES_SRC_DIR/ci" "$PROFILES_DIR/ci"
|
||||
cp "$PROFILES_SRC_DIR/sanitizers" "$PROFILES_DIR/sanitizers"
|
||||
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
cp "$PROFILES_SRC_DIR/apple-clang-17.profile" "$PROFILES_DIR/default"
|
||||
else
|
||||
cp "$PROFILES_SRC_DIR/default" "$PROFILES_DIR/default"
|
||||
fi
|
||||
8
conan/profiles/ci
Normal file
8
conan/profiles/ci
Normal file
@@ -0,0 +1,8 @@
|
||||
{% set os = detect_api.detect_os() %}
|
||||
include(sanitizers)
|
||||
|
||||
[conf]
|
||||
{% if os == "Linux" %}
|
||||
user.package:libc_version=2.31
|
||||
tools.info.package_id:confs+=["user.package:libc_version"]
|
||||
{% endif %}
|
||||
28
conan/profiles/default
Normal file
28
conan/profiles/default
Normal file
@@ -0,0 +1,28 @@
|
||||
{% set os = detect_api.detect_os() %}
|
||||
{% set arch = detect_api.detect_arch() %}
|
||||
{% set compiler, version, compiler_exe = detect_api.detect_default_compiler() %}
|
||||
{% set compiler_version = version %}
|
||||
{% if os == "Linux" %}
|
||||
{% set compiler_version = detect_api.default_compiler_version(compiler, version) %}
|
||||
{% endif %}
|
||||
|
||||
[settings]
|
||||
os={{ os }}
|
||||
arch={{ arch }}
|
||||
build_type=Debug
|
||||
compiler={{compiler}}
|
||||
compiler.version={{ compiler_version }}
|
||||
compiler.cppstd=20
|
||||
{% if os == "Windows" %}
|
||||
compiler.runtime=static
|
||||
{% else %}
|
||||
compiler.libcxx={{detect_api.detect_libcxx(compiler, version, compiler_exe)}}
|
||||
{% endif %}
|
||||
|
||||
[conf]
|
||||
{% if compiler == "gcc" and compiler_version < 13 %}
|
||||
tools.build:cxxflags+=['-Wno-restrict']
|
||||
{% endif %}
|
||||
{% if compiler == "clang" %}
|
||||
grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
{% endif %}
|
||||
120
conan/profiles/sanitizers
Normal file
120
conan/profiles/sanitizers
Normal file
@@ -0,0 +1,120 @@
|
||||
include(default)
|
||||
{% set compiler, version, compiler_exe = detect_api.detect_default_compiler() %}
|
||||
{% set arch = detect_api.detect_arch() %}
|
||||
{% set sanitizers = os.getenv("SANITIZERS") %}
|
||||
|
||||
{% if not sanitizers %}
|
||||
{# Sanitizers not configured; no additional settings needed #}
|
||||
{% else %}
|
||||
|
||||
{% if compiler == "msvc" %}
|
||||
{{ "Sanitizers are not supported on Windows/MSVC. Please unset the SANITIZERS environment variable." }}
|
||||
{% endif %}
|
||||
|
||||
{% set known_sanitizers = ["address", "thread", "undefinedbehavior"] %}
|
||||
{% set provided_sanitizers = [] %}
|
||||
{% for san in sanitizers.split(",") %}
|
||||
{% set san = san.strip() %}
|
||||
{% if san not in known_sanitizers %}
|
||||
{{ "Unknown sanitizer in SANITIZERS: " ~ san }}
|
||||
{% endif %}
|
||||
{% set _ = provided_sanitizers.append(san) %}
|
||||
{% endfor %}
|
||||
|
||||
{% set enable_asan = "address" in provided_sanitizers %}
|
||||
{% set enable_tsan = "thread" in provided_sanitizers %}
|
||||
{% set enable_ubsan = "undefinedbehavior" in provided_sanitizers %}
|
||||
|
||||
{% if enable_asan and enable_tsan %}
|
||||
{{ "AddressSanitizer and ThreadSanitizer are incompatible and cannot be enabled simultaneously." }}
|
||||
{% endif %}
|
||||
|
||||
{% set sanitizer_types = [] %}
|
||||
{% set defines = [] %}
|
||||
|
||||
{% if enable_asan %}
|
||||
{% set _ = sanitizer_types.append("address") %}
|
||||
{% set _ = defines.append("BOOST_USE_ASAN") %}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT") %}
|
||||
{% elif enable_tsan %}
|
||||
{% set _ = sanitizer_types.append("thread") %}
|
||||
{% set _ = defines.append("BOOST_USE_TSAN") %}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT") %}
|
||||
{% endif %}
|
||||
|
||||
{% if enable_ubsan %}
|
||||
{% set _ = sanitizer_types.append("undefined") %}
|
||||
{% set _ = sanitizer_types.append("float-divide-by-zero") %}
|
||||
{# Clang supports additional UB checks beyond the GCC baseline #}
|
||||
{% if compiler == "clang" or compiler == "apple-clang" %}
|
||||
{% set _ = sanitizer_types.append("unsigned-integer-overflow") %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# Frame pointer required for meaningful stack traces; -O1 for reasonable performance #}
|
||||
{% set sanitizer_compiler_flags = ["-fno-omit-frame-pointer", "-O1"] %}
|
||||
|
||||
{% if compiler == "gcc" %}
|
||||
{# Suppress false positive warnings with GCC #}
|
||||
{% set _ = sanitizer_compiler_flags.append("-Wno-stringop-overflow") %}
|
||||
|
||||
{% set relocation_flags = [] %}
|
||||
|
||||
{% if arch == "x86_64" and enable_asan %}
|
||||
{# Large code model prevents relocation errors in instrumented ASAN binaries #}
|
||||
{% set _ = sanitizer_compiler_flags.append("-mcmodel=large") %}
|
||||
{% set _ = relocation_flags.append("-mcmodel=large") %}
|
||||
{% elif enable_tsan %}
|
||||
{# GCC doesn't support atomic_thread_fence with TSAN; suppress warnings #}
|
||||
{% set _ = sanitizer_compiler_flags.append("-Wno-tsan") %}
|
||||
{% if arch == "x86_64" %}
|
||||
{# Medium code model for TSAN; large is incompatible #}
|
||||
{% set _ = sanitizer_compiler_flags.append("-mcmodel=medium") %}
|
||||
{% set _ = relocation_flags.append("-mcmodel=medium") %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% set fsanitize = "-fsanitize=" ~ ",".join(sanitizer_types) %}
|
||||
{% set _ = sanitizer_compiler_flags.append(fsanitize) %}
|
||||
{% set _ = relocation_flags.append(fsanitize) %}
|
||||
|
||||
{% set sanitizer_linker_flags = relocation_flags %}
|
||||
{% elif compiler == "clang" or compiler == "apple-clang" %}
|
||||
{% set fsanitize = "-fsanitize=" ~ ",".join(sanitizer_types) %}
|
||||
{% set _ = sanitizer_compiler_flags.append(fsanitize) %}
|
||||
|
||||
{% set sanitizer_linker_flags = [fsanitize] %}
|
||||
{% endif %}
|
||||
|
||||
[conf]
|
||||
tools.build:defines+={{defines}}
|
||||
tools.build:cxxflags+={{sanitizer_compiler_flags}}
|
||||
tools.build:sharedlinkflags+={{sanitizer_linker_flags}}
|
||||
tools.build:exelinkflags+={{sanitizer_linker_flags}}
|
||||
|
||||
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]
|
||||
|
||||
# &: means "apply only to the consumer/root package"
|
||||
&:tools.cmake.cmaketoolchain:extra_variables={"SANITIZERS": "{{sanitizers}}", "SANITIZERS_COMPILER_FLAGS": "{{sanitizer_compiler_flags | join(' ')}}", "SANITIZERS_LINKER_FLAGS": "{{sanitizer_linker_flags | join(' ')}}"}
|
||||
|
||||
[options]
|
||||
{% if enable_asan %}
|
||||
# Build Boost.Context with ucontext backend (not fcontext) so that
|
||||
# ASAN fiber-switching annotations (__sanitizer_start/finish_switch_fiber)
|
||||
# are compiled into the library. fcontext (assembly) has no ASAN support.
|
||||
# define=BOOST_USE_ASAN=1 is critical: it must be defined when building
|
||||
# Boost.Context itself so the ucontext backend compiles in the ASAN annotations.
|
||||
boost/*:extra_b2_flags=context-impl=ucontext address-sanitizer=on define=BOOST_USE_ASAN=1
|
||||
boost/*:without_context=False
|
||||
# Boost stacktrace fails to build with some sanitizers
|
||||
boost/*:without_stacktrace=True
|
||||
{% elif enable_tsan %}
|
||||
# Build Boost.Context with ucontext backend for TSAN. fcontext (assembly)
|
||||
# has no TSAN annotations, so without this the BOOST_USE_TSAN/BOOST_USE_UCONTEXT
|
||||
# defines in [conf] would be ineffective.
|
||||
boost/*:extra_b2_flags=context-impl=ucontext thread-sanitizer=on define=BOOST_USE_TSAN=1
|
||||
boost/*:without_context=False
|
||||
boost/*:without_stacktrace=True
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
@@ -1,6 +1,7 @@
|
||||
from conan import ConanFile
|
||||
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
|
||||
|
||||
from conan import ConanFile
|
||||
|
||||
|
||||
class ClioConan(ConanFile):
|
||||
name = "clio"
|
||||
@@ -44,7 +45,7 @@ class ClioConan(ConanFile):
|
||||
def requirements(self):
|
||||
self.requires("boost/1.83.0", force=True)
|
||||
self.requires("gtest/1.17.0")
|
||||
self.requires("benchmark/1.9.4")
|
||||
self.requires("benchmark/1.9.5")
|
||||
|
||||
def configure(self):
|
||||
if self.settings.compiler == "apple-clang":
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
ARG GHCR_REPO=invalid
|
||||
ARG CLANG_MAJOR_VERSION=invalid
|
||||
ARG GCC_VERSION=invalid
|
||||
|
||||
FROM ${GHCR_REPO}/clio-gcc:${GCC_VERSION} AS clio-gcc
|
||||
FROM ${GHCR_REPO}/clio-tools:latest AS clio-tools
|
||||
|
||||
FROM ${GHCR_REPO}/clio-clang:${CLANG_MAJOR_VERSION}
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
# Using root by default is not very secure but github checkout action doesn't work with any other user
|
||||
# https://github.com/actions/checkout/issues/956
|
||||
# And Github Actions doc recommends using root
|
||||
# https://docs.github.com/en/actions/sharing-automations/creating-actions/dockerfile-support-for-github-actions#user
|
||||
|
||||
# hadolint ignore=DL3002
|
||||
USER root
|
||||
WORKDIR /root
|
||||
|
||||
# Install common tools and dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
curl \
|
||||
dpkg-dev \
|
||||
file \
|
||||
git \
|
||||
git-lfs \
|
||||
gnupg \
|
||||
graphviz \
|
||||
jq \
|
||||
# libgmp, libmpfr and libncurses are gdb dependencies
|
||||
libgmp-dev \
|
||||
libmpfr-dev \
|
||||
libncurses-dev \
|
||||
make \
|
||||
wget \
|
||||
zip \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Python tools
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
python3 \
|
||||
python3-pip \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pip install -q --no-cache-dir \
|
||||
# TODO: Remove this once we switch to newer Ubuntu base image
|
||||
# lxml 6.0.0 is not compatible with our image
|
||||
'lxml<6.0.0' \
|
||||
cmake \
|
||||
conan==2.24.0 \
|
||||
gcovr \
|
||||
# We're adding pre-commit to this image as well,
|
||||
# because clang-tidy workflow requires it
|
||||
pre-commit
|
||||
|
||||
# Install LLVM tools
|
||||
ARG LLVM_TOOLS_VERSION=21
|
||||
|
||||
RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${LLVM_TOOLS_VERSION} main" >> /etc/apt/sources.list \
|
||||
&& wget --progress=dot:giga -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
clang-tidy-${LLVM_TOOLS_VERSION} \
|
||||
clang-tools-${LLVM_TOOLS_VERSION} \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG GCC_MAJOR_VERSION=invalid
|
||||
|
||||
# Install custom-built gcc and make ldconfig aware of the new libstdc++ location (for gcc)
|
||||
# Note: Clang is using libc++ instead
|
||||
COPY --from=clio-gcc /gcc${GCC_MAJOR_VERSION}.deb /
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
binutils \
|
||||
libc6-dev \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& dpkg -i /gcc${GCC_MAJOR_VERSION}.deb \
|
||||
&& rm -rf /gcc${GCC_MAJOR_VERSION}.deb \
|
||||
&& ldconfig
|
||||
|
||||
# Rewire to use our custom-built gcc as default compiler
|
||||
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/cc cc /usr/bin/gcc-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/gcov-dump gcov-dump /usr/bin/gcov-dump-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-${GCC_MAJOR_VERSION} 100
|
||||
|
||||
COPY --from=clio-tools \
|
||||
/usr/local/bin/mold \
|
||||
/usr/local/bin/ld.mold \
|
||||
/usr/local/bin/ccache \
|
||||
/usr/local/bin/doxygen \
|
||||
/usr/local/bin/ClangBuildAnalyzer \
|
||||
/usr/local/bin/git-cliff \
|
||||
/usr/local/bin/gh \
|
||||
/usr/local/bin/gdb \
|
||||
/usr/local/bin/ninja \
|
||||
/usr/local/bin/
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
# Setup conan
|
||||
RUN conan remote add --index 0 xrplf https://conan.ripplex.io
|
||||
|
||||
WORKDIR /root/.conan2
|
||||
COPY conan/global.conf ./global.conf
|
||||
|
||||
WORKDIR /root/.conan2/profiles
|
||||
|
||||
COPY conan/clang.profile ./clang
|
||||
COPY conan/sanitizer_template.profile ./clang.asan
|
||||
COPY conan/sanitizer_template.profile ./clang.tsan
|
||||
COPY conan/sanitizer_template.profile ./clang.ubsan
|
||||
|
||||
COPY conan/gcc.profile ./gcc
|
||||
COPY conan/sanitizer_template.profile ./gcc.asan
|
||||
COPY conan/sanitizer_template.profile ./gcc.tsan
|
||||
COPY conan/sanitizer_template.profile ./gcc.ubsan
|
||||
|
||||
WORKDIR /root
|
||||
@@ -1,26 +0,0 @@
|
||||
# CI image for XRPLF/clio
|
||||
|
||||
This image contains an environment to build [Clio](https://github.com/XRPLF/clio), check code and documentation.
|
||||
It is used in [Clio Github Actions](https://github.com/XRPLF/clio/actions) but can also be used to compile Clio locally.
|
||||
|
||||
The image is based on Ubuntu 20.04 and contains:
|
||||
|
||||
- ccache 4.12.2
|
||||
- Clang 19
|
||||
- ClangBuildAnalyzer 1.6.0
|
||||
- Conan 2.24.0
|
||||
- Doxygen 1.16.1
|
||||
- GCC 15.2.0
|
||||
- GDB 17.1
|
||||
- gh 2.83.2
|
||||
- git-cliff 2.11.0
|
||||
- LLVM Tools 21
|
||||
- mold 2.40.4
|
||||
- Ninja 1.13.2
|
||||
- Python 3.8
|
||||
- and some other useful tools
|
||||
|
||||
Conan is set up to build Clio without any additional steps.
|
||||
There are two preset conan profiles: `clang` and `gcc` to use corresponding compiler.
|
||||
`ASan`, `TSan` and `UBSan` sanitizer builds are enabled via conan profiles for each of the supported compilers.
|
||||
These can be selected using the following pattern (all lowercase): `[compiler].[sanitizer]` (e.g. `--profile:all gcc.tsan`).
|
||||
@@ -1,12 +0,0 @@
|
||||
[settings]
|
||||
arch={{detect_api.detect_arch()}}
|
||||
build_type=Release
|
||||
compiler=clang
|
||||
compiler.cppstd=20
|
||||
compiler.libcxx=libc++
|
||||
compiler.version=19
|
||||
os=Linux
|
||||
|
||||
[conf]
|
||||
tools.build:compiler_executables={"c": "/usr/bin/clang-19", "cpp": "/usr/bin/clang++-19"}
|
||||
grpc/1.50.1:tools.build:cxxflags+=["-Wno-missing-template-arg-list-after-template-kw"]
|
||||
@@ -1,11 +0,0 @@
|
||||
[settings]
|
||||
arch={{detect_api.detect_arch()}}
|
||||
build_type=Release
|
||||
compiler=gcc
|
||||
compiler.cppstd=20
|
||||
compiler.libcxx=libstdc++11
|
||||
compiler.version=15
|
||||
os=Linux
|
||||
|
||||
[conf]
|
||||
tools.build:compiler_executables={"c": "/usr/bin/gcc-15", "cpp": "/usr/bin/g++-15"}
|
||||
@@ -1,2 +0,0 @@
|
||||
core.download:parallel={{os.cpu_count()}}
|
||||
core.upload:parallel={{os.cpu_count()}}
|
||||
@@ -1,37 +0,0 @@
|
||||
{% set compiler, sani = profile_name.split('.') %}
|
||||
|
||||
{% set sanitizer_opt_map = {"asan": "address", "tsan": "thread", "ubsan": "undefined"} %}
|
||||
{% set sanitizer = sanitizer_opt_map[sani] %}
|
||||
|
||||
{% set sanitizer_b2_flags_map = {
|
||||
"address": "context-impl=ucontext address-sanitizer=norecover",
|
||||
"thread": "context-impl=ucontext thread-sanitizer=norecover",
|
||||
"undefined": "undefined-sanitizer=norecover"
|
||||
} %}
|
||||
{% set sanitizer_b2_flags_str = sanitizer_b2_flags_map[sanitizer] %}
|
||||
|
||||
{% set sanitizer_build_flags_str = "-fsanitize=" ~ sanitizer ~ " -g -O1 -fno-omit-frame-pointer" %}
|
||||
{% set sanitizer_build_flags = sanitizer_build_flags_str.split(' ') %}
|
||||
{% set sanitizer_link_flags_str = "-fsanitize=" ~ sanitizer %}
|
||||
{% set sanitizer_link_flags = sanitizer_link_flags_str.split(' ') %}
|
||||
|
||||
include({{ compiler }})
|
||||
|
||||
[options]
|
||||
boost/*:extra_b2_flags="{{ sanitizer_b2_flags_str }}"
|
||||
boost/*:without_context=False
|
||||
boost/*:without_stacktrace=True
|
||||
|
||||
[conf]
|
||||
tools.build:cflags+={{ sanitizer_build_flags }}
|
||||
tools.build:cxxflags+={{ sanitizer_build_flags }}
|
||||
tools.build:exelinkflags+={{ sanitizer_link_flags }}
|
||||
tools.build:sharedlinkflags+={{ sanitizer_link_flags }}
|
||||
|
||||
{% if sanitizer == "address" %}
|
||||
tools.build:defines+=["BOOST_USE_ASAN", "BOOST_USE_UCONTEXT"]
|
||||
{% elif sanitizer == "thread" %}
|
||||
tools.build:defines+=["BOOST_USE_TSAN", "BOOST_USE_UCONTEXT"]
|
||||
{% endif %}
|
||||
|
||||
tools.info.package_id:confs+=["tools.build:cflags", "tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]
|
||||
@@ -1,32 +0,0 @@
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
# hadolint ignore=DL3002
|
||||
USER root
|
||||
WORKDIR /root
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
wget \
|
||||
software-properties-common \
|
||||
gnupg \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG CLANG_MAJOR_VERSION=invalid
|
||||
# Bump this version to force rebuild of the image
|
||||
ARG BUILD_VERSION=1
|
||||
|
||||
RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
|
||||
&& chmod +x llvm.sh \
|
||||
&& ./llvm.sh ${CLANG_MAJOR_VERSION} \
|
||||
&& rm -rf llvm.sh \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
libc++-${CLANG_MAJOR_VERSION}-dev \
|
||||
libc++abi-${CLANG_MAJOR_VERSION}-dev \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
@@ -1,3 +0,0 @@
|
||||
# Clang compiler
|
||||
|
||||
This image contains clang compiler to build <https://github.com/XRPLF/clio>.
|
||||
@@ -1,120 +0,0 @@
|
||||
ARG UBUNTU_VERSION=20.04
|
||||
|
||||
ARG GCC_MAJOR_VERSION=invalid
|
||||
|
||||
FROM ubuntu:$UBUNTU_VERSION AS build
|
||||
|
||||
ARG UBUNTU_VERSION
|
||||
|
||||
ARG GCC_MAJOR_VERSION
|
||||
|
||||
ARG BUILD_VERSION=0
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG TARGETARCH
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
build-essential \
|
||||
file \
|
||||
flex \
|
||||
libz-dev \
|
||||
libzstd-dev \
|
||||
software-properties-common \
|
||||
wget \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG GCC_VERSION
|
||||
|
||||
WORKDIR /
|
||||
RUN wget --progress=dot:giga https://gcc.gnu.org/pub/gcc/releases/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.gz \
|
||||
&& tar xf gcc-$GCC_VERSION.tar.gz
|
||||
|
||||
WORKDIR /gcc-$GCC_VERSION
|
||||
RUN ./contrib/download_prerequisites
|
||||
|
||||
# hadolint ignore=DL3059
|
||||
RUN mkdir /gcc-build
|
||||
WORKDIR /gcc-build
|
||||
RUN /gcc-$GCC_VERSION/configure \
|
||||
--with-pkgversion="clio-build-$BUILD_VERSION https://github.com/XRPLF/clio" \
|
||||
--enable-languages=c,c++ \
|
||||
--prefix=/usr \
|
||||
--with-gcc-major-version-only \
|
||||
--program-suffix=-${GCC_MAJOR_VERSION} \
|
||||
--enable-shared \
|
||||
--enable-linker-build-id \
|
||||
--libexecdir=/usr/lib \
|
||||
--without-included-gettext \
|
||||
--enable-threads=posix \
|
||||
--libdir=/usr/lib \
|
||||
--disable-nls \
|
||||
--enable-clocale=gnu \
|
||||
--enable-libstdcxx-backtrace=yes \
|
||||
--enable-libstdcxx-debug \
|
||||
--enable-libstdcxx-time=yes \
|
||||
--with-default-libstdcxx-abi=new \
|
||||
--enable-gnu-unique-object \
|
||||
--disable-vtable-verify \
|
||||
--enable-plugin \
|
||||
--enable-default-pie \
|
||||
--with-system-zlib \
|
||||
--enable-libphobos-checking=release \
|
||||
--with-target-system-zlib=auto \
|
||||
--disable-werror \
|
||||
--enable-cet \
|
||||
--disable-multilib \
|
||||
--without-cuda-driver \
|
||||
--enable-checking=release
|
||||
|
||||
RUN make -j "$(nproc)"
|
||||
RUN make install-strip DESTDIR=/gcc-$GCC_VERSION-$BUILD_VERSION-ubuntu-$UBUNTU_VERSION
|
||||
|
||||
RUN export GDB_AUTOLOAD_DIR="/gcc-$GCC_VERSION-$BUILD_VERSION-ubuntu-$UBUNTU_VERSION/usr/share/gdb/auto-load/usr/lib64" \
|
||||
&& mkdir -p "$GDB_AUTOLOAD_DIR" \
|
||||
&& mv \
|
||||
/gcc-$GCC_VERSION-$BUILD_VERSION-ubuntu-$UBUNTU_VERSION/usr/lib64/libstdc++.so.*-gdb.py \
|
||||
$GDB_AUTOLOAD_DIR/
|
||||
|
||||
# Generate deb
|
||||
WORKDIR /
|
||||
COPY control.m4 /
|
||||
COPY ld.so.conf /gcc-$GCC_VERSION-$BUILD_VERSION-ubuntu-$UBUNTU_VERSION/etc/ld.so.conf.d/1-gcc-${GCC_MAJOR_VERSION}.conf
|
||||
|
||||
RUN mkdir /gcc-$GCC_VERSION-$BUILD_VERSION-ubuntu-$UBUNTU_VERSION/DEBIAN \
|
||||
&& m4 \
|
||||
-P \
|
||||
-DUBUNTU_VERSION=$UBUNTU_VERSION \
|
||||
-DVERSION=$GCC_VERSION-$BUILD_VERSION \
|
||||
-DTARGETARCH=$TARGETARCH \
|
||||
control.m4 > /gcc-$GCC_VERSION-$BUILD_VERSION-ubuntu-$UBUNTU_VERSION/DEBIAN/control \
|
||||
&& dpkg-deb \
|
||||
--build \
|
||||
--root-owner-group \
|
||||
/gcc-$GCC_VERSION-$BUILD_VERSION-ubuntu-$UBUNTU_VERSION \
|
||||
/gcc${GCC_MAJOR_VERSION}.deb
|
||||
|
||||
# Create final image
|
||||
FROM ubuntu:$UBUNTU_VERSION
|
||||
|
||||
ARG GCC_MAJOR_VERSION
|
||||
|
||||
COPY --from=build /gcc${GCC_MAJOR_VERSION}.deb /
|
||||
|
||||
# Install gcc-${GCC_MAJOR_VERSION}, but also leave gcc${GCC_MAJOR_VERSION}.deb for others to copy if needed
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
binutils \
|
||||
libc6-dev \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& dpkg -i /gcc${GCC_MAJOR_VERSION}.deb
|
||||
|
||||
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/cc cc /usr/bin/gcc-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/gcov-dump gcov-dump /usr/bin/gcov-dump-${GCC_MAJOR_VERSION} 100 \
|
||||
&& update-alternatives --install /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-${GCC_MAJOR_VERSION} 100
|
||||
@@ -1,3 +0,0 @@
|
||||
# GCC compiler
|
||||
|
||||
This image contains GCC compiler to build <https://github.com/XRPLF/clio>.
|
||||
@@ -1,7 +0,0 @@
|
||||
Package: gcc-15-ubuntu-UBUNTUVERSION
|
||||
Version: VERSION
|
||||
Architecture: TARGETARCH
|
||||
Maintainer: Alex Kremer <akremer@ripple.com>
|
||||
Uploaders: Ayaz Salikhov <asalikhov@ripple.com>
|
||||
Description: GCC VERSION build for ubuntu UBUNTUVERSION
|
||||
Depends: binutils, libc6-dev
|
||||
@@ -1,2 +0,0 @@
|
||||
# Path to the directory containing libstdc++.so.6
|
||||
/usr/lib64
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
clio_develop:
|
||||
image: ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
|
||||
volumes:
|
||||
- clio_develop_conan_data:/root/.conan2/p
|
||||
- clio_develop_ccache:/root/.ccache
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
ARG GHCR_REPO=invalid
|
||||
ARG GCC_VERSION=invalid
|
||||
|
||||
FROM ${GHCR_REPO}/clio-gcc:${GCC_VERSION}
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG TARGETARCH
|
||||
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
ARG BUILD_VERSION=0
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
python3 \
|
||||
python3-pip \
|
||||
software-properties-common \
|
||||
wget \
|
||||
&& pip3 install -q --no-cache-dir \
|
||||
cmake \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
ARG NINJA_VERSION=1.13.2
|
||||
|
||||
RUN wget --progress=dot:giga "https://github.com/ninja-build/ninja/archive/refs/tags/v${NINJA_VERSION}.tar.gz" \
|
||||
&& tar xf "v${NINJA_VERSION}.tar.gz" \
|
||||
&& cd "ninja-${NINJA_VERSION}" \
|
||||
&& ./configure.py --bootstrap \
|
||||
&& mv ninja /usr/local/bin/ninja \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
ARG MOLD_VERSION=2.40.4
|
||||
RUN wget --progress=dot:giga "https://github.com/rui314/mold/archive/refs/tags/v${MOLD_VERSION}.tar.gz" \
|
||||
&& tar xf "v${MOLD_VERSION}.tar.gz" \
|
||||
&& cd "mold-${MOLD_VERSION}" \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. \
|
||||
&& ninja install \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
ARG CCACHE_VERSION=4.12.2
|
||||
RUN wget --progress=dot:giga "https://github.com/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.gz" \
|
||||
&& tar xf "ccache-${CCACHE_VERSION}.tar.gz" \
|
||||
&& cd "ccache-${CCACHE_VERSION}" \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DENABLE_TESTING=False .. \
|
||||
&& ninja install \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
bison \
|
||||
flex \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG DOXYGEN_VERSION=1.16.1
|
||||
RUN wget --progress=dot:giga "https://github.com/doxygen/doxygen/releases/download/Release_${DOXYGEN_VERSION//./_}/doxygen-${DOXYGEN_VERSION}.src.tar.gz" \
|
||||
&& tar xf "doxygen-${DOXYGEN_VERSION}.src.tar.gz" \
|
||||
&& cd "doxygen-${DOXYGEN_VERSION}" \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. \
|
||||
&& ninja install \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
ARG CLANG_BUILD_ANALYZER_VERSION=1.6.0
|
||||
RUN wget --progress=dot:giga "https://github.com/aras-p/ClangBuildAnalyzer/archive/refs/tags/v${CLANG_BUILD_ANALYZER_VERSION}.tar.gz" \
|
||||
&& tar xf "v${CLANG_BUILD_ANALYZER_VERSION}.tar.gz" \
|
||||
&& cd "ClangBuildAnalyzer-${CLANG_BUILD_ANALYZER_VERSION}" \
|
||||
&& mkdir build \
|
||||
&& cd build \
|
||||
&& cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. \
|
||||
&& ninja install \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
ARG GIT_CLIFF_VERSION=2.11.0
|
||||
RUN wget --progress=dot:giga "https://github.com/orhun/git-cliff/releases/download/v${GIT_CLIFF_VERSION}/git-cliff-${GIT_CLIFF_VERSION}-x86_64-unknown-linux-musl.tar.gz" \
|
||||
&& tar xf git-cliff-${GIT_CLIFF_VERSION}-x86_64-unknown-linux-musl.tar.gz \
|
||||
&& mv git-cliff-${GIT_CLIFF_VERSION}/git-cliff /usr/local/bin/git-cliff \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
ARG GH_VERSION=2.83.2
|
||||
RUN wget --progress=dot:giga "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz" \
|
||||
&& tar xf gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz \
|
||||
&& mv gh_${GH_VERSION}_linux_${TARGETARCH}/bin/gh /usr/local/bin/gh \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends --no-install-suggests \
|
||||
libgmp-dev \
|
||||
libmpfr-dev \
|
||||
libncurses-dev \
|
||||
make \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG GDB_VERSION=17.1
|
||||
RUN wget --progress=dot:giga "https://sourceware.org/pub/gdb/releases/gdb-${GDB_VERSION}.tar.gz" \
|
||||
&& tar xf "gdb-${GDB_VERSION}.tar.gz" \
|
||||
&& cd "gdb-${GDB_VERSION}" \
|
||||
&& ./configure --prefix=/usr/local \
|
||||
&& make -j "$(nproc)" \
|
||||
&& make install-gdb \
|
||||
&& rm -rf /tmp/* /var/tmp/*
|
||||
|
||||
WORKDIR /root
|
||||
@@ -11,8 +11,8 @@
|
||||
- [**Optional**] [GCovr](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html): needed for code coverage generation
|
||||
- [**Optional**] [CCache](https://ccache.dev/): speeds up compilation if you are going to compile Clio often
|
||||
|
||||
We use our Docker image `ghcr.io/XRPLF/clio-ci` to build `Clio`, see [Building Clio with Docker](#building-clio-with-docker).
|
||||
You can find information about exact compiler versions and tools in the [image's README](https://github.com/XRPLF/clio/blob/develop/docker/ci/README.md).
|
||||
We use the Nix-based Docker image `ghcr.io/xrplf/xrpld/nix-ubuntu` to build `Clio`, see [Building Clio with Docker](#building-clio-with-docker).
|
||||
This image is produced by [rippled](https://github.com/XRPLF/rippled) and ships the compilers and tools listed below.
|
||||
|
||||
The following compiler version are guaranteed to work.
|
||||
Any compiler with lower version may not be able to build Clio:
|
||||
@@ -30,7 +30,7 @@ You can change it by using `$CONAN_HOME` env variable.
|
||||
[More info about Conan home](https://docs.conan.io/2/reference/environment.html#conan-home).
|
||||
|
||||
> [!TIP]
|
||||
> To setup Conan automatically, you can run `.github/scripts/conan/init.sh`.
|
||||
> To setup Conan automatically, you can run `conan/init.sh`.
|
||||
> This will delete Conan home directory (if it exists), set up profiles and add Artifactory remote.
|
||||
|
||||
The instruction below assumes that `$CONAN_HOME` is not set.
|
||||
@@ -175,7 +175,7 @@ Open the `index.html` file in your browser to see the documentation pages.
|
||||
It is also possible to build Clio using [Docker](https://www.docker.com/) if you don't want to install all the dependencies on your machine.
|
||||
|
||||
```sh
|
||||
docker run -it ghcr.io/xrplf/clio-ci:14342e087ceb8b593027198bf9ef06a43833c696
|
||||
docker run -it ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
|
||||
git clone https://github.com/XRPLF/clio
|
||||
cd clio
|
||||
```
|
||||
|
||||
@@ -3,21 +3,9 @@ add_executable(clio_server)
|
||||
target_sources(clio_server PRIVATE Main.cpp)
|
||||
target_link_libraries(clio_server PRIVATE clio_app)
|
||||
|
||||
if(static)
|
||||
if(san)
|
||||
message(FATAL_ERROR "Static linkage not allowed when using sanitizers")
|
||||
elseif(is_appleclang)
|
||||
message(FATAL_ERROR "Static linkage not supported on AppleClang")
|
||||
else()
|
||||
target_link_options(
|
||||
# Note: -static-libstdc++ can statically link both libstdc++ and libc++
|
||||
clio_server
|
||||
PRIVATE -static-libstdc++ -static-libgcc
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(
|
||||
clio_server
|
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
patch_nix_binary(clio_server)
|
||||
|
||||
@@ -58,4 +58,4 @@ target_sources(
|
||||
handlers/VaultInfo.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(clio_rpc PRIVATE clio_util)
|
||||
target_link_libraries(clio_rpc PUBLIC clio_util clio_data)
|
||||
|
||||
@@ -45,7 +45,7 @@ target_sources(
|
||||
)
|
||||
|
||||
# This must be above the target_link_libraries call otherwise backtrace doesn't work
|
||||
if("${san}" STREQUAL "")
|
||||
if(NOT SANITIZERS_ENABLED)
|
||||
target_link_libraries(clio_util PUBLIC Boost::stacktrace_backtrace)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "util/async/AnyStopToken.hpp"
|
||||
#include "util/async/AnyStrand.hpp"
|
||||
#include "util/async/Concepts.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
#include "util/async/impl/ErasedOperation.hpp"
|
||||
|
||||
#include <any>
|
||||
@@ -68,10 +69,10 @@ public:
|
||||
execute(SomeHandlerWithoutStopToken auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>(
|
||||
pimpl_->execute([fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
|
||||
pimpl_->execute([fn = std::forward<decltype(fn)>(fn)] mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn));
|
||||
return {};
|
||||
@@ -94,10 +95,10 @@ public:
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>(pimpl_->execute(
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -123,10 +124,10 @@ public:
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn, SomeStdDuration auto timeout)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>(pimpl_->execute(
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -153,11 +154,11 @@ public:
|
||||
scheduleAfter(SomeStdDuration auto delay, SomeHandlerWith<AnyStopToken> auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(delay);
|
||||
return AnyOperation<RetType>(pimpl_->scheduleAfter(
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -184,13 +185,13 @@ public:
|
||||
scheduleAfter(SomeStdDuration auto delay, SomeHandlerWith<AnyStopToken, bool> auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken, bool>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(delay);
|
||||
return AnyOperation<RetType>(pimpl_->scheduleAfter(
|
||||
millis,
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken, auto cancelled) mutable
|
||||
-> std::any {
|
||||
-> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken), cancelled);
|
||||
return {};
|
||||
@@ -214,12 +215,12 @@ public:
|
||||
executeRepeatedly(SomeStdDuration auto interval, SomeHandlerWithoutStopToken auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(interval);
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->executeRepeatedly(
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)] mutable -> impl::Any {
|
||||
std::invoke(std::forward<decltype(fn)>(fn));
|
||||
return {};
|
||||
}
|
||||
@@ -277,18 +278,18 @@ private:
|
||||
|
||||
virtual impl::ErasedOperation
|
||||
execute(
|
||||
std::function<std::any(AnyStopToken)>,
|
||||
std::function<impl::Any(AnyStopToken)>,
|
||||
std::optional<std::chrono::milliseconds> timeout = std::nullopt
|
||||
) = 0;
|
||||
virtual impl::ErasedOperation execute(std::function<std::any()>) = 0;
|
||||
virtual impl::ErasedOperation execute(std::function<impl::Any()>) = 0;
|
||||
virtual impl::ErasedOperation
|
||||
scheduleAfter(std::chrono::milliseconds, std::function<std::any(AnyStopToken)>) = 0;
|
||||
scheduleAfter(std::chrono::milliseconds, std::function<impl::Any(AnyStopToken)>) = 0;
|
||||
virtual impl::ErasedOperation scheduleAfter(
|
||||
std::chrono::milliseconds,
|
||||
std::function<std::any(AnyStopToken, bool)>
|
||||
std::function<impl::Any(AnyStopToken, bool)>
|
||||
) = 0;
|
||||
virtual impl::ErasedOperation
|
||||
executeRepeatedly(std::chrono::milliseconds, std::function<std::any()>) = 0;
|
||||
executeRepeatedly(std::chrono::milliseconds, std::function<impl::Any()>) = 0;
|
||||
virtual void submit(std::function<void()>) = 0;
|
||||
virtual AnyStrand
|
||||
makeStrand() = 0;
|
||||
@@ -309,7 +310,7 @@ private:
|
||||
|
||||
impl::ErasedOperation
|
||||
execute(
|
||||
std::function<std::any(AnyStopToken)> fn,
|
||||
std::function<impl::Any(AnyStopToken)> fn,
|
||||
std::optional<std::chrono::milliseconds> timeout
|
||||
) override
|
||||
{
|
||||
@@ -317,7 +318,7 @@ private:
|
||||
}
|
||||
|
||||
impl::ErasedOperation
|
||||
execute(std::function<std::any()> fn) override
|
||||
execute(std::function<impl::Any()> fn) override
|
||||
{
|
||||
return ctx.execute(std::move(fn));
|
||||
}
|
||||
@@ -325,7 +326,7 @@ private:
|
||||
impl::ErasedOperation
|
||||
scheduleAfter(
|
||||
std::chrono::milliseconds delay,
|
||||
std::function<std::any(AnyStopToken)> fn
|
||||
std::function<impl::Any(AnyStopToken)> fn
|
||||
) override
|
||||
{
|
||||
return ctx.scheduleAfter(delay, std::move(fn));
|
||||
@@ -334,14 +335,17 @@ private:
|
||||
impl::ErasedOperation
|
||||
scheduleAfter(
|
||||
std::chrono::milliseconds delay,
|
||||
std::function<std::any(AnyStopToken, bool)> fn
|
||||
std::function<impl::Any(AnyStopToken, bool)> fn
|
||||
) override
|
||||
{
|
||||
return ctx.scheduleAfter(delay, std::move(fn));
|
||||
}
|
||||
|
||||
impl::ErasedOperation
|
||||
executeRepeatedly(std::chrono::milliseconds interval, std::function<std::any()> fn) override
|
||||
executeRepeatedly(
|
||||
std::chrono::milliseconds interval,
|
||||
std::function<impl::Any()> fn
|
||||
) override
|
||||
{
|
||||
return ctx.executeRepeatedly(interval, std::move(fn));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/async/Error.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
#include "util/async/impl/ErasedOperation.hpp"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "util/async/AnyOperation.hpp"
|
||||
#include "util/async/AnyStopToken.hpp"
|
||||
#include "util/async/Concepts.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
#include "util/async/impl/ErasedOperation.hpp"
|
||||
|
||||
#include <any>
|
||||
@@ -46,10 +47,10 @@ public:
|
||||
execute(SomeHandlerWithoutStopToken auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->execute([fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
|
||||
pimpl_->execute([fn = std::forward<decltype(fn)>(fn)] mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn));
|
||||
return {};
|
||||
@@ -70,11 +71,11 @@ public:
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->execute(
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -99,11 +100,11 @@ public:
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn, SomeStdDuration auto timeout)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->execute(
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -129,12 +130,12 @@ public:
|
||||
executeRepeatedly(SomeStdDuration auto interval, SomeHandlerWithoutStopToken auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(interval);
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->executeRepeatedly(
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)] mutable -> impl::Any {
|
||||
std::invoke(std::forward<decltype(fn)>(fn));
|
||||
return {};
|
||||
}
|
||||
@@ -160,12 +161,12 @@ private:
|
||||
|
||||
[[nodiscard]] virtual impl::ErasedOperation
|
||||
execute(
|
||||
std::function<std::any(AnyStopToken)>,
|
||||
std::function<impl::Any(AnyStopToken)>,
|
||||
std::optional<std::chrono::milliseconds> timeout = std::nullopt
|
||||
) = 0;
|
||||
[[nodiscard]] virtual impl::ErasedOperation execute(std::function<std::any()>) = 0;
|
||||
[[nodiscard]] virtual impl::ErasedOperation execute(std::function<impl::Any()>) = 0;
|
||||
[[nodiscard]] virtual impl::ErasedOperation
|
||||
executeRepeatedly(std::chrono::milliseconds, std::function<std::any()>) = 0;
|
||||
executeRepeatedly(std::chrono::milliseconds, std::function<impl::Any()>) = 0;
|
||||
virtual void submit(std::function<void()>) = 0;
|
||||
};
|
||||
|
||||
@@ -181,7 +182,7 @@ private:
|
||||
|
||||
[[nodiscard]] impl::ErasedOperation
|
||||
execute(
|
||||
std::function<std::any(AnyStopToken)> fn,
|
||||
std::function<impl::Any(AnyStopToken)> fn,
|
||||
std::optional<std::chrono::milliseconds> timeout
|
||||
) override
|
||||
{
|
||||
@@ -189,13 +190,16 @@ private:
|
||||
}
|
||||
|
||||
[[nodiscard]] impl::ErasedOperation
|
||||
execute(std::function<std::any()> fn) override
|
||||
execute(std::function<impl::Any()> fn) override
|
||||
{
|
||||
return strand.execute(std::move(fn));
|
||||
}
|
||||
|
||||
impl::ErasedOperation
|
||||
executeRepeatedly(std::chrono::milliseconds interval, std::function<std::any()> fn) override
|
||||
executeRepeatedly(
|
||||
std::chrono::milliseconds interval,
|
||||
std::function<impl::Any()> fn
|
||||
) override
|
||||
{
|
||||
return strand.executeRepeatedly(interval, std::move(fn));
|
||||
}
|
||||
|
||||
@@ -6,11 +6,6 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
// for the static_assert at the bottom which fixes clang compilation:
|
||||
// see: https://godbolt.org/z/fzTjMd7G1 vs https://godbolt.org/z/jhKG7deen
|
||||
#include <any>
|
||||
#include <expected>
|
||||
|
||||
namespace util::async {
|
||||
|
||||
/**
|
||||
@@ -49,7 +44,4 @@ struct ExecutionError {
|
||||
std::string message;
|
||||
};
|
||||
|
||||
// these are not the droids you are looking for...
|
||||
static_assert(std::is_copy_constructible_v<std::expected<std::any, ExecutionError>>);
|
||||
|
||||
} // namespace util::async
|
||||
|
||||
41
src/util/async/impl/Any.hpp
Normal file
41
src/util/async/impl/Any.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <any>
|
||||
#include <type_traits>
|
||||
|
||||
namespace util::async::impl {
|
||||
|
||||
/**
|
||||
* @brief A wrapper for std::any used as the type-erased transport for async operation results.
|
||||
*
|
||||
* It exists to work around a recursive-constraint failure in libstdc++'s `<expected>` when the
|
||||
* value type is a raw `std::any`: `std::any`'s greedy templated constructor makes
|
||||
* `std::expected<std::any, E>` ask whether `std::any` is constructible from
|
||||
* `std::expected<std::any, E>`, which re-enters the same constraint. Newer Clang rejects this as
|
||||
* self-referential.
|
||||
*
|
||||
* `Any` only allows construction from `std::any` (never from an `expected`), which breaks the cycle
|
||||
* while still allowing transparent unwrapping back to `std::any&`.
|
||||
*/
|
||||
class Any {
|
||||
std::any value_;
|
||||
|
||||
public:
|
||||
Any() = default;
|
||||
Any(Any const&) = default;
|
||||
|
||||
Any(Any&&) = default;
|
||||
// note: this needs to be `auto` instead of `std::any` because of a bug in gcc 11.4
|
||||
Any(auto&& v)
|
||||
requires(std::is_same_v<std::decay_t<decltype(v)>, std::any>)
|
||||
: value_{std::forward<decltype(v)>(v)}
|
||||
{
|
||||
}
|
||||
|
||||
operator std::any&() noexcept
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace util::async::impl
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/async/Concepts.hpp"
|
||||
#include "util/async/Error.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
|
||||
#include <any>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
pimpl_->wait();
|
||||
}
|
||||
|
||||
std::expected<std::any, ExecutionError>
|
||||
std::expected<Any, ExecutionError>
|
||||
get()
|
||||
{
|
||||
return pimpl_->get();
|
||||
@@ -64,7 +64,7 @@ private:
|
||||
|
||||
virtual void
|
||||
wait() noexcept = 0;
|
||||
virtual std::expected<std::any, ExecutionError>
|
||||
virtual std::expected<Any, ExecutionError>
|
||||
get() = 0;
|
||||
virtual void
|
||||
abort() = 0;
|
||||
@@ -93,14 +93,14 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
std::expected<std::any, ExecutionError>
|
||||
std::expected<Any, ExecutionError>
|
||||
get() override
|
||||
{
|
||||
if constexpr (not SomeOperationWithData<OpType>) {
|
||||
ASSERT(false, "Called get() on an operation that does not support it");
|
||||
std::unreachable();
|
||||
} else {
|
||||
// Note: return type of the operation was already wrapped to std::any by
|
||||
// Note: return type of the operation was already wrapped to impl::Any by
|
||||
// AnyExecutionContext
|
||||
return operation.get();
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <expected>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
@@ -43,18 +44,36 @@ constexpr std::array kCertFilePaths{
|
||||
"/system/etc/security/cacerts", // Android
|
||||
};
|
||||
|
||||
std::optional<std::string>
|
||||
readCertificateFile(std::filesystem::path const& path)
|
||||
{
|
||||
if (not std::filesystem::exists(path)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::ifstream const fileStream{path, std::ios::in};
|
||||
if (not fileStream.is_open()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::stringstream buffer;
|
||||
buffer << fileStream.rdbuf();
|
||||
return std::move(buffer).str();
|
||||
}
|
||||
|
||||
std::expected<std::string, RequestError>
|
||||
getRootCertificate()
|
||||
{
|
||||
// Honor the OpenSSL-standard SSL_CERT_FILE environment variable first. Some
|
||||
// environments (e.g. the Nix-based CI/runtime image) point it at their CA
|
||||
// bundle instead of installing certificates at the well-known system paths.
|
||||
if (char const* const certFile = std::getenv("SSL_CERT_FILE"); certFile != nullptr) {
|
||||
if (auto contents = readCertificateFile(certFile); contents.has_value()) {
|
||||
return *std::move(contents);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& path : kCertFilePaths) {
|
||||
if (std::filesystem::exists(path)) {
|
||||
std::ifstream const fileStream{path, std::ios::in};
|
||||
if (not fileStream.is_open()) {
|
||||
continue;
|
||||
}
|
||||
std::stringstream buffer;
|
||||
buffer << fileStream.rdbuf();
|
||||
return std::move(buffer).str();
|
||||
if (auto contents = readCertificateFile(path); contents.has_value()) {
|
||||
return *std::move(contents);
|
||||
}
|
||||
}
|
||||
return std::unexpected{RequestError{"SSL setup failed: could not find root certificate"}};
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
#include "util/MockStrand.hpp"
|
||||
#include "util/async/AnyStopToken.hpp"
|
||||
#include "util/async/Error.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <any>
|
||||
#include <chrono>
|
||||
#include <expected>
|
||||
#include <functional>
|
||||
@@ -18,6 +18,8 @@ struct MockExecutionContext {
|
||||
template <typename T>
|
||||
using ValueType = std::expected<T, util::async::ExecutionError>;
|
||||
|
||||
using Any = util::async::impl::Any;
|
||||
|
||||
using StopSource = MockStopSource;
|
||||
using StopToken = MockStopToken;
|
||||
using Strand = MockStrand;
|
||||
@@ -34,36 +36,35 @@ struct MockExecutionContext {
|
||||
template <typename T>
|
||||
using RepeatingOperation = MockRepeatingOperation<T>;
|
||||
|
||||
MOCK_METHOD(Operation<std::any> const&, execute, (std::function<std::any()>), ());
|
||||
MOCK_METHOD(Operation<Any> const&, execute, (std::function<Any()>), ());
|
||||
MOCK_METHOD(
|
||||
Operation<std::any> const&,
|
||||
Operation<Any> const&,
|
||||
execute,
|
||||
(std::function<std::any()>, std::optional<std::chrono::milliseconds>),
|
||||
(std::function<Any()>, std::optional<std::chrono::milliseconds>),
|
||||
()
|
||||
);
|
||||
MOCK_METHOD(
|
||||
StoppableOperation<std::any> const&,
|
||||
StoppableOperation<Any> const&,
|
||||
execute,
|
||||
(std::function<std::any(util::async::AnyStopToken)>,
|
||||
std::optional<std::chrono::milliseconds>),
|
||||
(std::function<Any(util::async::AnyStopToken)>, std::optional<std::chrono::milliseconds>),
|
||||
()
|
||||
);
|
||||
MOCK_METHOD(
|
||||
ScheduledOperation<std::any> const&,
|
||||
ScheduledOperation<Any> const&,
|
||||
scheduleAfter,
|
||||
(std::chrono::milliseconds, std::function<std::any(util::async::AnyStopToken)>),
|
||||
(std::chrono::milliseconds, std::function<Any(util::async::AnyStopToken)>),
|
||||
()
|
||||
);
|
||||
MOCK_METHOD(
|
||||
ScheduledOperation<std::any> const&,
|
||||
ScheduledOperation<Any> const&,
|
||||
scheduleAfter,
|
||||
(std::chrono::milliseconds, std::function<std::any(util::async::AnyStopToken, bool)>),
|
||||
(std::chrono::milliseconds, std::function<Any(util::async::AnyStopToken, bool)>),
|
||||
()
|
||||
);
|
||||
MOCK_METHOD(
|
||||
RepeatingOperation<std::any> const&,
|
||||
RepeatingOperation<Any> const&,
|
||||
executeRepeatedly,
|
||||
(std::chrono::milliseconds, std::function<std::any()>),
|
||||
(std::chrono::milliseconds, std::function<Any()>),
|
||||
()
|
||||
);
|
||||
MOCK_METHOD(void, submit, (std::function<void()>), ());
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
#include "util/MockOperation.hpp"
|
||||
#include "util/async/AnyStopToken.hpp"
|
||||
#include "util/async/Error.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <any>
|
||||
#include <chrono>
|
||||
#include <expected>
|
||||
#include <functional>
|
||||
@@ -16,6 +16,8 @@ struct MockStrand {
|
||||
template <typename T>
|
||||
using ValueType = std::expected<T, util::async::ExecutionError>;
|
||||
|
||||
using Any = util::async::impl::Any;
|
||||
|
||||
template <typename T>
|
||||
using Operation = MockOperation<T>;
|
||||
|
||||
@@ -25,30 +27,29 @@ struct MockStrand {
|
||||
template <typename T>
|
||||
using RepeatingOperation = MockRepeatingOperation<T>;
|
||||
|
||||
MOCK_METHOD(Operation<std::any> const&, execute, (std::function<std::any()>), (const));
|
||||
MOCK_METHOD(Operation<Any> const&, execute, (std::function<Any()>), (const));
|
||||
MOCK_METHOD(
|
||||
Operation<std::any> const&,
|
||||
Operation<Any> const&,
|
||||
execute,
|
||||
(std::function<std::any()>, std::optional<std::chrono::milliseconds>),
|
||||
(std::function<Any()>, std::optional<std::chrono::milliseconds>),
|
||||
(const)
|
||||
);
|
||||
MOCK_METHOD(
|
||||
StoppableOperation<std::any> const&,
|
||||
StoppableOperation<Any> const&,
|
||||
execute,
|
||||
(std::function<std::any(util::async::AnyStopToken)>),
|
||||
(std::function<Any(util::async::AnyStopToken)>),
|
||||
(const)
|
||||
);
|
||||
MOCK_METHOD(
|
||||
StoppableOperation<std::any> const&,
|
||||
StoppableOperation<Any> const&,
|
||||
execute,
|
||||
(std::function<std::any(util::async::AnyStopToken)>,
|
||||
std::optional<std::chrono::milliseconds>),
|
||||
(std::function<Any(util::async::AnyStopToken)>, std::optional<std::chrono::milliseconds>),
|
||||
(const)
|
||||
);
|
||||
MOCK_METHOD(
|
||||
RepeatingOperation<std::any> const&,
|
||||
RepeatingOperation<Any> const&,
|
||||
executeRepeatedly,
|
||||
(std::chrono::milliseconds, std::function<std::any()>),
|
||||
(std::chrono::milliseconds, std::function<Any()>),
|
||||
(const)
|
||||
);
|
||||
MOCK_METHOD(void, submit, (std::function<void()>), (const));
|
||||
|
||||
@@ -28,3 +28,5 @@ set_target_properties(
|
||||
clio_integration_tests
|
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
patch_nix_binary(clio_integration_tests)
|
||||
|
||||
@@ -239,6 +239,8 @@ set_target_properties(
|
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
patch_nix_binary(clio_tests)
|
||||
|
||||
# Generate `coverage_report` target if coverage is enabled
|
||||
if(coverage)
|
||||
if(DEFINED CODE_COVERAGE_REPORT_FORMAT)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "util/async/Outcome.hpp"
|
||||
#include "util/async/context/SyncExecutionContext.hpp"
|
||||
#include "util/async/context/impl/Cancellation.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
#include "util/async/impl/ErasedOperation.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
@@ -105,8 +106,8 @@ struct AnyExecutionContextTests : Test {
|
||||
|
||||
TEST_F(AnyExecutionContextTests, Move)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<std::any()>>()))
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<impl::Any()>>()))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
EXPECT_CALL(mockOp, get());
|
||||
|
||||
@@ -116,8 +117,8 @@ TEST_F(AnyExecutionContextTests, Move)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, CopyIsRefCounted)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<std::any()>>()))
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<impl::Any()>>()))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
EXPECT_CALL(mockOp, get());
|
||||
|
||||
@@ -127,8 +128,8 @@ TEST_F(AnyExecutionContextTests, CopyIsRefCounted)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, ExecuteWithoutTokenAndVoid)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<std::any()>>()))
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<impl::Any()>>()))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
EXPECT_CALL(mockOp, get());
|
||||
|
||||
@@ -140,17 +141,17 @@ TEST_F(AnyExecutionContextTests, ExecuteWithoutTokenAndVoid)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, ExecuteWithoutTokenAndVoidThrowsException)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<std::any()>>()))
|
||||
.WillOnce([](auto&&) -> OperationType<std::any> const& { throw 0; });
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<impl::Any()>>()))
|
||||
.WillOnce([](auto&&) -> OperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
EXPECT_ANY_THROW([[maybe_unused]] auto unused = ctx.execute([] { throw 0; }));
|
||||
}
|
||||
|
||||
TEST_F(AnyExecutionContextTests, ExecuteWithStopTokenAndVoid)
|
||||
{
|
||||
auto mockOp = StoppableOperationType<std::any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<std::any(AnyStopToken)>>(), _))
|
||||
auto mockOp = StoppableOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
EXPECT_CALL(mockOp, get());
|
||||
|
||||
@@ -162,17 +163,17 @@ TEST_F(AnyExecutionContextTests, ExecuteWithStopTokenAndVoid)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, ExecuteWithStopTokenAndVoidThrowsException)
|
||||
{
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<std::any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<std::any> const& { throw 0; });
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
EXPECT_ANY_THROW([[maybe_unused]] auto unused = ctx.execute([](auto) { throw 0; }));
|
||||
}
|
||||
|
||||
TEST_F(AnyExecutionContextTests, ExecuteWithStopTokenAndReturnValue)
|
||||
{
|
||||
auto mockOp = StoppableOperationType<std::any>{};
|
||||
auto mockOp = StoppableOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(std::make_any<int>(42)));
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<std::any(AnyStopToken)>>(), _))
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto op = ctx.execute([](auto) -> int { throw 0; });
|
||||
@@ -183,19 +184,19 @@ TEST_F(AnyExecutionContextTests, ExecuteWithStopTokenAndReturnValue)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, ExecuteWithStopTokenAndReturnValueThrowsException)
|
||||
{
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<std::any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<std::any> const& { throw 0; });
|
||||
EXPECT_CALL(mockExecutionContext, execute(A<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
EXPECT_ANY_THROW([[maybe_unused]] auto unused = ctx.execute([](auto) -> int { throw 0; }));
|
||||
}
|
||||
|
||||
TEST_F(AnyExecutionContextTests, TimerCancellation)
|
||||
{
|
||||
auto mockScheduledOp = ScheduledOperationType<std::any>{};
|
||||
auto mockScheduledOp = ScheduledOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockScheduledOp, cancel());
|
||||
EXPECT_CALL(
|
||||
mockExecutionContext,
|
||||
scheduleAfter(std::chrono::milliseconds{12}, A<std::function<std::any(AnyStopToken)>>())
|
||||
scheduleAfter(std::chrono::milliseconds{12}, A<std::function<impl::Any(AnyStopToken)>>())
|
||||
)
|
||||
.WillOnce(ReturnRef(mockScheduledOp));
|
||||
|
||||
@@ -207,13 +208,13 @@ TEST_F(AnyExecutionContextTests, TimerCancellation)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, TimerExecuted)
|
||||
{
|
||||
auto mockScheduledOp = ScheduledOperationType<std::any>{};
|
||||
auto mockScheduledOp = ScheduledOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockScheduledOp, get()).WillOnce(Return(std::make_any<int>(42)));
|
||||
EXPECT_CALL(
|
||||
mockExecutionContext,
|
||||
scheduleAfter(std::chrono::milliseconds{12}, A<std::function<std::any(AnyStopToken)>>())
|
||||
scheduleAfter(std::chrono::milliseconds{12}, A<std::function<impl::Any(AnyStopToken)>>())
|
||||
)
|
||||
.WillOnce([&mockScheduledOp](auto, auto&&) -> ScheduledOperationType<std::any> const& {
|
||||
.WillOnce([&mockScheduledOp](auto, auto&&) -> ScheduledOperationType<impl::Any> const& {
|
||||
return mockScheduledOp;
|
||||
});
|
||||
|
||||
@@ -225,12 +226,12 @@ TEST_F(AnyExecutionContextTests, TimerExecuted)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, TimerWithBoolHandlerCancellation)
|
||||
{
|
||||
auto mockScheduledOp = ScheduledOperationType<std::any>{};
|
||||
auto mockScheduledOp = ScheduledOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockScheduledOp, cancel());
|
||||
EXPECT_CALL(
|
||||
mockExecutionContext,
|
||||
scheduleAfter(
|
||||
std::chrono::milliseconds{12}, A<std::function<std::any(AnyStopToken, bool)>>()
|
||||
std::chrono::milliseconds{12}, A<std::function<impl::Any(AnyStopToken, bool)>>()
|
||||
)
|
||||
)
|
||||
.WillOnce(ReturnRef(mockScheduledOp));
|
||||
@@ -243,15 +244,15 @@ TEST_F(AnyExecutionContextTests, TimerWithBoolHandlerCancellation)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, TimerWithBoolHandlerExecuted)
|
||||
{
|
||||
auto mockScheduledOp = ScheduledOperationType<std::any>{};
|
||||
auto mockScheduledOp = ScheduledOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockScheduledOp, get()).WillOnce(Return(std::make_any<int>(42)));
|
||||
EXPECT_CALL(
|
||||
mockExecutionContext,
|
||||
scheduleAfter(
|
||||
std::chrono::milliseconds{12}, A<std::function<std::any(AnyStopToken, bool)>>()
|
||||
std::chrono::milliseconds{12}, A<std::function<impl::Any(AnyStopToken, bool)>>()
|
||||
)
|
||||
)
|
||||
.WillOnce([&mockScheduledOp](auto, auto&&) -> ScheduledOperationType<std::any> const& {
|
||||
.WillOnce([&mockScheduledOp](auto, auto&&) -> ScheduledOperationType<impl::Any> const& {
|
||||
return mockScheduledOp;
|
||||
});
|
||||
|
||||
@@ -264,13 +265,13 @@ TEST_F(AnyExecutionContextTests, TimerWithBoolHandlerExecuted)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, RepeatingOperation)
|
||||
{
|
||||
auto mockRepeatingOp = RepeatingOperationType<std::any>{};
|
||||
auto mockRepeatingOp = RepeatingOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockRepeatingOp, wait());
|
||||
EXPECT_CALL(
|
||||
mockExecutionContext,
|
||||
executeRepeatedly(std::chrono::milliseconds{1}, A<std::function<std::any()>>())
|
||||
executeRepeatedly(std::chrono::milliseconds{1}, A<std::function<impl::Any()>>())
|
||||
)
|
||||
.WillOnce([&mockRepeatingOp] -> RepeatingOperationType<std::any> const& {
|
||||
.WillOnce([&mockRepeatingOp] -> RepeatingOperationType<impl::Any> const& {
|
||||
return mockRepeatingOp;
|
||||
});
|
||||
|
||||
@@ -281,11 +282,11 @@ TEST_F(AnyExecutionContextTests, RepeatingOperation)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, StrandExecuteWithVoid)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
auto mockStrand = StrandType{};
|
||||
EXPECT_CALL(mockOp, get());
|
||||
EXPECT_CALL(mockExecutionContext, makeStrand()).WillOnce(ReturnRef(mockStrand));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<std::any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<impl::Any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto strand = ctx.makeStrand();
|
||||
static_assert(std::is_same_v<decltype(strand), AnyStrand>);
|
||||
@@ -300,8 +301,8 @@ TEST_F(AnyExecutionContextTests, StrandExecuteWithVoidThrowsException)
|
||||
{
|
||||
auto mockStrand = StrandType{};
|
||||
EXPECT_CALL(mockExecutionContext, makeStrand()).WillOnce(ReturnRef(mockStrand));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<std::any()>>()))
|
||||
.WillOnce([](auto&&) -> OperationType<std::any> const& { throw 0; });
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<impl::Any()>>()))
|
||||
.WillOnce([](auto&&) -> OperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
auto strand = ctx.makeStrand();
|
||||
static_assert(std::is_same_v<decltype(strand), AnyStrand>);
|
||||
@@ -311,11 +312,11 @@ TEST_F(AnyExecutionContextTests, StrandExecuteWithVoidThrowsException)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, StrandExecuteWithReturnValue)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
auto mockStrand = StrandType{};
|
||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(std::make_any<int>(42)));
|
||||
EXPECT_CALL(mockExecutionContext, makeStrand()).WillOnce(ReturnRef(mockStrand));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<std::any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<impl::Any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto strand = ctx.makeStrand();
|
||||
static_assert(std::is_same_v<decltype(strand), AnyStrand>);
|
||||
@@ -330,8 +331,8 @@ TEST_F(AnyExecutionContextTests, StrandExecuteWithReturnValueThrowsException)
|
||||
{
|
||||
auto mockStrand = StrandType{};
|
||||
EXPECT_CALL(mockExecutionContext, makeStrand()).WillOnce(ReturnRef(mockStrand));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<std::any()>>()))
|
||||
.WillOnce([](auto&&) -> OperationType<std::any> const& { throw 0; });
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<impl::Any()>>()))
|
||||
.WillOnce([](auto&&) -> OperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
auto strand = ctx.makeStrand();
|
||||
static_assert(std::is_same_v<decltype(strand), AnyStrand>);
|
||||
@@ -341,11 +342,11 @@ TEST_F(AnyExecutionContextTests, StrandExecuteWithReturnValueThrowsException)
|
||||
|
||||
TEST_F(AnyExecutionContextTests, StrandExecuteWithStopTokenAndVoid)
|
||||
{
|
||||
auto mockOp = StoppableOperationType<std::any>{};
|
||||
auto mockOp = StoppableOperationType<impl::Any>{};
|
||||
auto mockStrand = StrandType{};
|
||||
EXPECT_CALL(mockOp, get());
|
||||
EXPECT_CALL(mockExecutionContext, makeStrand()).WillOnce(ReturnRef(mockStrand));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<std::any(AnyStopToken)>>(), _))
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto strand = ctx.makeStrand();
|
||||
@@ -361,8 +362,8 @@ TEST_F(AnyExecutionContextTests, StrandExecuteWithStopTokenAndVoidThrowsExceptio
|
||||
{
|
||||
auto mockStrand = StrandType{};
|
||||
EXPECT_CALL(mockExecutionContext, makeStrand()).WillOnce(ReturnRef(mockStrand));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<std::any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<std::any> const& { throw 0; });
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
auto strand = ctx.makeStrand();
|
||||
static_assert(std::is_same_v<decltype(strand), AnyStrand>);
|
||||
@@ -372,11 +373,11 @@ TEST_F(AnyExecutionContextTests, StrandExecuteWithStopTokenAndVoidThrowsExceptio
|
||||
|
||||
TEST_F(AnyExecutionContextTests, StrandExecuteWithStopTokenAndReturnValue)
|
||||
{
|
||||
auto mockOp = StoppableOperationType<std::any>{};
|
||||
auto mockOp = StoppableOperationType<impl::Any>{};
|
||||
auto mockStrand = StrandType{};
|
||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(std::make_any<int>(42)));
|
||||
EXPECT_CALL(mockExecutionContext, makeStrand()).WillOnce(ReturnRef(mockStrand));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<std::any(AnyStopToken)>>(), _))
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto strand = ctx.makeStrand();
|
||||
@@ -392,8 +393,8 @@ TEST_F(AnyExecutionContextTests, StrandExecuteWithStopTokenAndReturnValueThrowsE
|
||||
{
|
||||
auto mockStrand = StrandType{};
|
||||
EXPECT_CALL(mockExecutionContext, makeStrand()).WillOnce(ReturnRef(mockStrand));
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<std::any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<std::any> const& { throw 0; });
|
||||
EXPECT_CALL(mockStrand, execute(A<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
auto strand = ctx.makeStrand();
|
||||
static_assert(std::is_same_v<decltype(strand), AnyStrand>);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "util/MockOperation.hpp"
|
||||
#include "util/async/AnyOperation.hpp"
|
||||
#include "util/async/Error.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
@@ -15,10 +16,10 @@ using namespace util::async;
|
||||
using namespace ::testing;
|
||||
|
||||
struct AnyOperationTests : virtual Test {
|
||||
using OperationType = MockOperation<std::expected<std::any, ExecutionError>>;
|
||||
using StoppableOperationType = MockStoppableOperation<std::expected<std::any, ExecutionError>>;
|
||||
using ScheduledOperationType = MockScheduledOperation<std::expected<std::any, ExecutionError>>;
|
||||
using RepeatingOperationType = MockRepeatingOperation<std::expected<std::any, ExecutionError>>;
|
||||
using OperationType = MockOperation<std::expected<impl::Any, ExecutionError>>;
|
||||
using StoppableOperationType = MockStoppableOperation<std::expected<impl::Any, ExecutionError>>;
|
||||
using ScheduledOperationType = MockScheduledOperation<std::expected<impl::Any, ExecutionError>>;
|
||||
using RepeatingOperationType = MockRepeatingOperation<std::expected<impl::Any, ExecutionError>>;
|
||||
|
||||
NaggyMock<OperationType> mockOp;
|
||||
NaggyMock<StoppableOperationType> mockStoppableOp;
|
||||
@@ -40,7 +41,7 @@ struct AnyOperationTests : virtual Test {
|
||||
|
||||
TEST_F(AnyOperationTests, Move)
|
||||
{
|
||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(std::any{}));
|
||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(impl::Any{}));
|
||||
auto yoink = std::move(voidOp);
|
||||
auto res = yoink.get();
|
||||
ASSERT_TRUE(res);
|
||||
@@ -48,7 +49,7 @@ TEST_F(AnyOperationTests, Move)
|
||||
|
||||
TEST_F(AnyOperationTests, VoidDataYieldsNoError)
|
||||
{
|
||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(std::any{}));
|
||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(impl::Any{}));
|
||||
auto res = voidOp.get();
|
||||
ASSERT_TRUE(res);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "util/async/AnyOperation.hpp"
|
||||
#include "util/async/AnyStopToken.hpp"
|
||||
#include "util/async/AnyStrand.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
@@ -33,8 +34,8 @@ struct AnyStrandTests : ::testing::Test {
|
||||
|
||||
TEST_F(AnyStrandTests, Move)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
EXPECT_CALL(mockOp, get());
|
||||
|
||||
auto mineNow = std::move(strand);
|
||||
@@ -43,8 +44,8 @@ TEST_F(AnyStrandTests, Move)
|
||||
|
||||
TEST_F(AnyStrandTests, CopyIsRefCounted)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto yoink = strand;
|
||||
ASSERT_TRUE(yoink.execute([] { throw 0; }).get());
|
||||
@@ -52,8 +53,8 @@ TEST_F(AnyStrandTests, CopyIsRefCounted)
|
||||
|
||||
TEST_F(AnyStrandTests, ExecuteWithoutTokenAndVoid)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any()>>())).WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto op = strand.execute([] {});
|
||||
static_assert(std::is_same_v<decltype(op), AnyOperation<void>>);
|
||||
@@ -63,17 +64,17 @@ TEST_F(AnyStrandTests, ExecuteWithoutTokenAndVoid)
|
||||
|
||||
TEST_F(AnyStrandTests, ExecuteWithoutTokenAndVoidThrowsException)
|
||||
{
|
||||
auto mockOp = OperationType<std::any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any()>>()))
|
||||
.WillOnce([](auto&&) -> OperationType<std::any> const& { throw 0; });
|
||||
auto mockOp = OperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any()>>()))
|
||||
.WillOnce([](auto&&) -> OperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
EXPECT_ANY_THROW([[maybe_unused]] auto unused = strand.execute([] {}));
|
||||
}
|
||||
|
||||
TEST_F(AnyStrandTests, ExecuteWithStopTokenAndVoid)
|
||||
{
|
||||
auto mockOp = StoppableOperationType<std::any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any(AnyStopToken)>>(), _))
|
||||
auto mockOp = StoppableOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto op = strand.execute([](auto) {});
|
||||
@@ -84,17 +85,17 @@ TEST_F(AnyStrandTests, ExecuteWithStopTokenAndVoid)
|
||||
|
||||
TEST_F(AnyStrandTests, ExecuteWithStopTokenAndVoidThrowsException)
|
||||
{
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<std::any> const& { throw 0; });
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
EXPECT_ANY_THROW([[maybe_unused]] auto unused = strand.execute([](auto) {}));
|
||||
}
|
||||
|
||||
TEST_F(AnyStrandTests, ExecuteWithStopTokenAndReturnValue)
|
||||
{
|
||||
auto mockOp = StoppableOperationType<std::any>{};
|
||||
auto mockOp = StoppableOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(std::make_any<int>(42)));
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any(AnyStopToken)>>(), _))
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto op = strand.execute([](auto) { return 42; });
|
||||
@@ -105,17 +106,17 @@ TEST_F(AnyStrandTests, ExecuteWithStopTokenAndReturnValue)
|
||||
|
||||
TEST_F(AnyStrandTests, ExecuteWithStopTokenAndReturnValueThrowsException)
|
||||
{
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<std::any> const& { throw 0; });
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
EXPECT_ANY_THROW([[maybe_unused]] auto unused = strand.execute([](auto) { return 42; }));
|
||||
}
|
||||
|
||||
TEST_F(AnyStrandTests, ExecuteWithTimeoutAndStopTokenAndReturnValue)
|
||||
{
|
||||
auto mockOp = StoppableOperationType<std::any>{};
|
||||
auto mockOp = StoppableOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockOp, get()).WillOnce(Return(std::make_any<int>(42)));
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any(AnyStopToken)>>(), _))
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce(ReturnRef(mockOp));
|
||||
|
||||
auto op = strand.execute([](auto) { return 42; }, std::chrono::milliseconds{1});
|
||||
@@ -126,8 +127,8 @@ TEST_F(AnyStrandTests, ExecuteWithTimeoutAndStopTokenAndReturnValue)
|
||||
|
||||
TEST_F(AnyStrandTests, ExecuteWithTimeoutAndStopTokenAndReturnValueThrowsException)
|
||||
{
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<std::any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<std::any> const& { throw 0; });
|
||||
EXPECT_CALL(mockStrand, execute(An<std::function<impl::Any(AnyStopToken)>>(), _))
|
||||
.WillOnce([](auto&&, auto) -> StoppableOperationType<impl::Any> const& { throw 0; });
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
[[maybe_unused]] auto unused =
|
||||
@@ -137,12 +138,12 @@ TEST_F(AnyStrandTests, ExecuteWithTimeoutAndStopTokenAndReturnValueThrowsExcepti
|
||||
|
||||
TEST_F(AnyStrandTests, RepeatingOperation)
|
||||
{
|
||||
auto mockRepeatingOp = RepeatingOperationType<std::any>{};
|
||||
auto mockRepeatingOp = RepeatingOperationType<impl::Any>{};
|
||||
EXPECT_CALL(mockRepeatingOp, wait());
|
||||
EXPECT_CALL(
|
||||
mockStrand, executeRepeatedly(std::chrono::milliseconds{1}, A<std::function<std::any()>>())
|
||||
mockStrand, executeRepeatedly(std::chrono::milliseconds{1}, A<std::function<impl::Any()>>())
|
||||
)
|
||||
.WillOnce([&mockRepeatingOp] -> RepeatingOperationType<std::any> const& {
|
||||
.WillOnce([&mockRepeatingOp] -> RepeatingOperationType<impl::Any> const& {
|
||||
return mockRepeatingOp;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user