Compare commits

..

16 Commits

Author SHA1 Message Date
Peter Chen
7eaf0005e4 Merge tag 'experiment' into experimental_keyspace
test keyspace
2025-09-16 09:08:58 -07:00
Peter Chen
497721ee7c change connections per host 2025-09-15 10:06:12 -07:00
Peter Chen
26530108e3 fix comments 2025-09-15 08:55:14 -07:00
Alex Kremer
fc88abdaeb Merge branch 'develop' into SupportKeyspace 2025-09-15 14:59:54 +01:00
Ayaz Salikhov
8bc36c2c0b Merge branch 'develop' into SupportKeyspace 2025-09-04 18:23:37 +01:00
Peter Chen
4e9558f76b 'Merge branch 'SupportKeyspace' into experimental_keyspace 2025-09-04 08:44:50 -07:00
Ayaz Salikhov
84db880ce7 Merge branch 'develop' into SupportKeyspace 2025-08-28 15:11:58 +01:00
Peter Chen
f88ce31363 let scylladb use same schema to update ledger range as before 2025-08-27 14:34:34 -07:00
Peter Chen
e03f5e46c0 Merge branch 'develop' into SupportKeyspace 2025-08-24 18:58:38 -04:00
Peter Chen
30da8d8f63 fix val 2025-08-24 18:58:07 -04:00
Peter Chen
8f6bec2e25 merge develop 2025-08-21 12:37:19 -04:00
Peter Chen
0d9a83fd4d fix comments 2025-08-20 12:29:01 -04:00
Peter Chen
47c2af0421 Merge branch 'develop' into SupportKeyspace 2025-08-19 16:37:08 -04:00
Peter Chen
c3e04426d3 fix bug and comments 2025-08-19 16:19:44 -04:00
Peter Chen
d598396445 remove unnecessary comment 2025-08-18 16:33:12 -04:00
Peter Chen
bbd2884e3b feat: Support Keyspace 2025-08-18 15:38:56 -04:00
1017 changed files with 45749 additions and 51186 deletions

View File

@@ -22,7 +22,7 @@ BreakBeforeBinaryOperators: false
BreakBeforeBraces: WebKit BreakBeforeBraces: WebKit
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true BreakConstructorInitializersBeforeComma: true
ColumnLimit: 100 ColumnLimit: 120
CommentPragmas: "^ IWYU pragma:" CommentPragmas: "^ IWYU pragma:"
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4
@@ -49,7 +49,6 @@ IndentFunctionDeclarationAfterType: false
IndentWidth: 4 IndentWidth: 4
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
IndentRequiresClause: true IndentRequiresClause: true
InsertNewlineAtEOF: true
RequiresClausePosition: OwnLine RequiresClausePosition: OwnLine
KeepEmptyLinesAtTheStartOfBlocks: false KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1

View File

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

@@ -1,31 +0,0 @@
name: Build clio
description: Build clio in build directory
inputs:
targets:
description: Space-separated build target names
default: all
nproc_subtract:
description: The number of processors to subtract when calculating parallelism.
required: true
default: "0"
runs:
using: composite
steps:
- name: Get number of processors
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
id: nproc
with:
subtract: ${{ inputs.nproc_subtract }}
- name: Build targets
shell: bash
env:
CMAKE_TARGETS: ${{ inputs.targets }}
run: |
cd build
cmake \
--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}"

29
.github/actions/build_clio/action.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Build clio
description: Build clio in build directory
inputs:
targets:
description: Space-separated build target names
default: all
subtract_threads:
description: An option for the action get_number_of_threads. See get_number_of_threads
required: true
default: "0"
runs:
using: composite
steps:
- name: Get number of threads
uses: ./.github/actions/get_number_of_threads
id: number_of_threads
with:
subtract_threads: ${{ inputs.subtract_threads }}
- name: Build targets
shell: bash
run: |
cd build
cmake \
--build . \
--parallel "${{ steps.number_of_threads.outputs.threads_number }}" \
--target ${{ inputs.targets }}

View File

@@ -34,32 +34,32 @@ runs:
steps: steps:
- name: Login to DockerHub - name: Login to DockerHub
if: ${{ inputs.push_image == 'true' && inputs.dockerhub_repo != '' }} if: ${{ inputs.push_image == 'true' && inputs.dockerhub_repo != '' }}
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with: with:
username: ${{ env.DOCKERHUB_USER }} username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_PW }} password: ${{ env.DOCKERHUB_PW }}
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
if: ${{ inputs.push_image == 'true' }} if: ${{ inputs.push_image == 'true' }}
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ env.GITHUB_TOKEN }} password: ${{ env.GITHUB_TOKEN }}
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 - uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
with: with:
cache-image: false cache-image: false
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 - uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
id: meta id: meta
with: with:
images: ${{ inputs.images }} images: ${{ inputs.images }}
tags: ${{ inputs.tags }} tags: ${{ inputs.tags }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with: with:
context: ${{ inputs.directory }} context: ${{ inputs.directory }}
platforms: ${{ inputs.platforms }} platforms: ${{ inputs.platforms }}

View File

@@ -6,6 +6,9 @@ inputs:
description: Build directory description: Build directory
required: false required: false
default: "build" default: "build"
conan_profile:
description: Conan profile name
required: true
build_type: build_type:
description: Build type for third-party libraries and clio. Could be 'Release', 'Debug' description: Build type for third-party libraries and clio. Could be 'Release', 'Debug'
required: true required: true
@@ -22,6 +25,10 @@ inputs:
description: Whether to enable code coverage description: Whether to enable code coverage
required: true required: true
default: "false" default: "false"
static:
description: Whether Clio is to be statically linked
required: true
default: "false"
time_trace: time_trace:
description: Whether to enable compiler trace reports description: Whether to enable compiler trace reports
required: true required: true
@@ -30,10 +37,6 @@ inputs:
description: Whether to generate Debian package description: Whether to generate Debian package
required: true required: true
default: "false" default: "false"
version:
description: Version of the clio_server binary
required: false
default: ""
runs: runs:
using: composite using: composite
@@ -41,36 +44,30 @@ runs:
- name: Run cmake - name: Run cmake
shell: bash shell: bash
env: env:
BUILD_DIR: "${{ inputs.build_dir }}"
BUILD_TYPE: "${{ inputs.build_type }}" 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' }}" INTEGRATION_TESTS: "${{ inputs.integration_tests == 'true' && 'ON' || 'OFF' }}"
BENCHMARK: "${{ inputs.benchmark == 'true' && 'ON' || 'OFF' }}" BENCHMARK: "${{ inputs.benchmark == 'true' && 'ON' || 'OFF' }}"
COVERAGE: "${{ inputs.code_coverage == 'true' && 'ON' || 'OFF' }}" COVERAGE: "${{ inputs.code_coverage == 'true' && 'ON' || 'OFF' }}"
STATIC: "${{ inputs.static == 'true' && 'ON' || 'OFF' }}"
TIME_TRACE: "${{ inputs.time_trace == 'true' && 'ON' || 'OFF' }}" TIME_TRACE: "${{ inputs.time_trace == 'true' && 'ON' || 'OFF' }}"
PACKAGE: "${{ inputs.package == 'true' && 'ON' || 'OFF' }}" PACKAGE: "${{ inputs.package == 'true' && 'ON' || 'OFF' }}"
# GitHub creates a merge commit for a PR
# https://www.kenmuse.com/blog/the-many-shas-of-a-github-pull-request/
#
# We:
# - explicitly provide branch name
# - use `github.head_ref` to get the SHA of last commit in the PR branch
#
# This way it works both for PRs and pushes to branches.
GITHUB_BRANCH_NAME: "${{ github.head_ref || github.ref_name }}"
GITHUB_HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
#
# If tag is being pushed, or it's a nightly release, we use that version.
FORCE_CLIO_VERSION: ${{ inputs.version }}
run: | run: |
cmake \ cmake \
-B "${BUILD_DIR}" \ -B ${{inputs.build_dir}} \
-S . \ -S . \
-G Ninja \ -G Ninja \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \ -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-Dtests=ON \ "${SANITIZER_OPTION}" \
-Dintegration_tests="${INTEGRATION_TESTS}" \ -Dtests=ON \
-Dbenchmark="${BENCHMARK}" \ -Dintegration_tests="${INTEGRATION_TESTS}" \
-Dcoverage="${COVERAGE}" \ -Dbenchmark="${BENCHMARK}" \
-Dtime_trace="${TIME_TRACE}" \ -Dcoverage="${COVERAGE}" \
-Dpackage="${PACKAGE}" -Dstatic="${STATIC}" \
-Dtime_trace="${TIME_TRACE}" \
-Dpackage="${PACKAGE}"

View File

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

View File

@@ -6,6 +6,9 @@ inputs:
description: Build directory description: Build directory
required: false required: false
default: "build" default: "build"
conan_profile:
description: Conan profile name
required: true
force_conan_source_build: force_conan_source_build:
description: Whether conan should build all dependencies from source description: Whether conan should build all dependencies from source
required: true required: true
@@ -14,25 +17,22 @@ inputs:
description: Build type for third-party libraries and clio. Could be 'Release', 'Debug' description: Build type for third-party libraries and clio. Could be 'Release', 'Debug'
required: true required: true
default: "Release" default: "Release"
sanitizers:
description: Sanitizer to enable, read by the 'sanitizers' conan profile (e.g. 'address', 'thread', 'undefinedbehavior')
required: false
default: ""
runs: runs:
using: composite using: composite
steps: steps:
- name: Create build directory
shell: bash
run: mkdir -p "${{ inputs.build_dir }}"
- name: Run conan - name: Run conan
shell: bash shell: bash
env: env:
BUILD_DIR: "${{ inputs.build_dir }}"
CONAN_BUILD_OPTION: "${{ inputs.force_conan_source_build == 'true' && '*' || 'missing' }}" CONAN_BUILD_OPTION: "${{ inputs.force_conan_source_build == 'true' && '*' || 'missing' }}"
BUILD_TYPE: "${{ inputs.build_type }}"
SANITIZERS: "${{ inputs.sanitizers }}"
run: | run: |
conan \ conan \
install . \ install . \
-of "${BUILD_DIR}" \ -of build \
-b "${CONAN_BUILD_OPTION}" \ -b "$CONAN_BUILD_OPTION" \
-s "build_type=${BUILD_TYPE}" \ -s "build_type=${{ inputs.build_type }}" \
--profile:all ci --profile:all "${{ inputs.conan_profile }}"

41
.github/actions/create_issue/action.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
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
run: |
echo -e '${{ inputs.body }}' > issue.md
gh issue create \
--assignee '${{ inputs.assignees }}' \
--label '${{ inputs.labels }}' \
--title '${{ inputs.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

@@ -0,0 +1,36 @@
name: Get number of threads
description: Determines number of threads to use on macOS and Linux
inputs:
subtract_threads:
description: How many threads to subtract from the calculated number
required: true
default: "0"
outputs:
threads_number:
description: Number of threads to use
value: ${{ steps.number_of_threads_export.outputs.num }}
runs:
using: composite
steps:
- name: Get number of threads on mac
id: mac_threads
if: ${{ runner.os == 'macOS' }}
shell: bash
run: echo "num=$(($(sysctl -n hw.logicalcpu) - 2))" >> $GITHUB_OUTPUT
- name: Get number of threads on Linux
id: linux_threads
if: ${{ runner.os == 'Linux' }}
shell: bash
run: echo "num=$(($(nproc) - 2))" >> $GITHUB_OUTPUT
- name: Shift and export number of threads
id: number_of_threads_export
shell: bash
run: |
num_of_threads="${{ steps.mac_threads.outputs.num || steps.linux_threads.outputs.num }}"
shift_by="${{ inputs.subtract_threads }}"
shifted="$((num_of_threads - shift_by))"
echo "num=$(( shifted > 1 ? shifted : 1 ))" >> $GITHUB_OUTPUT

View File

@@ -13,4 +13,4 @@ runs:
id: find_common_ancestor id: find_common_ancestor
shell: bash shell: bash
run: | 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

@@ -0,0 +1,38 @@
name: Restore cache
description: Find and restores ccache cache
inputs:
conan_profile:
description: Conan profile name
required: true
ccache_dir:
description: Path to .ccache directory
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:
ccache_cache_hit:
description: True if ccache cache has been downloaded
value: ${{ steps.ccache_cache.outputs.cache-hit }}
runs:
using: composite
steps:
- name: Find common commit
id: git_common_ancestor
uses: ./.github/actions/git_common_ancestor
- name: Restore ccache cache
uses: actions/cache/restore@v4
id: ccache_cache
if: ${{ env.CCACHE_DISABLE != '1' }}
with:
path: ${{ inputs.ccache_dir }}
key: clio-ccache-${{ runner.os }}-${{ inputs.build_type }}${{ inputs.code_coverage == 'true' && '-code_coverage' || '' }}-${{ inputs.conan_profile }}-develop-${{ steps.git_common_ancestor.outputs.commit }}

38
.github/actions/save_cache/action.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Save cache
description: Save ccache cache for develop branch
inputs:
conan_profile:
description: Conan profile name
required: true
ccache_dir:
description: Path to .ccache directory
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"
ccache_cache_hit:
description: Whether ccache cache has been downloaded
required: true
ccache_cache_miss_rate:
description: How many ccache cache misses happened
runs:
using: composite
steps:
- name: Find common commit
id: git_common_ancestor
uses: ./.github/actions/git_common_ancestor
- name: Save ccache cache
if: ${{ inputs.ccache_cache_hit != 'true' || inputs.ccache_cache_miss_rate == '100.0' }}
uses: actions/cache/save@v4
with:
path: ${{ inputs.ccache_dir }}
key: clio-ccache-${{ runner.os }}-${{ inputs.build_type }}${{ inputs.code_coverage == 'true' && '-code_coverage' || '' }}-${{ inputs.conan_profile }}-develop-${{ steps.git_common_ancestor.outputs.commit }}

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

141
.github/dependabot.yml vendored
View File

@@ -1,16 +1,137 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: github-actions - package-ecosystem: github-actions
directories: directory: /
- / schedule:
- .github/actions/build-clio/ interval: weekly
- .github/actions/build-docker-image/ day: monday
- .github/actions/build-identifier/ time: "04:00"
- .github/actions/cmake/ timezone: Etc/GMT
- .github/actions/code-coverage/ reviewers:
- .github/actions/conan/ - XRPLF/clio-dev-team
- .github/actions/git-common-ancestor/ commit-message:
- .github/actions/set-compiler-env/ 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/get_number_of_threads/
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/restore_cache/
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/save_cache/
schedule: schedule:
interval: weekly interval: weekly
day: monday day: monday

View File

@@ -4,7 +4,7 @@ build_type=Release
compiler=apple-clang compiler=apple-clang
compiler.cppstd=20 compiler.cppstd=20
compiler.libcxx=libc++ compiler.libcxx=libc++
compiler.version=17.0 compiler.version=17
os=Macos os=Macos
[conf] [conf]

View File

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

@@ -1,25 +0,0 @@
#!/usr/bin/env bash
set -ex
TEMP_DIR=$(mktemp -d)
trap "rm -rf $TEMP_DIR" EXIT
echo "Using temporary CONAN_HOME: $TEMP_DIR"
# We use a temporary Conan home to avoid polluting the user's existing Conan
# configuration and to not use local cache (which leads to non-reproducible lockfiles).
export CONAN_HOME="$TEMP_DIR"
# Ensure that the xrplf remote is the first to be consulted, so any recipes we
# patched are used. We also add it there to not created huge diff when the
# official Conan Center Index is updated.
conan remote add --force --index 0 xrplf https://conan.ripplex.io
# Delete any existing lockfile.
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

45
.github/scripts/execute-tests-under-sanitizer vendored Executable file
View File

@@ -0,0 +1,45 @@
#!/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"
for TEST in $TESTS; do
OUTPUT_FILE="$OUTPUT_DIR/${TEST//\//_}"
export TSAN_OPTIONS="log_path=\"$OUTPUT_FILE\" die_after_fork=0"
export ASAN_OPTIONS="log_path=\"$OUTPUT_FILE\""
export UBSAN_OPTIONS="log_path=\"$OUTPUT_FILE\""
export MallocNanoZone='0' # for MacOSX
$TEST_BINARY --gtest_filter="$TEST" > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "'$TEST' failed a sanitizer check."
fi
done

View File

@@ -20,5 +20,5 @@ for artifact_name in $(ls); do
rm "${artifact_name}/${BINARY_NAME}" rm "${artifact_name}/${BINARY_NAME}"
rm -r "${artifact_name}" rm -r "${artifact_name}"
sha256sum "./${artifact_name}.zip" >"./${artifact_name}.zip.sha256sum" sha256sum "./${artifact_name}.zip" > "./${artifact_name}.zip.sha256sum"
done done

View File

@@ -8,13 +8,14 @@ on:
paths: paths:
- .github/workflows/build.yml - .github/workflows/build.yml
- .github/workflows/reusable-build-test.yml - .github/workflows/build_and_test.yml
- .github/workflows/reusable-build.yml - .github/workflows/build_impl.yml
- .github/workflows/reusable-test.yml - .github/workflows/test_impl.yml
- .github/workflows/reusable-upload-coverage-report.yml - .github/workflows/upload_coverage_report.yml
- ".github/actions/**" - ".github/actions/**"
- "!.github/actions/build-docker-image/**" - "!.github/actions/build_docker_image/**"
- "!.github/actions/create_issue/**"
- CMakeLists.txt - CMakeLists.txt
- conanfile.py - conanfile.py
@@ -22,7 +23,6 @@ on:
- "cmake/**" - "cmake/**"
- "src/**" - "src/**"
- "tests/**" - "tests/**"
- "benchmarks/**"
- docs/config-description.md - docs/config-description.md
workflow_dispatch: workflow_dispatch:
@@ -33,10 +33,6 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/develop' && github.run_number || 'branch' }} group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/develop' && github.run_number || 'branch' }}
cancel-in-progress: true cancel-in-progress: true
defaults:
run:
shell: bash
jobs: jobs:
build-and-test: build-and-test:
name: Build and Test name: Build and Test
@@ -45,24 +41,28 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [heavy] os: [heavy]
compiler: [gcc, clang] conan_profile: [gcc, clang]
build_type: [Release, Debug] build_type: [Release, Debug]
container: ['{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }'] container:
[
'{ "image": "ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d" }',
]
static: [true]
include: include:
- os: macos15 - os: macos15
compiler: apple-clang conan_profile: apple-clang
build_type: Release build_type: Release
container: "" container: ""
static: false
uses: ./.github/workflows/reusable-build-test.yml uses: ./.github/workflows/build_and_test.yml
with: with:
runs_on: ${{ matrix.os }} runs_on: ${{ matrix.os }}
container: ${{ matrix.container }} container: ${{ matrix.container }}
compiler: ${{ matrix.compiler }} conan_profile: ${{ matrix.conan_profile }}
build_type: ${{ matrix.build_type }} build_type: ${{ matrix.build_type }}
download_ccache: true static: ${{ matrix.static }}
upload_ccache: true
run_unit_tests: true run_unit_tests: true
run_integration_tests: false run_integration_tests: false
upload_clio_server: true upload_clio_server: true
@@ -70,36 +70,54 @@ jobs:
code_coverage: code_coverage:
name: Run Code Coverage name: Run Code Coverage
uses: ./.github/workflows/reusable-build.yml uses: ./.github/workflows/build_impl.yml
with: with:
runs_on: heavy runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }' container: '{ "image": "ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d" }'
compiler: gcc conan_profile: gcc
build_type: Debug build_type: Debug
download_ccache: true disable_cache: false
upload_ccache: true
code_coverage: true code_coverage: true
static: true
upload_clio_server: false upload_clio_server: false
targets: all targets: all
analyze_build_time: false analyze_build_time: false
secrets: secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
package:
name: Build packages
uses: ./.github/workflows/build_impl.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d" }'
conan_profile: gcc
build_type: Release
disable_cache: false
code_coverage: false
static: true
upload_clio_server: false
package: true
targets: package
analyze_build_time: false
check_config: check_config:
name: Check Config Description name: Check Config Description
needs: build-and-test needs: build-and-test
runs-on: heavy runs-on: heavy
container: container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b image: ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@v4
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - uses: actions/download-artifact@v5
with: with:
name: clio_server_Linux_Release_gcc name: clio_server_Linux_Release_gcc
- name: Compare Config Description - name: Compare Config Description
shell: bash
run: | run: |
repoConfigFile=docs/config-description.md repoConfigFile=docs/config-description.md
configDescriptionFile=config_description_new.md configDescriptionFile=config_description_new.md

