Compare commits

..

18 Commits

Author SHA1 Message Date
Sergey Kuznetsov
bcc0345c35 chore: Use released libxrpl 3.2.0 (#3105) 2026-06-16 17:31:10 +01:00
Sergey Kuznetsov
14645e1494 fix: Proxy support (#3103)
Port of two changes onto release/2.7.1:
- #3006 (d3381a1d): resolve proxy ip before processing any request
- #3043 (d7bcf6e7): re-resolve client ip when a proxy reuses a TCP
connection for different clients (resolveClientIp now returns
std::optional; extractClientIp made public; isProxyConnection_ tracked)
2026-06-09 16:25:02 +01:00
Sergey Kuznetsov
ce44aec245 ci: Use docker images with glibc version in conan (#3100) 2026-06-08 15:16:50 +01:00
Sergey Kuznetsov
94da8459dd ci: Use glibc version in conan profile (#3099) 2026-06-08 14:01:33 +01:00
Sergey Kuznetsov
8f3afd09e6 chore: Use libxrpl 3.2.0 (#3095) 2026-06-05 17:48:07 +01:00
Sergey Kuznetsov
6bb4953f16 ci: Remove arm (#3094) 2026-06-05 15:37:58 +01:00
Sergey Kuznetsov
884c1e8cde ci: Remove arm 2026-06-05 15:33:38 +01:00
Sergey Kuznetsov
7edeb14629 ci: Update docker actions, fix llvm repo (#3093) 2026-06-05 14:34:51 +01:00
Sergey Kuznetsov
b6241b7c7f ci: Update actions, fix llvm repo 2026-06-05 13:00:31 +01:00
Sergey Kuznetsov
2c715323a9 ci: Fix docker update ci (#3092) 2026-06-05 12:18:10 +01:00
Sergey Kuznetsov
b5889e4382 Fix docker update ci 2026-06-05 12:00:42 +01:00
Sergey Kuznetsov
df295ff6ed ci: Ubuntu 20.04 -> 22.04 (#3090) 2026-06-05 11:03:06 +01:00
Sergey Kuznetsov
419ab53caa ci: Ubuntu 20.04 -> 22.04 2026-06-04 17:16:37 +01:00
Ayaz Salikhov
3215e43c11 ci: Restart colima on macOS (#2923) 2026-01-15 19:03:47 +00:00
Ayaz Salikhov
e8c977e7de chore: Commits for 2.7.0-rc3 (#2912) 2026-01-13 16:53:44 +00:00
Ayaz Salikhov
c59fcf343f chore: Commits for 2.7.0-rc2 (#2868) 2025-12-19 15:45:02 +00:00
Ayaz Salikhov
c35649eb6e chore: Commits for 2.7.0-rc1 (#2846) 2025-12-10 16:26:07 +00:00
Sergey Kuznetsov
4da4b49eda chore: Commits for 2.7.0-b2 (#2795) 2025-11-20 14:53:12 +00:00
919 changed files with 35893 additions and 35499 deletions

View File

@@ -22,7 +22,7 @@ BreakBeforeBinaryOperators: false
BreakBeforeBraces: WebKit
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
ColumnLimit: 100
ColumnLimit: 120
CommentPragmas: "^ IWYU pragma:"
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4

View File

@@ -4,7 +4,6 @@ Checks: "-*,
bugprone-assert-side-effect,
bugprone-bad-signal-to-kill-thread,
bugprone-bool-pointer-implicit-conversion,
bugprone-capturing-this-in-member-variable,
bugprone-casting-through-void,
bugprone-chained-comparison,
bugprone-compare-pointer-to-member-virtual-function,
@@ -24,7 +23,6 @@ Checks: "-*,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misleading-setter-of-reference,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
@@ -66,7 +64,6 @@ Checks: "-*,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-unchecked-optional-access,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-exception-at-new,
@@ -85,7 +82,6 @@ Checks: "-*,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-rvalue-reference-param-not-moved,
cppcoreguidelines-use-default-member-init,
cppcoreguidelines-use-enum-class,
cppcoreguidelines-virtual-class-destructor,
hicpp-ignored-remove-result,
llvm-namespace-comment,
@@ -109,10 +105,8 @@ Checks: "-*,
modernize-use-emplace,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nodiscard,
modernize-use-override,
modernize-use-ranges,
modernize-use-scoped-lock,
modernize-use-starts-ends-with,
modernize-use-std-numbers,
modernize-use-using,
@@ -124,7 +118,6 @@ Checks: "-*,
performance-move-constructor-init,
performance-no-automatic-move,
performance-trivially-destructible,
readability-ambiguous-smartptr-reset-call,
readability-avoid-nested-conditional-operator,
readability-avoid-return-with-void-value,
readability-braces-around-statements,
@@ -135,9 +128,9 @@ Checks: "-*,
readability-duplicate-include,
readability-else-after-return,
readability-enum-initial-value,
readability-identifier-naming,
readability-implicit-bool-conversion,
readability-inconsistent-declaration-parameter-name,
readability-identifier-naming,
readability-make-member-function-const,
readability-math-missing-parentheses,
readability-misleading-indentation,
@@ -156,11 +149,6 @@ Checks: "-*,
"
CheckOptions:
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
misc-include-cleaner.IgnoreHeaders: '.*/(detail|impl)/.*;.*(expected|unexpected).*;.*ranges_lower_bound\.h;time.h;stdlib.h;__chrono/.*;fmt/chrono.h;boost/uuid/uuid_hash.hpp'
readability-braces-around-statements.ShortStatementLines: 2
readability-identifier-naming.MacroDefinitionCase: UPPER_CASE
readability-identifier-naming.ClassCase: CamelCase
@@ -169,7 +157,7 @@ CheckOptions:
readability-identifier-naming.EnumCase: CamelCase
readability-identifier-naming.EnumConstantCase: CamelCase
readability-identifier-naming.ScopedEnumConstantCase: CamelCase
readability-identifier-naming.GlobalConstantCase: CamelCase
readability-identifier-naming.GlobalConstantCase: UPPER_CASE
readability-identifier-naming.GlobalConstantPrefix: "k"
readability-identifier-naming.GlobalVariableCase: CamelCase
readability-identifier-naming.GlobalVariablePrefix: "g"
@@ -177,25 +165,27 @@ CheckOptions:
readability-identifier-naming.ConstexprMethodCase: camelBack
readability-identifier-naming.ClassMethodCase: camelBack
readability-identifier-naming.ClassMemberCase: camelBack
readability-identifier-naming.ClassConstantCase: CamelCase
readability-identifier-naming.ClassConstantCase: UPPER_CASE
readability-identifier-naming.ClassConstantPrefix: "k"
readability-identifier-naming.StaticConstantCase: CamelCase
readability-identifier-naming.StaticConstantCase: UPPER_CASE
readability-identifier-naming.StaticConstantPrefix: "k"
readability-identifier-naming.StaticVariableCase: camelBack
readability-identifier-naming.ConstexprVariableCase: camelBack
readability-identifier-naming.StaticVariableCase: UPPER_CASE
readability-identifier-naming.StaticVariablePrefix: "k"
readability-identifier-naming.ConstexprVariableCase: UPPER_CASE
readability-identifier-naming.ConstexprVariablePrefix: "k"
readability-identifier-naming.LocalConstantCase: camelBack
readability-identifier-naming.LocalVariableCase: camelBack
readability-identifier-naming.TemplateParameterCase: CamelCase
readability-identifier-naming.ParameterCase: camelBack
readability-identifier-naming.FunctionCase: camelBack
readability-identifier-naming.MemberCase: camelBack
readability-identifier-naming.PrivateMemberCase: camelBack
readability-identifier-naming.PrivateMemberSuffix: _
readability-identifier-naming.ProtectedMemberCase: camelBack
readability-identifier-naming.ProtectedMemberSuffix: _
readability-identifier-naming.PublicMemberCase: camelBack
readability-identifier-naming.PublicMemberSuffix: ""
readability-identifier-naming.FunctionIgnoredRegexp: ".*tag_invoke.*"
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
misc-include-cleaner.IgnoreHeaders: '.*/(detail|impl)/.*;.*(expected|unexpected).*;.*ranges_lower_bound\.h;time.h;stdlib.h;__chrono/.*;fmt/chrono.h;boost/uuid/uuid_hash.hpp'
HeaderFilterRegex: '^.*/(src|tests)/.*\.(h|hpp)$'
WarningsAsErrors: "*"

245
.cmake-format.yaml Normal file
View File

@@ -0,0 +1,245 @@
_help_parse: Options affecting listfile parsing
parse:
_help_additional_commands:
- Specify structure for custom cmake functions
additional_commands:
foo:
flags:
- BAR
- BAZ
kwargs:
HEADERS: "*"
SOURCES: "*"
DEPENDS: "*"
_help_override_spec:
- Override configurations per-command where available
override_spec: {}
_help_vartags:
- Specify variable tags.
vartags: []
_help_proptags:
- Specify property tags.
proptags: []
_help_format: Options affecting formatting.
format:
_help_disable:
- Disable formatting entirely, making cmake-format a no-op
disable: false
_help_line_width:
- How wide to allow formatted cmake files
line_width: 120
_help_tab_size:
- How many spaces to tab for indent
tab_size: 2
_help_use_tabchars:
- If true, lines are indented using tab characters (utf-8
- 0x09) instead of <tab_size> space characters (utf-8 0x20).
- In cases where the layout would require a fractional tab
- character, the behavior of the fractional indentation is
- governed by <fractional_tab_policy>
use_tabchars: false
_help_fractional_tab_policy:
- If <use_tabchars> is True, then the value of this variable
- indicates how fractional indentions are handled during
- whitespace replacement. If set to 'use-space', fractional
- indentation is left as spaces (utf-8 0x20). If set to
- "`round-up` fractional indentation is replaced with a single"
- tab character (utf-8 0x09) effectively shifting the column
- to the next tabstop
fractional_tab_policy: use-space
_help_max_subgroups_hwrap:
- If an argument group contains more than this many sub-groups
- (parg or kwarg groups) then force it to a vertical layout.
max_subgroups_hwrap: 4
_help_max_pargs_hwrap:
- If a positional argument group contains more than this many
- arguments, then force it to a vertical layout.
max_pargs_hwrap: 5
_help_max_rows_cmdline:
- If a cmdline positional group consumes more than this many
- lines without nesting, then invalidate the layout (and nest)
max_rows_cmdline: 2
_help_separate_ctrl_name_with_space:
- If true, separate flow control names from their parentheses
- with a space
separate_ctrl_name_with_space: true
_help_separate_fn_name_with_space:
- If true, separate function names from parentheses with a
- space
separate_fn_name_with_space: false
_help_dangle_parens:
- If a statement is wrapped to more than one line, than dangle
- the closing parenthesis on its own line.
dangle_parens: true
_help_dangle_align:
- If the trailing parenthesis must be 'dangled' on its on
- "line, then align it to this reference: `prefix`: the start"
- "of the statement, `prefix-indent`: the start of the"
- "statement, plus one indentation level, `child`: align to"
- the column of the arguments
dangle_align: prefix
_help_min_prefix_chars:
- If the statement spelling length (including space and
- parenthesis) is smaller than this amount, then force reject
- nested layouts.
min_prefix_chars: 4
_help_max_prefix_chars:
- If the statement spelling length (including space and
- parenthesis) is larger than the tab width by more than this
- amount, then force reject un-nested layouts.
max_prefix_chars: 10
_help_max_lines_hwrap:
- If a candidate layout is wrapped horizontally but it exceeds
- this many lines, then reject the layout.
max_lines_hwrap: 2
_help_line_ending:
- What style line endings to use in the output.
line_ending: unix
_help_command_case:
- Format command names consistently as 'lower' or 'upper' case
command_case: canonical
_help_keyword_case:
- Format keywords consistently as 'lower' or 'upper' case
keyword_case: unchanged
_help_always_wrap:
- A list of command names which should always be wrapped
always_wrap: []
_help_enable_sort:
- If true, the argument lists which are known to be sortable
- will be sorted lexicographicall
enable_sort: true
_help_autosort:
- If true, the parsers may infer whether or not an argument
- list is sortable (without annotation).
autosort: true
_help_require_valid_layout:
- By default, if cmake-format cannot successfully fit
- everything into the desired linewidth it will apply the
- last, most aggressive attempt that it made. If this flag is
- True, however, cmake-format will print error, exit with non-
- zero status code, and write-out nothing
require_valid_layout: false
_help_layout_passes:
- A dictionary mapping layout nodes to a list of wrap
- decisions. See the documentation for more information.
layout_passes: {}
_help_markup: Options affecting comment reflow and formatting.
markup:
_help_bullet_char:
- What character to use for bulleted lists
bullet_char: "*"
_help_enum_char:
- What character to use as punctuation after numerals in an
- enumerated list
enum_char: .
_help_first_comment_is_literal:
- If comment markup is enabled, don't reflow the first comment
- block in each listfile. Use this to preserve formatting of
- your copyright/license statements.
first_comment_is_literal: false
_help_literal_comment_pattern:
- If comment markup is enabled, don't reflow any comment block
- which matches this (regex) pattern. Default is `None`
- (disabled).
literal_comment_pattern: null
_help_fence_pattern:
- Regular expression to match preformat fences in comments
- default= ``r'^\s*([`~]{3}[`~]*)(.*)$'``
fence_pattern: ^\s*([`~]{3}[`~]*)(.*)$
_help_ruler_pattern:
- Regular expression to match rulers in comments default=
- '``r''^\s*[^\w\s]{3}.*[^\w\s]{3}$''``'
ruler_pattern: ^\s*[^\w\s]{3}.*[^\w\s]{3}$
_help_explicit_trailing_pattern:
- If a comment line matches starts with this pattern then it
- is explicitly a trailing comment for the preceding
- argument. Default is '#<'
explicit_trailing_pattern: "#<"
_help_hashruler_min_length:
- If a comment line starts with at least this many consecutive
- hash characters, then don't lstrip() them off. This allows
- for lazy hash rulers where the first hash char is not
- separated by space
hashruler_min_length: 10
_help_canonicalize_hashrulers:
- If true, then insert a space between the first hash char and
- remaining hash chars in a hash ruler, and normalize its
- length to fill the column
canonicalize_hashrulers: true
_help_enable_markup:
- enable comment markup parsing and reflow
enable_markup: true
_help_lint: Options affecting the linter
lint:
_help_disabled_codes:
- a list of lint codes to disable
disabled_codes: []
_help_function_pattern:
- regular expression pattern describing valid function names
function_pattern: "[0-9a-z_]+"
_help_macro_pattern:
- regular expression pattern describing valid macro names
macro_pattern: "[0-9A-Z_]+"
_help_global_var_pattern:
- regular expression pattern describing valid names for
- variables with global (cache) scope
global_var_pattern: "[A-Z][0-9A-Z_]+"
_help_internal_var_pattern:
- regular expression pattern describing valid names for
- variables with global scope (but internal semantic)
internal_var_pattern: _[A-Z][0-9A-Z_]+
_help_local_var_pattern:
- regular expression pattern describing valid names for
- variables with local scope
local_var_pattern: "[a-z][a-z0-9_]+"
_help_private_var_pattern:
- regular expression pattern describing valid names for
- privatedirectory variables
private_var_pattern: _[0-9a-z_]+
_help_public_var_pattern:
- regular expression pattern describing valid names for public
- directory variables
public_var_pattern: "[A-Z][0-9A-Z_]+"
_help_argument_var_pattern:
- regular expression pattern describing valid names for
- function/macro arguments and loop variables.
argument_var_pattern: "[a-z][a-z0-9_]+"
_help_keyword_pattern:
- regular expression pattern describing valid names for
- keywords used in functions or macros
keyword_pattern: "[A-Z][0-9A-Z_]+"
_help_max_conditionals_custom_parser:
- In the heuristic for C0201, how many conditionals to match
- within a loop in before considering the loop a parser.
max_conditionals_custom_parser: 2
_help_min_statement_spacing:
- Require at least this many newlines between statements
min_statement_spacing: 1
_help_max_statement_spacing:
- Require no more than this many newlines between statements
max_statement_spacing: 2
max_returns: 6
max_branches: 12
max_arguments: 5
max_localvars: 15
max_statements: 50
_help_encode: Options affecting file encoding
encode:
_help_emit_byteorder_mark:
- If true, emit the unicode byte-order mark (BOM) at the start
- of the file
emit_byteorder_mark: false
_help_input_encoding:
- Specify the encoding of the input file. Defaults to utf-8
input_encoding: utf-8
_help_output_encoding:
- Specify the encoding of the output file. Defaults to utf-8.
- Note that cmake only claims to support utf-8 so be careful
- when using anything else
output_encoding: utf-8
_help_misc: Miscellaneous configurations options.
misc:
_help_per_command:
- A dictionary containing any per-command configuration
- overrides. Currently only `command_case` is supported.
per_command: {}

View File

@@ -1,22 +0,0 @@
# Custom CMake command definitions for gersemi formatting.
# These stubs teach gersemi the signatures of project-specific commands
# so it can format their invocations correctly.
function(setup_target_for_coverage_gcovr)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME FORMAT)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(
THIS_FUNCTION_PREFIX
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
endfunction()
function(append_coverage_compiler_flags_to_target name mode)
endfunction()
function(patch_nix_binary target)
endfunction()

View File

@@ -1 +0,0 @@
definitions: [.gersemi]

View File

@@ -26,6 +26,6 @@ runs:
run: |
cd build
cmake \
--build . \
--parallel "${{ steps.nproc.outputs.nproc }}" \
--target ${CMAKE_TARGETS}
--build . \
--parallel "${{ steps.nproc.outputs.nproc }}" \
--target ${CMAKE_TARGETS}

View File

@@ -1,53 +0,0 @@
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 Normal file
View File

@@ -0,0 +1,41 @@
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}"

View File

@@ -6,6 +6,9 @@ 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
@@ -22,6 +25,10 @@ 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
@@ -43,9 +50,15 @@ 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
@@ -63,14 +76,16 @@ runs:
FORCE_CLIO_VERSION: ${{ inputs.version }}
run: |
cmake \
-B "${BUILD_DIR}" \
-S . \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-Dtests=ON \
-Dintegration_tests="${INTEGRATION_TESTS}" \
-Dbenchmark="${BENCHMARK}" \
-Dcoverage="${COVERAGE}" \
-Dtime_trace="${TIME_TRACE}" \
-Dpackage="${PACKAGE}"
-B "${BUILD_DIR}" \
-S . \
-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}"

View File

@@ -15,16 +15,16 @@ runs:
shell: bash
run: |
gcovr \
-e benchmarks \
-e tests \
-e src/data/cassandra \
-e src/data/CassandraBackend.hpp \
-e 'src/data/BackendFactory.*' \
--xml build/coverage_report.xml \
-j8 --exclude-throw-branches
-e benchmarks \
-e tests \
-e src/data/cassandra \
-e src/data/CassandraBackend.hpp \
-e 'src/data/BackendFactory.*' \
--xml build/coverage_report.xml \
-j8 --exclude-throw-branches
- name: Archive coverage report
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: coverage-report.xml
path: build/coverage_report.xml

View File

@@ -6,6 +6,9 @@ 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
@@ -14,10 +17,6 @@ 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
@@ -28,11 +27,11 @@ runs:
BUILD_DIR: "${{ inputs.build_dir }}"
CONAN_BUILD_OPTION: "${{ inputs.force_conan_source_build == 'true' && '*' || 'missing' }}"
BUILD_TYPE: "${{ inputs.build_type }}"
SANITIZERS: "${{ inputs.sanitizers }}"
CONAN_PROFILE: "${{ inputs.conan_profile }}"
run: |
conan \
install . \
-of "${BUILD_DIR}" \
-b "${CONAN_BUILD_OPTION}" \
-s "build_type=${BUILD_TYPE}" \
--profile:all ci
install . \
-of "${BUILD_DIR}" \
-b "${CONAN_BUILD_OPTION}" \
-s "build_type=${BUILD_TYPE}" \
--profile:all "${CONAN_PROFILE}"

46
.github/actions/create-issue/action.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Create an issue
description: Create an issue
inputs:
title:
description: Issue title
required: true
body:
description: Issue body
required: true
labels:
description: Comma-separated list of labels
required: true
default: "bug"
assignees:
description: Comma-separated list of assignees
required: true
default: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
outputs:
created_issue_id:
description: Created issue id
value: ${{ steps.create_issue.outputs.created_issue }}
runs:
using: composite
steps:
- name: Create an issue
id: create_issue
shell: bash
env:
ISSUE_BODY: ${{ inputs.body }}
ISSUE_ASSIGNEES: ${{ inputs.assignees }}
ISSUE_LABELS: ${{ inputs.labels }}
ISSUE_TITLE: ${{ inputs.title }}
run: |
echo -e "${ISSUE_BODY}" > issue.md
gh issue create \
--assignee "${ISSUE_ASSIGNEES}" \
--label "${ISSUE_LABELS}" \
--title "${ISSUE_TITLE}" \
--body-file ./issue.md \
> create_issue.log
created_issue="$(sed 's|.*/||' create_issue.log)"
echo "created_issue=$created_issue" >> $GITHUB_OUTPUT
rm create_issue.log issue.md

View File

@@ -13,4 +13,4 @@ runs:
id: find_common_ancestor
shell: bash
run: |
echo "commit=\"$(git merge-base --fork-point origin/develop)\"" >>$GITHUB_OUTPUT
echo "commit=\"$(git merge-base --fork-point origin/develop)\"" >> $GITHUB_OUTPUT

View File

@@ -1,34 +0,0 @@
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

115
.github/dependabot.yml vendored
View File

@@ -1,16 +1,111 @@
version: 2
updates:
- package-ecosystem: github-actions
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/
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/create-issue/
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/
schedule:
interval: weekly
day: monday

View File

@@ -3,7 +3,9 @@ import itertools
import json
LINUX_OS = ["heavy", "heavy-arm64"]
LINUX_CONTAINERS = ['{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }']
LINUX_CONTAINERS = [
'{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
]
LINUX_COMPILERS = ["gcc", "clang"]
MACOS_OS = ["macos15"]
@@ -11,10 +13,7 @@ MACOS_CONTAINERS = [""]
MACOS_COMPILERS = ["apple-clang"]
BUILD_TYPES = ["Release", "Debug"]
# Values of the `SANITIZERS` environment variable read by the `sanitizers` conan
# profile. An empty string builds without any sanitizers.
SANITIZERS = ["address", "thread", "undefinedbehavior", ""]
SANITIZER_EXT = [".asan", ".tsan", ".ubsan", ""]
def generate_matrix():
@@ -24,13 +23,13 @@ def generate_matrix():
itertools.product(LINUX_OS, LINUX_CONTAINERS, LINUX_COMPILERS),
itertools.product(MACOS_OS, MACOS_CONTAINERS, MACOS_COMPILERS),
):
for sanitizers, build_type in itertools.product(SANITIZERS, BUILD_TYPES):
for sanitizer_ext, build_type in itertools.product(SANITIZER_EXT, BUILD_TYPES):
configurations.append(
{
"os": os,
"container": container,
"compiler": compiler,
"sanitizers": sanitizers,
"sanitizer_ext": sanitizer_ext,
"build_type": build_type,
}
)

48
.github/scripts/conan/init.sh vendored Executable file
View File

@@ -0,0 +1,48 @@
#!/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

View File

@@ -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=./conan/profiles/apple-clang-17.profile
--profile:all=.github/scripts/conan/apple-clang-17.profile

View File

@@ -0,0 +1,46 @@
#!/bin/bash
set -o pipefail
# Note: This script is intended to be run from the root of the repository.
#
# This script runs each unit-test separately and generates reports from the currently active sanitizer.
# Output is saved in ./.sanitizer-report in the root of the repository
if [[ -z "$1" ]]; then
cat <<EOF
ERROR
-----------------------------------------------------------------------------
Path to clio_tests should be passed as first argument to the script.
-----------------------------------------------------------------------------
EOF
exit 1
fi
TEST_BINARY=$1
if [[ ! -f "$TEST_BINARY" ]]; then
echo "Test binary not found: $TEST_BINARY"
exit 1
fi
TESTS=$($TEST_BINARY --gtest_list_tests | awk '/^ / {print suite $1} !/^ / {suite=$1}')
OUTPUT_DIR="./.sanitizer-report"
mkdir -p "$OUTPUT_DIR"
export TSAN_OPTIONS="die_after_fork=0"
export MallocNanoZone='0' # for MacOSX
for TEST in $TESTS; do
OUTPUT_FILE="$OUTPUT_DIR/${TEST//\//_}.log"
$TEST_BINARY --gtest_filter="$TEST" >"$OUTPUT_FILE" 2>&1
if [ $? -ne 0 ]; then
echo "'$TEST' failed a sanitizer check."
else
rm "$OUTPUT_FILE"
fi
done

View File

@@ -14,9 +14,9 @@ on:
type: boolean
description: Whether to strip clio binary
default: true
push_image:
publish_image:
type: boolean
description: Whether to push docker image
description: Whether to publish docker image
required: true
workflow_dispatch:
@@ -43,16 +43,16 @@ defaults:
shell: bash
jobs:
build_and_push_image:
build_and_publish_image:
name: Build and publish image
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Download Clio binary from artifact
if: ${{ inputs.artifact_name != null }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: ${{ inputs.artifact_name }}
path: ./docker/clio/artifact/
@@ -65,8 +65,8 @@ jobs:
run: |
wget "${BINARY_URL}" -P ./docker/clio/artifact/
if [ "$(sha256sum ./docker/clio/clio_server | awk '{print $1}')" != "${BINARY_SHA256}" ]; then
echo "Binary sha256 sum doesn't match"
exit 1
echo "Binary sha256 sum doesn't match"
exit 1
fi
- name: Unpack binary
run: |
@@ -74,9 +74,9 @@ jobs:
cd docker/clio/artifact
artifact=$(find . -type f)
if [[ $artifact == *.zip ]]; then
unzip $artifact
unzip $artifact
elif [[ $artifact == *.tar.gz ]]; then
tar -xvf $artifact
tar -xvf $artifact
fi
chmod +x ./clio_server
mv ./clio_server ../
@@ -90,7 +90,7 @@ jobs:
- name: Set GHCR_REPO
id: set-ghcr-repo
run: |
echo "GHCR_REPO=$(echo ghcr.io/${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >>${GITHUB_OUTPUT}
echo "GHCR_REPO=$(echo ghcr.io/${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> ${GITHUB_OUTPUT}
- name: Build Docker image
uses: ./.github/actions/build-docker-image
@@ -102,7 +102,7 @@ jobs:
images: |
ghcr.io/${{ steps.set-ghcr-repo.outputs.GHCR_REPO }}/clio
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio' || '' }}
push_image: ${{ inputs.push_image }}
push_image: ${{ inputs.publish_image }}
directory: docker/clio
tags: ${{ inputs.tags }}
platforms: linux/amd64

View File

@@ -15,6 +15,7 @@ on:
- ".github/actions/**"
- "!.github/actions/build-docker-image/**"
- "!.github/actions/create-issue/**"
- CMakeLists.txt
- conanfile.py
@@ -22,7 +23,6 @@ on:
- "cmake/**"
- "src/**"
- "tests/**"
- "benchmarks/**"
- docs/config-description.md
workflow_dispatch:
@@ -45,24 +45,30 @@ jobs:
fail-fast: false
matrix:
os: [heavy]
compiler: [gcc, clang]
conan_profile: [gcc, clang]
build_type: [Release, Debug]
container: ['{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }']
container:
[
'{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }',
]
static: [true]
include:
- os: macos15
compiler: apple-clang
conan_profile: apple-clang
build_type: Release
container: ""
static: false
uses: ./.github/workflows/reusable-build-test.yml
with:
runs_on: ${{ matrix.os }}
container: ${{ matrix.container }}
compiler: ${{ matrix.compiler }}
conan_profile: ${{ matrix.conan_profile }}
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
@@ -73,12 +79,13 @@ jobs:
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
compiler: gcc
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
conan_profile: 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
@@ -90,12 +97,12 @@ jobs:
needs: build-and-test
runs-on: heavy
container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: clio_server_Linux_Release_gcc

View File

@@ -10,7 +10,7 @@ concurrency:
cancel-in-progress: true
env:
COMPILER: gcc
CONAN_PROFILE: gcc
defaults:
run:
@@ -21,10 +21,10 @@ jobs:
name: Build Clio / `libXRPL ${{ github.event.client_payload.version }}`
runs-on: heavy
container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
@@ -33,17 +33,6 @@ jobs:
with:
enable_ccache: false
- 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
@@ -51,13 +40,17 @@ jobs:
- name: Update conan lockfile
run: |
conan lock create . --profile:all ci
conan lock create . --profile:all ${{ env.CONAN_PROFILE }}
- 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
@@ -66,7 +59,7 @@ jobs:
run: strip build/clio_tests
- name: Upload clio_tests
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_tests_check_libxrpl
path: build/clio_tests
@@ -76,10 +69,10 @@ jobs:
needs: build
runs-on: heavy
container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: clio_tests_check_libxrpl
@@ -99,15 +92,17 @@ jobs:
issues: write
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Create an issue
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
uses: ./.github/actions/create-issue
env:
GH_TOKEN: ${{ github.token }}
with:
labels: "compatibility,bug"
title: "Proposed libXRPL check failed"
body: >
Clio build or tests failed against `libXRPL ${{ github.event.client_payload.conan_ref }}`.
PR: ${{ github.event.client_payload.pr_url }}
labels: "compatibility,bug"
assignees: "godexsoft,kuznetsss,mathbunnyru"
Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/

View File

@@ -5,6 +5,26 @@ on:
types: [opened, edited, reopened, synchronize]
branches: [develop]
defaults:
run:
shell: bash
jobs:
check_title:
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81
runs-on: ubuntu-latest
steps:
- uses: ytanikin/pr-conventional-commits@fda730cb152c05a849d6d84325e50c6182d9d1e9 # 1.5.1
with:
task_types: '["build","feat","fix","docs","test","ci","style","refactor","perf","chore"]'
add_label: false
custom_labels: '{"build":"build", "feat":"enhancement", "fix":"bug", "docs":"documentation", "test":"testability", "ci":"ci", "style":"refactoring", "refactor":"refactoring", "perf":"performance", "chore":"tooling"}'
- name: Check if message starts with upper-case letter
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
if [[ ! "${PR_TITLE}" =~ ^[a-z]+:\ [\[A-Z] ]]; then
echo "Error: PR title must start with an upper-case letter."
exit 1
fi

View File

@@ -1,22 +1,16 @@
name: Run clang-tidy on files
name: Clang-tidy check
on:
push:
branches: [develop]
schedule:
- cron: "0 9 * * 1-5"
workflow_dispatch:
pull_request:
branches: [develop]
paths:
- .github/workflows/clang-tidy.yml
- CMakeLists.txt
- conanfile.py
- conan.lock
- "cmake/**"
- "src/**"
- "tests/**"
- "benchmarks/**"
- .clang_tidy
concurrency:
@@ -25,33 +19,19 @@ concurrency:
cancel-in-progress: true
env:
BUILD_DIR: build
BUILD_TYPE: Debug # Debug so that ASSERTS and such participate in clang-tidy check
OUTPUT_FILE: clang-tidy-output.txt
DIFF_FILE: clang-tidy-git-diff.txt
ISSUE_FILE: clang-tidy-issue.md
COMPILER: clang
CONAN_PROFILE: clang
LLVM_TOOLS_VERSION: 20
defaults:
run:
shell: bash
jobs:
determine-files:
if: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@224f3c48d3014d082a1129237b8291ff0b0a331f
run-clang-tidy:
name: Run clang tidy
needs: [determine-files]
if: ${{ always() && !cancelled() && (github.event_name != 'pull_request' || needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
clang_tidy:
if: github.event_name != 'push' || contains(github.event.head_commit.message, 'clang-tidy auto fixes')
runs-on: heavy
container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
permissions:
contents: write
@@ -59,61 +39,38 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
enable_ccache: false
- 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 }}
build_type: ${{ env.BUILD_TYPE }}
conan_profile: ${{ env.CONAN_PROFILE }}
- name: Run CMake
uses: ./.github/actions/cmake
with:
build_dir: ${{ env.BUILD_DIR }}
build_type: ${{ env.BUILD_TYPE }}
conan_profile: ${{ env.CONAN_PROFILE }}
- name: Get number of processors
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
id: nproc
- name: Run clang tidy
- name: Run clang-tidy (several times)
continue-on-error: true
id: run_clang_tidy
env:
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' }}
id: clang_tidy
run: |
set -o pipefail
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' }}
run: |
sed '/error\||/!d' "${OUTPUT_FILE}"
- name: Upload clang-tidy output
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
path: ${{ env.OUTPUT_FILE }}
archive: false
retention-days: 30
# We run clang-tidy several times, because some fixes may enable new fixes in subsequent runs.
CLANG_TIDY_COMMAND="run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j ${{ steps.nproc.outputs.nproc }} -fix -quiet"
${CLANG_TIDY_COMMAND} ||
${CLANG_TIDY_COMMAND} ||
${CLANG_TIDY_COMMAND}
- name: Check for changes
id: files_changed
@@ -121,78 +78,26 @@ jobs:
run: |
git diff --exit-code
- name: Fix style
- name: Fix local includes and clang-format style
if: ${{ steps.files_changed.outcome != 'success' }}
run: |
pre-commit run --all-files || true
pre-commit run --all-files fix-local-includes || true
pre-commit run --all-files clang-format || true
- name: Generate git diff
if: ${{ steps.files_changed.outcome != 'success' }}
run: |
git diff | tee "${DIFF_FILE}"
- name: Upload clang-tidy diff output
if: ${{ github.event.repository.visibility == 'public' && steps.files_changed.outcome != 'success' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
- name: Create an issue
if: ${{ (steps.clang_tidy.outcome != 'success' || steps.files_changed.outcome != 'success') && github.event_name != 'pull_request' }}
id: create_issue
uses: ./.github/actions/create-issue
env:
GH_TOKEN: ${{ github.token }}
with:
path: ${{ env.DIFF_FILE }}
archive: false
retention-days: 30
title: "Clang-tidy found bugs in code 🐛"
body: >
Clang-tidy found issues in the code:
- name: Write issue header
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
cat >"${ISSUE_FILE}" <<EOF
## Clang-tidy Check Failed
List of the issues found: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
### Clang-tidy Output:
\`\`\`
EOF
- name: Append clang-tidy output to issue body (filter for errors and warnings)
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
if [ -f "${OUTPUT_FILE}" ]; then
# Extract lines containing 'error:', 'warning:', or 'note:'
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" >filtered-output.txt || true
# If filtered output is empty, use original (might be a different error format)
if [ ! -s filtered-output.txt ]; then
cp "${OUTPUT_FILE}" filtered-output.txt
fi
# Truncate if too large
head -c 60000 filtered-output.txt >>"${ISSUE_FILE}"
if [ "$(wc -c <filtered-output.txt)" -gt 60000 ]; then
echo "" >>"${ISSUE_FILE}"
echo "... (output truncated, see artifacts for full output)" >>"${ISSUE_FILE}"
fi
rm filtered-output.txt
else
echo "No output file found" >>"${ISSUE_FILE}"
fi
- name: Append issue footer
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
cat >>"${ISSUE_FILE}" <<EOF
\`\`\`
---
*This issue was automatically created by the clang-tidy workflow.*
EOF
- name: Create issue
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
title: "Clang-tidy check failed"
body_file: ${{ env.ISSUE_FILE }}
labels: "bug"
assignees: "godexsoft,mathbunnyru"
- uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd # v7.0.0
- uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
if: ${{ steps.files_changed.outcome != 'success' && github.event_name != 'pull_request' }}
with:
gpg_private_key: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
@@ -202,7 +107,7 @@ jobs:
- name: Create PR with fixes
if: ${{ steps.files_changed.outcome != 'success' && github.event_name != 'pull_request' }}
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
@@ -213,14 +118,9 @@ jobs:
branch-suffix: timestamp
delete-branch: true
title: "style: clang-tidy auto fixes"
body: >
Fixes #${{ steps.create_issue.outputs.issue_number }}.
Please review and commit clang-tidy fixes.
reviewers: "godexsoft,kuznetsss,mathbunnyru"
body: "Fixes #${{ steps.create_issue.outputs.created_issue_id }}. Please review and commit clang-tidy fixes."
reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
- name: Fail the job
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
echo "Clang-tidy check failed!"
exit 1
if: ${{ steps.clang_tidy.outcome != 'success' || steps.files_changed.outcome != 'success' }}
run: exit 1

View File

@@ -18,11 +18,11 @@ jobs:
build:
runs-on: ubuntu-latest
container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
lfs: true
@@ -31,9 +31,6 @@ jobs:
with:
enable_ccache: false
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
- name: Create build directory
run: mkdir build_docs
@@ -46,17 +43,15 @@ jobs:
run: cmake --build . --target docs
- name: Setup Pages
if: ${{ github.repository == 'XRPLF/clio' && github.event_name == 'push' }}
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
- name: Upload artifact
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
with:
path: build_docs/html
name: docs-develop
deploy:
if: ${{ github.repository == 'XRPLF/clio' && github.event_name == 'push' }}
needs: build
permissions:
pages: write
@@ -71,6 +66,6 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
with:
artifact_name: docs-develop

View File

@@ -37,7 +37,7 @@ jobs:
- name: Get current date
id: get_date
run: |
echo "date=$(date +'%Y%m%d')" >>$GITHUB_OUTPUT
echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
build-and-test:
name: Build and Test
@@ -48,29 +48,32 @@ jobs:
matrix:
include:
- os: macos15
compiler: apple-clang
conan_profile: apple-clang
build_type: Release
static: false
- os: heavy
compiler: gcc
conan_profile: gcc
build_type: Release
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
static: true
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
- os: heavy
compiler: gcc
conan_profile: gcc
build_type: Debug
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
static: true
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
- os: heavy
compiler: gcc
sanitizers: undefinedbehavior
conan_profile: gcc.ubsan
build_type: Release
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
static: false
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
uses: ./.github/workflows/reusable-build-test.yml
with:
runs_on: ${{ matrix.os }}
container: ${{ matrix.container }}
compiler: ${{ matrix.compiler }}
sanitizers: ${{ matrix.sanitizers }}
conan_profile: ${{ matrix.conan_profile }}
build_type: ${{ matrix.build_type }}
static: ${{ matrix.static }}
run_unit_tests: true
run_integration_tests: true
upload_clio_server: true
@@ -85,12 +88,13 @@ jobs:
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
compiler: gcc
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
conan_profile: 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 }}
@@ -106,20 +110,23 @@ jobs:
matrix:
include:
- os: heavy
compiler: clang
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
conan_profile: clang
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
static: true
- os: macos15
compiler: apple-clang
conan_profile: apple-clang
container: ""
static: false
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: ${{ matrix.os }}
container: ${{ matrix.container }}
compiler: ${{ matrix.compiler }}
conan_profile: ${{ matrix.conan_profile }}
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
@@ -150,7 +157,7 @@ jobs:
type=raw,value=${{ github.sha }}
artifact_name: clio_server_Linux_Release_gcc
strip_binary: true
push_image: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
publish_image: ${{ github.event_name != 'pull_request' }}
create_issue_on_failure:
needs: [build-and-test, nightly_release, build_and_publish_docker_image]
@@ -162,12 +169,15 @@ jobs:
issues: write
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Create an issue
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
uses: ./.github/actions/create-issue
env:
GH_TOKEN: ${{ github.token }}
with:
title: "Nightly release failed 🌙"
body: ""
labels: "bug"
assignees: "godexsoft,kuznetsss,mathbunnyru"
body: >
Nightly release failed:
Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/

View File

@@ -12,11 +12,11 @@ on:
jobs:
auto-update:
uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@5e942d61bf32f7557a7c159cfac4712a687b3e3a
uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@ad4ab1ae5a54a4bab0e87294c31fc0729f788b2b
with:
sign_commit: true
committer: "Clio CI <skuznetsov@ripple.com>"
reviewers: "godexsoft,kuznetsss,mathbunnyru"
reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
secrets:
GPG_PRIVATE_KEY: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.ACTIONS_GPG_PASSPHRASE }}

View File

@@ -8,7 +8,7 @@ on:
jobs:
run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81
uses: XRPLF/actions/.github/workflows/pre-commit.yml@282890f46d6921249d5659dd38babcb0bd8aef48
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/clio-pre-commit:14342e087ceb8b593027198bf9ef06a43833c696" }'
container: '{ "image": "ghcr.io/xrplf/clio-pre-commit:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'

View File

@@ -22,19 +22,22 @@ jobs:
matrix:
include:
- os: macos15
compiler: apple-clang
conan_profile: apple-clang
build_type: Release
static: false
- os: heavy
compiler: gcc
conan_profile: gcc
build_type: Release
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
static: true
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
uses: ./.github/workflows/reusable-build-test.yml
with:
runs_on: ${{ matrix.os }}
container: ${{ matrix.container }}
compiler: ${{ matrix.compiler }}
conan_profile: ${{ matrix.conan_profile }}
build_type: ${{ matrix.build_type }}
static: ${{ matrix.static }}
run_unit_tests: true
run_integration_tests: true
upload_clio_server: true
@@ -48,12 +51,13 @@ jobs:
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
compiler: gcc
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
conan_profile: 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 || '' }}

View File

@@ -13,17 +13,11 @@ on:
required: true
type: string
compiler:
description: 'Compiler to build with ("gcc", "clang" or "apple-clang")'
conan_profile:
description: Conan profile to use
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
@@ -41,6 +35,12 @@ 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 }}
compiler: ${{ inputs.compiler }}
sanitizers: ${{ inputs.sanitizers }}
conan_profile: ${{ inputs.conan_profile }}
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,8 +99,7 @@ jobs:
with:
runs_on: ${{ inputs.runs_on }}
container: ${{ inputs.container }}
compiler: ${{ inputs.compiler }}
sanitizers: ${{ inputs.sanitizers }}
conan_profile: ${{ inputs.conan_profile }}
build_type: ${{ inputs.build_type }}
run_unit_tests: ${{ inputs.run_unit_tests }}
run_integration_tests: ${{ inputs.run_integration_tests }}

View File

@@ -13,17 +13,11 @@ on:
required: true
type: string
compiler:
description: 'Compiler to build with ("gcc", "clang" or "apple-clang")'
conan_profile:
description: Conan profile to use
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
@@ -46,6 +40,11 @@ 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
@@ -89,9 +88,9 @@ jobs:
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
@@ -100,47 +99,40 @@ jobs:
with:
enable_ccache: ${{ inputs.download_ccache }}
- 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: ${{ inputs.compiler }}
- name: Setup conan
run: conan/init.sh
- name: Generate build identifier
uses: ./.github/actions/build-identifier
id: build_identifier
- name: Generate cache key
uses: ./.github/actions/cache-key
id: cache_key
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
uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.build_identifier.outputs.cache_key }}
key: ${{ steps.cache_key.outputs.key }}
restore-keys: |
${{ steps.build_identifier.outputs.build_identifier }}
${{ steps.cache_key.outputs.restore_keys }}
- 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 }}
@@ -154,14 +146,14 @@ jobs:
if: ${{ inputs.analyze_build_time }}
run: |
ClangBuildAnalyzer --all build/ build_time_report.bin
ClangBuildAnalyzer --analyze build_time_report.bin >build_time_report.txt
ClangBuildAnalyzer --analyze build_time_report.bin > build_time_report.txt
cat build_time_report.txt
- name: Upload build time analyze report
if: ${{ inputs.analyze_build_time }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: build_time_report_${{ steps.build_identifier.outputs.build_identifier }}
name: build_time_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build_time_report.txt
- name: Show ccache's statistics and zero it
@@ -172,45 +164,45 @@ jobs:
- name: Save ccache cache
if: ${{ inputs.upload_ccache && github.ref == 'refs/heads/develop' }}
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/save@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.build_identifier.outputs.cache_key }}
key: ${{ steps.cache_key.outputs.key }}
- name: Strip unit_tests
if: ${{ inputs.sanitizers == '' && !inputs.code_coverage && !inputs.analyze_build_time }}
if: ${{ !endsWith(inputs.conan_profile, 'san') && !inputs.code_coverage && !inputs.analyze_build_time }}
run: strip build/clio_tests
- name: Strip integration_tests
if: ${{ inputs.sanitizers == '' && !inputs.code_coverage && !inputs.analyze_build_time }}
if: ${{ !endsWith(inputs.conan_profile, 'san') && !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
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_server_${{ steps.build_identifier.outputs.build_identifier }}
name: clio_server_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
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
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_tests_${{ steps.build_identifier.outputs.build_identifier }}
name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
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
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_integration_tests_${{ steps.build_identifier.outputs.build_identifier }}
name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build/clio_integration_tests
- name: Upload Clio Linux package
if: ${{ inputs.package }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_deb_package_${{ steps.build_identifier.outputs.build_identifier }}
name: clio_deb_package_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build/*.deb
# This is run as part of the build job, because it requires the following:
@@ -232,13 +224,13 @@ jobs:
set -e
EXPECTED_VERSION="clio-${INPUT_VERSION}"
if [[ "${BUILD_TYPE}" == "Debug" ]]; then
EXPECTED_VERSION="${EXPECTED_VERSION}+DEBUG"
EXPECTED_VERSION="${EXPECTED_VERSION}+DEBUG"
fi
actual_version=$(./build/clio_server --version | head -n 1)
if [[ "${actual_version}" != "${EXPECTED_VERSION}" ]]; then
echo "Expected version '${EXPECTED_VERSION}', but got '${actual_version}'"
exit 1
echo "Expected version '${EXPECTED_VERSION}', but got '${actual_version}'"
exit 1
fi
# `codecov/codecov-action` will rerun `gcov` if it's available and build directory is present

View File

@@ -46,7 +46,7 @@ jobs:
release:
runs-on: heavy
container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
@@ -55,7 +55,7 @@ jobs:
contents: write
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
@@ -64,7 +64,7 @@ jobs:
with:
enable_ccache: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
path: release_artifacts
pattern: clio_server_*
@@ -72,7 +72,7 @@ jobs:
- name: Prepare release artifacts
run: .github/scripts/prepare-release-artifacts.sh release_artifacts
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
path: release_artifacts
pattern: clio_deb_package_*
@@ -81,9 +81,9 @@ jobs:
env:
RELEASE_HEADER: ${{ inputs.header }}
run: |
echo "# Release notes" >"${RUNNER_TEMP}/release_notes.md"
echo "" >>"${RUNNER_TEMP}/release_notes.md"
printf '%s\n' "${RELEASE_HEADER}" >>"${RUNNER_TEMP}/release_notes.md"
echo "# Release notes" > "${RUNNER_TEMP}/release_notes.md"
echo "" >> "${RUNNER_TEMP}/release_notes.md"
printf '%s\n' "${RELEASE_HEADER}" >> "${RUNNER_TEMP}/release_notes.md"
- name: Generate changelog
if: ${{ inputs.generate_changelog }}
@@ -91,10 +91,10 @@ jobs:
LAST_TAG="$(gh release view --json tagName -q .tagName --repo XRPLF/clio)"
LAST_TAG_COMMIT="$(git rev-parse $LAST_TAG)"
BASE_COMMIT="$(git merge-base HEAD $LAST_TAG_COMMIT)"
git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b|-rc" >>"${RUNNER_TEMP}/release_notes.md"
git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b|-rc" >> "${RUNNER_TEMP}/release_notes.md"
- name: Upload release notes
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: release_notes_${{ inputs.version }}
path: "${RUNNER_TEMP}/release_notes.md"
@@ -106,10 +106,10 @@ jobs:
run: |
RELEASES_TO_DELETE=$(gh release list --limit 50 --repo "${GH_REPO}" | grep -E "${DELETE_PATTERN}" | awk -F'\t' '{print $3}' || true)
if [ -n "$RELEASES_TO_DELETE" ]; then
for RELEASE in $RELEASES_TO_DELETE; do
echo "Deleting release: $RELEASE"
gh release delete "$RELEASE" --repo "${GH_REPO}" --yes --cleanup-tag
done
for RELEASE in $RELEASES_TO_DELETE; do
echo "Deleting release: $RELEASE"
gh release delete "$RELEASE" --repo "${GH_REPO}" --yes --cleanup-tag
done
fi
- name: Publish release
@@ -121,9 +121,9 @@ jobs:
DRAFT_OPTION: ${{ inputs.draft && '--draft' || '' }}
run: |
gh release create "${RELEASE_VERSION}" \
${PRERELEASE_OPTION} \
--title "${RELEASE_TITLE}" \
--target "${GITHUB_SHA}" \
${DRAFT_OPTION} \
--notes-file "${RUNNER_TEMP}/release_notes.md" \
./release_artifacts/clio_*
${PRERELEASE_OPTION} \
--title "${RELEASE_TITLE}" \
--target "${GITHUB_SHA}" \
${DRAFT_OPTION} \
--notes-file "${RUNNER_TEMP}/release_notes.md" \
./release_artifacts/clio_*

View File

@@ -13,17 +13,11 @@ on:
required: true
type: string
compiler:
description: 'Compiler the binaries were built with ("gcc", "clang" or "apple-clang")'
conan_profile:
description: Conan profile to use
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
@@ -51,49 +45,65 @@ jobs:
if: ${{ inputs.run_unit_tests }}
env:
# TODO: remove completely when we have fixed all currently existing issues with sanitizers
SANITIZER_IGNORE_ERRORS: ${{ endsWith(inputs.conan_profile, '.tsan') }}
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- name: Generate build identifier
uses: ./.github/actions/build-identifier
id: build_identifier
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
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_${{ steps.build_identifier.outputs.build_identifier }}
name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
- name: Make clio_tests executable
run: chmod +x ./clio_tests
- name: Run clio_tests
continue-on-error: true
id: run_clio_tests
- name: Run clio_tests (regular)
if: ${{ env.SANITIZER_IGNORE_ERRORS == 'false' }}
run: ./clio_tests
- name: Create an issue
if: ${{ steps.run_clio_tests.outcome == 'failure' && inputs.sanitizers != '' }}
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
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"
- name: Run clio_tests (sanitizer errors ignored)
if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' }}
run: ./.github/scripts/execute-tests-under-sanitizer.sh ./clio_tests
- name: Fail the job if clio_tests failed
if: ${{ steps.run_clio_tests.outcome == 'failure' }}
run: exit 1
- name: Check for sanitizer report
if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' }}
id: check_report
run: |
if ls .sanitizer-report/* 1> /dev/null 2>&1; then
echo "found_report=true" >> $GITHUB_OUTPUT
else
echo "found_report=false" >> $GITHUB_OUTPUT
fi
- name: Upload sanitizer report
if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' && steps.check_report.outputs.found_report == 'true' }}
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: sanitizer_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: .sanitizer-report/*
include-hidden-files: true
- name: Create an issue
if: ${{ false && env.SANITIZER_IGNORE_ERRORS == 'true' && steps.check_report.outputs.found_report == 'true' }}
uses: ./.github/actions/create-issue
env:
GH_TOKEN: ${{ github.token }}
with:
labels: "bug"
title: "[${{ inputs.conan_profile }}] reported issues"
body: >
Clio tests failed one or more sanitizer checks when built with ${{ inputs.conan_profile }}`.
Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
Reports are available as artifacts.
integration_tests:
name: Integration testing
@@ -114,61 +124,37 @@ jobs:
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf
- 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
- name: Restart colima
if: ${{ runner.os == 'macOS' }}
run: |
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.
- name: Spin up scylladb
if: ${{ runner.os == 'macOS' }}
run: docker rm --force scylladb || true
- name: Spin up scylladb (macOS)
if: ${{ runner.os == 'macOS' }}
timeout-minutes: 1
timeout-minutes: 3
run: |
docker rm --force scylladb || true
docker run \
--detach \
--name scylladb \
--health-cmd "cqlsh -e 'describe cluster'" \
--health-interval 10s \
--health-timeout 5s \
--health-retries 5 \
--publish 9042:9042 \
--memory 16G \
scylladb/scylla
--detach \
--name scylladb \
--health-cmd "cqlsh -e 'describe cluster'" \
--health-interval 10s \
--health-timeout 5s \
--health-retries 5 \
--publish 9042:9042 \
--memory 16G \
scylladb/scylla
- name: Wait for scylladb container to be healthy (macOS)
if: ${{ runner.os == 'macOS' }}
timeout-minutes: 1
run: |
until [ "$(docker inspect -f '{{.State.Health.Status}}' scylladb)" == "healthy" ]; do
sleep 1
sleep 5
done
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: clio_integration_tests_${{ steps.build_identifier.outputs.build_identifier }}
name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
- name: Run clio_integration_tests
run: |

View File

@@ -16,19 +16,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- name: Download report artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: coverage-report.xml
path: build
- name: Upload coverage report
if: ${{ github.repository == 'XRPLF/clio' && hashFiles('build/coverage_report.xml') != '' }}
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
if: ${{ hashFiles('build/coverage_report.xml') != '' }}
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
with:
files: build/coverage_report.xml
fail_ci_if_error: true

View File

@@ -14,12 +14,14 @@ on:
- ".github/actions/**"
- "!.github/actions/build-docker-image/**"
- "!.github/actions/create-issue/**"
- .github/scripts/execute-tests-under-sanitizer.sh
- CMakeLists.txt
- conanfile.py
- conan.lock
- "cmake/**"
# We don't run sanitizers on code change, because it takes too long
# We don't run sanitizer on code change, because it takes too long
# - "src/**"
# - "tests/**"
@@ -36,18 +38,18 @@ jobs:
fail-fast: false
matrix:
compiler: [gcc, clang]
sanitizers: [address, thread, undefinedbehavior]
sanitizer_ext: [.asan, .tsan, .ubsan]
build_type: [Release, Debug]
uses: ./.github/workflows/reusable-build-test.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553" }'
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
download_ccache: false
upload_ccache: false
compiler: ${{ matrix.compiler }}
sanitizers: ${{ matrix.sanitizers }}
conan_profile: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
build_type: ${{ matrix.build_type }}
static: false
run_unit_tests: true
run_integration_tests: false
upload_clio_server: false

371
.github/workflows/update-docker-ci.yml vendored Normal file
View File

@@ -0,0 +1,371 @@
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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
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.event_name != 'pull_request' }}
directory: docker/compilers/gcc
tags: |
type=raw,value=latest
type=raw,value=${{ env.GCC_MAJOR_VERSION }}
type=raw,value=${{ env.GCC_VERSION }}
type=raw,value=${{ 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:
if: false
name: Build and push GCC docker image (arm64)
runs-on: heavy-arm64
needs: repo
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
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.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:
if: false
name: Merge and push multi-arch GCC docker image
runs-on: heavy
needs: [repo, gcc-amd64, gcc-arm64]
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
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_owner == 'XRPLF' && 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_owner }} == 'XRPLF' ]]; then
push_image rippleci/clio_gcc
fi
clang:
name: Build and push Clang docker image
runs-on: heavy
needs: repo
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
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.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
platforms: linux/amd64
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-amd64]
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
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.event_name != 'pull_request' }}
directory: docker/tools
tags: |
type=raw,value=latest
type=raw,value=${{ github.sha }}
platforms: linux/amd64
build_args: |
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
GCC_VERSION=${{ env.GCC_VERSION }}
tools-arm64:
if: false
name: Build and push tools docker image (arm64)
runs-on: heavy-arm64
needs: [repo, gcc-amd64]
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
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.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:
if: false
name: Merge and push multi-arch tools docker image
runs-on: heavy
needs: [repo, tools-amd64, tools-arm64]
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
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-amd64]
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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.event_name != 'pull_request' }}
directory: docker/pre-commit
tags: |
type=raw,value=latest
type=raw,value=${{ github.sha }}
# platforms: linux/amd64,linux/arm64
platforms: linux/amd64
build_args: |
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
ci:
name: Build and push CI docker image
runs-on: heavy
needs: [repo, gcc-amd64, clang, tools-amd64]
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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.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
platforms: linux/amd64
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.

View File

@@ -52,14 +52,14 @@ jobs:
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Calculate conan matrix
id: set-matrix
run: .github/scripts/conan/generate_matrix.py >>"${GITHUB_OUTPUT}"
run: .github/scripts/conan/generate_matrix.py >> "${GITHUB_OUTPUT}"
upload-conan-deps:
name: Build ${{ matrix.compiler }} ${{ matrix.sanitizers }} ${{ matrix.build_type }}
name: Build ${{ matrix.compiler }}${{ matrix.sanitizer_ext }} ${{ matrix.build_type }}
needs: generate-matrix
@@ -71,46 +71,39 @@ 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
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
enable_ccache: false
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
- 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: Setup conan on macOS
if: ${{ runner.os == 'macOS' }}
run: ./.github/scripts/conan/init.sh
- name: Show conan profile
env:
SANITIZERS: ${{ matrix.sanitizers }}
run: conan profile show --profile:all ci
run: conan profile show --profile:all ${{ env.CONAN_PROFILE }}
- name: Run conan
uses: ./.github/actions/conan
with:
sanitizers: ${{ matrix.sanitizers }}
conan_profile: ${{ env.CONAN_PROFILE }}
# 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' }}
build_type: ${{ matrix.build_type }}
- name: Log into Conan remote
if: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }}
- name: Login to Conan
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' }}
run: conan remote login -p ${{ secrets.CONAN_PASSWORD }} xrplf ${{ secrets.CONAN_USERNAME }}
- name: Upload Conan packages
if: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' && github.event_name != 'schedule' }}
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' && github.event_name != 'schedule' }}
env:
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
run: conan upload "*" -r=xrplf --confirm ${FORCE_OPTION}

5
.gitignore vendored
View File

@@ -4,13 +4,8 @@
.build
.cache
.vscode
.zed
.python-version
.DS_Store
.sanitizer-report
CMakeUserPresets.json
config.json
CLAUDE.md
.claude/**
.agents/**
.augment/**

View File

@@ -29,18 +29,18 @@ repos:
# Autoformat: YAML, JSON, Markdown, etc.
- repo: https://github.com/rbubley/mirrors-prettier
rev: 515f543f5718ebfd6ce22e16708bb32c68ff96e1 # frozen: v3.8.3
rev: 14abee445aea04b39069c19b4bd54efff6775819 # frozen: v3.7.4
hooks:
- id: prettier
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: e72a3ca1632f0b11a07d171449fe447a7ff6795e # frozen: v0.48.0
rev: 76b3d32d3f4b965e1d6425253c59407420ae2c43 # frozen: v0.47.0
hooks:
- id: markdownlint-fix
exclude: LICENSE.md
- repo: https://github.com/hadolint/hadolint
rev: 57e1618d78fd469a92c1e584e8c9313024656623 # frozen: v2.14.0
rev: 4e697ba704fd23b2409b947a319c19c3ee54d24f # frozen: v2.14.0
hooks:
- id: hadolint-docker
# hadolint-docker is a special hook that runs hadolint in a Docker container
@@ -49,7 +49,7 @@ repos:
entry: hadolint/hadolint:v2.14.0 hadolint
- repo: https://github.com/codespell-project/codespell
rev: 2ccb47ff45ad361a21071a7eedda4c37e6ae8c5a # frozen: v2.4.2
rev: 63c8f8312b7559622c0d82815639671ae42132ac # frozen: v2.4.1
hooks:
- id: codespell
args:
@@ -59,15 +59,15 @@ repos:
]
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 4160603246a6b365d4a2af661c6d71b0a0f50478 # frozen: 26.5.1
rev: 831207fd435b47aeffdf6af853097e64322b4d44 # frozen: 25.12.0
hooks:
- id: black
- repo: https://github.com/scop/pre-commit-shfmt
rev: 05c1426671b9237fb5e1444dd63aa5731bec0dfb # frozen: v3.13.1-1
rev: 2a30809d16bc7a60d9b97353c797f42b510d3368 # frozen: v3.12.0-2
hooks:
- id: shfmt
args: [--write, --indent=4, --case-indent=true]
args: ["-i", "4", "--write"]
# Running some C++ hooks before clang-format
# to ensure that the style is consistent.
@@ -94,16 +94,17 @@ repos:
language: script
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
rev: 75ca4ad908dc4a99f57921f29b7e6c1521e10b26 # frozen: v21.1.8
hooks:
- id: clang-format
args: [--style=file]
types: [c++]
- repo: https://github.com/BlankSpruce/gersemi-pre-commit
rev: e98930bdc210d3387007f9252d8c1694ea7e410f # frozen: 0.27.7
- repo: https://github.com/cheshirekow/cmake-format-precommit
rev: e2c2116d86a80e72e7146a06e68b7c228afc6319 # frozen: v0.6.13
hooks:
- id: gersemi
- id: cmake-format
additional_dependencies: [PyYAML]
- repo: local
hooks:

View File

@@ -1,10 +1,7 @@
cmake_minimum_required(VERSION 3.20)
project(
clio
VERSION ${CLIO_VERSION}
HOMEPAGE_URL "https://github.com/XRPLF/clio"
DESCRIPTION "An XRP Ledger API Server"
project(clio VERSION ${CLIO_VERSION} HOMEPAGE_URL "https://github.com/XRPLF/clio"
DESCRIPTION "An XRP Ledger API Server"
)
# =========================== Options ====================================== #
@@ -16,15 +13,15 @@ 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
"Build using -ftime-trace to create compiler trace reports"
FALSE
)
option(time_trace "Build using -ftime-trace to create compiler trace reports" FALSE)
# ========================================================================== #
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})
@@ -38,30 +35,14 @@ 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()
if (verbose)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
endif ()
# Clio tweaks and checks
include(CheckCompiler)
include(Settings)
include(SourceLocation)
include(PatchNixBinary)
# Clio deps
include(deps/libxrpl)
@@ -76,20 +57,37 @@ include(deps/spdlog)
add_subdirectory(src)
add_subdirectory(tests)
if(benchmark)
add_subdirectory(benchmarks)
endif()
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)
endif()
if (docs)
add_subdirectory(docs)
endif ()
include(install/install)
if(package)
include(ClioPackage)
endif()
if (package)
include(ClioPackage)
endif ()
if(snapshot)
add_subdirectory(tools/snapshot)
endif()
if (snapshot)
add_subdirectory(tools/snapshot)
endif ()

View File

@@ -133,7 +133,7 @@ This is a non-exhaustive list of recommended style guidelines. These are not alw
Code must conform to `clang-format`, unless the result is unreasonably difficult to read or maintain.
In most cases the `pre-commit` hook takes care of formatting and fixes any issues automatically.
To manually format your code, run `pre-commit run clang-format --files <your changed files>` for C++ files, and `pre-commit run gersemi --files <your changed files>` for CMake files.
To manually format your code, run `pre-commit run clang-format --files <your changed files>` for C++ files, and `pre-commit run cmake-format --files <your changed files>` for CMake files.
### Documentation

View File

@@ -1,6 +1,6 @@
ISC License
Copyright (c) 2022-present, the clio developers
Copyright (c) 2022, the clio developers
Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

View File

@@ -1,27 +1,20 @@
add_executable(clio_benchmark)
target_sources(
clio_benchmark
PRIVATE
# Common
Main.cpp
Playground.cpp
# ExecutionContext
util/async/ExecutionContextBenchmarks.cpp
# Logger
util/log/LoggerBenchmark.cpp
# WorkQueue
rpc/WorkQueueBenchmarks.cpp
clio_benchmark
PRIVATE # Common
Main.cpp
Playground.cpp
# ExecutionContext
util/async/ExecutionContextBenchmarks.cpp
# Logger
util/log/LoggerBenchmark.cpp
# WorkQueue
rpc/WorkQueueBenchmarks.cpp
)
include(deps/gbench)
target_include_directories(clio_benchmark PRIVATE .)
target_link_libraries(
clio_benchmark
PRIVATE clio_rpc clio_util benchmark::benchmark_main spdlog::spdlog
)
set_target_properties(
clio_benchmark
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
target_link_libraries(clio_benchmark PUBLIC clio_util clio_rpc benchmark::benchmark_main spdlog::spdlog)
set_target_properties(clio_benchmark PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2023, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <benchmark/benchmark.h>
BENCHMARK_MAIN();

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2023, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
/*
* Use this file for temporary benchmarks and implementations.
* Usage example:

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2025, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "rpc/WorkQueue.hpp"
#include "util/Assert.hpp"
#include "util/config/Array.hpp"
@@ -10,6 +29,8 @@
#include <benchmark/benchmark.h>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/thread_pool.hpp>
#include <boost/json/object.hpp>
#include <algorithm>
#include <atomic>
@@ -26,21 +47,18 @@ using namespace util::config;
namespace {
auto const kConfig = ClioConfigDefinition{
auto const kCONFIG = ClioConfigDefinition{
{"prometheus.compress_reply", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
{"prometheus.enabled", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
{"log.channels.[].channel", Array{ConfigValue{ConfigType::String}}},
{"log.channels.[].level", Array{ConfigValue{ConfigType::String}}},
{"log.level", ConfigValue{ConfigType::String}.defaultValue("info")},
{"log.format",
ConfigValue{ConfigType::String}.defaultValue(R"(%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v)")},
{"log.format", ConfigValue{ConfigType::String}.defaultValue(R"(%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v)")},
{"log.is_async", ConfigValue{ConfigType::Boolean}.defaultValue(false)},
{"log.enable_console", ConfigValue{ConfigType::Boolean}.defaultValue(false)},
{"log.directory", ConfigValue{ConfigType::String}.optional()},
{"log.rotation_size",
ConfigValue{ConfigType::Integer}.defaultValue(2048).withConstraint(gValidateUint32)},
{"log.directory_max_files",
ConfigValue{ConfigType::Integer}.defaultValue(25).withConstraint(gValidateUint32)},
{"log.rotation_size", ConfigValue{ConfigType::Integer}.defaultValue(2048).withConstraint(gValidateUint32)},
{"log.directory_max_files", ConfigValue{ConfigType::Integer}.defaultValue(25).withConstraint(gValidateUint32)},
{"log.tag_style", ConfigValue{ConfigType::String}.defaultValue("none")},
};
@@ -48,10 +66,10 @@ auto const kConfig = ClioConfigDefinition{
void
init()
{
static std::once_flag kOnce;
std::call_once(kOnce, [] {
PrometheusService::init(kConfig);
(void)util::LogService::init(kConfig);
static std::once_flag kONCE;
std::call_once(kONCE, [] {
PrometheusService::init(kCONFIG);
(void)util::LogService::init(kCONFIG);
});
}
@@ -108,14 +126,9 @@ benchmarkWorkQueue(benchmark::State& state)
ASSERT(totalQueued <= itemsPerClient * clientThreads, "Queued more than requested");
if (maxQueueSize == 0) {
ASSERT(
totalQueued == itemsPerClient * clientThreads, "Queued exactly the expected amount"
);
ASSERT(totalQueued == itemsPerClient * clientThreads, "Queued exactly the expected amount");
} else {
ASSERT(
totalQueued >= std::min(maxQueueSize, itemsPerClient * clientThreads),
"Queued less than expected"
);
ASSERT(totalQueued >= std::min(maxQueueSize, itemsPerClient * clientThreads), "Queued less than expected");
}
}
}

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "etl/ETLHelpers.hpp"
#include "util/Random.hpp"
#include "util/async/AnyExecutionContext.hpp"
@@ -169,11 +188,11 @@ public:
static auto
generateData()
{
constexpr auto kTotal = 10'000;
constexpr auto kTOTAL = 10'000;
std::vector<uint64_t> data;
data.reserve(kTotal);
data.reserve(kTOTAL);
util::MTRandomGenerator randomGenerator;
for (auto i = 0; i < kTotal; ++i)
for (auto i = 0; i < kTOTAL; ++i)
data.push_back(randomGenerator.uniform(1, 100'000'000));
return data;

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2025, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "util/config/ConfigDefinition.hpp"
#include "util/log/Logger.hpp"
#include "util/prometheus/Prometheus.hpp"
@@ -11,7 +30,6 @@
#include <barrier>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <memory>
#include <string>
@@ -21,19 +39,13 @@
using namespace util;
static constexpr auto kLogFormat = "%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v";
static constexpr auto kLOG_FORMAT = "%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v";
struct BenchmarkLoggingInitializer {
[[nodiscard]] static std::shared_ptr<spdlog::sinks::sink>
createFileSink(std::string const& logDir, uint32_t sizeMB, uint32_t maxFiles)
createFileSink(LogService::FileLoggingParams const& params)
{
return LogService::createFileSink(
LogService::FileLoggingParams{
.logDir = logDir,
.rotation = LogService::RotationParams{.sizeMB = sizeMB, .maxFiles = maxFiles},
},
kLogFormat
);
return LogService::createFileSink(params, kLOG_FORMAT);
}
static Logger
@@ -50,9 +62,8 @@ uniqueLogDir()
{
auto const epochTime = std::chrono::high_resolution_clock::now().time_since_epoch();
auto const tmpDir = std::filesystem::temp_directory_path();
std::string const dirName = fmt::format(
"logs_{}", std::chrono::duration_cast<std::chrono::microseconds>(epochTime).count()
);
std::string const dirName =
fmt::format("logs_{}", std::chrono::duration_cast<std::chrono::microseconds>(epochTime).count());
return tmpDir / "clio_benchmark" / dirName;
}
@@ -71,11 +82,15 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
state.PauseTiming();
std::filesystem::create_directories(logDir);
static constexpr size_t kQueueSize = 8192;
static constexpr size_t kThreadCount = 1;
spdlog::init_thread_pool(kQueueSize, kThreadCount);
static constexpr size_t kQUEUE_SIZE = 8192;
static constexpr size_t kTHREAD_COUNT = 1;
spdlog::init_thread_pool(kQUEUE_SIZE, kTHREAD_COUNT);
auto fileSink = BenchmarkLoggingInitializer::createFileSink(logDir, 5, 25);
auto fileSink = BenchmarkLoggingInitializer::createFileSink({
.logDir = logDir,
.rotationSizeMB = 5,
.dirMaxFiles = 25,
});
std::vector<std::thread> threads;
threads.reserve(numThreads);
@@ -93,8 +108,7 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
channel, fileSink, spdlog::thread_pool(), spdlog::async_overflow_policy::block
);
spdlog::register_logger(logger);
Logger const threadLogger =
BenchmarkLoggingInitializer::getLogger(std::move(logger));
Logger const threadLogger = BenchmarkLoggingInitializer::getLogger(std::move(logger));
barrier.arrive_and_wait();
@@ -110,16 +124,13 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
spdlog::shutdown();
auto const end = std::chrono::high_resolution_clock::now();
state.SetIterationTime(
std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count()
);
state.SetIterationTime(std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count());
std::filesystem::remove_all(logDir);
}
auto const totalMessages = numThreads * messagesPerThread;
state.counters["TotalMessagesRate"] =
benchmark::Counter(totalMessages, benchmark::Counter::kIsRate);
state.counters["TotalMessagesRate"] = benchmark::Counter(totalMessages, benchmark::Counter::kIsRate);
state.counters["Threads"] = numThreads;
state.counters["MessagesPerThread"] = messagesPerThread;
}

View File

@@ -1,5 +1,5 @@
find_program(CCACHE_PATH "ccache")
if(CCACHE_PATH)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PATH}")
message(STATUS "Using ccache: ${CCACHE_PATH}")
endif()
if (CCACHE_PATH)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PATH}")
message(STATUS "Using ccache: ${CCACHE_PATH}")
endif ()

View File

@@ -1,21 +1,42 @@
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
message(FATAL_ERROR "Clang 16+ required for building clio")
endif()
set(is_clang TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
message(FATAL_ERROR "AppleClang 15+ required for building clio")
endif()
set(is_appleclang TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12)
message(FATAL_ERROR "GCC 12+ required for building clio")
endif()
set(is_gcc TRUE)
else()
message(
FATAL_ERROR
"Supported compilers: AppleClang 15+, Clang 16+, GCC 12+"
)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
message(FATAL_ERROR "Clang 16+ required for building clio")
endif ()
set(is_clang TRUE)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
message(FATAL_ERROR "AppleClang 15+ required for building clio")
endif ()
set(is_appleclang TRUE)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12)
message(FATAL_ERROR "GCC 12+ required for building clio")
endif ()
set(is_gcc TRUE)
else ()
message(FATAL_ERROR "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 ()

View File

@@ -1,41 +1,33 @@
if(lint)
# Find clang-tidy binary
if(DEFINED ENV{CLIO_CLANG_TIDY_BIN})
set(_CLANG_TIDY_BIN $ENV{CLIO_CLANG_TIDY_BIN})
if((NOT EXISTS ${_CLANG_TIDY_BIN}) OR IS_DIRECTORY ${_CLANG_TIDY_BIN})
message(
FATAL_ERROR
"$ENV{CLIO_CLANG_TIDY_BIN} no such file. Check CLIO_CLANG_TIDY_BIN env variable"
)
endif()
message(STATUS "Using clang-tidy from CLIO_CLANG_TIDY_BIN")
else()
find_program(
_CLANG_TIDY_BIN
NAMES "clang-tidy-20" "clang-tidy"
REQUIRED
)
endif()
if (lint)
if(NOT _CLANG_TIDY_BIN)
message(
FATAL_ERROR
"clang-tidy binary not found. Please set the CLIO_CLANG_TIDY_BIN environment variable or install clang-tidy."
)
endif()
# Find clang-tidy binary
if (DEFINED ENV{CLIO_CLANG_TIDY_BIN})
set(_CLANG_TIDY_BIN $ENV{CLIO_CLANG_TIDY_BIN})
if ((NOT EXISTS ${_CLANG_TIDY_BIN}) OR IS_DIRECTORY ${_CLANG_TIDY_BIN})
message(FATAL_ERROR "$ENV{CLIO_CLANG_TIDY_BIN} no such file. Check CLIO_CLANG_TIDY_BIN env variable")
endif ()
message(STATUS "Using clang-tidy from CLIO_CLANG_TIDY_BIN")
else ()
find_program(_CLANG_TIDY_BIN NAMES "clang-tidy-20" "clang-tidy" REQUIRED)
endif ()
# Support for https://github.com/matus-chochlik/ctcache
find_program(CLANG_TIDY_CACHE_PATH NAMES "clang-tidy-cache")
if(CLANG_TIDY_CACHE_PATH)
set(_CLANG_TIDY_CMD
"${CLANG_TIDY_CACHE_PATH};${_CLANG_TIDY_BIN}"
CACHE STRING
"A combined command to run clang-tidy with caching wrapper"
)
else()
set(_CLANG_TIDY_CMD "${_CLANG_TIDY_BIN}")
endif()
if (NOT _CLANG_TIDY_BIN)
message(
FATAL_ERROR
"clang-tidy binary not found. Please set the CLIO_CLANG_TIDY_BIN environment variable or install clang-tidy."
)
endif ()
set(CMAKE_CXX_CLANG_TIDY "${_CLANG_TIDY_CMD};--quiet")
message(STATUS "Using clang-tidy: ${CMAKE_CXX_CLANG_TIDY}")
endif()
# Support for https://github.com/matus-chochlik/ctcache
find_program(CLANG_TIDY_CACHE_PATH NAMES "clang-tidy-cache")
if (CLANG_TIDY_CACHE_PATH)
set(_CLANG_TIDY_CMD "${CLANG_TIDY_CACHE_PATH};${_CLANG_TIDY_BIN}"
CACHE STRING "A combined command to run clang-tidy with caching wrapper"
)
else ()
set(_CLANG_TIDY_CMD "${_CLANG_TIDY_BIN}")
endif ()
set(CMAKE_CXX_CLANG_TIDY "${_CLANG_TIDY_CMD};--quiet")
message(STATUS "Using clang-tidy: ${CMAKE_CXX_CLANG_TIDY}")
endif ()

View File

@@ -1,67 +1,47 @@
find_package(Git REQUIRED)
if(DEFINED ENV{GITHUB_BRANCH_NAME})
set(GIT_BUILD_BRANCH $ENV{GITHUB_BRANCH_NAME})
set(GIT_COMMIT_HASH $ENV{GITHUB_HEAD_SHA})
else()
set(GIT_COMMAND branch --show-current)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BUILD_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
if (DEFINED ENV{GITHUB_BRANCH_NAME})
set(GIT_BUILD_BRANCH $ENV{GITHUB_BRANCH_NAME})
set(GIT_COMMIT_HASH $ENV{GITHUB_HEAD_SHA})
else ()
set(GIT_COMMAND branch --show-current)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_BUILD_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
)
set(GIT_COMMAND rev-parse HEAD)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
endif()
set(GIT_COMMAND rev-parse HEAD)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
)
endif ()
execute_process(
COMMAND date +%Y%m%d%H%M%S
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_DATE
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
COMMAND date +%Y%m%d%H%M%S WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE BUILD_DATE
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
)
message(STATUS "Git branch: ${GIT_BUILD_BRANCH}")
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}")
message(STATUS "Build date: ${BUILD_DATE}")
if(
DEFINED ENV{FORCE_CLIO_VERSION}
AND NOT "$ENV{FORCE_CLIO_VERSION}" STREQUAL ""
)
message(
STATUS
"Using explicitly provided '${FORCE_CLIO_VERSION}' as Clio version"
)
if (DEFINED ENV{FORCE_CLIO_VERSION} AND NOT "$ENV{FORCE_CLIO_VERSION}" STREQUAL "")
message(STATUS "Using explicitly provided '${FORCE_CLIO_VERSION}' as Clio version")
set(CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}")
set(DOC_CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}")
else()
message(
STATUS
"Using 'YYYYMMDDHMS-<branch>-<git short rev>' as Clio version"
)
set(CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}")
set(DOC_CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}")
else ()
message(STATUS "Using 'YYYYMMDDHMS-<branch>-<git short rev>' as Clio version")
string(SUBSTRING ${GIT_COMMIT_HASH} 0 7 GIT_COMMIT_HASH_SHORT)
string(SUBSTRING ${GIT_COMMIT_HASH} 0 7 GIT_COMMIT_HASH_SHORT)
set(CLIO_VERSION
"${BUILD_DATE}-${GIT_BUILD_BRANCH}-${GIT_COMMIT_HASH_SHORT}"
)
set(DOC_CLIO_VERSION "develop")
endif()
set(CLIO_VERSION "${BUILD_DATE}-${GIT_BUILD_BRANCH}-${GIT_COMMIT_HASH_SHORT}")
set(DOC_CLIO_VERSION "develop")
endif ()
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(CLIO_VERSION "${CLIO_VERSION}+DEBUG")
endif()
if (CMAKE_BUILD_TYPE MATCHES Debug)
set(CLIO_VERSION "${CLIO_VERSION}+DEBUG")
endif ()
message(STATUS "Build version: ${CLIO_VERSION}")

View File

@@ -106,120 +106,78 @@ option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
# Check prereqs
find_program(GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
if(DEFINED CODE_COVERAGE_GCOV_TOOL)
set(GCOV_TOOL "${CODE_COVERAGE_GCOV_TOOL}")
elseif(DEFINED ENV{CODE_COVERAGE_GCOV_TOOL})
set(GCOV_TOOL "$ENV{CODE_COVERAGE_GCOV_TOOL}")
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if(APPLE)
execute_process(
COMMAND xcrun -f llvm-cov
OUTPUT_VARIABLE LLVMCOV_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else()
find_program(LLVMCOV_PATH llvm-cov)
endif()
if(LLVMCOV_PATH)
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
find_program(GCOV_PATH gcov)
set(GCOV_TOOL "${GCOV_PATH}")
endif()
if (DEFINED CODE_COVERAGE_GCOV_TOOL)
set(GCOV_TOOL "${CODE_COVERAGE_GCOV_TOOL}")
elseif (DEFINED ENV{CODE_COVERAGE_GCOV_TOOL})
set(GCOV_TOOL "$ENV{CODE_COVERAGE_GCOV_TOOL}")
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if (APPLE)
execute_process(COMMAND xcrun -f llvm-cov OUTPUT_VARIABLE LLVMCOV_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
else ()
find_program(LLVMCOV_PATH llvm-cov)
endif ()
if (LLVMCOV_PATH)
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
endif ()
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
find_program(GCOV_PATH gcov)
set(GCOV_TOOL "${GCOV_PATH}")
endif ()
# Check supported compiler (Clang, GNU and Flang)
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(LANG ${LANGUAGES})
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
message(
FATAL_ERROR
"Clang version must be 3.0.0 or greater! Aborting..."
)
endif()
elseif(
NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang"
)
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
endif()
endforeach()
foreach (LANG ${LANGUAGES})
if ("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if ("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
endif ()
elseif (NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU" AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES
"(LLVM)?[Ff]lang"
)
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
endif ()
endforeach ()
set(COVERAGE_COMPILER_FLAGS "-g --coverage" CACHE INTERNAL "")
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
if(HAVE_cxx_fprofile_abs_path)
set(COVERAGE_CXX_COMPILER_FLAGS
"${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path"
)
endif()
include(CheckCCompilerFlag)
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
if(HAVE_c_fprofile_abs_path)
set(COVERAGE_C_COMPILER_FLAGS
"${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path"
)
endif()
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
if (HAVE_cxx_fprofile_abs_path)
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
endif ()
include(CheckCCompilerFlag)
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
if (HAVE_c_fprofile_abs_path)
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
endif ()
endif ()
set(CMAKE_Fortran_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING
"Flags used by the Fortran compiler during coverage builds."
FORCE
set(CMAKE_Fortran_FLAGS_COVERAGE ${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the Fortran compiler during coverage builds." FORCE
)
set(CMAKE_CXX_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING
"Flags used by the C++ compiler during coverage builds."
FORCE
set(CMAKE_CXX_FLAGS_COVERAGE ${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C++ compiler during coverage builds." FORCE
)
set(CMAKE_C_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING
"Flags used by the C compiler during coverage builds."
FORCE
set(CMAKE_C_FLAGS_COVERAGE ${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C compiler during coverage builds." FORCE
)
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
""
CACHE STRING
"Flags used for linking binaries during coverage builds."
FORCE
)
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
""
CACHE STRING
"Flags used by the shared libraries linker during coverage builds."
FORCE
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "" CACHE STRING "Flags used for linking binaries during coverage builds." FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE ""
CACHE STRING "Flags used by the shared libraries linker during coverage builds." FORCE
)
mark_as_advanced(
CMAKE_Fortran_FLAGS_COVERAGE
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE
CMAKE_Fortran_FLAGS_COVERAGE CMAKE_CXX_FLAGS_COVERAGE CMAKE_C_FLAGS_COVERAGE CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE
)
get_property(
GENERATOR_IS_MULTI_CONFIG
GLOBAL
PROPERTY GENERATOR_IS_MULTI_CONFIG
)
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
message(
WARNING
"Code coverage results with an optimised (non-Debug) build may be misleading"
)
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if (NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
endif () # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
if(
CMAKE_C_COMPILER_ID STREQUAL "GNU"
OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU"
)
link_libraries(gcov)
endif()
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
link_libraries(gcov)
endif ()
# Defines a target for running and collection code coverage information Builds dependencies, runs the given executable
# and outputs reports. NOTE! The executable should always have a ZERO as exit code otherwise the coverage generation
@@ -233,236 +191,171 @@ endif()
# defaults to xml) EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative # to BASE_DIRECTORY,
# with CMake 3.4+) ) The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the GCVOR
# command.
function(setup_target_for_coverage_gcovr)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME FORMAT)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(
Coverage
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
function (setup_target_for_coverage_gcovr)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME FORMAT)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOV_TOOL)
message(FATAL_ERROR "Could not find gcov or llvm-cov tool! Aborting...")
endif()
if (NOT GCOV_TOOL)
message(FATAL_ERROR "Could not find gcov or llvm-cov tool! Aborting...")
endif ()
if(NOT GCOVR_PATH)
message(FATAL_ERROR "Could not find gcovr tool! Aborting...")
endif()
if (NOT GCOVR_PATH)
message(FATAL_ERROR "Could not find gcovr tool! Aborting...")
endif ()
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if (DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else ()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif ()
if(NOT DEFINED Coverage_FORMAT)
set(Coverage_FORMAT xml)
endif()
if (NOT DEFINED Coverage_FORMAT)
set(Coverage_FORMAT xml)
endif ()
if("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
message(
FATAL_ERROR
"Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting..."
)
else()
if(
(Coverage_FORMAT STREQUAL "html-details")
OR (Coverage_FORMAT STREQUAL "html-nested")
)
set(GCOVR_OUTPUT_FILE
${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html
)
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
elseif(Coverage_FORMAT STREQUAL "html-single")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
elseif(
(Coverage_FORMAT STREQUAL "json-summary")
OR (Coverage_FORMAT STREQUAL "json-details")
if ("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting...")
else ()
if ((Coverage_FORMAT STREQUAL "html-details") OR (Coverage_FORMAT STREQUAL "html-nested"))
set(GCOVR_OUTPUT_FILE ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html)
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
elseif (Coverage_FORMAT STREQUAL "html-single")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
elseif ((Coverage_FORMAT STREQUAL "json-summary") OR (Coverage_FORMAT STREQUAL "json-details")
OR (Coverage_FORMAT STREQUAL "coveralls")
)
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
elseif(Coverage_FORMAT STREQUAL "txt")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
elseif(Coverage_FORMAT STREQUAL "csv")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
else()
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
endif()
endif()
if(
(Coverage_FORMAT STREQUAL "cobertura")
OR (Coverage_FORMAT STREQUAL "xml")
)
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty)
set(Coverage_FORMAT cobertura) # overwrite xml
elseif(Coverage_FORMAT STREQUAL "sonarqube")
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}")
elseif(Coverage_FORMAT STREQUAL "json-summary")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
elseif(Coverage_FORMAT STREQUAL "json-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --json "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
elseif(Coverage_FORMAT STREQUAL "coveralls")
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
elseif(Coverage_FORMAT STREQUAL "csv")
list(APPEND GCOVR_ADDITIONAL_ARGS --csv "${GCOVR_OUTPUT_FILE}")
elseif(Coverage_FORMAT STREQUAL "txt")
list(APPEND GCOVR_ADDITIONAL_ARGS --txt "${GCOVR_OUTPUT_FILE}")
elseif(Coverage_FORMAT STREQUAL "html-single")
list(APPEND GCOVR_ADDITIONAL_ARGS --html "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-self-contained)
elseif(Coverage_FORMAT STREQUAL "html-nested")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-nested "${GCOVR_OUTPUT_FILE}")
elseif(Coverage_FORMAT STREQUAL "html-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details "${GCOVR_OUTPUT_FILE}")
else()
message(
FATAL_ERROR
"Unsupported output style ${Coverage_FORMAT}! Aborting..."
)
endif()
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
elseif (Coverage_FORMAT STREQUAL "txt")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
elseif (Coverage_FORMAT STREQUAL "csv")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
else ()
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
endif ()
endif ()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(
EXCLUDE
${Coverage_EXCLUDE}
${COVERAGE_EXCLUDES}
${COVERAGE_GCOVR_EXCLUDES}
)
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(
EXCLUDE
${EXCLUDE}
ABSOLUTE
BASE_DIR ${BASEDIR}
)
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
if ((Coverage_FORMAT STREQUAL "cobertura") OR (Coverage_FORMAT STREQUAL "xml"))
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty)
set(Coverage_FORMAT cobertura) # overwrite xml
elseif (Coverage_FORMAT STREQUAL "sonarqube")
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}")
elseif (Coverage_FORMAT STREQUAL "json-summary")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
elseif (Coverage_FORMAT STREQUAL "json-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --json "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
elseif (Coverage_FORMAT STREQUAL "coveralls")
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
elseif (Coverage_FORMAT STREQUAL "csv")
list(APPEND GCOVR_ADDITIONAL_ARGS --csv "${GCOVR_OUTPUT_FILE}")
elseif (Coverage_FORMAT STREQUAL "txt")
list(APPEND GCOVR_ADDITIONAL_ARGS --txt "${GCOVR_OUTPUT_FILE}")
elseif (Coverage_FORMAT STREQUAL "html-single")
list(APPEND GCOVR_ADDITIONAL_ARGS --html "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-self-contained)
elseif (Coverage_FORMAT STREQUAL "html-nested")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-nested "${GCOVR_OUTPUT_FILE}")
elseif (Coverage_FORMAT STREQUAL "html-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details "${GCOVR_OUTPUT_FILE}")
else ()
message(FATAL_ERROR "Unsupported output style ${Coverage_FORMAT}! Aborting...")
endif ()
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach (EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if (CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif ()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach ()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Set up commands which will be run to generate coverage data Run tests
set(GCOVR_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach (EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach ()
# Create folder
if(DEFINED GCOVR_CREATE_FOLDER)
set(GCOVR_FOLDER_CMD
${CMAKE_COMMAND}
-E
make_directory
${GCOVR_CREATE_FOLDER}
)
else()
set(GCOVR_FOLDER_CMD echo) # dummy
endif()
# Set up commands which will be run to generate coverage data Run tests
set(GCOVR_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
# Running gcovr
set(GCOVR_CMD
${GCOVR_PATH}
--gcov-executable
${GCOV_TOOL}
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
-r
${BASEDIR}
${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS}
--object-directory=${PROJECT_BINARY_DIR}
)
# Create folder
if (DEFINED GCOVR_CREATE_FOLDER)
set(GCOVR_FOLDER_CMD ${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
else ()
set(GCOVR_FOLDER_CMD echo) # dummy
endif ()
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
# Running gcovr
set(GCOVR_CMD
${GCOVR_PATH}
--gcov-executable
${GCOV_TOOL}
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
-r
${BASEDIR}
${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS}
--object-directory=${PROJECT_BINARY_DIR}
)
message(STATUS "Command to run tests: ")
string(
REPLACE ";"
" "
GCOVR_EXEC_TESTS_CMD_SPACED
"${GCOVR_EXEC_TESTS_CMD}"
)
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
if (CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
if(NOT GCOVR_FOLDER_CMD STREQUAL "echo")
message(STATUS "Command to create a folder: ")
string(
REPLACE ";"
" "
GCOVR_FOLDER_CMD_SPACED
"${GCOVR_FOLDER_CMD}"
)
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
endif()
message(STATUS "Command to run tests: ")
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
message(STATUS "Command to generate gcovr coverage data: ")
string(REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD}")
message(STATUS "${GCOVR_CMD_SPACED}")
endif()
if (NOT GCOVR_FOLDER_CMD STREQUAL "echo")
message(STATUS "Command to create a folder: ")
string(REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD}")
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
endif ()
add_custom_target(
${Coverage_NAME}
COMMAND ${GCOVR_EXEC_TESTS_CMD}
COMMAND ${GCOVR_FOLDER_CMD}
COMMAND ${GCOVR_CMD}
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce code coverage report."
)
message(STATUS "Command to generate gcovr coverage data: ")
string(REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD}")
message(STATUS "${GCOVR_CMD_SPACED}")
endif ()
# Show info where to find the report
add_custom_command(
TARGET ${Coverage_NAME}
POST_BUILD
COMMAND ;
COMMENT
"Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
)
endfunction() # setup_target_for_coverage_gcovr
add_custom_target(
${Coverage_NAME}
COMMAND ${GCOVR_EXEC_TESTS_CMD}
COMMAND ${GCOVR_FOLDER_CMD}
COMMAND ${GCOVR_CMD}
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce code coverage report."
)
function(append_coverage_compiler_flags)
set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
PARENT_SCOPE
)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
PARENT_SCOPE
)
set(CMAKE_Fortran_FLAGS
"${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
PARENT_SCOPE
)
message(
STATUS
"Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}"
)
endfunction() # append_coverage_compiler_flags
# Show info where to find the report
add_custom_command(
TARGET ${Coverage_NAME} POST_BUILD COMMAND ;
COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
)
endfunction () # setup_target_for_coverage_gcovr
function (append_coverage_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
endfunction () # append_coverage_compiler_flags
# Setup coverage for specific library
function(append_coverage_compiler_flags_to_target name mode)
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
target_compile_options(${name} ${mode} ${_flag_list})
if(
CMAKE_C_COMPILER_ID STREQUAL "GNU"
OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU"
)
target_link_libraries(${name} ${mode} gcov)
endif()
endfunction()
function (append_coverage_compiler_flags_to_target name mode)
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
target_compile_options(${name} ${mode} ${_flag_list})
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
target_link_libraries(${name} ${mode} gcov)
endif ()
endfunction ()

View File

@@ -12,9 +12,9 @@ set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT})
add_custom_target(
docs
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM
docs
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM
)

View File

@@ -1,11 +1,11 @@
if(DEFINED CMAKE_LINKER_TYPE)
message(STATUS "Custom linker is already set: ${CMAKE_LINKER_TYPE}")
return()
endif()
if (DEFINED CMAKE_LINKER_TYPE)
message(STATUS "Custom linker is already set: ${CMAKE_LINKER_TYPE}")
return()
endif ()
find_program(MOLD_PATH mold)
if(MOLD_PATH AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(STATUS "Using Mold linker: ${MOLD_PATH}")
set(CMAKE_LINKER_TYPE MOLD)
endif()
if (MOLD_PATH AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(STATUS "Using Mold linker: ${MOLD_PATH}")
set(CMAKE_LINKER_TYPE MOLD)
endif ()

View File

@@ -1,55 +0,0 @@
#[===================================================================[
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()

View File

@@ -1,47 +0,0 @@
#[===================================================================[
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})

View File

@@ -30,77 +30,53 @@ set(COMPILER_FLAGS
# TODO: re-enable when we change CI #884 if (is_gcc AND NOT lint) list(APPEND COMPILER_FLAGS -Wduplicated-branches
# -Wduplicated-cond -Wlogical-op -Wuseless-cast ) endif ()
if(is_clang)
# gcc is too aggressive with shadowing
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78147
list(APPEND COMPILER_FLAGS -Wshadow)
endif()
if (is_clang)
list(APPEND COMPILER_FLAGS -Wshadow # gcc is to aggressive with shadowing
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78147
)
endif ()
if(is_appleclang)
list(APPEND COMPILER_FLAGS -Wreorder-init-list)
endif()
if (is_appleclang)
list(APPEND COMPILER_FLAGS -Wreorder-init-list)
endif ()
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
# are reported from deep inside libraries like boost or libxrpl.
#
# TODO: Address in https://github.com/XRPLF/clio/issues/1885
list(
APPEND COMPILER_FLAGS
-Wno-error=tsan # Disables treating TSAN warnings as errors
-Wno-tsan # Disables TSAN warnings (thread-safety analysis)
-Wno-uninitialized # Disables warnings about uninitialized variables (AddressSanitizer,
# UndefinedBehaviorSanitizer, etc.)
-Wno-stringop-overflow # Disables warnings about potential string operation overflows (AddressSanitizer)
-Wno-unsafe-buffer-usage # Disables warnings about unsafe memory operations (AddressSanitizer)
-Wno-frame-larger-than # Disables warnings about stack frame size being too large (AddressSanitizer)
-Wno-unused-function # Disables warnings about unused functions (LeakSanitizer, memory-related issues)
-Wno-unused-but-set-variable # Disables warnings about unused variables (MemorySanitizer)
-Wno-thread-safety-analysis # Disables warnings related to thread safety usage (ThreadSanitizer)
-Wno-thread-safety # Disables warnings related to thread safety usage (ThreadSanitizer)
-Wno-sign-compare # Disables warnings about signed/unsigned comparison (UndefinedBehaviorSanitizer)
-Wno-nonnull # Disables warnings related to null pointer dereferencing (UndefinedBehaviorSanitizer)
-Wno-address # Disables warnings about address-related issues (UndefinedBehaviorSanitizer)
-Wno-array-bounds # Disables array bounds checks (UndefinedBehaviorSanitizer)
)
endif()
if (san)
# 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 are
# reported from deep inside libraries like boost or libxrpl.
#
# TODO: Address in https://github.com/XRPLF/clio/issues/1885
list(
APPEND
COMPILER_FLAGS
-Wno-error=tsan # Disables treating TSAN warnings as errors
-Wno-tsan # Disables TSAN warnings (thread-safety analysis)
-Wno-uninitialized # Disables warnings about uninitialized variables (AddressSanitizer, UndefinedBehaviorSanitizer,
# etc.)
-Wno-stringop-overflow # Disables warnings about potential string operation overflows (AddressSanitizer)
-Wno-unsafe-buffer-usage # Disables warnings about unsafe memory operations (AddressSanitizer)
-Wno-frame-larger-than # Disables warnings about stack frame size being too large (AddressSanitizer)
-Wno-unused-function # Disables warnings about unused functions (LeakSanitizer, memory-related issues)
-Wno-unused-but-set-variable # Disables warnings about unused variables (MemorySanitizer)
-Wno-thread-safety-analysis # Disables warnings related to thread safety usage (ThreadSanitizer)
-Wno-thread-safety # Disables warnings related to thread safety usage (ThreadSanitizer)
-Wno-sign-compare # Disables warnings about signed/unsigned comparison (UndefinedBehaviorSanitizer)
-Wno-nonnull # Disables warnings related to null pointer dereferencing (UndefinedBehaviorSanitizer)
-Wno-address # Disables warnings about address-related issues (UndefinedBehaviorSanitizer)
-Wno-array-bounds # Disables array bounds checks (UndefinedBehaviorSanitizer)
)
endif ()
# See https://github.com/cpp-best-practices/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#gcc--clang for
# the flags description
if(time_trace)
if(is_clang OR is_appleclang)
list(APPEND COMPILER_FLAGS -ftime-trace)
else()
message(
FATAL_ERROR
"Clang or AppleClang is required to use `-ftime-trace`"
)
endif()
endif()
if (time_trace)
if (is_clang OR is_appleclang)
list(APPEND COMPILER_FLAGS -ftime-trace)
else ()
message(FATAL_ERROR "Clang or AppleClang is required to use `-ftime-trace`")
endif ()
endif ()
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()

View File

@@ -1,17 +1,11 @@
include(CheckIncludeFileCXX)
check_include_file_cxx("source_location" SOURCE_LOCATION_AVAILABLE)
if(SOURCE_LOCATION_AVAILABLE)
target_compile_definitions(clio_options INTERFACE "HAS_SOURCE_LOCATION")
endif()
if (SOURCE_LOCATION_AVAILABLE)
target_compile_definitions(clio_options INTERFACE "HAS_SOURCE_LOCATION")
endif ()
check_include_file_cxx(
"experimental/source_location"
EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE
)
if(EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE)
target_compile_definitions(
clio_options
INTERFACE "HAS_EXPERIMENTAL_SOURCE_LOCATION"
)
endif()
check_include_file_cxx("experimental/source_location" EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE)
if (EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE)
target_compile_definitions(clio_options INTERFACE "HAS_EXPERIMENTAL_SOURCE_LOCATION")
endif ()

View File

@@ -1,10 +1,4 @@
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
find_package(
Boost
1.82
REQUIRED
CONFIG
COMPONENTS program_options coroutine system log log_setup
)
find_package(Boost 1.82 REQUIRED CONFIG COMPONENTS program_options system log log_setup)

View File

@@ -1,6 +1,3 @@
find_package(OpenSSL 1.1.1 REQUIRED CONFIG)
find_package(OpenSSL 3 REQUIRED CONFIG)
set_target_properties(
OpenSSL::SSL
PROPERTIES INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2
)
set_target_properties(OpenSSL::SSL PROPERTIES INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2)

View File

@@ -1,14 +1,11 @@
if(NOT SANITIZERS_ENABLED)
target_compile_definitions(clio_options INTERFACE BOOST_STACKTRACE_LINK)
target_compile_definitions(
clio_options
INTERFACE BOOST_STACKTRACE_USE_BACKTRACE
)
find_package(libbacktrace REQUIRED CONFIG)
else()
# Some sanitizers (TSAN and ASAN for sure) can't be used with libbacktrace because they have their own backtracing
# capabilities and there are conflicts. In any case, this makes sure Clio code knows that backtrace is not
# available. See relevant conan profiles for sanitizers where we disable stacktrace in Boost explicitly.
target_compile_definitions(clio_options INTERFACE CLIO_WITHOUT_STACKTRACE)
message(STATUS "Sanitizer enabled, disabling stacktrace")
endif()
if ("${san}" STREQUAL "")
target_compile_definitions(clio_options INTERFACE BOOST_STACKTRACE_LINK)
target_compile_definitions(clio_options INTERFACE BOOST_STACKTRACE_USE_BACKTRACE)
find_package(libbacktrace REQUIRED CONFIG)
else ()
# Some sanitizers (TSAN and ASAN for sure) can't be used with libbacktrace because they have their own backtracing
# capabilities and there are conflicts. In any case, this makes sure Clio code knows that backtrace is not available.
# See relevant conan profiles for sanitizers where we disable stacktrace in Boost explicitly.
target_compile_definitions(clio_options INTERFACE CLIO_WITHOUT_STACKTRACE)
message(STATUS "Sanitizer enabled, disabling stacktrace")
endif ()

View File

@@ -1,5 +1,5 @@
find_package(spdlog REQUIRED)
if(NOT TARGET spdlog::spdlog)
message(FATAL_ERROR "spdlog::spdlog target not found")
endif()
if (NOT TARGET spdlog::spdlog)
message(FATAL_ERROR "spdlog::spdlog target not found")
endif ()

View File

@@ -1,10 +1,5 @@
set(CLIO_INSTALL_DIR "/opt/clio")
set(CMAKE_INSTALL_PREFIX
"${CLIO_INSTALL_DIR}"
CACHE PATH
"Install prefix"
FORCE
)
set(CMAKE_INSTALL_PREFIX "${CLIO_INSTALL_DIR}" CACHE PATH "Install prefix" FORCE)
set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
@@ -15,17 +10,7 @@ install(TARGETS clio_server DESTINATION "${CMAKE_INSTALL_BINDIR}")
file(READ docs/examples/config/example-config.json config)
string(REGEX REPLACE "./clio_log" "/var/log/clio/" config "${config}")
file(WRITE ${CMAKE_BINARY_DIR}/install-config.json "${config}")
install(
FILES ${CMAKE_BINARY_DIR}/install-config.json
DESTINATION etc
RENAME config.json
)
install(FILES ${CMAKE_BINARY_DIR}/install-config.json DESTINATION etc RENAME config.json)
configure_file(
"${CMAKE_SOURCE_DIR}/cmake/install/clio.service.in"
"${CMAKE_BINARY_DIR}/clio.service"
)
install(
FILES "${CMAKE_BINARY_DIR}/clio.service"
DESTINATION /lib/systemd/system
)
configure_file("${CMAKE_SOURCE_DIR}/cmake/install/clio.service.in" "${CMAKE_BINARY_DIR}/clio.service")
install(FILES "${CMAKE_BINARY_DIR}/clio.service" DESTINATION /lib/systemd/system)

View File

@@ -10,36 +10,36 @@ CLIO_BIN="$CLIO_PREFIX/bin/${CLIO_EXECUTABLE}"
CLIO_CONFIG="$CLIO_PREFIX/etc/config.json"
case "$1" in
configure)
if ! id -u "$USER_NAME" >/dev/null 2>&1; then
# Users who should not have a home directory should have their home directory set to /nonexistent
# https://www.debian.org/doc/debian-policy/ch-opersys.html#non-existent-home-directories
useradd \
--system \
--home-dir /nonexistent \
--no-create-home \
--shell /usr/sbin/nologin \
--comment "system user for ${CLIO_EXECUTABLE}" \
--user-group \
${USER_NAME}
fi
configure)
if ! id -u "$USER_NAME" >/dev/null 2>&1; then
# Users who should not have a home directory should have their home directory set to /nonexistent
# https://www.debian.org/doc/debian-policy/ch-opersys.html#non-existent-home-directories
useradd \
--system \
--home-dir /nonexistent \
--no-create-home \
--shell /usr/sbin/nologin \
--comment "system user for ${CLIO_EXECUTABLE}" \
--user-group \
${USER_NAME}
fi
install -d -o "$USER_NAME" -g "$GROUP_NAME" /var/log/clio
install -d -o "$USER_NAME" -g "$GROUP_NAME" /var/log/clio
if [ -f "$CLIO_CONFIG" ]; then
chown "$USER_NAME:$GROUP_NAME" "$CLIO_CONFIG"
fi
if [ -f "$CLIO_CONFIG" ]; then
chown "$USER_NAME:$GROUP_NAME" "$CLIO_CONFIG"
fi
chown -R "$USER_NAME:$GROUP_NAME" "$CLIO_PREFIX"
chown -R "$USER_NAME:$GROUP_NAME" "$CLIO_PREFIX"
ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
;;
abort-upgrade | abort-remove | abort-deconfigure) ;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
;;
abort-upgrade | abort-remove | abort-deconfigure) ;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

View File

@@ -1,61 +1,76 @@
{
"version": "0.5",
"requires": [
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"xrpl/3.1.3#eabc6838b4553671bdde4b3aa1f8e3e6%1778495466.414",
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926",
"xrpl/3.2.0#c3c124909c6461012758a4fab7c90cd5%1781569913.756",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1778091117.311",
"spdlog/1.17.0#bcbaaf7147bda6ad24ffbd1ac3d7142c%1768312128.781",
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
"re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
"secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1774398111.888",
"rapidjson/cci.20220822#1b9d8c2256876a154172dc5cfbe447c6%1754325007.656",
"protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456",
"openssl/1.1.1w#a8f0792d7c5121b954578a7149d23e03%1756223730.729",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"openssl/3.6.2#4789bbf131b77d0515d15e094c8f697f%1778071755.506",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1775040983.408",
"minizip/1.2.13#9e87d57804bd372d6d1e32b1871517a3%1754325004.374",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libuv/1.46.0#dc28c1f653fa197f00db5b577a6f6011%1754325003.592",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
"libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1778091117.848",
"http_parser/2.9.4#98d91690d6fd021e9e624218a85d9d97%1754325001.385",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
"grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1756234248.958",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342",
"fmt/12.1.0#50abab23274d56bb8f42c94b3b9a40c7%1763984116.926",
"doctest/2.4.11#a4211dfc329a16ba9f280f9574025659%1756234220.819",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
"cassandra-cpp-driver/2.17.0#bd3934138689482102c265d01288a316%1764175359.611",
"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.5#b885dc73ad67b40a55d45684d1c88ad1%1774363287.434",
"abseil/20230802.1#90ba607d4ee8fb5fb157c3db540671fc%1764175359.429"
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778091165.282",
"benchmark/1.9.4#ce4403f7a24d3e1f907cd9da4b678be4%1754578869.672",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
],
"build_requires": [
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
"protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456",
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
"cmake/3.31.11#f325c933f618a1fcebc1e1c0babfd1ba%1774439246.719",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447"
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
],
"python_requires": [],
"overrides": {
"protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88": [
null,
"protobuf/3.21.12"
"zlib/[>=1.2.11 <2]": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb"
],
"boost/1.83.0#91d8b1572534d2c334d6790e3c34d0c1": [
"zlib/1.3.2": [
null,
"boost/1.83.0#91d8b1572534d2c334d6790e3c34d0c1"
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb"
],
"boost/1.91.0": [
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c"
],
"protobuf/[>=5.27.0 <7]": [
"protobuf/6.33.5"
],
"lz4/1.9.4": [
"lz4/1.10.0"
],
"boost/[>=1.83.0 <1.91.0]": [
"boost/1.83.0"
"boost/1.91.0"
],
"sqlite3/[>=3.44 <4]": [
"sqlite3/3.49.1"
"sqlite3/3.53.0"
],
"boost/1.83.0": [
"boost/1.91.0"
],
"lz4/[>=1.9.4 <2]": [
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
]
},
"config_requires": []

View File

@@ -1,7 +0,0 @@
# 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

View File

@@ -1,30 +0,0 @@
#!/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

View File

@@ -1,8 +0,0 @@
{% 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 %}

View File

@@ -1,28 +0,0 @@
{% 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 %}

View File

@@ -1,120 +0,0 @@
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 %}

View File

@@ -1,6 +1,5 @@
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
class ClioConan(ConanFile):
@@ -15,13 +14,9 @@ class ClioConan(ConanFile):
requires = [
"cassandra-cpp-driver/2.17.0",
"fmt/12.1.0",
"grpc/1.50.1",
"libbacktrace/cci.20210118",
"openssl/1.1.1w",
"protobuf/3.21.12",
"spdlog/1.17.0",
"xrpl/3.1.3",
"zlib/1.3.1",
"xrpl/3.2.0",
]
default_options = {
@@ -36,16 +31,28 @@ class ClioConan(ConanFile):
"protobuf/*:shared": False,
"protobuf/*:with_zlib": True,
"snappy/*:shared": False,
"xrpl/*:rocksdb": False,
"xrpl/*:rocksdb": True, # TODO: revert to false when includes are fixed in libxrpl
"xrpl/*:tests": False,
}
exports_sources = ("CMakeLists.txt", "cmake/*", "src/*")
def requirements(self):
self.requires("boost/1.83.0", force=True)
self.requires("gtest/1.17.0")
self.requires("benchmark/1.9.5")
self.requires("benchmark/1.9.4")
# Clio's own code includes grpc (<grpcpp/...>) and openssl (via
# <boost/asio/ssl>) headers directly, but xrpl does not re-export them
# (only boost/date/xxhash are required with transitive_headers=True).
# So they must be direct requirements of clio to get their include dirs;
# the version pins match xrpl's, so this does not change any package_id.
self.requires("grpc/1.78.1")
self.requires("openssl/3.6.2")
# Pin the remaining transitive deps to the exact versions xrpl uses.
# override=True only sets the version when the package appears
# transitively (it does not make them direct deps), and matches xrpl's
# force=True boost pin that overrides nudb's `boost < 1.91.0` cap.
self.requires("boost/1.91.0", override=True)
self.requires("zlib/1.3.2", override=True)
def configure(self):
if self.settings.compiler == "apple-clang":

132
docker/ci/Dockerfile Normal file
View File

@@ -0,0 +1,132 @@
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=20
RUN echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${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

25
docker/ci/README.md Normal file
View File

@@ -0,0 +1,25 @@
# 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 22.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
- 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`).

View File

@@ -0,0 +1,14 @@
[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"]
user.package:libc_version=2.32
tools.info.package_id:confs+=["user.package:libc_version"]

View File

@@ -0,0 +1,13 @@
[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"}
user.package:libc_version=2.32
tools.info.package_id:confs+=["user.package:libc_version"]

View File

@@ -0,0 +1,2 @@
core.download:parallel={{os.cpu_count()}}
core.upload:parallel={{os.cpu_count()}}

View File

@@ -0,0 +1,37 @@
{% 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"]

View File

@@ -0,0 +1,32 @@
FROM ubuntu:22.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/*

View File

@@ -0,0 +1,3 @@
# Clang compiler
This image contains clang compiler to build <https://github.com/XRPLF/clio>.

View File

@@ -0,0 +1,120 @@
ARG UBUNTU_VERSION=22.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

View File

@@ -0,0 +1,3 @@
# GCC compiler
This image contains GCC compiler to build <https://github.com/XRPLF/clio>.

View File

@@ -0,0 +1,7 @@
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

View File

@@ -0,0 +1,2 @@
# Path to the directory containing libstdc++.so.6
/usr/lib64

View File

@@ -1,6 +1,6 @@
services:
clio_develop:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-7b9d553
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
volumes:
- clio_develop_conan_data:/root/.conan2/p
- clio_develop_ccache:/root/.ccache

View File

@@ -41,26 +41,26 @@ EOF
}
case $1 in
-h | --help)
print_help
;;
-h | --help)
print_help
;;
-t | --terminal)
open_terminal
;;
-t | --terminal)
open_terminal
;;
-s | --stop)
stop_container
;;
-s | --stop)
stop_container
;;
-*)
echo "Unknown option: $1"
print_help
;;
-*)
echo "Unknown option: $1"
print_help
;;
*)
run "$@"
;;
*)
run "$@"
;;
esac
popd >/dev/null

112
docker/tools/Dockerfile Normal file
View File

@@ -0,0 +1,112 @@
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

View File

@@ -3,6 +3,8 @@ project(docs)
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ClioVersion.cmake)
# cmake-format: off
# Generate `docs` target for doxygen documentation
# Note: use `cmake --build . --target docs` from your `build` directory to generate the documentation
# cmake-format: on
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Docs.cmake)

View File

@@ -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 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.
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).
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 `conan/init.sh`.
> To setup Conan automatically, you can run `.github/scripts/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/xrpld/nix-ubuntu:sha-7b9d553
docker run -it ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
git clone https://github.com/XRPLF/clio
cd clio
```

View File

@@ -230,7 +230,7 @@ This document provides a list of all available Clio configuration properties in
- **Required**: False
- **Type**: string
- **Default value**: None
- **Constraints**: The value must be a valid IP address.
- **Constraints**: None
- **Description**: The list of IP addresses to whitelist for DOS protection.
### dos_guard.max_fetches
@@ -342,7 +342,7 @@ This document provides a list of all available Clio configuration properties in
- **Required**: True
- **Type**: string
- **Default value**: None
- **Constraints**: The value must be a valid IP address.
- **Constraints**: None
- **Description**: List of proxy ip addresses. When Clio receives a request from proxy it will use `Forwarded` value (if any) as client ip. When this option is used together with `server.proxy.tokens` Clio will identify proxy by ip or by token.
### server.proxy.tokens.[]
@@ -433,14 +433,6 @@ This document provides a list of all available Clio configuration properties in
- **Constraints**: The minimum value is `1`. The maximum value is `65535`.
- **Description**: The number of ledger objects to fetch concurrently per marker.
### cache.limit_load_in_cluster
- **Required**: True
- **Type**: boolean
- **Default value**: `False`
- **Constraints**: None
- **Description**: If enabled only one clio node in a cluster (sharing the same database) will load cache at a time
### cache.load
- **Required**: True
@@ -561,14 +553,6 @@ Documentation can be found at: <https://github.com/gabime/spdlog/wiki/Custom-for
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
- **Description**: The maximum number of log files in the directory.
### log.rotate
- **Required**: True
- **Type**: boolean
- **Default value**: `True`
- **Constraints**: None
- **Description**: Enables or disables log file rotation. When disabled, a single log file is used without size-based rotation. Useful when rotation is managed externally (e.g., via logrotate).
### log.tag_style
- **Required**: True

View File

@@ -93,42 +93,3 @@ To completely disable Prometheus metrics add `"prometheus": { "enabled": false }
It is important to know that Clio responds to Prometheus request only if they are admin requests. If you are using the admin password feature, the same password should be provided in the Authorization header of Prometheus requests.
You can find an example Docker Compose file, with Prometheus and Grafana configs, in [examples/infrastructure](../docs/examples/infrastructure/).
## Ledger cache file
Since version 2.7.0, Clio supports saving the ledger cache to a local file on shutdown and loading it on startup. This feature is disabled by default but can significantly improve restart times.
### Benefits
- **Faster startup**: Loading cache from a file takes less than a minute, compared to 40-90 minutes on Mainnet when loading from the database.
- **Reduced database load**: Clio doesn't put extra load on the database when starting with a cache file.
- **Improved availability**: Faster restart times mean less downtime during maintenance or updates.
> [!NOTE]
> This feature only works when Clio is restarted. When starting Clio for the first time, the cache must be loaded from `rippled` or the database as usual.
### Configuration
To enable the ledger cache file feature, specify the [`cache.file.path`](./config-description.md#cachefilepath) option in your `config.json`:
```json
"cache": {
"file": {
"path": "/path/to/cache/file"
}
}
```
You can optionally configure additional settings such as [`cache.file.max_sequence_age`](./config-description.md#cachefilemax_sequence_age) and [`cache.file.async_save`](./config-description.md#cachefileasync_save) to fine-tune the behavior. For a complete list of available options and their default values, see the [Configuration Description](./config-description.md#cachefilepath) documentation.
### How it works
1. **On shutdown**: Clio saves the current ledger cache to the specified file path. The file includes a hash for integrity verification.
2. **On startup**: Clio checks if a cache file exists at the configured path. If the file exists, Clio will:
- Verify the file's integrity to ensure it is complete and not corrupted.
- Compare the latest ledger sequence in the cache file with the latest sequence in the database.
- Use the cache file only if the difference is less than [`cache.file.max_sequence_age`](./config-description.md#cachefilemax_sequence_age).
- If validation fails or the cache is too old, Clio will fall back to loading from the database.
> [!IMPORTANT]
> The cache file path should point to a location with sufficient disk space. On typical deployments, the cache file size can be several gigabytes.

View File

@@ -1,56 +1,51 @@
#!/bin/bash
# Annotated tags have object type "tag"; lightweight tags have type "commit".
# To inspect tags: git for-each-ref refs/tags
#
# To always sign commits and tags, configure:
# git config --global commit.gpgsign true
# git config --global tag.gpgsign true
# git for-each-ref refs/tags # see which tags are annotated and which are lightweight. Annotated tags are "tag" objects.
# # Set these so your commits and tags are always signed
# git config commit.gpgsign true
# git config tag.gpgsign true
verify_commit_signed() {
if git verify-commit HEAD &>/dev/null; then
echo "HEAD commit is signed."
:
# echo "HEAD commit seems signed..."
else
echo "HEAD commit is not signed!"
echo "HEAD commit isn't signed!"
exit 1
fi
}
verify_tag_annotated() {
local version="$1"
# git cat-file -t returns "tag" for annotated tags, "commit" for lightweight.
if [[ "$(git cat-file -t "$version")" == "tag" ]]; then
echo "Tag '$version' is annotated."
verify_tag() {
if git describe --exact-match --tags HEAD &>/dev/null; then
: # You might be ok to push
# echo "Tag is annotated."
return 0
else
echo "Tag '$version' is not annotated!"
echo "Re-create it with: git tag -a -s -m \"$version\" \"$version\""
echo "Tag for [$version] not an annotated tag."
exit 1
fi
}
verify_tag_signed() {
local version="$1"
if git verify-tag "$version" &>/dev/null; then
echo "Tag '$version' is signed."
: # ok, I guess we'll let you push
# echo "Tag appears signed"
return 0
else
echo "Tag '$version' is not signed!"
echo "Sign it with: git tag -a -s -m \"$version\" \"$version\""
echo "$version tag isn't signed"
echo "Sign it with [git tag -ams\"$version\" $version]"
exit 1
fi
}
# Enforce signing and annotated tags when pushing to a release branch.
if echo "$PRE_COMMIT_REMOTE_BRANCH" | grep -q "^refs/heads/release/"; then
# git describe --exact-match guarantees a single tag; git tag --points-at HEAD
# can return multiple newline-separated values, which breaks downstream commands.
version=$(git describe --exact-match --tags HEAD 2>/dev/null)
if [[ -z "$version" ]]; then
echo "No tag found at HEAD — cannot push an untagged release commit!"
# Check some things if we're pushing a branch called "release/"
if echo "$PRE_COMMIT_REMOTE_BRANCH" | grep ^refs\/heads\/release\/ &>/dev/null; then
version=$(git tag --points-at HEAD)
echo "Looks like you're trying to push a $version release..."
echo "Making sure you've signed and tagged it."
if verify_commit_signed && verify_tag && verify_tag_signed; then
: # Ok, I guess you can push
else
exit 1
fi
echo "Looks like you're trying to push a '$version' release..."
echo "Verifying the commit is signed and the tag is annotated and signed."
verify_commit_signed
verify_tag_annotated "$version"
verify_tag_signed "$version"
fi

View File

@@ -1,11 +1,13 @@
add_library(clio_app)
target_sources(
clio_app
PRIVATE CliArgs.cpp ClioApplication.cpp Stopper.cpp WebHandlers.cpp
)
target_sources(clio_app PRIVATE CliArgs.cpp ClioApplication.cpp Stopper.cpp WebHandlers.cpp)
target_link_libraries(
clio_app
PUBLIC clio_cluster clio_etl clio_feed clio_migration clio_rpc clio_web
PRIVATE Boost::program_options
clio_app
PUBLIC clio_cluster
clio_etl
clio_feed
clio_migration
clio_rpc
clio_web
PRIVATE Boost::program_options
)

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "app/CliArgs.hpp"
#include "migration/MigrationApplication.hpp"
@@ -28,7 +47,7 @@ CliArgs::parse(int argc, char const* argv[])
description.add_options()
("help,h", "Print help message and exit")
("version,v", "Print version and exit")
("conf,c", po::value<std::string>()->default_value(kDefaultConfigPath), "Configuration file")
("conf,c", po::value<std::string>()->default_value(kDEFAULT_CONFIG_PATH), "Configuration file")
("ng-web-server,w", "Use ng-web-server")
("migrate", po::value<std::string>(), "Start migration helper")
("verify", "Checks the validity of config values")
@@ -39,16 +58,12 @@ CliArgs::parse(int argc, char const* argv[])
positional.add("conf", 1);
auto const printHelp = [&description]() {
std::cout << "Clio server " << util::build::getClioFullVersionString() << "\n\n"
<< description;
std::cout << "Clio server " << util::build::getClioFullVersionString() << "\n\n" << description;
};
po::variables_map parsed;
try {
po::store(
po::command_line_parser(argc, argv).options(description).positional(positional).run(),
parsed
);
po::store(po::command_line_parser(argc, argv).options(description).positional(positional).run(), parsed);
po::notify(parsed);
} catch (po::error const& e) {
std::cerr << "Error: " << e.what() << std::endl << std::endl;
@@ -72,8 +87,7 @@ CliArgs::parse(int argc, char const* argv[])
if (parsed.contains("config-description")) {
std::filesystem::path const filePath = parsed["config-description"].as<std::string>();
auto const res =
util::config::ClioConfigDescription::generateConfigDescriptionToFile(filePath);
auto const res = util::config::ClioConfigDescription::generateConfigDescriptionToFile(filePath);
if (res.has_value())
return Action{Action::Exit{EXIT_SUCCESS}};
@@ -85,22 +99,15 @@ CliArgs::parse(int argc, char const* argv[])
if (parsed.contains("migrate")) {
auto const opt = parsed["migrate"].as<std::string>();
if (opt == "status") {
return Action{Action::Migrate{
.configPath = std::move(configPath), .subCmd = MigrateSubCmd::status()
}};
}
return Action{Action::Migrate{
.configPath = std::move(configPath), .subCmd = MigrateSubCmd::migration(opt)
}};
if (opt == "status")
return Action{Action::Migrate{.configPath = std::move(configPath), .subCmd = MigrateSubCmd::status()}};
return Action{Action::Migrate{.configPath = std::move(configPath), .subCmd = MigrateSubCmd::migration(opt)}};
}
if (parsed.contains("verify"))
return Action{Action::VerifyConfig{.configPath = std::move(configPath)}};
return Action{Action::Run{
.configPath = std::move(configPath), .useNgWebServer = parsed.contains("ng-web-server")
}};
return Action{Action::Run{.configPath = std::move(configPath), .useNgWebServer = parsed.contains("ng-web-server")}};
}
} // namespace app

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#pragma once
#include "migration/MigrationApplication.hpp"
@@ -16,7 +35,7 @@ public:
/**
* @brief Default configuration path.
*/
static constexpr char kDefaultConfigPath[] = "/etc/opt/clio/config.json";
static constexpr char kDEFAULT_CONFIG_PATH[] = "/etc/opt/clio/config.json";
/**
* @brief An action parsed from the command line.
@@ -60,8 +79,7 @@ public:
/**
* @brief Apply a function to the action.
*
* @tparam Processors Action processors types. Must be callable with the action type and
* return int.
* @tparam Processors Action processors types. Must be callable with the action type and return int.
* @param processors Action processors.
* @return Exit code.
*/

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "app/ClioApplication.hpp"
#include "app/Stopper.hpp"
@@ -10,7 +29,6 @@
#include "etl/ETLService.hpp"
#include "etl/LoadBalancer.hpp"
#include "etl/NetworkValidatedLedgers.hpp"
#include "etl/SystemState.hpp"
#include "feed/SubscriptionManager.hpp"
#include "migration/MigrationInspectorFactory.hpp"
#include "rpc/Counters.hpp"
@@ -92,14 +110,9 @@ ClioApplication::run(bool const useNgWebServer)
boost::asio::io_context ioc{threads};
// Rate limiter, to prevent abuse
auto whitelistHandler = web::dosguard::WhitelistHandler::create(config_);
if (not whitelistHandler.has_value()) {
LOG(util::LogService::fatal()) << whitelistHandler.error();
return EXIT_FAILURE;
}
auto whitelistHandler = web::dosguard::WhitelistHandler{config_};
auto const dosguardWeights = web::dosguard::Weights::make(config_);
auto dosGuard = web::dosguard::DOSGuard{config_, *whitelistHandler, dosguardWeights};
auto dosGuard = web::dosguard::DOSGuard{config_, whitelistHandler, dosguardWeights};
auto sweepHandler = web::dosguard::IntervalSweepHandler{config_, ioc, dosGuard};
auto cache = data::LedgerCache{};
@@ -108,11 +121,8 @@ ClioApplication::run(bool const useNgWebServer)
// Interface to the database
auto backend = data::makeBackend(config_, cache);
auto systemState = etl::SystemState::makeSystemState(config_);
auto [clusterCommunicationService, cacheLoadingState] =
cluster::ClusterCommunicationService::make(config_, backend, systemState);
clusterCommunicationService->run();
cluster::ClusterCommunicationService clusterCommunicationService{backend};
clusterCommunicationService.run();
auto const amendmentCenter = std::make_shared<data::AmendmentCenter const>(backend);
@@ -120,15 +130,14 @@ ClioApplication::run(bool const useNgWebServer)
auto const migrationInspector = migration::makeMigrationInspector(config_, backend);
// Check if any migration is blocking Clio server starting.
if (migrationInspector->isBlockingClio() and backend->hardFetchLedgerRangeNoThrow()) {
LOG(util::LogService::error()) << "Existing Migration is blocking Clio, Please "
"complete the database migration first.";
LOG(util::LogService::error())
<< "Existing Migration is blocking Clio, Please complete the database migration first.";
return EXIT_FAILURE;
}
}
// Manages clients subscribed to streams
auto subscriptions =
feed::SubscriptionManager::makeSubscriptionManager(config_, backend, amendmentCenter);
auto subscriptions = feed::SubscriptionManager::makeSubscriptionManager(config_, backend, amendmentCenter);
// Tracks which ledgers have been validated by the network
auto ledgers = etl::NetworkValidatedLedgers::makeValidatedLedgers();
@@ -141,18 +150,8 @@ ClioApplication::run(bool const useNgWebServer)
config_, ioc, backend, subscriptions, std::make_unique<util::MTRandomGenerator>(), ledgers
);
// ETL is responsible for writing and publishing to streams. In read-only mode, ETL only
// publishes
auto etl = etl::ETLService::makeETLService(
config_,
std::move(systemState),
std::move(cacheLoadingState),
ctx,
backend,
subscriptions,
balancer,
ledgers
);
// ETL is responsible for writing and publishing to streams. In read-only mode, ETL only publishes
auto etl = etl::ETLService::makeETLService(config_, ctx, backend, subscriptions, balancer, ledgers);
auto workQueue = rpc::WorkQueue::makeWorkQueue(config_);
auto counters = rpc::Counters::makeCounters(workQueue);
@@ -162,19 +161,15 @@ ClioApplication::run(bool const useNgWebServer)
);
using RPCEngineType = rpc::RPCEngine<rpc::Counters>;
auto const rpcEngine = RPCEngineType::makeRPCEngine(
config_, backend, balancer, dosGuard, workQueue, counters, handlerProvider
);
auto const rpcEngine =
RPCEngineType::makeRPCEngine(config_, backend, balancer, dosGuard, workQueue, counters, handlerProvider);
if (useNgWebServer or config_.get<bool>("server.__ng_web_server")) {
web::ng::RPCServerHandler<RPCEngineType> handler{
config_, backend, rpcEngine, etl, dosGuard
};
web::ng::RPCServerHandler<RPCEngineType> handler{config_, backend, rpcEngine, etl, dosGuard};
auto expectedAdminVerifier = web::makeAdminVerificationStrategy(config_);
if (not expectedAdminVerifier.has_value()) {
LOG(util::LogService::error())
<< "Error creating admin verifier: " << expectedAdminVerifier.error();
LOG(util::LogService::error()) << "Error creating admin verifier: " << expectedAdminVerifier.error();
return EXIT_FAILURE;
}
auto const adminVerifier = std::move(expectedAdminVerifier).value();
@@ -202,16 +197,7 @@ ClioApplication::run(bool const useNgWebServer)
}
appStopper_.setOnStop(
Stopper::makeOnStopCallback(
httpServer.value(),
*balancer,
*etl,
*subscriptions,
*backend,
cacheSaver,
*clusterCommunicationService,
ioc
)
Stopper::makeOnStopCallback(httpServer.value(), *balancer, *etl, *subscriptions, *backend, cacheSaver, ioc)
);
// Blocks until stopped.
@@ -223,27 +209,11 @@ ClioApplication::run(bool const useNgWebServer)
}
// Init the web server
auto handler = std::make_shared<web::RPCServerHandler<RPCEngineType>>(
config_, backend, rpcEngine, etl, dosGuard
);
auto const expectedHttpServer = web::makeHttpServer(config_, ioc, dosGuard, handler, cache);
if (not expectedHttpServer.has_value()) {
LOG(util::LogService::fatal()) << expectedHttpServer.error();
return EXIT_FAILURE;
}
auto handler = std::make_shared<web::RPCServerHandler<RPCEngineType>>(config_, backend, rpcEngine, etl, dosGuard);
auto const httpServer = web::makeHttpServer(config_, ioc, dosGuard, handler, cache);
appStopper_.setOnStop(
Stopper::makeOnStopCallback(
**expectedHttpServer,
*balancer,
*etl,
*subscriptions,
*backend,
cacheSaver,
*clusterCommunicationService,
ioc
)
Stopper::makeOnStopCallback(*httpServer, *balancer, *etl, *subscriptions, *backend, cacheSaver, ioc)
);
// Blocks until stopped.

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#pragma once
#include "app/Stopper.hpp"