View File

@@ -13,34 +13,28 @@ on:
required: true required: true
type: string type: string
compiler: conan_profile:
description: 'Compiler to build with ("gcc", "clang" or "apple-clang")' description: Conan profile to use
required: true required: true
type: string type: string
sanitizers:
description: 'Sanitizers to enable ("address", "thread", "undefinedbehavior" or empty)'
required: false
type: string
default: ""
build_type: build_type:
description: Build type description: Build type
required: true required: true
type: string type: string
download_ccache: disable_cache:
description: Whether to download ccache from the cache description: Whether ccache should be disabled
required: false
type: boolean
default: true
upload_ccache:
description: Whether to upload ccache to the cache
required: false required: false
type: boolean type: boolean
default: false default: false
static:
description: Whether to build static binaries
required: true
type: boolean
default: true
run_unit_tests: run_unit_tests:
description: Whether to run unit tests description: Whether to run unit tests
required: true required: true
@@ -63,44 +57,42 @@ on:
type: string type: string
default: all default: all
expected_version:
description: Expected version of the clio_server binary
required: false
type: string
default: ""
package: package:
description: Whether to generate Debian package description: Whether to generate Debian package
required: false required: false
type: boolean type: boolean
default: false default: false
version:
description: Version of the clio_server binary
required: false
type: string
default: ""
jobs: jobs:
build: build:
uses: ./.github/workflows/reusable-build.yml uses: ./.github/workflows/build_impl.yml
with: with:
runs_on: ${{ inputs.runs_on }} runs_on: ${{ inputs.runs_on }}
container: ${{ inputs.container }} container: ${{ inputs.container }}
compiler: ${{ inputs.compiler }} conan_profile: ${{ inputs.conan_profile }}
sanitizers: ${{ inputs.sanitizers }}
build_type: ${{ inputs.build_type }} build_type: ${{ inputs.build_type }}
download_ccache: ${{ inputs.download_ccache }} disable_cache: ${{ inputs.disable_cache }}
upload_ccache: ${{ inputs.upload_ccache }}
code_coverage: false code_coverage: false
static: ${{ inputs.static }}
upload_clio_server: ${{ inputs.upload_clio_server }} upload_clio_server: ${{ inputs.upload_clio_server }}
targets: ${{ inputs.targets }} targets: ${{ inputs.targets }}
analyze_build_time: false analyze_build_time: false
expected_version: ${{ inputs.expected_version }}
package: ${{ inputs.package }} package: ${{ inputs.package }}
version: ${{ inputs.version }}
test: test:
needs: build needs: build
uses: ./.github/workflows/reusable-test.yml uses: ./.github/workflows/test_impl.yml
with: with:
runs_on: ${{ inputs.runs_on }} runs_on: ${{ inputs.runs_on }}
container: ${{ inputs.container }} container: ${{ inputs.container }}
compiler: ${{ inputs.compiler }} conan_profile: ${{ inputs.conan_profile }}
sanitizers: ${{ inputs.sanitizers }}
build_type: ${{ inputs.build_type }} build_type: ${{ inputs.build_type }}
run_unit_tests: ${{ inputs.run_unit_tests }} run_unit_tests: ${{ inputs.run_unit_tests }}
run_integration_tests: ${{ inputs.run_integration_tests }} run_integration_tests: ${{ inputs.run_integration_tests }}

View File

@@ -14,9 +14,9 @@ on:
type: boolean type: boolean
description: Whether to strip clio binary description: Whether to strip clio binary
default: true default: true
push_image: publish_image:
type: boolean type: boolean
description: Whether to push docker image description: Whether to publish docker image
required: true required: true
workflow_dispatch: workflow_dispatch:
@@ -38,45 +38,40 @@ on:
description: Whether to strip clio binary description: Whether to strip clio binary
default: true default: true
defaults:
run:
shell: bash
jobs: jobs:
build_and_push_image: build_and_publish_image:
name: Build and publish image name: Build and publish image
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@v4
- name: Download Clio binary from artifact - name: Download Clio binary from artifact
if: ${{ inputs.artifact_name != null }} if: ${{ inputs.artifact_name != null }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 uses: actions/download-artifact@v5
with: with:
name: ${{ inputs.artifact_name }} name: ${{ inputs.artifact_name }}
path: ./docker/clio/artifact/ path: ./docker/clio/artifact/
- name: Download Clio binary from url - name: Download Clio binary from url
if: ${{ inputs.clio_server_binary_url != null }} if: ${{ inputs.clio_server_binary_url != null }}
env: shell: bash
BINARY_URL: ${{ inputs.clio_server_binary_url }}
BINARY_SHA256: ${{ inputs.binary_sha256 }}
run: | run: |
wget "${BINARY_URL}" -P ./docker/clio/artifact/ wget "${{inputs.clio_server_binary_url}}" -P ./docker/clio/artifact/
if [ "$(sha256sum ./docker/clio/clio_server | awk '{print $1}')" != "${BINARY_SHA256}" ]; then if [ "$(sha256sum ./docker/clio/clio_server | awk '{print $1}')" != "${{inputs.binary_sha256}}" ]; then
echo "Binary sha256 sum doesn't match" echo "Binary sha256 sum doesn't match"
exit 1 exit 1
fi fi
- name: Unpack binary - name: Unpack binary
shell: bash
run: | run: |
sudo apt update && sudo apt install -y tar unzip sudo apt update && sudo apt install -y tar unzip
cd docker/clio/artifact cd docker/clio/artifact
artifact=$(find . -type f) artifact=$(find . -type f)
if [[ $artifact == *.zip ]]; then if [[ $artifact == *.zip ]]; then
unzip $artifact unzip $artifact
elif [[ $artifact == *.tar.gz ]]; then elif [[ $artifact == *.tar.gz ]]; then
tar -xvf $artifact tar -xvf $artifact
fi fi
chmod +x ./clio_server chmod +x ./clio_server
mv ./clio_server ../ mv ./clio_server ../
@@ -85,15 +80,16 @@ jobs:
- name: Strip binary - name: Strip binary
if: ${{ inputs.strip_binary }} if: ${{ inputs.strip_binary }}
shell: bash
run: strip ./docker/clio/clio_server run: strip ./docker/clio/clio_server
- name: Set GHCR_REPO - name: Set GHCR_REPO
id: set-ghcr-repo id: set-ghcr-repo
run: | 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 - name: Build Docker image
uses: ./.github/actions/build-docker-image uses: ./.github/actions/build_docker_image
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }} DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
@@ -102,7 +98,7 @@ jobs:
images: | images: |
ghcr.io/${{ steps.set-ghcr-repo.outputs.GHCR_REPO }}/clio ghcr.io/${{ steps.set-ghcr-repo.outputs.GHCR_REPO }}/clio
${{ github.repository_owner == 'XRPLF' && 'rippleci/clio' || '' }} ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio' || '' }}
push_image: ${{ inputs.push_image }} push_image: ${{ inputs.publish_image }}
directory: docker/clio directory: docker/clio
tags: ${{ inputs.tags }} tags: ${{ inputs.tags }}
platforms: linux/amd64 platforms: linux/amd64

236
.github/workflows/build_impl.yml vendored Normal file
View File

@@ -0,0 +1,236 @@
name: Reusable build
on:
workflow_call:
inputs:
runs_on:
description: Runner to run the job on
required: true
type: string
container:
description: "The container object as a JSON string (leave empty to run natively)"
required: true
type: string
conan_profile:
description: Conan profile to use
required: true
type: string
build_type:
description: Build type
required: true
type: string
disable_cache:
description: Whether ccache should be disabled
required: false
type: boolean
code_coverage:
description: Whether to enable code coverage
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
type: boolean
targets:
description: Space-separated build target names
required: true
type: string
analyze_build_time:
description: Whether to enable build time analysis
required: true
type: boolean
expected_version:
description: Expected version of the clio_server binary
required: false
type: string
default: ""
package:
description: Whether to generate Debian package
required: false
type: boolean
secrets:
CODECOV_TOKEN:
required: false
jobs:
build:
name: Build
runs-on: ${{ inputs.runs_on }}
container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
- uses: actions/checkout@v4
with:
fetch-depth: 0
# We need to fetch tags to have correct version in the release
# The workaround is based on https://github.com/actions/checkout/issues/1467
fetch-tags: true
ref: ${{ github.ref }}
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
with:
disable_ccache: ${{ inputs.disable_cache }}
- name: Setup conan on macOS
if: runner.os == 'macOS'
shell: bash
run: ./.github/scripts/conan/init.sh
- name: Restore cache
if: ${{ !inputs.disable_cache }}
uses: ./.github/actions/restore_cache
id: restore_cache
with:
conan_profile: ${{ inputs.conan_profile }}
ccache_dir: ${{ env.CCACHE_DIR }}
build_type: ${{ inputs.build_type }}
code_coverage: ${{ inputs.code_coverage }}
- name: Run conan
uses: ./.github/actions/conan
with:
conan_profile: ${{ inputs.conan_profile }}
build_type: ${{ inputs.build_type }}
- 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 }}
- name: Build Clio
uses: ./.github/actions/build_clio
with:
targets: ${{ inputs.targets }}
- name: Show build time analyze report
if: ${{ inputs.analyze_build_time }}
run: |
ClangBuildAnalyzer --all build/ build_time_report.bin
ClangBuildAnalyzer --analyze build_time_report.bin > build_time_report.txt
cat build_time_report.txt
shell: bash
- name: Upload build time analyze report
if: ${{ inputs.analyze_build_time }}
uses: actions/upload-artifact@v4
with:
name: build_time_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build_time_report.txt
- name: Show ccache's statistics
if: ${{ !inputs.disable_cache }}
shell: bash
id: ccache_stats
run: |
ccache -s > /tmp/ccache.stats
miss_rate=$(cat /tmp/ccache.stats | grep 'Misses' | head -n1 | sed 's/.*(\(.*\)%).*/\1/')
echo "miss_rate=${miss_rate}" >> $GITHUB_OUTPUT
cat /tmp/ccache.stats
- name: Strip unit_tests
if: ${{ !endsWith(inputs.conan_profile, 'san') && !inputs.code_coverage && !inputs.analyze_build_time }}
run: strip build/clio_tests
- name: Strip integration_tests
if: ${{ !endsWith(inputs.conan_profile, 'san') && !inputs.code_coverage && !inputs.analyze_build_time }}
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@v4
with:
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@v4
with:
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@v4
with:
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@v4
with:
name: clio_deb_package_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build/*.deb
- name: Save cache
if: ${{ !inputs.disable_cache && github.ref == 'refs/heads/develop' }}
uses: ./.github/actions/save_cache
with:
conan_profile: ${{ inputs.conan_profile }}
ccache_dir: ${{ env.CCACHE_DIR }}
build_type: ${{ inputs.build_type }}
code_coverage: ${{ inputs.code_coverage }}
ccache_cache_hit: ${{ steps.restore_cache.outputs.ccache_cache_hit }}
ccache_cache_miss_rate: ${{ steps.ccache_stats.outputs.miss_rate }}
# This is run as part of the build job, because it requires the following:
# - source code
# - conan packages
# - .gcno files in build directory
#
# It's all available in the build job, but not in the test job
- name: Run code coverage
if: ${{ inputs.code_coverage }}
uses: ./.github/actions/code_coverage
- name: Verify expected version
if: ${{ inputs.expected_version != '' }}
shell: bash
run: |
set -e
EXPECTED_VERSION="clio-${{ inputs.expected_version }}"
actual_version=$(./build/clio_server --version)
if [[ "$actual_version" != "$EXPECTED_VERSION" ]]; then
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
# To prevent this from happening, we run this action in a separate workflow
#
# More info: https://github.com/XRPLF/clio/pull/2066
upload_coverage_report:
if: ${{ inputs.code_coverage }}
name: Codecov
needs: build
uses: ./.github/workflows/upload_coverage_report.yml
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -1,10 +0,0 @@
name: Check PR title
on:
pull_request:
types: [opened, edited, reopened, synchronize]
branches: [develop]
jobs:
check_title:
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81

View File

@@ -10,63 +10,54 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
env: env:
COMPILER: gcc CONAN_PROFILE: gcc
defaults:
run:
shell: bash
jobs: jobs:
build: build:
name: Build Clio / `libXRPL ${{ github.event.client_payload.version }}` name: Build Clio / `libXRPL ${{ github.event.client_payload.version }}`
runs-on: heavy runs-on: heavy
container: container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b image: ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
with: with:
enable_ccache: false disable_ccache: true
- 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 - name: Update libXRPL version requirement
shell: bash
run: | run: |
sed -i.bak -E "s|'xrpl/[a-zA-Z0-9\\.\\-]+'|'xrpl/${{ github.event.client_payload.conan_ref }}'|g" conanfile.py sed -i.bak -E "s|'xrpl/[a-zA-Z0-9\\.\\-]+'|'xrpl/${{ github.event.client_payload.conan_ref }}'|g" conanfile.py
rm -f conanfile.py.bak rm -f conanfile.py.bak
- name: Update conan lockfile - name: Update conan lockfile
shell: bash
run: | run: |
conan lock create . --profile:all ci conan lock create . --profile:all ${{ env.CONAN_PROFILE }}
- name: Run conan - name: Run conan
uses: ./.github/actions/conan uses: ./.github/actions/conan
with:
conan_profile: ${{ env.CONAN_PROFILE }}
- name: Run CMake - name: Run CMake
uses: ./.github/actions/cmake uses: ./.github/actions/cmake
with:
conan_profile: ${{ env.CONAN_PROFILE }}
- name: Build Clio - name: Build Clio
uses: ./.github/actions/build-clio uses: ./.github/actions/build_clio
- name: Strip tests - name: Strip tests
run: strip build/clio_tests run: strip build/clio_tests
- name: Upload clio_tests - name: Upload clio_tests
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@v4
with: with:
name: clio_tests_check_libxrpl name: clio_tests_check_libxrpl
path: build/clio_tests path: build/clio_tests
@@ -76,10 +67,10 @@ jobs:
needs: build needs: build
runs-on: heavy runs-on: heavy
container: container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b image: ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d
steps: steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - uses: actions/download-artifact@v5
with: with:
name: clio_tests_check_libxrpl name: clio_tests_check_libxrpl
@@ -99,15 +90,17 @@ jobs:
issues: write issues: write
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@v4
- name: Create an issue - name: Create an issue
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712 uses: ./.github/actions/create_issue
env:
GH_TOKEN: ${{ github.token }}
with: with:
labels: "compatibility,bug"
title: "Proposed libXRPL check failed" title: "Proposed libXRPL check failed"
body: > body: >
Clio build or tests failed against `libXRPL ${{ github.event.client_payload.conan_ref }}`. Clio build or tests failed against `libXRPL ${{ github.event.client_payload.conan_ref }}`.
PR: ${{ github.event.client_payload.pr_url }} PR: ${{ github.event.client_payload.pr_url }}
labels: "compatibility,bug" Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
assignees: "godexsoft,kuznetsss,mathbunnyru"

17
.github/workflows/check_pr_title.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Check PR title
on:
pull_request:
types: [opened, edited, reopened, synchronize]
branches: [develop]
jobs:
check_title:
runs-on: ubuntu-latest
steps:
- uses: ytanikin/pr-conventional-commits@b72758283dcbee706975950e96bc4bf323a8d8c0 # v1.4.2
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"}'

View File

@@ -1,22 +1,14 @@
name: Run clang-tidy on files name: Clang-tidy check
on: on:
push: schedule:
branches: [develop] - cron: "0 9 * * 1-5"
workflow_dispatch: workflow_dispatch:
pull_request: pull_request:
branches: [develop] branches: [develop]
paths: paths:
- .github/workflows/clang-tidy.yml - .github/workflows/clang-tidy.yml
- CMakeLists.txt
- conanfile.py
- conan.lock
- "cmake/**"
- "src/**"
- "tests/**"
- "benchmarks/**"
- .clang_tidy - .clang_tidy
concurrency: concurrency:
@@ -25,34 +17,14 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
env: env:
BUILD_DIR: build CONAN_PROFILE: clang
BUILD_TYPE: Debug # Debug so that ASSERTS and such participate in clang-tidy check LLVM_TOOLS_VERSION: 20
OUTPUT_FILE: /tmp/clang-tidy-output.txt
FILTERED_OUTPUT_FILE: /tmp/clang-tidy-filtered-output.txt
DIFF_FILE: /tmp/clang-tidy-git-diff.txt
ISSUE_FILE: /tmp/clang-tidy-issue.md
COMPILER: clang
defaults:
run:
shell: bash
jobs: jobs:
determine-files: clang_tidy:
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') }}
runs-on: heavy runs-on: heavy
container: container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b image: ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d
permissions: permissions:
contents: write contents: write
@@ -60,142 +32,73 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
with: with:
enable_ccache: false disable_ccache: true
- name: Print build environment - name: Restore cache
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574 uses: ./.github/actions/restore_cache
id: restore_cache
- name: Set compiler environment
uses: ./.github/actions/set-compiler-env
with: with:
compiler: ${{ env.COMPILER }} conan_profile: ${{ env.CONAN_PROFILE }}
ccache_dir: ${{ env.CCACHE_DIR }}
- name: Setup conan
run: conan/init.sh
- name: Run conan - name: Run conan
uses: ./.github/actions/conan uses: ./.github/actions/conan
with: with:
build_dir: ${{ env.BUILD_DIR }} conan_profile: ${{ env.CONAN_PROFILE }}
build_type: ${{ env.BUILD_TYPE }}
- name: Run CMake - name: Run CMake
uses: ./.github/actions/cmake uses: ./.github/actions/cmake
with: with:
build_dir: ${{ env.BUILD_DIR }} conan_profile: ${{ env.CONAN_PROFILE }}
build_type: ${{ env.BUILD_TYPE }}
- name: Get number of processors - name: Get number of threads
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf uses: ./.github/actions/get_number_of_threads
id: nproc id: number_of_threads
- name: Run clang tidy - name: Run clang-tidy
continue-on-error: true continue-on-error: true
shell: bash
id: run_clang_tidy 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' }}
run: | run: |
set -o pipefail run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j "${{ steps.number_of_threads.outputs.threads_number }}" -fix -quiet 1>output.txt
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 - name: Fix local includes and clang-format style
if: ${{ steps.run_clang_tidy.outcome != 'success' }} if: ${{ steps.run_clang_tidy.outcome != 'success' }}
shell: bash
run: | run: |
sed '/error\||/!d' "${OUTPUT_FILE}" pre-commit run --all-files fix-local-includes || true
pre-commit run --all-files clang-format || true
- name: Upload clang-tidy output - name: Print issues found
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
- name: Check for changes
id: files_changed
continue-on-error: true
run: |
git diff --exit-code
- name: Fix style
if: ${{ steps.files_changed.outcome != 'success' }}
run: |
pre-commit run --all-files || 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
with:
path: ${{ env.DIFF_FILE }}
archive: false
retention-days: 30
- name: Write issue header
if: ${{ steps.run_clang_tidy.outcome != 'success' }} if: ${{ steps.run_clang_tidy.outcome != 'success' }}
shell: bash
run: | run: |
cat >"${ISSUE_FILE}" <<EOF sed -i '/error\||/!d' ./output.txt
## Clang-tidy Check Failed cat output.txt
rm output.txt
### Clang-tidy Output: - name: Create an issue
\`\`\`
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_FILE}" || true
# If filtered output is empty, use original (might be a different error format)
if [ ! -s "${FILTERED_OUTPUT_FILE}" ]; then
cp "${OUTPUT_FILE}" "${FILTERED_OUTPUT_FILE}"
fi
# Truncate if too large
head -c 60000 "${FILTERED_OUTPUT_FILE}" >>"${ISSUE_FILE}"
if [ "$(wc -c <"${FILTERED_OUTPUT_FILE}")" -gt 60000 ]; then
echo "" >>"${ISSUE_FILE}"
echo "... (output truncated, see artifacts for full output)" >>"${ISSUE_FILE}"
fi
rm "${FILTERED_OUTPUT_FILE}"
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
id: create_issue
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }} if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712 id: create_issue
uses: ./.github/actions/create_issue
env:
GH_TOKEN: ${{ github.token }}
with: with:
title: "Clang-tidy check failed" title: "Clang-tidy found bugs in code 🐛"
body_file: ${{ env.ISSUE_FILE }} body: >
labels: "bug" Clang-tidy found issues in the code:
assignees: "godexsoft,mathbunnyru"
- uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd # v7.0.0 List of the issues found: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
if: ${{ steps.files_changed.outcome != 'success' && github.event_name != 'pull_request' }}
- uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
with: with:
gpg_private_key: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }} gpg_private_key: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.ACTIONS_GPG_PASSPHRASE }} passphrase: ${{ secrets.ACTIONS_GPG_PASSPHRASE }}
@@ -203,8 +106,8 @@ jobs:
git_commit_gpgsign: true git_commit_gpgsign: true
- name: Create PR with fixes - name: Create PR with fixes
if: ${{ steps.files_changed.outcome != 'success' && github.event_name != 'pull_request' }} if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
env: env:
GH_REPO: ${{ github.repository }} GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
@@ -214,15 +117,11 @@ jobs:
branch: "clang_tidy/autofix" branch: "clang_tidy/autofix"
branch-suffix: timestamp branch-suffix: timestamp
delete-branch: true delete-branch: true
title: "style: Apply clang-tidy auto fixes" title: "style: clang-tidy auto fixes"
body: > body: "Fixes #${{ steps.create_issue.outputs.created_issue_id }}. Please review and commit clang-tidy fixes."
Fixes #${{ steps.create_issue.outputs.issue_number }}. reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
Please review and commit clang-tidy fixes.
reviewers: "godexsoft,kuznetsss,mathbunnyru"
- name: Fail the job - name: Fail the job
if: ${{ steps.run_clang_tidy.outcome != 'success' }} if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: | shell: bash
echo "Clang-tidy check failed!" run: exit 1
exit 1

View File

@@ -0,0 +1,30 @@
name: Restart clang-tidy workflow
on:
push:
branches: [develop]
workflow_dispatch:
jobs:
restart_clang_tidy:
runs-on: ubuntu-latest
permissions:
actions: write
steps:
- uses: actions/checkout@v4
- name: Check last commit matches clang-tidy auto fixes
id: check
shell: bash
run: |
passed=$(if [[ "$(git log -1 --pretty=format:%s | grep 'style: clang-tidy auto fixes')" ]]; then echo 'true' ; else echo 'false' ; fi)
echo "passed=\"$passed\"" >> $GITHUB_OUTPUT
- name: Run clang-tidy workflow
if: ${{ contains(steps.check.outputs.passed, 'true') }}
shell: bash
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: gh workflow run clang-tidy.yml

View File

@@ -4,47 +4,28 @@ on:
push: push:
branches: [develop] branches: [develop]
workflow_dispatch: workflow_dispatch:
pull_request:
branches: [release/*, develop]
paths:
- .github/workflows/docs.yml
- CMakeLists.txt
- conanfile.py
- conan.lock
- "cmake/**"
- "docs/**"
- "src/**"
- "tests/**"
concurrency: concurrency:
# Only cancel in-progress jobs or runs for the current workflow - matches against branch & tags # Only cancel in-progress jobs or runs for the current workflow - matches against branch & tags
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
defaults:
run:
shell: bash
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b image: ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 uses: actions/checkout@v4
with: with:
lfs: true lfs: true
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
with: with:
enable_ccache: false disable_ccache: true
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
- name: Create build directory - name: Create build directory
run: mkdir build_docs run: mkdir build_docs
@@ -58,17 +39,15 @@ jobs:
run: cmake --build . --target docs run: cmake --build . --target docs
- name: Setup Pages - name: Setup Pages
if: ${{ github.repository == 'XRPLF/clio' && github.event_name == 'push' }} uses: actions/configure-pages@v5
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 uses: actions/upload-pages-artifact@v4
with: with:
path: build_docs/html path: build_docs/html
name: docs-develop name: docs-develop
deploy: deploy:
if: ${{ github.repository == 'XRPLF/clio' && github.event_name == 'push' }}
needs: build needs: build
permissions: permissions:
pages: write pages: write
@@ -83,6 +62,6 @@ jobs:
steps: steps:
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 uses: actions/deploy-pages@v4
with: with:
artifact_name: docs-develop artifact_name: docs-develop

View File

@@ -8,14 +8,14 @@ on:
paths: paths:
- .github/workflows/nightly.yml - .github/workflows/nightly.yml
- .github/workflows/reusable-release.yml - .github/workflows/release_impl.yml
- .github/workflows/reusable-build-test.yml - .github/workflows/build_and_test.yml
- .github/workflows/reusable-build.yml - .github/workflows/build_impl.yml
- .github/workflows/reusable-test.yml - .github/workflows/test_impl.yml
- .github/workflows/build-clio-docker-image.yml - .github/workflows/build_clio_docker_image.yml
- ".github/actions/**" - ".github/actions/**"
- "!.github/actions/code-coverage/**" - "!.github/actions/code_coverage/**"
- .github/scripts/prepare-release-artifacts.sh - .github/scripts/prepare-release-artifacts.sh
concurrency: concurrency:
@@ -23,125 +23,91 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
defaults:
run:
shell: bash
jobs: jobs:
get_date:
name: Get Date
runs-on: ubuntu-latest
outputs:
date: ${{ steps.get_date.outputs.date }}
steps:
- name: Get current date
id: get_date
run: |
echo "date=$(date +'%Y%m%d')" >>$GITHUB_OUTPUT
build-and-test: build-and-test:
name: Build and Test name: Build and Test
needs: get_date
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: macos15 - os: macos15
compiler: apple-clang conan_profile: apple-clang
build_type: Release build_type: Release
static: false
- os: heavy - os: heavy
compiler: gcc conan_profile: gcc
build_type: Release build_type: Release
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }' static: true
container: '{ "image": "ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d" }'
- os: heavy - os: heavy
compiler: gcc conan_profile: gcc
build_type: Debug build_type: Debug
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }' static: true
container: '{ "image": "ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d" }'
- os: heavy - os: heavy
compiler: gcc conan_profile: gcc.ubsan
sanitizers: undefinedbehavior
build_type: Release build_type: Release
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }' static: false
container: '{ "image": "ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d" }'
uses: ./.github/workflows/reusable-build-test.yml uses: ./.github/workflows/build_and_test.yml
with: with:
runs_on: ${{ matrix.os }} runs_on: ${{ matrix.os }}
container: ${{ matrix.container }} container: ${{ matrix.container }}
compiler: ${{ matrix.compiler }} conan_profile: ${{ matrix.conan_profile }}
sanitizers: ${{ matrix.sanitizers }}
build_type: ${{ matrix.build_type }} build_type: ${{ matrix.build_type }}
static: ${{ matrix.static }}
run_unit_tests: true run_unit_tests: true
run_integration_tests: true run_integration_tests: true
upload_clio_server: true upload_clio_server: true
download_ccache: false disable_cache: true
upload_ccache: false
version: nightly-${{ needs.get_date.outputs.date }}
package:
name: Build debian package
needs: get_date
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }'
compiler: gcc
build_type: Release
download_ccache: false
upload_ccache: false
code_coverage: false
upload_clio_server: false
package: true
version: nightly-${{ needs.get_date.outputs.date }}
targets: package
analyze_build_time: false
analyze_build_time: analyze_build_time:
name: Analyze Build Time name: Analyze Build Time
needs: get_date
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: heavy - os: heavy
compiler: clang conan_profile: clang
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }' container: '{ "image": "ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d" }'
static: true
- os: macos15 - os: macos15
compiler: apple-clang conan_profile: apple-clang
container: "" container: ""
uses: ./.github/workflows/reusable-build.yml static: false
uses: ./.github/workflows/build_impl.yml
with: with:
runs_on: ${{ matrix.os }} runs_on: ${{ matrix.os }}
container: ${{ matrix.container }} container: ${{ matrix.container }}
compiler: ${{ matrix.compiler }} conan_profile: ${{ matrix.conan_profile }}
build_type: Release build_type: Release
download_ccache: false disable_cache: true
upload_ccache: false
code_coverage: false code_coverage: false
static: ${{ matrix.static }}
upload_clio_server: false upload_clio_server: false
targets: all targets: all
analyze_build_time: true analyze_build_time: true
version: nightly-${{ needs.get_date.outputs.date }}
nightly_release: nightly_release:
needs: [build-and-test, package, get_date] needs: build-and-test
uses: ./.github/workflows/reusable-release.yml uses: ./.github/workflows/release_impl.yml
with: with:
delete_pattern: "nightly-*" overwrite_release: true
prerelease: true prerelease: true
title: "Clio development build (nightly-${{ needs.get_date.outputs.date }})" title: "Clio development (nightly) build"
version: nightly-${{ needs.get_date.outputs.date }} version: nightly
header: > header: >
> **Note:** Please remember that this is a development release and it is not recommended for production use. > **Note:** Please remember that this is a development release and it is not recommended for production use.
Changelog (including previous releases): <https://github.com/XRPLF/clio/commits/nightly-${{ needs.get_date.outputs.date }}> Changelog (including previous releases): <https://github.com/XRPLF/clio/commits/nightly>
generate_changelog: false generate_changelog: false
draft: false draft: false
build_and_publish_docker_image: build_and_publish_docker_image:
uses: ./.github/workflows/build-clio-docker-image.yml uses: ./.github/workflows/build_clio_docker_image.yml
needs: build-and-test needs: build-and-test
secrets: inherit secrets: inherit
with: with:
@@ -150,7 +116,7 @@ jobs:
type=raw,value=${{ github.sha }} type=raw,value=${{ github.sha }}
artifact_name: clio_server_Linux_Release_gcc artifact_name: clio_server_Linux_Release_gcc
strip_binary: true 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: create_issue_on_failure:
needs: [build-and-test, nightly_release, build_and_publish_docker_image] needs: [build-and-test, nightly_release, build_and_publish_docker_image]
@@ -162,12 +128,15 @@ jobs:
issues: write issues: write
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@v4
- name: Create an issue - name: Create an issue
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712 uses: ./.github/actions/create_issue
env:
GH_TOKEN: ${{ github.token }}
with: with:
title: "Nightly release failed 🌙" title: "Nightly release failed 🌙"
body: "" body: >
labels: "bug" Nightly release failed:
assignees: "godexsoft,kuznetsss,mathbunnyru"
Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/

View File

@@ -1,8 +1,8 @@
name: Pre-commit auto-update name: Pre-commit auto-update
on: on:
# every first day of the month
schedule: schedule:
# every first day of the month
- cron: "0 0 1 * *" - cron: "0 0 1 * *"
pull_request: pull_request:
branches: [release/*, develop] branches: [release/*, develop]
@@ -12,11 +12,11 @@ on:
jobs: jobs:
auto-update: auto-update:
uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@5e942d61bf32f7557a7c159cfac4712a687b3e3a uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@afbcbdafbe0ce5439492fb87eda6441371086386
with: with:
sign_commit: true sign_commit: true
committer: "Clio CI <skuznetsov@ripple.com>" committer: "Clio CI <skuznetsov@ripple.com>"
reviewers: "godexsoft,kuznetsss,mathbunnyru" reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
secrets: secrets:
GPG_PRIVATE_KEY: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.ACTIONS_GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.ACTIONS_GPG_PASSPHRASE }}

View File

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

View File

@@ -22,53 +22,37 @@ jobs:
matrix: matrix:
include: include:
- os: macos15 - os: macos15
compiler: apple-clang conan_profile: apple-clang
build_type: Release build_type: Release
static: false
- os: heavy - os: heavy
compiler: gcc conan_profile: gcc
build_type: Release build_type: Release
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }' static: true
container: '{ "image": "ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d" }'
uses: ./.github/workflows/reusable-build-test.yml uses: ./.github/workflows/build_and_test.yml
with: with:
runs_on: ${{ matrix.os }} runs_on: ${{ matrix.os }}
container: ${{ matrix.container }} container: ${{ matrix.container }}
compiler: ${{ matrix.compiler }} conan_profile: ${{ matrix.conan_profile }}
build_type: ${{ matrix.build_type }} build_type: ${{ matrix.build_type }}
static: ${{ matrix.static }}
run_unit_tests: true run_unit_tests: true
run_integration_tests: true run_integration_tests: true
upload_clio_server: true upload_clio_server: true
download_ccache: false disable_cache: true
upload_ccache: false expected_version: ${{ github.event_name == 'push' && github.ref_name || '' }}
version: ${{ github.event_name == 'push' && github.ref_name || '' }}
package:
name: Build debian package
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }'
compiler: gcc
build_type: Release
download_ccache: false
upload_ccache: false
code_coverage: false
upload_clio_server: false
package: true
version: ${{ github.event_name == 'push' && github.ref_name || '' }}
targets: package
analyze_build_time: false
release: release:
needs: [build-and-test, package] needs: build-and-test
uses: ./.github/workflows/reusable-release.yml uses: ./.github/workflows/release_impl.yml
with: with:
delete_pattern: "" overwrite_release: false
prerelease: ${{ contains(github.ref_name, '-') }} prerelease: ${{ contains(github.ref_name, '-') }}
title: "${{ github.ref_name }}" title: "${{ github.ref_name}}"
version: "${{ github.ref_name }}" version: "${{ github.ref_name }}"
header: > header: >
${{ contains(github.ref_name, '-') && '> **Note:** Please remember that this is a release candidate and it is not recommended for production use.' || '' }} ${{ contains(github.ref_name, '-') && '> **Note:** Please remember that this is a release candidate and it is not recommended for production use.' || '' }}
generate_changelog: ${{ !contains(github.ref_name, '-') }} generate_changelog: ${{ !contains(github.ref_name, '-') }}
draft: ${{ !contains(github.ref_name, '-') }} draft: true

112
.github/workflows/release_impl.yml vendored Normal file
View File

@@ -0,0 +1,112 @@
name: Make release
on:
workflow_call:
inputs:
overwrite_release:
description: "Overwrite the current release and tag"
required: true
type: boolean
prerelease:
description: "Create a prerelease"
required: true
type: boolean
title:
description: "Release title"
required: true
type: string
version:
description: "Release version"
required: true
type: string
header:
description: "Release notes header"
required: true
type: string
generate_changelog:
description: "Generate changelog"
required: true
type: boolean
draft:
description: "Create a draft release"
required: true
type: boolean
jobs:
release:
runs-on: heavy
container:
image: ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
with:
disable_ccache: true
- uses: actions/download-artifact@v5
with:
path: release_artifacts
pattern: clio_server_*
- name: Create release notes
shell: bash
run: |
echo "# Release notes" > "${RUNNER_TEMP}/release_notes.md"
echo "" >> "${RUNNER_TEMP}/release_notes.md"
printf '%s\n' "${{ inputs.header }}" >> "${RUNNER_TEMP}/release_notes.md"
- name: Generate changelog
shell: bash
if: ${{ inputs.generate_changelog }}
run: |
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"
cat CHANGELOG.md >> "${RUNNER_TEMP}/release_notes.md"
- name: Prepare release artifacts
shell: bash
run: .github/scripts/prepare-release-artifacts.sh release_artifacts
- name: Upload release notes
uses: actions/upload-artifact@v4
with:
name: release_notes_${{ inputs.version }}
path: "${RUNNER_TEMP}/release_notes.md"
- name: Remove current release and tag
if: ${{ github.event_name != 'pull_request' && inputs.overwrite_release }}
shell: bash
run: |
gh release delete ${{ inputs.version }} --yes || true
git push origin :${{ inputs.version }} || true
- name: Publish release
if: ${{ github.event_name != 'pull_request' }}
shell: bash
run: |
gh release create "${{ inputs.version }}" \
${{ inputs.prerelease && '--prerelease' || '' }} \
--title "${{ inputs.title }}" \
--target "${GITHUB_SHA}" \
${{ inputs.draft && '--draft' || '' }} \
--notes-file "${RUNNER_TEMP}/release_notes.md" \
./release_artifacts/clio_server*

View File

@@ -1,254 +0,0 @@
name: Reusable build
on:
workflow_call:
inputs:
runs_on:
description: Runner to run the job on
required: true
type: string
container:
description: "The container object as a JSON string (leave empty to run natively)"
required: true
type: string
compiler:
description: 'Compiler to build with ("gcc", "clang" or "apple-clang")'
required: true
type: string
sanitizers:
description: 'Sanitizers to enable ("address", "thread", "undefinedbehavior" or empty)'
required: false
type: string
default: ""
build_type:
description: Build type
required: true
type: string
download_ccache:
description: Whether to download ccache from the cache
required: false
type: boolean
default: true
upload_ccache:
description: Whether to upload ccache to the cache
required: false
type: boolean
default: false
code_coverage:
description: Whether to enable code coverage
required: true
type: boolean
upload_clio_server:
description: Whether to upload clio_server
required: true
type: boolean
targets:
description: Space-separated build target names
required: true
type: string
analyze_build_time:
description: Whether to enable build time analysis
required: true
type: boolean
package:
description: Whether to generate Debian package
required: false
type: boolean
version:
description: Version of the clio_server binary
required: false
type: string
default: ""
secrets:
CODECOV_TOKEN:
required: false
defaults:
run:
shell: bash
jobs:
build:
name: Build
runs-on: ${{ inputs.runs_on }}
container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
enable_ccache: ${{ inputs.download_ccache }}
- 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: ${{ inputs.compiler }}
- name: Setup conan
run: conan/init.sh
- name: Generate build identifier
uses: ./.github/actions/build-identifier
id: build_identifier
with:
build_type: ${{ inputs.build_type }}
compiler: ${{ inputs.compiler }}
code_coverage: ${{ inputs.code_coverage }}
sanitizers: ${{ inputs.sanitizers }}
- name: Restore ccache cache
if: ${{ inputs.download_ccache && github.ref != 'refs/heads/develop' }}
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.build_identifier.outputs.cache_key }}
restore-keys: |
${{ steps.build_identifier.outputs.build_identifier }}
- name: Run conan
uses: ./.github/actions/conan
with:
build_type: ${{ inputs.build_type }}
sanitizers: ${{ inputs.sanitizers }}
- name: Run CMake
uses: ./.github/actions/cmake
with:
build_type: ${{ inputs.build_type }}
code_coverage: ${{ inputs.code_coverage }}
time_trace: ${{ inputs.analyze_build_time }}
package: ${{ inputs.package }}
version: ${{ inputs.version }}
- name: Build Clio
uses: ./.github/actions/build-clio
with:
targets: ${{ inputs.targets }}
- name: Show build time analyze report
if: ${{ inputs.analyze_build_time }}
run: |
ClangBuildAnalyzer --all build/ build_time_report.bin
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
with:
name: build_time_report_${{ steps.build_identifier.outputs.build_identifier }}
path: build_time_report.txt
- name: Show ccache's statistics and zero it
if: ${{ inputs.download_ccache }}
run: |
ccache --show-stats -vv
ccache --zero-stats
- name: Save ccache cache
if: ${{ inputs.upload_ccache && github.ref == 'refs/heads/develop' }}
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.build_identifier.outputs.cache_key }}
- name: Strip unit_tests
if: ${{ inputs.sanitizers == '' && !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 }}
run: strip build/clio_integration_tests
- name: Upload clio_server
if: ${{ inputs.upload_clio_server && !inputs.code_coverage && !inputs.analyze_build_time }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: clio_server_${{ steps.build_identifier.outputs.build_identifier }}
path: build/clio_server
- name: Upload clio_tests
if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: clio_tests_${{ steps.build_identifier.outputs.build_identifier }}
path: build/clio_tests
- name: Upload clio_integration_tests
if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: clio_integration_tests_${{ steps.build_identifier.outputs.build_identifier }}
path: build/clio_integration_tests
- name: Upload Clio Linux package
if: ${{ inputs.package }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: clio_deb_package_${{ steps.build_identifier.outputs.build_identifier }}
path: build/*.deb
# This is run as part of the build job, because it requires the following:
# - source code
# - conan packages
# - .gcno files in build directory
#
# It's all available in the build job, but not in the test job
- name: Run code coverage
if: ${{ inputs.code_coverage }}
uses: ./.github/actions/code-coverage
- name: Verify version is expected
if: ${{ inputs.version != '' }}
env:
INPUT_VERSION: ${{ inputs.version }}
BUILD_TYPE: ${{ inputs.build_type }}
run: |
set -e
EXPECTED_VERSION="clio-${INPUT_VERSION}"
if [[ "${BUILD_TYPE}" == "Debug" ]]; then
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
fi
# `codecov/codecov-action` will rerun `gcov` if it's available and build directory is present
# To prevent this from happening, we run this action in a separate workflow
#
# More info: https://github.com/XRPLF/clio/pull/2066
upload_coverage_report:
if: ${{ inputs.code_coverage }}
name: Codecov
needs: build
uses: ./.github/workflows/reusable-upload-coverage-report.yml
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -1,129 +0,0 @@
name: Make release
on:
workflow_call:
inputs:
delete_pattern:
description: "Pattern to delete previous releases"
required: true
type: string
prerelease:
description: "Create a prerelease"
required: true
type: boolean
title:
description: "Release title"
required: true
type: string
version:
description: "Release version"
required: true
type: string
header:
description: "Release notes header"
required: true
type: string
generate_changelog:
description: "Generate changelog"
required: true
type: boolean
draft:
description: "Create a draft release"
required: true
type: boolean
defaults:
run:
shell: bash
jobs:
release:
runs-on: heavy
container:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
permissions:
contents: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
enable_ccache: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: release_artifacts
pattern: clio_server_*
- name: Prepare release artifacts
run: .github/scripts/prepare-release-artifacts.sh release_artifacts
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: release_artifacts
pattern: clio_deb_package_*
- name: Create release notes
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"
- name: Generate changelog
if: ${{ inputs.generate_changelog }}
run: |
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"
- name: Upload release notes
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release_notes_${{ inputs.version }}
path: "${RUNNER_TEMP}/release_notes.md"
- name: Remove previous release with a pattern
if: ${{ github.event_name != 'pull_request' && inputs.delete_pattern != '' }}
env:
DELETE_PATTERN: ${{ inputs.delete_pattern }}
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
fi
- name: Publish release
if: ${{ github.event_name != 'pull_request' }}
env:
RELEASE_VERSION: ${{ inputs.version }}
PRERELEASE_OPTION: ${{ inputs.prerelease && '--prerelease' || '' }}
RELEASE_TITLE: ${{ inputs.title }}
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_*

View File

@@ -1,182 +0,0 @@
name: Reusable test
on:
workflow_call:
inputs:
runs_on:
description: Runner to run the job on
required: true
type: string
container:
description: "The container object as a JSON string (leave empty to run natively)"
required: true
type: string
compiler:
description: 'Compiler the binaries were built with ("gcc", "clang" or "apple-clang")'
required: true
type: string
sanitizers:
description: 'Sanitizers the binaries were built with ("address", "thread", "undefinedbehavior" or empty)'
required: false
type: string
default: ""
build_type:
description: Build type
required: true
type: string
run_unit_tests:
description: Whether to run unit tests
required: true
type: boolean
run_integration_tests:
description: Whether to run integration tests
required: true
type: boolean
defaults:
run:
shell: bash
jobs:
unit_tests:
name: Unit testing
runs-on: ${{ inputs.runs_on }}
container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}
if: ${{ inputs.run_unit_tests }}
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Generate build identifier
uses: ./.github/actions/build-identifier
id: build_identifier
with:
build_type: ${{ inputs.build_type }}
compiler: ${{ inputs.compiler }}
# code_coverage is run inside build environment
code_coverage: false
sanitizers: ${{ inputs.sanitizers }}
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: clio_tests_${{ steps.build_identifier.outputs.build_identifier }}
- name: Make clio_tests executable
run: chmod +x ./clio_tests
- name: Run clio_tests
continue-on-error: true
id: run_clio_tests
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: Fail the job if clio_tests failed
if: ${{ steps.run_clio_tests.outcome == 'failure' }}
run: exit 1
integration_tests:
name: Integration testing
runs-on: ${{ inputs.runs_on }}
container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}
if: ${{ inputs.run_integration_tests }}
services:
scylladb:
image: ${{ inputs.container != '' && 'scylladb/scylla' || '' }}
options: >-
--health-cmd "cqlsh -e 'describe cluster'"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Generate build identifier
uses: ./.github/actions/build-identifier
id: build_identifier
with:
build_type: ${{ inputs.build_type }}
compiler: ${{ inputs.compiler }}
# code_coverage is run inside build environment
code_coverage: false
sanitizers: ${{ inputs.sanitizers }}
- name: Delete and start colima (macOS)
# This is a temporary workaround for colima issues on macOS runners
if: ${{ runner.os == 'macOS' }}
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.
if: ${{ runner.os == 'macOS' }}
run: docker rm --force scylladb || true
- name: Spin up scylladb (macOS)
if: ${{ runner.os == 'macOS' }}
timeout-minutes: 1
run: |
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
- 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
done
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: clio_integration_tests_${{ steps.build_identifier.outputs.build_identifier }}
- name: Run clio_integration_tests
run: |
chmod +x ./clio_integration_tests
./clio_integration_tests ${{ runner.os != 'macOS' && '--backend_host=scylladb' || '' }}
- name: Show docker logs and stop scylladb
if: ${{ always() && runner.os == 'macOS' }}
run: |
docker logs scylladb
docker rm --force scylladb || true

View File

@@ -8,18 +8,20 @@ on:
paths: paths:
- .github/workflows/sanitizers.yml - .github/workflows/sanitizers.yml
- .github/workflows/reusable-build-test.yml - .github/workflows/build_and_test.yml
- .github/workflows/reusable-build.yml - .github/workflows/build_impl.yml
- .github/workflows/reusable-test.yml - .github/workflows/test_impl.yml
- ".github/actions/**" - ".github/actions/**"
- "!.github/actions/build-docker-image/**" - "!.github/actions/build_docker_image/**"
- "!.github/actions/create_issue/**"
- .github/scripts/execute-tests-under-sanitizer
- CMakeLists.txt - CMakeLists.txt
- conanfile.py - conanfile.py
- conan.lock - conan.lock
- "cmake/**" - "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/**" # - "src/**"
# - "tests/**" # - "tests/**"
@@ -36,19 +38,19 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
compiler: [gcc, clang] compiler: [gcc, clang]
sanitizers: [address, thread, undefinedbehavior] sanitizer_ext: [.asan, .tsan, .ubsan]
build_type: [Release, Debug] build_type: [Release, Debug]
uses: ./.github/workflows/reusable-build-test.yml uses: ./.github/workflows/build_and_test.yml
with: with:
runs_on: heavy runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b" }' container: '{ "image": "ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d" }'
download_ccache: false disable_cache: true
upload_ccache: false conan_profile: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
compiler: ${{ matrix.compiler }}
sanitizers: ${{ matrix.sanitizers }}
build_type: ${{ matrix.build_type }} build_type: ${{ matrix.build_type }}
run_unit_tests: true static: false
# Currently, both gcc.tsan and clang.tsan unit tests hang
run_unit_tests: ${{ matrix.sanitizer_ext != '.tsan' }}
run_integration_tests: false run_integration_tests: false
upload_clio_server: false upload_clio_server: false
targets: clio_tests clio_integration_tests targets: clio_tests clio_integration_tests

160
.github/workflows/test_impl.yml vendored Normal file
View File

@@ -0,0 +1,160 @@
name: Reusable test
on:
workflow_call:
inputs:
runs_on:
description: Runner to run the job on
required: true
type: string
container:
description: "The container object as a JSON string (leave empty to run natively)"
required: true
type: string
conan_profile:
description: Conan profile to use
required: true
type: string
build_type:
description: Build type
required: true
type: string
run_unit_tests:
description: Whether to run unit tests
required: true
type: boolean
run_integration_tests:
description: Whether to run integration tests
required: true
type: boolean
jobs:
unit_tests:
name: Unit testing
runs-on: ${{ inputs.runs_on }}
container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}
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, '.asan') || endsWith(inputs.conan_profile, '.tsan') }}
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/download-artifact@v5
with:
name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
- name: Make clio_tests executable
shell: bash
run: chmod +x ./clio_tests
- name: Run clio_tests (regular)
if: env.SANITIZER_IGNORE_ERRORS == 'false'
run: ./clio_tests
- name: Run clio_tests (sanitizer errors ignored)
if: env.SANITIZER_IGNORE_ERRORS == 'true'
run: ./.github/scripts/execute-tests-under-sanitizer ./clio_tests
- name: Check for sanitizer report
if: env.SANITIZER_IGNORE_ERRORS == 'true'
shell: bash
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@v4
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
runs-on: ${{ inputs.runs_on }}
container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}
if: inputs.run_integration_tests
services:
scylladb:
image: ${{ inputs.container != '' && 'scylladb/scylla' || '' }}
options: >-
--health-cmd "cqlsh -e 'describe cluster'"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
- name: Spin up scylladb
if: ${{ runner.os == 'macOS' }}
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
until [ "$(docker inspect -f '{{.State.Health.Status}}' scylladb)" == "healthy" ]; do
sleep 5
done
- uses: actions/download-artifact@v5
with:
name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
- name: Run clio_integration_tests
run: |
chmod +x ./clio_integration_tests
./clio_integration_tests ${{ runner.os != 'macOS' && '--backend_host=scylladb' || '' }}
- name: Show docker logs and stop scylladb
if: ${{ always() && runner.os == 'macOS' }}
run: |
docker logs scylladb
docker rm --force scylladb || true

338
.github/workflows/update_docker_ci.yml vendored Normal file
View File

@@ -0,0 +1,338 @@
name: Update CI docker image
on:
pull_request:
paths:
- .github/workflows/update_docker_ci.yml
- ".github/actions/build_docker_image/**"
- "docker/ci/**"
- "docker/compilers/**"
- "docker/tools/**"
push:
branches: [develop]
paths:
- .github/workflows/update_docker_ci.yml
- ".github/actions/build_docker_image/**"
- "docker/ci/**"
- "docker/compilers/**"
- "docker/tools/**"
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
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@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
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=amd64-latest
type=raw,value=amd64-${{ env.GCC_MAJOR_VERSION }}
type=raw,value=amd64-${{ env.GCC_VERSION }}
type=raw,value=amd64-${{ github.sha }}
platforms: linux/amd64
build_args: |
GCC_MAJOR_VERSION=${{ env.GCC_MAJOR_VERSION }}
GCC_VERSION=${{ env.GCC_VERSION }}
dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_gcc' || '' }}
dockerhub_description: GCC compiler for XRPLF/clio.
gcc-arm64:
name: Build and push GCC docker image (arm64)
runs-on: heavy-arm64
needs: repo
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
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:
name: Merge and push multi-arch GCC docker image
runs-on: heavy
needs: [repo, gcc-amd64, gcc-arm64]
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
with:
files: "docker/compilers/gcc/**"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.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@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.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_clang
fi
clang:
name: Build and push Clang docker image
runs-on: heavy
needs: repo
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
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
build_args: |
CLANG_MAJOR_VERSION=${{ env.CLANG_MAJOR_VERSION }}
dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_clang' || '' }}
dockerhub_description: Clang compiler for XRPLF/clio.
tools-amd64:
name: Build and push tools docker image (amd64)
runs-on: heavy
needs: [repo, gcc-merge]
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
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=amd64-latest
type=raw,value=amd64-${{ github.sha }}
platforms: linux/amd64
build_args: |
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
GCC_VERSION=${{ env.GCC_VERSION }}
tools-arm64:
name: Build and push tools docker image (arm64)
runs-on: heavy-arm64
needs: [repo, gcc-merge]
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
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:
name: Merge and push multi-arch tools docker image
runs-on: heavy
needs: [repo, tools-amd64, tools-arm64]
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
with:
files: "docker/tools/**"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.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
ci:
name: Build and push CI docker image
runs-on: heavy
needs: [repo, gcc-merge, clang, tools-merge]
steps:
- uses: actions/checkout@v4
- 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
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

@@ -18,22 +18,20 @@ on:
pull_request: pull_request:
branches: [develop] branches: [develop]
paths: paths:
- .github/workflows/upload-conan-deps.yml - .github/workflows/upload_conan_deps.yml
- .github/actions/conan/action.yml - .github/actions/conan/action.yml
- ".github/scripts/conan/**" - ".github/scripts/conan/**"
- "!.github/scripts/conan/regenerate_lockfile.sh"
- conanfile.py - conanfile.py
- conan.lock - conan.lock
push: push:
branches: [develop] branches: [develop]
paths: paths:
- .github/workflows/upload-conan-deps.yml - .github/workflows/upload_conan_deps.yml
- .github/actions/conan/action.yml - .github/actions/conan/action.yml
- ".github/scripts/conan/**" - ".github/scripts/conan/**"
- "!.github/scripts/conan/regenerate_lockfile.sh"
- conanfile.py - conanfile.py
- conan.lock - conan.lock
@@ -42,24 +40,20 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
defaults:
run:
shell: bash
jobs: jobs:
generate-matrix: generate-matrix:
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }} matrix: ${{ steps.set-matrix.outputs.matrix }}
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@v4
- name: Calculate conan matrix - name: Calculate conan matrix
id: set-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: 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 needs: generate-matrix
@@ -71,46 +65,38 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
container: ${{ matrix.container != '' && fromJson(matrix.container) || null }} container: ${{ matrix.container != '' && fromJson(matrix.container) || null }}
env:
CONAN_PROFILE: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@v4
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab uses: XRPLF/actions/.github/actions/prepare-runner@7951b682e5a2973b28b0719a72f01fc4b0d0c34f
with: with:
enable_ccache: false disable_ccache: true
- name: Print build environment - name: Setup conan on macOS
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574 if: runner.os == 'macOS'
shell: bash
- name: Set compiler environment run: ./.github/scripts/conan/init.sh
if: ${{ runner.os == 'Linux' }}
uses: ./.github/actions/set-compiler-env
with:
compiler: ${{ matrix.compiler }}
- name: Setup conan
run: conan/init.sh
- name: Show conan profile - name: Show conan profile
env: run: conan profile show --profile:all ${{ env.CONAN_PROFILE }}
SANITIZERS: ${{ matrix.sanitizers }}
run: conan profile show --profile:all ci
- name: Run conan - name: Run conan
uses: ./.github/actions/conan uses: ./.github/actions/conan
with: with:
sanitizers: ${{ matrix.sanitizers }} conan_profile: ${{ env.CONAN_PROFILE }}
# We check that everything builds fine from source on scheduled runs # We check that everything builds fine from source on scheduled runs
# But we do build and upload packages with build=missing by default # 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' }} force_conan_source_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }}
build_type: ${{ matrix.build_type }} build_type: ${{ matrix.build_type }}
- name: Log into Conan remote - name: Login to Conan
if: ${{ github.repository == 'XRPLF/clio' && github.event_name != 'pull_request' }} if: github.repository_owner == 'XRPLF' && github.event_name != 'pull_request'
run: conan remote login -p ${{ secrets.CONAN_PASSWORD }} xrplf ${{ secrets.CONAN_USERNAME }} run: conan remote login -p ${{ secrets.CONAN_PASSWORD }} xrplf ${{ secrets.CONAN_USERNAME }}
- name: Upload Conan packages - 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: run: conan upload "*" -r=xrplf --confirm ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
run: conan upload "*" -r=xrplf --confirm ${FORCE_OPTION}

View File

@@ -1,34 +1,31 @@
name: Upload report name: Upload report
on: on:
workflow_dispatch:
workflow_call: workflow_call:
secrets: secrets:
CODECOV_TOKEN: CODECOV_TOKEN:
required: true required: true
defaults:
run:
shell: bash
jobs: jobs:
upload_report: upload_report:
name: Upload report name: Upload report
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Download report artifact - name: Download report artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 uses: actions/download-artifact@v5
with: with:
name: coverage-report.xml name: coverage-report.xml
path: build path: build
- name: Upload coverage report - name: Upload coverage report
if: ${{ github.repository == 'XRPLF/clio' && hashFiles('build/coverage_report.xml') != '' }} if: ${{ hashFiles('build/coverage_report.xml') != '' }}
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
with: with:
files: build/coverage_report.xml files: build/coverage_report.xml
fail_ci_if_error: true fail_ci_if_error: true

5
.gitignore vendored
View File

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

View File

@@ -11,10 +11,7 @@
# #
# See https://pre-commit.com for more information # See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks # See https://pre-commit.com/hooks.html for more hooks
exclude: | exclude: ^(docs/doxygen-awesome-theme/|conan\.lock$)
(?x)^(
docs/doxygen-awesome-theme/.*
)$
repos: repos:
# `pre-commit sample-config` default hooks # `pre-commit sample-config` default hooks
@@ -29,27 +26,27 @@ repos:
# Autoformat: YAML, JSON, Markdown, etc. # Autoformat: YAML, JSON, Markdown, etc.
- repo: https://github.com/rbubley/mirrors-prettier - repo: https://github.com/rbubley/mirrors-prettier
rev: 515f543f5718ebfd6ce22e16708bb32c68ff96e1 # frozen: v3.8.3 rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
hooks: hooks:
- id: prettier - id: prettier
- repo: https://github.com/igorshubovych/markdownlint-cli - repo: https://github.com/igorshubovych/markdownlint-cli
rev: e72a3ca1632f0b11a07d171449fe447a7ff6795e # frozen: v0.48.0 rev: 192ad822316c3a22fb3d3cc8aa6eafa0b8488360 # frozen: v0.45.0
hooks: hooks:
- id: markdownlint-fix - id: markdownlint-fix
exclude: LICENSE.md exclude: LICENSE.md
- repo: https://github.com/hadolint/hadolint - repo: https://github.com/hadolint/hadolint
rev: 57e1618d78fd469a92c1e584e8c9313024656623 # frozen: v2.14.0 rev: c3dc18df7a501f02a560a2cc7ba3c69a85ca01d3 # frozen: v2.13.1-beta
hooks: hooks:
- id: hadolint-docker - id: hadolint-docker
# hadolint-docker is a special hook that runs hadolint in a Docker container # hadolint-docker is a special hook that runs hadolint in a Docker container
# Docker is not installed in the environment where pre-commit is run # Docker is not installed in the environment where pre-commit is run
stages: [manual] stages: [manual]
entry: hadolint/hadolint:v2.14.0 hadolint entry: hadolint/hadolint:v2.12.1-beta hadolint
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: 2ccb47ff45ad361a21071a7eedda4c37e6ae8c5a # frozen: v2.4.2 rev: 63c8f8312b7559622c0d82815639671ae42132ac # frozen: v2.4.1
hooks: hooks:
- id: codespell - id: codespell
args: args:
@@ -58,17 +55,6 @@ repos:
--ignore-words=pre-commit-hooks/codespell_ignore.txt, --ignore-words=pre-commit-hooks/codespell_ignore.txt,
] ]
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 4160603246a6b365d4a2af661c6d71b0a0f50478 # frozen: 26.5.1
hooks:
- id: black
- repo: https://github.com/scop/pre-commit-shfmt
rev: 05c1426671b9237fb5e1444dd63aa5731bec0dfb # frozen: v3.13.1-1
hooks:
- id: shfmt
args: [--write, --indent=4, --case-indent=true]
# Running some C++ hooks before clang-format # Running some C++ hooks before clang-format
# to ensure that the style is consistent. # to ensure that the style is consistent.
- repo: local - repo: local
@@ -93,23 +79,18 @@ repos:
types: [c++] types: [c++]
language: script language: script
- id: fix-pragma-once
name: fix missing '#pragma once' declarations in header files
language: python
entry: ./pre-commit-hooks/fix_pragma_once.py
files: \.(h|hpp)$
- repo: https://github.com/pre-commit/mirrors-clang-format - repo: https://github.com/pre-commit/mirrors-clang-format
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5 rev: 86fdcc9bd34d6afbbd29358b97436c8ffe3aa3b2 # frozen: v21.1.0
hooks: hooks:
- id: clang-format - id: clang-format
args: [--style=file] args: [--style=file]
types: [c++] types: [c++]
- repo: https://github.com/BlankSpruce/gersemi-pre-commit - repo: https://github.com/cheshirekow/cmake-format-precommit
rev: e98930bdc210d3387007f9252d8c1694ea7e410f # frozen: 0.27.7 rev: e2c2116d86a80e72e7146a06e68b7c228afc6319 # frozen: v0.6.13
hooks: hooks:
- id: gersemi - id: cmake-format
additional_dependencies: [PyYAML]
- repo: local - repo: local
hooks: hooks:

View File

@@ -1,10 +1,7 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project( project(clio VERSION ${CLIO_VERSION} HOMEPAGE_URL "https://github.com/XRPLF/clio"
clio DESCRIPTION "An XRP Ledger API Server"
VERSION ${CLIO_VERSION}
HOMEPAGE_URL "https://github.com/XRPLF/clio"
DESCRIPTION "An XRP Ledger API Server"
) )
# =========================== Options ====================================== # # =========================== Options ====================================== #
@@ -16,15 +13,15 @@ option(docs "Generate doxygen docs" FALSE)
option(coverage "Build test coverage report" FALSE) option(coverage "Build test coverage report" FALSE)
option(package "Create distribution packages" FALSE) option(package "Create distribution packages" FALSE)
option(lint "Run clang-tidy checks during compilation" FALSE) option(lint "Run clang-tidy checks during compilation" FALSE)
option(static "Statically linked Clio" FALSE)
option(snapshot "Build snapshot tool" FALSE) option(snapshot "Build snapshot tool" FALSE)
option( option(time_trace "Build using -ftime-trace to create compiler trace reports" FALSE)
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(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}) 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_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) target_include_directories(clio_options INTERFACE ${CMAKE_SOURCE_DIR}/src)
if( if (verbose)
CMAKE_CXX_COMPILER_ID STREQUAL "Clang" set(CMAKE_VERBOSE_MAKEFILE TRUE)
OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU" endif ()
)
# 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()
# Clio tweaks and checks # Clio tweaks and checks
include(CheckCompiler) include(CheckCompiler)
include(Settings) include(Settings)
include(SourceLocation) include(SourceLocation)
include(PatchNixBinary)
# Clio deps # Clio deps
include(deps/libxrpl) include(deps/libxrpl)
@@ -76,20 +57,41 @@ include(deps/spdlog)
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(tests) add_subdirectory(tests)
if(benchmark) if (benchmark)
add_subdirectory(benchmarks) add_subdirectory(benchmarks)
endif() 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_compile_definitions(
clio_options INTERFACE $<$<STREQUAL:${san},address>:SANITIZER=ASAN> $<$<STREQUAL:${san},thread>:SANITIZER=TSAN>
$<$<STREQUAL:${san},memory>:SANITIZER=MSAN> $<$<STREQUAL:${san},undefined>:SANITIZER=UBSAN>
)
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 # Generate `docs` target for doxygen documentation if enabled Note: use `make docs` to generate the documentation
if(docs) if (docs)
add_subdirectory(docs) add_subdirectory(docs)
endif() endif ()
include(install/install) include(install/install)
if(package) if (package)
include(ClioPackage) include(ClioPackage)
endif() endif ()
if(snapshot) if (snapshot)
add_subdirectory(tools/snapshot) add_subdirectory(tools/snapshot)
endif() 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. 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. 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 ### Documentation
@@ -180,7 +180,6 @@ Existing maintainers can resign, or be subject to a vote for removal at the behe
- [kuznetsss](https://github.com/kuznetsss) (Ripple) - [kuznetsss](https://github.com/kuznetsss) (Ripple)
- [legleux](https://github.com/legleux) (Ripple) - [legleux](https://github.com/legleux) (Ripple)
- [PeterChen13579](https://github.com/PeterChen13579) (Ripple) - [PeterChen13579](https://github.com/PeterChen13579) (Ripple)
- [mathbunnyru](https://github.com/mathbunnyru) (Ripple)
### Honorable ex-Maintainers ### Honorable ex-Maintainers

View File

@@ -1,6 +1,6 @@
ISC License 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. 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

@@ -34,6 +34,7 @@ Below are some useful docs to learn more about Clio.
- [How to configure Clio and rippled](./docs/configure-clio.md) - [How to configure Clio and rippled](./docs/configure-clio.md)
- [How to run Clio](./docs/run-clio.md) - [How to run Clio](./docs/run-clio.md)
- [Logging](./docs/logging.md)
- [Troubleshooting guide](./docs/trouble_shooting.md) - [Troubleshooting guide](./docs/trouble_shooting.md)
**General reference material:** **General reference material:**

View File

@@ -1,27 +1,18 @@
add_executable(clio_benchmark) add_executable(clio_benchmark)
target_sources( target_sources(
clio_benchmark clio_benchmark
PRIVATE PRIVATE # Common
# Common Main.cpp
Main.cpp Playground.cpp
Playground.cpp # ExecutionContext
# ExecutionContext util/async/ExecutionContextBenchmarks.cpp
util/async/ExecutionContextBenchmarks.cpp # Logger
# Logger util/log/LoggerBenchmark.cpp
util/log/LoggerBenchmark.cpp
# WorkQueue
rpc/WorkQueueBenchmarks.cpp
) )
include(deps/gbench) include(deps/gbench)
target_include_directories(clio_benchmark PRIVATE .) target_include_directories(clio_benchmark PRIVATE .)
target_link_libraries( target_link_libraries(clio_benchmark PUBLIC clio_util benchmark::benchmark_main spdlog::spdlog)
clio_benchmark set_target_properties(clio_benchmark PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
PRIVATE clio_rpc clio_util 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> #include <benchmark/benchmark.h>
BENCHMARK_MAIN(); 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. * Use this file for temporary benchmarks and implementations.
* Usage example: * Usage example:

View File

@@ -1,134 +0,0 @@
#include "rpc/WorkQueue.hpp"
#include "util/Assert.hpp"
#include "util/config/Array.hpp"
#include "util/config/ConfigConstraints.hpp"
#include "util/config/ConfigDefinition.hpp"
#include "util/config/ConfigValue.hpp"
#include "util/config/Types.hpp"
#include "util/log/Logger.hpp"
#include "util/prometheus/Prometheus.hpp"
#include <benchmark/benchmark.h>
#include <boost/asio/steady_timer.hpp>
#include <algorithm>
#include <atomic>
#include <cassert>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <mutex>
#include <thread>
#include <vector>
using namespace rpc;
using namespace util::config;
namespace {
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.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.tag_style", ConfigValue{ConfigType::String}.defaultValue("none")},
};
// this should be a fixture but it did not work with Args very well
void
init()
{
static std::once_flag kOnce;
std::call_once(kOnce, [] {
PrometheusService::init(kConfig);
(void)util::LogService::init(kConfig);
});
}
} // namespace
static void
benchmarkWorkQueue(benchmark::State& state)
{
init();
auto const wqThreads = static_cast<uint32_t>(state.range(0));
auto const maxQueueSize = static_cast<uint32_t>(state.range(1));
auto const clientThreads = static_cast<uint32_t>(state.range(2));
auto const itemsPerClient = static_cast<uint32_t>(state.range(3));
auto const clientProcessingMs = static_cast<uint32_t>(state.range(4));
for (auto _ : state) {
std::atomic_size_t totalExecuted = 0uz;
std::atomic_size_t totalQueued = 0uz;
state.PauseTiming();
WorkQueue queue(wqThreads, maxQueueSize);
state.ResumeTiming();
std::vector<std::thread> threads;
threads.reserve(clientThreads);
for (auto t = 0uz; t < clientThreads; ++t) {
threads.emplace_back([&] {
for (auto i = 0uz; i < itemsPerClient; ++i) {
totalQueued += static_cast<std::size_t>(queue.postCoro(
[&clientProcessingMs, &totalExecuted](auto yield) {
++totalExecuted;
boost::asio::steady_timer timer(
yield.get_executor(), std::chrono::milliseconds{clientProcessingMs}
);
timer.async_wait(yield);
std::this_thread::sleep_for(std::chrono::microseconds{10});
},
/* isWhiteListed = */ false
));
}
});
}
for (auto& t : threads)
t.join();
queue.stop();
ASSERT(totalExecuted == totalQueued, "Totals don't match");
ASSERT(totalQueued <= itemsPerClient * clientThreads, "Queued more than requested");
if (maxQueueSize == 0) {
ASSERT(
totalQueued == itemsPerClient * clientThreads, "Queued exactly the expected amount"
);
} else {
ASSERT(
totalQueued >= std::min(maxQueueSize, itemsPerClient * clientThreads),
"Queued less than expected"
);
}
}
}
// Usage example:
/*
./clio_benchmark \
--benchmark_repetitions=10 \
--benchmark_display_aggregates_only=true \
--benchmark_min_time=1x \
--benchmark_filter="WorkQueue"
*/
// TODO: figure out what happens on 1 thread
BENCHMARK(benchmarkWorkQueue)
->ArgsProduct({{2, 4, 8, 16}, {0, 5'000}, {4, 8, 16}, {1'000, 10'000}, {10, 100, 250}})
->Unit(benchmark::kMillisecond);

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 "etl/ETLHelpers.hpp"
#include "util/Random.hpp" #include "util/Random.hpp"
#include "util/async/AnyExecutionContext.hpp" #include "util/async/AnyExecutionContext.hpp"
@@ -169,11 +188,11 @@ public:
static auto static auto
generateData() generateData()
{ {
constexpr auto kTotal = 10'000; constexpr auto kTOTAL = 10'000;
std::vector<uint64_t> data; std::vector<uint64_t> data;
data.reserve(kTotal); data.reserve(kTOTAL);
util::MTRandomGenerator randomGenerator; 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)); data.push_back(randomGenerator.uniform(1, 100'000'000));
return data; 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/config/ConfigDefinition.hpp"
#include "util/log/Logger.hpp" #include "util/log/Logger.hpp"
#include "util/prometheus/Prometheus.hpp" #include "util/prometheus/Prometheus.hpp"
@@ -11,7 +30,6 @@
#include <barrier> #include <barrier>
#include <chrono> #include <chrono>
#include <cstddef> #include <cstddef>
#include <cstdint>
#include <filesystem> #include <filesystem>
#include <memory> #include <memory>
#include <string> #include <string>
@@ -21,19 +39,13 @@
using namespace util; 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 { struct BenchmarkLoggingInitializer {
[[nodiscard]] static std::shared_ptr<spdlog::sinks::sink> [[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( return LogService::createFileSink(params, kLOG_FORMAT);
LogService::FileLoggingParams{
.logDir = logDir,
.rotation = LogService::RotationParams{.sizeMB = sizeMB, .maxFiles = maxFiles},
},
kLogFormat
);
} }
static Logger static Logger
@@ -50,9 +62,8 @@ uniqueLogDir()
{ {
auto const epochTime = std::chrono::high_resolution_clock::now().time_since_epoch(); auto const epochTime = std::chrono::high_resolution_clock::now().time_since_epoch();
auto const tmpDir = std::filesystem::temp_directory_path(); auto const tmpDir = std::filesystem::temp_directory_path();
std::string const dirName = fmt::format( std::string const dirName =
"logs_{}", std::chrono::duration_cast<std::chrono::microseconds>(epochTime).count() fmt::format("logs_{}", std::chrono::duration_cast<std::chrono::microseconds>(epochTime).count());
);
return tmpDir / "clio_benchmark" / dirName; return tmpDir / "clio_benchmark" / dirName;
} }
@@ -71,11 +82,15 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
state.PauseTiming(); state.PauseTiming();
std::filesystem::create_directories(logDir); std::filesystem::create_directories(logDir);
static constexpr size_t kQueueSize = 8192; static constexpr size_t kQUEUE_SIZE = 8192;
static constexpr size_t kThreadCount = 1; static constexpr size_t kTHREAD_COUNT = 1;
spdlog::init_thread_pool(kQueueSize, kThreadCount); 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; std::vector<std::thread> threads;
threads.reserve(numThreads); threads.reserve(numThreads);
@@ -93,8 +108,7 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
channel, fileSink, spdlog::thread_pool(), spdlog::async_overflow_policy::block channel, fileSink, spdlog::thread_pool(), spdlog::async_overflow_policy::block
); );
spdlog::register_logger(logger); spdlog::register_logger(logger);
Logger const threadLogger = Logger const threadLogger = BenchmarkLoggingInitializer::getLogger(std::move(logger));
BenchmarkLoggingInitializer::getLogger(std::move(logger));
barrier.arrive_and_wait(); barrier.arrive_and_wait();
@@ -110,16 +124,13 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
spdlog::shutdown(); spdlog::shutdown();
auto const end = std::chrono::high_resolution_clock::now(); auto const end = std::chrono::high_resolution_clock::now();
state.SetIterationTime( state.SetIterationTime(std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count());
std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count()
);
std::filesystem::remove_all(logDir); std::filesystem::remove_all(logDir);
} }
auto const totalMessages = numThreads * messagesPerThread; auto const totalMessages = numThreads * messagesPerThread;
state.counters["TotalMessagesRate"] = state.counters["TotalMessagesRate"] = benchmark::Counter(totalMessages, benchmark::Counter::kIsRate);
benchmark::Counter(totalMessages, benchmark::Counter::kIsRate);
state.counters["Threads"] = numThreads; state.counters["Threads"] = numThreads;
state.counters["MessagesPerThread"] = messagesPerThread; state.counters["MessagesPerThread"] = messagesPerThread;
} }