View File

@@ -1,3 +1,22 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2025, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "app/Stopper.hpp"
#include "util/Spawn.hpp"

View File

@@ -1,6 +1,24 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#pragma once
#include "cluster/Concepts.hpp"
#include "data/BackendInterface.hpp"
#include "data/LedgerCacheSaver.hpp"
#include "etl/ETLServiceInterface.hpp"
@@ -20,8 +38,7 @@
namespace app {
/**
* @brief Application stopper class. On stop it will create a new thread to run all the shutdown
* tasks.
* @brief Application stopper class. On stop it will create a new thread to run all the shutdown tasks.
*/
class Stopper {
boost::asio::io_context ctx_;
@@ -65,14 +82,10 @@ public:
* @param subscriptions The subscription manager to stop.
* @param backend The backend to stop.
* @param cacheSaver The ledger cache saver
* @param clusterCommunicationService The cluster communication service to stop.
* @param ioc The io_context to stop.
* @return The callback to be called on application stop.
*/
template <
web::SomeServer ServerType,
data::SomeLedgerCacheSaver LedgerCacheSaverType,
cluster::SomeClusterCommunicationService ClusterCommunicationServiceType>
template <web::SomeServer ServerType, data::SomeLedgerCacheSaver LedgerCacheSaverType>
static std::function<void(boost::asio::yield_context)>
makeOnStopCallback(
ServerType& server,
@@ -81,7 +94,6 @@ public:
feed::SubscriptionManagerInterface& subscriptions,
data::BackendInterface& backend,
LedgerCacheSaverType& cacheSaver,
ClusterCommunicationServiceType& clusterCommunicationService,
boost::asio::io_context& ioc
)
{
@@ -99,8 +111,6 @@ public:
});
coroutineGroup.asyncWait(yield);
clusterCommunicationService.stop();
etl.stop();
LOG(util::LogService::info()) << "ETL stopped";

Some files were not shown because too many files have changed in this diff Show More