View File

@@ -49,6 +49,8 @@ postprocessors = [
] ]
# render body even when there are no releases to process # render body even when there are no releases to process
# render_always = true # render_always = true
# output file path
output = "CHANGELOG.md"
[git] [git]
# parse the commits based on https://www.conventionalcommits.org # parse the commits based on https://www.conventionalcommits.org

View File

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

View File

@@ -1,21 +1,42 @@
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
message(FATAL_ERROR "Clang 16+ required for building clio") message(FATAL_ERROR "Clang 16+ required for building clio")
endif() endif ()
set(is_clang TRUE) set(is_clang TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
message(FATAL_ERROR "AppleClang 15+ required for building clio") message(FATAL_ERROR "AppleClang 15+ required for building clio")
endif() endif ()
set(is_appleclang TRUE) set(is_appleclang TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12)
message(FATAL_ERROR "GCC 12+ required for building clio") message(FATAL_ERROR "GCC 12+ required for building clio")
endif() endif ()
set(is_gcc TRUE) set(is_gcc TRUE)
else() else ()
message( message(FATAL_ERROR "Supported compilers: AppleClang 15+, Clang 16+, GCC 12+")
FATAL_ERROR endif ()
"Supported compilers: AppleClang 15+, Clang 16+, GCC 12+"
) if (san)
endif() 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) 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(NOT _CLANG_TIDY_BIN) # Find clang-tidy binary
message( if (DEFINED ENV{CLIO_CLANG_TIDY_BIN})
FATAL_ERROR set(_CLANG_TIDY_BIN $ENV{CLIO_CLANG_TIDY_BIN})
"clang-tidy binary not found. Please set the CLIO_CLANG_TIDY_BIN environment variable or install clang-tidy." 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() 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 if (NOT _CLANG_TIDY_BIN)
find_program(CLANG_TIDY_CACHE_PATH NAMES "clang-tidy-cache") message(
if(CLANG_TIDY_CACHE_PATH) FATAL_ERROR
set(_CLANG_TIDY_CMD "clang-tidy binary not found. Please set the CLIO_CLANG_TIDY_BIN environment variable or install clang-tidy."
"${CLANG_TIDY_CACHE_PATH};${_CLANG_TIDY_BIN}" )
CACHE STRING endif ()
"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") # Support for https://github.com/matus-chochlik/ctcache
message(STATUS "Using clang-tidy: ${CMAKE_CXX_CLANG_TIDY}") find_program(CLANG_TIDY_CACHE_PATH NAMES "clang-tidy-cache")
endif() 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) find_package(Git REQUIRED)
if(DEFINED ENV{GITHUB_BRANCH_NAME}) set(GIT_COMMAND describe --tags --exact-match)
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()
execute_process( execute_process(
COMMAND date +%Y%m%d%H%M%S COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_DATE OUTPUT_VARIABLE TAG
OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE RC
COMMAND_ERROR_IS_FATAL ANY ERROR_VARIABLE ERR
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE
) )
message(STATUS "Git branch: ${GIT_BUILD_BRANCH}") if (RC EQUAL 0)
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}") message(STATUS "Found tag '${TAG}' in git. Will use it as Clio version")
message(STATUS "Build date: ${BUILD_DATE}") set(CLIO_VERSION "${TAG}")
set(DOC_CLIO_VERSION "${TAG}")
else ()
message(STATUS "Error finding tag in git: ${ERR}")
message(STATUS "Will use 'YYYYMMDDHMS-<branch>-<git-rev>' as Clio version")
if( set(GIT_COMMAND show -s --date=format:%Y%m%d%H%M%S --format=%cd)
DEFINED ENV{FORCE_CLIO_VERSION} execute_process(
AND NOT "$ENV{FORCE_CLIO_VERSION}" STREQUAL "" COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE DATE
) OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
message( )
STATUS
"Using explicitly provided '${FORCE_CLIO_VERSION}' as Clio version"
)
set(CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}") set(GIT_COMMAND branch --show-current)
set(DOC_CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}") execute_process(
else() COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE BRANCH
message( OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
STATUS )
"Using 'YYYYMMDDHMS-<branch>-<git short rev>' as Clio version"
)
string(SUBSTRING ${GIT_COMMIT_HASH} 0 7 GIT_COMMIT_HASH_SHORT) set(GIT_COMMAND rev-parse --short HEAD)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE REV
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
)
set(CLIO_VERSION set(CLIO_VERSION "${DATE}-${BRANCH}-${REV}")
"${BUILD_DATE}-${GIT_BUILD_BRANCH}-${GIT_COMMIT_HASH_SHORT}" set(DOC_CLIO_VERSION "develop")
) endif ()
set(DOC_CLIO_VERSION "develop")
endif()
if(CMAKE_BUILD_TYPE MATCHES Debug) if (CMAKE_BUILD_TYPE MATCHES Debug)
set(CLIO_VERSION "${CLIO_VERSION}+DEBUG") set(CLIO_VERSION "${CLIO_VERSION}+DEBUG")
endif() endif ()
message(STATUS "Build version: ${CLIO_VERSION}") message(STATUS "Build version: ${CLIO_VERSION}")

View File

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

View File

@@ -1,11 +1,11 @@
if(DEFINED CMAKE_LINKER_TYPE) if (DEFINED CMAKE_LINKER_TYPE)
message(STATUS "Custom linker is already set: ${CMAKE_LINKER_TYPE}") message(STATUS "Custom linker is already set: ${CMAKE_LINKER_TYPE}")
return() return()
endif() endif ()
find_program(MOLD_PATH mold) find_program(MOLD_PATH mold)
if(MOLD_PATH AND CMAKE_SYSTEM_NAME STREQUAL "Linux") if (MOLD_PATH AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(STATUS "Using Mold linker: ${MOLD_PATH}") message(STATUS "Using Mold linker: ${MOLD_PATH}")
set(CMAKE_LINKER_TYPE MOLD) set(CMAKE_LINKER_TYPE MOLD)
endif() 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 # 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 () # -Wduplicated-cond -Wlogical-op -Wuseless-cast ) endif ()
if(is_clang) if (is_clang)
# gcc is too aggressive with shadowing list(APPEND COMPILER_FLAGS -Wshadow # gcc is to aggressive with shadowing
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78147 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78147
list(APPEND COMPILER_FLAGS -Wshadow) )
endif() endif ()
if(is_appleclang) if (is_appleclang)
list(APPEND COMPILER_FLAGS -Wreorder-init-list) list(APPEND COMPILER_FLAGS -Wreorder-init-list)
endif() endif ()
if(SANITIZERS_ENABLED) if (san)
# When building with sanitizers some compilers will actually produce extra warnings/errors. We don't want this yet, # When building with sanitizers some compilers will actually produce extra warnings/errors. We don't want this yet, at
# at least not until we have fixed all runtime issues reported by the sanitizers. Once that is done we can start # least not until we have fixed all runtime issues reported by the sanitizers. Once that is done we can start removing
# removing some of these and trying to fix it in our codebase. We can never remove all of below because most of them # some of these and trying to fix it in our codebase. We can never remove all of below because most of them are
# are reported from deep inside libraries like boost or libxrpl. # reported from deep inside libraries like boost or libxrpl.
# #
# TODO: Address in https://github.com/XRPLF/clio/issues/1885 # TODO: Address in https://github.com/XRPLF/clio/issues/1885
list( list(
APPEND COMPILER_FLAGS APPEND
-Wno-error=tsan # Disables treating TSAN warnings as errors COMPILER_FLAGS
-Wno-tsan # Disables TSAN warnings (thread-safety analysis) -Wno-error=tsan # Disables treating TSAN warnings as errors
-Wno-uninitialized # Disables warnings about uninitialized variables (AddressSanitizer, -Wno-tsan # Disables TSAN warnings (thread-safety analysis)
# UndefinedBehaviorSanitizer, etc.) -Wno-uninitialized # Disables warnings about uninitialized variables (AddressSanitizer, UndefinedBehaviorSanitizer,
-Wno-stringop-overflow # Disables warnings about potential string operation overflows (AddressSanitizer) # etc.)
-Wno-unsafe-buffer-usage # Disables warnings about unsafe memory operations (AddressSanitizer) -Wno-stringop-overflow # Disables warnings about potential string operation overflows (AddressSanitizer)
-Wno-frame-larger-than # Disables warnings about stack frame size being too large (AddressSanitizer) -Wno-unsafe-buffer-usage # Disables warnings about unsafe memory operations (AddressSanitizer)
-Wno-unused-function # Disables warnings about unused functions (LeakSanitizer, memory-related issues) -Wno-frame-larger-than # Disables warnings about stack frame size being too large (AddressSanitizer)
-Wno-unused-but-set-variable # Disables warnings about unused variables (MemorySanitizer) -Wno-unused-function # Disables warnings about unused functions (LeakSanitizer, memory-related issues)
-Wno-thread-safety-analysis # Disables warnings related to thread safety usage (ThreadSanitizer) -Wno-unused-but-set-variable # Disables warnings about unused variables (MemorySanitizer)
-Wno-thread-safety # Disables warnings related to thread safety usage (ThreadSanitizer) -Wno-thread-safety-analysis # Disables warnings related to thread safety usage (ThreadSanitizer)
-Wno-sign-compare # Disables warnings about signed/unsigned comparison (UndefinedBehaviorSanitizer) -Wno-thread-safety # Disables warnings related to thread safety usage (ThreadSanitizer)
-Wno-nonnull # Disables warnings related to null pointer dereferencing (UndefinedBehaviorSanitizer) -Wno-sign-compare # Disables warnings about signed/unsigned comparison (UndefinedBehaviorSanitizer)
-Wno-address # Disables warnings about address-related issues (UndefinedBehaviorSanitizer) -Wno-nonnull # Disables warnings related to null pointer dereferencing (UndefinedBehaviorSanitizer)
-Wno-array-bounds # Disables array bounds checks (UndefinedBehaviorSanitizer) -Wno-address # Disables warnings about address-related issues (UndefinedBehaviorSanitizer)
) -Wno-array-bounds # Disables array bounds checks (UndefinedBehaviorSanitizer)
endif() )
endif ()
# See https://github.com/cpp-best-practices/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#gcc--clang for # See https://github.com/cpp-best-practices/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#gcc--clang for
# the flags description # the flags description
if(time_trace) if (time_trace)
if(is_clang OR is_appleclang) if (is_clang OR is_appleclang)
list(APPEND COMPILER_FLAGS -ftime-trace) list(APPEND COMPILER_FLAGS -ftime-trace)
else() else ()
message( message(FATAL_ERROR "Clang or AppleClang is required to use `-ftime-trace`")
FATAL_ERROR endif ()
"Clang or AppleClang is required to use `-ftime-trace`" endif ()
)
endif()
endif()
target_compile_options(clio_options INTERFACE ${COMPILER_FLAGS}) 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) include(CheckIncludeFileCXX)
check_include_file_cxx("source_location" SOURCE_LOCATION_AVAILABLE) check_include_file_cxx("source_location" SOURCE_LOCATION_AVAILABLE)
if(SOURCE_LOCATION_AVAILABLE) if (SOURCE_LOCATION_AVAILABLE)
target_compile_definitions(clio_options INTERFACE "HAS_SOURCE_LOCATION") target_compile_definitions(clio_options INTERFACE "HAS_SOURCE_LOCATION")
endif() endif ()
check_include_file_cxx( check_include_file_cxx("experimental/source_location" EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE)
"experimental/source_location" if (EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE)
EXPERIMENTAL_SOURCE_LOCATION_AVAILABLE target_compile_definitions(clio_options INTERFACE "HAS_EXPERIMENTAL_SOURCE_LOCATION")
) endif ()
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_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON) set(Boost_USE_STATIC_RUNTIME ON)
find_package( find_package(Boost 1.82 REQUIRED CONFIG COMPONENTS program_options coroutine system log log_setup)
Boost
1.82
REQUIRED
CONFIG
COMPONENTS program_options system log log_setup
)

View File

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

View File

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

View File

@@ -1,17 +0,0 @@
[Unit]
Description=Clio XRPL API server
Documentation=https://github.com/XRPLF/clio.git
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=@CLIO_INSTALL_DIR@/bin/clio_server @CLIO_INSTALL_DIR@/etc/config.json
Restart=on-failure
User=clio
Group=clio
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

View File

@@ -1,10 +1,5 @@
set(CLIO_INSTALL_DIR "/opt/clio") set(CLIO_INSTALL_DIR "/opt/clio")
set(CMAKE_INSTALL_PREFIX set(CMAKE_INSTALL_PREFIX "${CLIO_INSTALL_DIR}" CACHE PATH "Install prefix" FORCE)
"${CLIO_INSTALL_DIR}"
CACHE PATH
"Install prefix"
FORCE
)
set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
@@ -15,17 +10,4 @@ install(TARGETS clio_server DESTINATION "${CMAKE_INSTALL_BINDIR}")
file(READ docs/examples/config/example-config.json config) file(READ docs/examples/config/example-config.json config)
string(REGEX REPLACE "./clio_log" "/var/log/clio/" config "${config}") string(REGEX REPLACE "./clio_log" "/var/log/clio/" config "${config}")
file(WRITE ${CMAKE_BINARY_DIR}/install-config.json "${config}") file(WRITE ${CMAKE_BINARY_DIR}/install-config.json "${config}")
install( install(FILES ${CMAKE_BINARY_DIR}/install-config.json DESTINATION etc RENAME config.json)
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
)

View File

@@ -35,7 +35,8 @@ case "$1" in
ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}" ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
;; ;;
abort-upgrade | abort-remove | abort-deconfigure) ;; abort-upgrade|abort-remove|abort-deconfigure)
;;
*) *)
echo "postinst called with unknown argument \`$1'" >&2 echo "postinst called with unknown argument \`$1'" >&2
exit 1 exit 1

View File

@@ -1,77 +1,61 @@
{ {
"version": "0.5", "version": "0.5",
"requires": [ "requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056", "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987", "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1756234289.683",
"xrpl/3.2.0#c3c124909c6461012758a4fab7c90cd5%1781569913.756", "xrpl/2.6.0#57b93b5a6c99dc8511fccb3bb5390352%1756820296.642",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1778091117.311", "sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1756234266.869",
"spdlog/1.17.0#bcbaaf7147bda6ad24ffbd1ac3d7142c%1768312128.781", "spdlog/1.15.3#3ca0e9e6b83af4d0151e26541d140c86%1754401846.61",
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231", "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878", "re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1756234257.976",
"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", "rapidjson/cci.20220822#1b9d8c2256876a154172dc5cfbe447c6%1754325007.656",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12", "protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
"openssl/3.6.2#4789bbf131b77d0515d15e094c8f697f%1778071755.506", "openssl/1.1.1w#a8f0792d7c5121b954578a7149d23e03%1756223730.729",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1775040983.408", "nudb/2.0.9#c62cfd501e57055a7e0d8ee3d5e5427d%1756234237.107",
"minizip/1.2.13#9e87d57804bd372d6d1e32b1871517a3%1754325004.374", "minizip/1.2.13#9e87d57804bd372d6d1e32b1871517a3%1754325004.374",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914", "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999",
"libuv/1.46.0#dc28c1f653fa197f00db5b577a6f6011%1754325003.592", "libuv/1.46.0#dc28c1f653fa197f00db5b577a6f6011%1754325003.592",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492", "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03", "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1756230911.03",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1778091117.848", "libarchive/3.8.1#5cf685686322e906cb42706ab7e099a8%1756234256.696",
"http_parser/2.9.4#98d91690d6fd021e9e624218a85d9d97%1754325001.385", "http_parser/2.9.4#98d91690d6fd021e9e624218a85d9d97%1754325001.385",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152", "gtest/1.14.0#f8f0757a574a8dd747d16af62d6eb1b7%1754325000.842",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342", "grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1756234248.958",
"fmt/12.1.0#50abab23274d56bb8f42c94b3b9a40c7%1763984116.926", "fmt/11.2.0#579bb2cdf4a7607621beea4eb4651e0f%1754324999.086",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772", "doctest/2.4.11#a4211dfc329a16ba9f280f9574025659%1756234220.819",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772", "date/3.0.4#f74bbba5a08fa388256688743136cb6f%1756234217.493",
"cassandra-cpp-driver/2.17.0#bd3934138689482102c265d01288a316%1764175359.611", "cassandra-cpp-driver/2.17.0#e50919efac8418c26be6671fd702540a%1754324997.363",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681", "c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1756234217.915",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837", "bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1756234261.716",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778091165.282", "boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368%1754325043.336",
"benchmark/1.9.5#b885dc73ad67b40a55d45684d1c88ad1%1774363287.434", "benchmark/1.9.4#ce4403f7a24d3e1f907cd9da4b678be4%1754578869.672",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196" "abseil/20230802.1#f0f91485b111dc9837a68972cb19ca7b%1756234220.907"
], ],
"build_requires": [ "build_requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056", "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12", "protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183", "cmake/3.31.8#dde3bde00bb843687e55aea5afa0e220%1756234232.89",
"cmake/3.31.11#f325c933f618a1fcebc1e1c0babfd1ba%1774439246.719", "b2/5.3.3#107c15377719889654eb9a162a673975%1756234226.28"
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
], ],
"python_requires": [], "python_requires": [],
"overrides": { "overrides": {
"zlib/[>=1.2.11 <2]": [ "boost/1.83.0": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb"
],
"zlib/1.3.2": [
null, null,
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb" "boost/1.83.0"
], ],
"boost/1.91.0": [ "protobuf/3.21.12": [
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c" null,
"protobuf/3.21.12"
], ],
"protobuf/[>=5.27.0 <7]": [ "boost/1.86.0": [
"protobuf/6.33.5" "boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368"
], ],
"lz4/1.9.4": [ "lz4/1.9.4": [
"lz4/1.10.0" "lz4/1.10.0"
], ],
"boost/[>=1.83.0 <1.91.0]": [ "sqlite3/3.44.2": [
"boost/1.91.0" "sqlite3/3.49.1"
],
"sqlite3/[>=3.44 <4]": [
"sqlite3/3.53.0"
],
"boost/1.83.0": [
"boost/1.91.0"
],
"lz4/[>=1.9.4 <2]": [
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
] ]
}, },
"config_requires": [] "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,71 +1,64 @@
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan import ConanFile from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
class ClioConan(ConanFile): class ClioConan(ConanFile):
name = "clio" name = 'clio'
license = "ISC" license = 'ISC'
author = "Alex Kremer <akremer@ripple.com>, John Freeman <jfreeman@ripple.com>, Ayaz Salikhov <asalikhov@ripple.com>" author = 'Alex Kremer <akremer@ripple.com>, John Freeman <jfreeman@ripple.com>, Ayaz Salikhov <asalikhov@ripple.com>'
url = "https://github.com/xrplf/clio" url = 'https://github.com/xrplf/clio'
description = "Clio RPC server" description = 'Clio RPC server'
settings = "os", "compiler", "build_type", "arch" settings = 'os', 'compiler', 'build_type', 'arch'
options = {} options = {}
requires = [ requires = [
"cassandra-cpp-driver/2.17.0", 'boost/1.83.0',
"fmt/12.1.0", 'cassandra-cpp-driver/2.17.0',
"libbacktrace/cci.20210118", 'fmt/11.2.0',
"spdlog/1.17.0", 'protobuf/3.21.12',
"xrpl/3.2.0", 'grpc/1.50.1',
'openssl/1.1.1w',
'xrpl/2.6.0',
'zlib/1.3.1',
'libbacktrace/cci.20210118',
'spdlog/1.15.3',
] ]
default_options = { default_options = {
"cassandra-cpp-driver/*:shared": False, 'xrpl/*:tests': False,
"date/*:header_only": True, 'xrpl/*:rocksdb': False,
"grpc/*:secure": True, 'cassandra-cpp-driver/*:shared': False,
"grpc/*:shared": False, 'date/*:header_only': True,
"gtest/*:no_main": True, 'grpc/*:shared': False,
"libpq/*:shared": False, 'grpc/*:secure': True,
"lz4/*:shared": False, 'libpq/*:shared': False,
"openssl/*:shared": False, 'lz4/*:shared': False,
"protobuf/*:shared": False, 'openssl/*:shared': False,
"protobuf/*:with_zlib": True, 'protobuf/*:shared': False,
"snappy/*:shared": False, 'protobuf/*:with_zlib': True,
"xrpl/*:rocksdb": True, # TODO: revert to false when includes are fixed in libxrpl 'snappy/*:shared': False,
"xrpl/*:tests": False, 'gtest/*:no_main': True,
} }
exports_sources = ("CMakeLists.txt", "cmake/*", "src/*") exports_sources = (
'CMakeLists.txt', 'cmake/*', 'src/*'
)
def requirements(self): def requirements(self):
self.requires("gtest/1.17.0") self.requires('gtest/1.14.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): def configure(self):
if self.settings.compiler == "apple-clang": if self.settings.compiler == 'apple-clang':
self.options["boost"].visibility = "global" self.options['boost'].visibility = 'global'
def layout(self): def layout(self):
cmake_layout(self) cmake_layout(self)
# Fix this setting to follow the default introduced in Conan 1.48 # Fix this setting to follow the default introduced in Conan 1.48
# to align with our build instructions. # to align with our build instructions.
self.folders.generators = "build/generators" self.folders.generators = 'build/generators'
generators = "CMakeDeps" generators = 'CMakeDeps'
def generate(self): def generate(self):
tc = CMakeToolchain(self) tc = CMakeToolchain(self)

135
docker/ci/Dockerfile Normal file
View File

@@ -0,0 +1,135 @@
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 \
ninja-build \
wget \
zip \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Install Python tools
ARG PYTHON_VERSION=3.13
RUN add-apt-repository ppa:deadsnakes/ppa \
&& apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests \
python${PYTHON_VERSION} \
python${PYTHON_VERSION}-venv \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& curl -sS https://bootstrap.pypa.io/get-pip.py | python${PYTHON_VERSION}
# Create a virtual environment for python tools
RUN python${PYTHON_VERSION} -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install -q --no-cache-dir \
cmake \
conan==2.20.1 \
gcovr \
pre-commit
# Install LLVM tools
ARG LLVM_TOOLS_VERSION=20
RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${LLVM_TOOLS_VERSION} main" >> /etc/apt/sources.list \
&& wget --progress=dot:giga -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
RUN apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests \
clang-tidy-${LLVM_TOOLS_VERSION} \
clang-tools-${LLVM_TOOLS_VERSION} \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ARG GCC_MAJOR_VERSION=invalid
# Install custom-built gcc and make ldconfig aware of the new libstdc++ location (for gcc)
# Note: Clang is using libc++ instead
COPY --from=clio-gcc /gcc${GCC_MAJOR_VERSION}.deb /
RUN apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests \
binutils \
libc6-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& dpkg -i /gcc${GCC_MAJOR_VERSION}.deb \
&& rm -rf /gcc${GCC_MAJOR_VERSION}.deb \
&& ldconfig
# Rewire to use our custom-built gcc as default compiler
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_MAJOR_VERSION} 100 \
&& update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++-${GCC_MAJOR_VERSION} 100 \
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_MAJOR_VERSION} 100 \
&& update-alternatives --install /usr/bin/cc cc /usr/bin/gcc-${GCC_MAJOR_VERSION} 100 \
&& update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-${GCC_MAJOR_VERSION} 100 \
&& update-alternatives --install /usr/bin/gcov-dump gcov-dump /usr/bin/gcov-dump-${GCC_MAJOR_VERSION} 100 \
&& update-alternatives --install /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-${GCC_MAJOR_VERSION} 100
COPY --from=clio-tools \
/usr/local/bin/mold \
/usr/local/bin/ld.mold \
/usr/local/bin/ccache \
/usr/local/bin/doxygen \
/usr/local/bin/ClangBuildAnalyzer \
/usr/local/bin/git-cliff \
/usr/local/bin/gh \
/usr/local/bin/gdb \
/usr/local/bin/
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

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

@@ -0,0 +1,24 @@
# CI image for XRPLF/clio
This image contains an environment to build [Clio](https://github.com/XRPLF/clio), check code and documentation.
It is used in [Clio Github Actions](https://github.com/XRPLF/clio/actions) but can also be used to compile Clio locally.
The image is based on Ubuntu 20.04 and contains:
- ccache 4.11.3
- Clang 19
- ClangBuildAnalyzer 1.6.0
- Conan 2.20.1
- Doxygen 1.12
- GCC 15.2.0
- GDB 16.3
- gh 2.74
- git-cliff 2.9.1
- mold 2.40.1
- Python 3.13
- 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,12 @@
[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"]

View File

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

View File

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

View File

@@ -0,0 +1,23 @@
{% set compiler, sani = profile_name.split('.') %}
{% set sanitizer_opt_map = {"asan": "address", "tsan": "thread", "ubsan": "undefined"} %}
{% set sanitizer = sanitizer_opt_map[sani] %}
{% 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="cxxflags=\"{{ sanitizer_build_flags_str }}\" linkflags=\"{{ sanitizer_link_flags_str }}\""
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 }}
tools.info.package_id:confs+=["tools.build:cflags", "tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"]

View File

@@ -0,0 +1,32 @@
FROM ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive
SHELL ["/bin/bash", "-c"]
# hadolint ignore=DL3002
USER root
WORKDIR /root
RUN apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests \
wget \
software-properties-common \
gnupg \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ARG CLANG_MAJOR_VERSION=invalid
# Bump this version to force rebuild of the image
ARG BUILD_VERSION=1
RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
&& chmod +x llvm.sh \
&& ./llvm.sh ${CLANG_MAJOR_VERSION} \
&& rm -rf llvm.sh \
&& apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests \
libc++-${CLANG_MAJOR_VERSION}-dev \
libc++abi-${CLANG_MAJOR_VERSION}-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

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,119 @@
ARG UBUNTU_VERSION=20.04
ARG GCC_MAJOR_VERSION=invalid
FROM ubuntu:$UBUNTU_VERSION AS build
ARG UBUNTU_VERSION
ARG GCC_MAJOR_VERSION
ARG BUILD_VERSION=1
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
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: services:
clio_develop: clio_develop:
image: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-cb2642b image: ghcr.io/xrplf/clio-ci:384e79cd32f5f6c0ab9be3a1122ead41c5a7e67d
volumes: volumes:
- clio_develop_conan_data:/root/.conan2/p - clio_develop_conan_data:/root/.conan2/p
- clio_develop_ccache:/root/.ccache - clio_develop_ccache:/root/.ccache

View File

@@ -2,7 +2,7 @@
script_dir=$(dirname $0) script_dir=$(dirname $0)
pushd $script_dir >/dev/null pushd $script_dir > /dev/null
function start_container { function start_container {
if [ -z "$(docker ps -q -f name=clio_develop)" ]; then if [ -z "$(docker ps -q -f name=clio_develop)" ]; then
@@ -41,26 +41,21 @@ EOF
} }
case $1 in case $1 in
-h | --help) -h|--help)
print_help print_help ;;
;;
-t | --terminal) -t|--terminal)
open_terminal open_terminal ;;
;;
-s | --stop) -s|--stop)
stop_container stop_container ;;
;;
-*) -*)
echo "Unknown option: $1" echo "Unknown option: $1"
print_help print_help ;;
;;
*) *)
run "$@" run "$@" ;;
;;
esac esac
popd >/dev/null popd > /dev/null

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