mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Compare commits
130 Commits
legleux/tr
...
a1q123456/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bbb14696e | ||
|
|
df39ac33d2 | ||
|
|
96fdc711c0 | ||
|
|
a1344b91c3 | ||
|
|
5c8dfe5456 | ||
|
|
ab8c168e3b | ||
|
|
3a477e4d01 | ||
|
|
96bfc32fe2 | ||
|
|
de671863e2 | ||
|
|
e0cabb9f8c | ||
|
|
3d9c545f59 | ||
|
|
9b944ee8c2 | ||
|
|
509677abfd | ||
|
|
addc1e8e25 | ||
|
|
faf69da4b0 | ||
|
|
76e3b4fb0f | ||
|
|
e8bdbf975a | ||
|
|
2c765f6eb0 | ||
|
|
a9269fa846 | ||
|
|
15fd9feae5 | ||
|
|
b9d07730f3 | ||
|
|
85b65c8e9a | ||
|
|
8f182e825a | ||
|
|
cd78569d94 | ||
|
|
2c7af360c2 | ||
|
|
403fd7c649 | ||
|
|
dfed0481f7 | ||
|
|
0dc0c8e912 | ||
|
|
0510ee47d7 | ||
|
|
589c9c694c | ||
|
|
4096623ae1 | ||
|
|
dda162087f | ||
|
|
85a4015a64 | ||
|
|
f7bb4018fa | ||
|
|
0eedefbf45 | ||
|
|
8b986e4ab0 | ||
|
|
dcfcdab14e | ||
|
|
e0dbe90370 | ||
|
|
c463d0ff06 | ||
|
|
be1cc48d84 | ||
|
|
cf2eb149ee | ||
|
|
762922a07f | ||
|
|
fd28656ded | ||
|
|
9316da784a | ||
|
|
6efd31229a | ||
|
|
12954d5392 | ||
|
|
b1e5ba0518 | ||
|
|
d360e7c5b6 | ||
|
|
804a351773 | ||
|
|
697fb64e8c | ||
|
|
57e4cbbcd9 | ||
|
|
b92a9a3053 | ||
|
|
dcaef828b4 | ||
|
|
6fbeb04d9e | ||
|
|
2a325e7e2c | ||
|
|
808e814489 | ||
|
|
9e14707e77 | ||
|
|
95a45d7442 | ||
|
|
5fc4ab3e37 | ||
|
|
b129b71c33 | ||
|
|
013c2d6a56 | ||
|
|
72f4cb097f | ||
|
|
b523770486 | ||
|
|
a5185890ff | ||
|
|
0a9513e7f3 | ||
|
|
78b2d70a11 | ||
|
|
252c6768df | ||
|
|
5ae97fa8ae | ||
|
|
eff344faf9 | ||
|
|
7e7b71d84c | ||
|
|
ffea3977f0 | ||
|
|
47a235b7be | ||
|
|
f5e2415c98 | ||
|
|
1a4c359351 | ||
|
|
e4dbaf5efc | ||
|
|
983816248a | ||
|
|
b585dc78bb | ||
|
|
918185e18f | ||
|
|
1738a69619 | ||
|
|
1bf9e6e7da | ||
|
|
0446bef7e5 | ||
|
|
7a3bf1692d | ||
|
|
c1d108e565 | ||
|
|
1ba1bf9ade | ||
|
|
7dd3e0b3cc | ||
|
|
2b14ee3018 | ||
|
|
ce31a7ed16 | ||
|
|
91a23cf80b | ||
|
|
e460ea0840 | ||
|
|
46d5c67a8d | ||
|
|
ce9ccf844a | ||
|
|
c791cae1ec | ||
|
|
7b3724b7a3 | ||
|
|
bee2d112c6 | ||
|
|
01c977bbfe | ||
|
|
3baf5454f2 | ||
|
|
24a5cbaa93 | ||
|
|
eb7c8c6c7a | ||
|
|
f27d8f3890 | ||
|
|
8345cd77df | ||
|
|
c38aabdaee | ||
|
|
a896ed3987 | ||
|
|
1a7d67c4db | ||
|
|
92983d8040 | ||
|
|
320a65f77c | ||
|
|
45b8c4d732 | ||
|
|
e284969ae4 | ||
|
|
0335076359 | ||
|
|
7e2b137131 | ||
|
|
e2290b1a0a | ||
|
|
1ee0567b14 | ||
|
|
6b301efc8c | ||
|
|
9e0d350fca | ||
|
|
7b12c00e6b | ||
|
|
5865bd017f | ||
|
|
af0ec7defd | ||
|
|
0c74270b05 | ||
|
|
dde450784d | ||
|
|
08e734457f | ||
|
|
77518394e8 | ||
|
|
c69091bded | ||
|
|
595f0dd461 | ||
|
|
b451d5e412 | ||
|
|
af97df5a63 | ||
|
|
e39954d128 | ||
|
|
3cd1e3d94e | ||
|
|
fcec31ed20 | ||
|
|
0abd762781 | ||
|
|
5300e65686 | ||
|
|
afc660a1b5 |
153
.clang-tidy
153
.clang-tidy
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
# This entire group of checks was applied to all cpp files but not all header files.
|
||||||
|
# ---
|
||||||
Checks: "-*,
|
Checks: "-*,
|
||||||
bugprone-argument-comment,
|
bugprone-argument-comment,
|
||||||
bugprone-assert-side-effect,
|
bugprone-assert-side-effect,
|
||||||
@@ -8,33 +10,42 @@ Checks: "-*,
|
|||||||
bugprone-chained-comparison,
|
bugprone-chained-comparison,
|
||||||
bugprone-compare-pointer-to-member-virtual-function,
|
bugprone-compare-pointer-to-member-virtual-function,
|
||||||
bugprone-copy-constructor-init,
|
bugprone-copy-constructor-init,
|
||||||
|
# bugprone-crtp-constructor-accessibility, # has issues
|
||||||
bugprone-dangling-handle,
|
bugprone-dangling-handle,
|
||||||
bugprone-dynamic-static-initializers,
|
bugprone-dynamic-static-initializers,
|
||||||
|
# bugprone-empty-catch, # has issues
|
||||||
bugprone-fold-init-type,
|
bugprone-fold-init-type,
|
||||||
bugprone-forward-declaration-namespace,
|
# bugprone-forward-declaration-namespace, # has issues
|
||||||
bugprone-inaccurate-erase,
|
# bugprone-inaccurate-erase,
|
||||||
bugprone-incorrect-enable-if,
|
# bugprone-inc-dec-in-conditions,
|
||||||
bugprone-incorrect-roundings,
|
# bugprone-incorrect-enable-if,
|
||||||
bugprone-infinite-loop,
|
# bugprone-incorrect-roundings,
|
||||||
bugprone-integer-division,
|
# bugprone-infinite-loop,
|
||||||
|
# bugprone-integer-division,
|
||||||
bugprone-lambda-function-name,
|
bugprone-lambda-function-name,
|
||||||
bugprone-macro-parentheses,
|
# bugprone-macro-parentheses, # has issues
|
||||||
bugprone-macro-repeated-side-effects,
|
bugprone-macro-repeated-side-effects,
|
||||||
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,
|
||||||
bugprone-multi-level-implicit-pointer-conversion,
|
bugprone-move-forwarding-reference,
|
||||||
|
# bugprone-multi-level-implicit-pointer-conversion, # has issues
|
||||||
bugprone-multiple-new-in-one-expression,
|
bugprone-multiple-new-in-one-expression,
|
||||||
bugprone-multiple-statement-macro,
|
bugprone-multiple-statement-macro,
|
||||||
bugprone-no-escape,
|
bugprone-no-escape,
|
||||||
bugprone-non-zero-enum-to-bool-conversion,
|
bugprone-non-zero-enum-to-bool-conversion,
|
||||||
|
bugprone-optional-value-conversion,
|
||||||
bugprone-parent-virtual-call,
|
bugprone-parent-virtual-call,
|
||||||
|
bugprone-pointer-arithmetic-on-polymorphic-object,
|
||||||
bugprone-posix-return,
|
bugprone-posix-return,
|
||||||
bugprone-redundant-branch-condition,
|
bugprone-redundant-branch-condition,
|
||||||
|
# bugprone-reserved-identifier, # has issues
|
||||||
|
# bugprone-return-const-ref-from-parameter, # has issues
|
||||||
bugprone-shared-ptr-array-mismatch,
|
bugprone-shared-ptr-array-mismatch,
|
||||||
bugprone-signal-handler,
|
bugprone-signal-handler,
|
||||||
bugprone-signed-char-misuse,
|
bugprone-signed-char-misuse,
|
||||||
bugprone-sizeof-container,
|
bugprone-sizeof-container,
|
||||||
|
# bugprone-sizeof-expression, # has issues
|
||||||
bugprone-spuriously-wake-up-functions,
|
bugprone-spuriously-wake-up-functions,
|
||||||
bugprone-standalone-empty,
|
bugprone-standalone-empty,
|
||||||
bugprone-string-constructor,
|
bugprone-string-constructor,
|
||||||
@@ -45,97 +56,92 @@ Checks: "-*,
|
|||||||
bugprone-suspicious-include,
|
bugprone-suspicious-include,
|
||||||
bugprone-suspicious-memory-comparison,
|
bugprone-suspicious-memory-comparison,
|
||||||
bugprone-suspicious-memset-usage,
|
bugprone-suspicious-memset-usage,
|
||||||
|
bugprone-suspicious-missing-comma,
|
||||||
bugprone-suspicious-realloc-usage,
|
bugprone-suspicious-realloc-usage,
|
||||||
bugprone-suspicious-semicolon,
|
bugprone-suspicious-semicolon,
|
||||||
bugprone-suspicious-string-compare,
|
bugprone-suspicious-string-compare,
|
||||||
|
bugprone-suspicious-stringview-data-usage,
|
||||||
bugprone-swapped-arguments,
|
bugprone-swapped-arguments,
|
||||||
|
# bugprone-switch-missing-default-case, # has issues
|
||||||
bugprone-terminating-continue,
|
bugprone-terminating-continue,
|
||||||
bugprone-throw-keyword-missing,
|
bugprone-throw-keyword-missing,
|
||||||
|
bugprone-too-small-loop-variable,
|
||||||
|
# bugprone-unchecked-optional-access, # see https://github.com/XRPLF/rippled/pull/6502
|
||||||
bugprone-undefined-memory-manipulation,
|
bugprone-undefined-memory-manipulation,
|
||||||
bugprone-undelegated-constructor,
|
bugprone-undelegated-constructor,
|
||||||
bugprone-unhandled-exception-at-new,
|
bugprone-unhandled-exception-at-new,
|
||||||
|
bugprone-unhandled-self-assignment,
|
||||||
bugprone-unique-ptr-array-mismatch,
|
bugprone-unique-ptr-array-mismatch,
|
||||||
bugprone-unsafe-functions,
|
bugprone-unsafe-functions,
|
||||||
|
# bugprone-use-after-move, # has issues
|
||||||
|
bugprone-unused-raii,
|
||||||
|
bugprone-unused-return-value,
|
||||||
|
bugprone-unused-local-non-trivial-variable,
|
||||||
bugprone-virtual-near-miss,
|
bugprone-virtual-near-miss,
|
||||||
|
# cppcoreguidelines-init-variables, # has issues
|
||||||
|
# cppcoreguidelines-misleading-capture-default-by-value, # has issues
|
||||||
cppcoreguidelines-no-suspend-with-lock,
|
cppcoreguidelines-no-suspend-with-lock,
|
||||||
cppcoreguidelines-virtual-class-destructor,
|
# cppcoreguidelines-pro-type-member-init, # has issues
|
||||||
|
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||||
|
# cppcoreguidelines-rvalue-reference-param-not-moved, # has issues
|
||||||
|
# cppcoreguidelines-use-default-member-init, # has issues
|
||||||
|
# cppcoreguidelines-virtual-class-destructor, # has issues
|
||||||
hicpp-ignored-remove-result,
|
hicpp-ignored-remove-result,
|
||||||
misc-definitions-in-headers,
|
# misc-definitions-in-headers, # has issues
|
||||||
misc-header-include-cycle,
|
misc-header-include-cycle,
|
||||||
misc-misplaced-const,
|
misc-misplaced-const,
|
||||||
misc-static-assert,
|
misc-static-assert,
|
||||||
misc-throw-by-value-catch-by-reference,
|
# misc-throw-by-value-catch-by-reference, # has issues
|
||||||
misc-unused-alias-decls,
|
misc-unused-alias-decls,
|
||||||
misc-unused-using-decls,
|
misc-unused-using-decls,
|
||||||
readability-duplicate-include,
|
|
||||||
readability-enum-initial-value,
|
|
||||||
readability-misleading-indentation,
|
|
||||||
readability-non-const-parameter,
|
|
||||||
readability-redundant-declaration,
|
|
||||||
readability-reference-to-constructed-temporary,
|
|
||||||
modernize-deprecated-headers,
|
modernize-deprecated-headers,
|
||||||
modernize-make-shared,
|
modernize-make-shared,
|
||||||
modernize-make-unique,
|
modernize-make-unique,
|
||||||
|
performance-faster-string-find,
|
||||||
|
performance-for-range-copy,
|
||||||
performance-implicit-conversion-in-loop,
|
performance-implicit-conversion-in-loop,
|
||||||
|
performance-inefficient-vector-operation,
|
||||||
|
performance-move-const-arg,
|
||||||
performance-move-constructor-init,
|
performance-move-constructor-init,
|
||||||
performance-trivially-destructible
|
performance-no-automatic-move,
|
||||||
|
performance-trivially-destructible,
|
||||||
|
# readability-avoid-nested-conditional-operator, # has issues
|
||||||
|
# readability-avoid-return-with-void-value, # has issues
|
||||||
|
# readability-braces-around-statements, # has issues
|
||||||
|
# readability-const-return-type, # has issues
|
||||||
|
# readability-container-contains, # has issues
|
||||||
|
# readability-container-size-empty, # has issues
|
||||||
|
# readability-convert-member-functions-to-static, # has issues
|
||||||
|
readability-duplicate-include,
|
||||||
|
# readability-else-after-return, # has issues
|
||||||
|
# readability-enum-initial-value, # has issues
|
||||||
|
# readability-implicit-bool-conversion, # has issues
|
||||||
|
# readability-make-member-function-const, # has issues
|
||||||
|
# readability-math-missing-parentheses, # has issues
|
||||||
|
readability-misleading-indentation,
|
||||||
|
readability-non-const-parameter,
|
||||||
|
# readability-redundant-casting, # has issues
|
||||||
|
# readability-redundant-declaration, # has issues
|
||||||
|
# readability-redundant-inline-specifier, # has issues
|
||||||
|
# readability-redundant-member-init, # has issues
|
||||||
|
readability-redundant-string-init,
|
||||||
|
readability-reference-to-constructed-temporary,
|
||||||
|
# readability-simplify-boolean-expr, # has issues
|
||||||
|
# readability-static-definition-in-anonymous-namespace, # has issues
|
||||||
|
# readability-suspicious-call-argument, # has issues
|
||||||
|
readability-use-std-min-max
|
||||||
"
|
"
|
||||||
# ---
|
# ---
|
||||||
# checks that have some issues that need to be resolved:
|
# other checks that have issues that need to be resolved:
|
||||||
#
|
|
||||||
# bugprone-empty-catch,
|
|
||||||
# bugprone-crtp-constructor-accessibility,
|
|
||||||
# bugprone-inc-dec-in-conditions,
|
|
||||||
# bugprone-reserved-identifier,
|
|
||||||
# bugprone-move-forwarding-reference,
|
|
||||||
# bugprone-unused-local-non-trivial-variable,
|
|
||||||
# bugprone-return-const-ref-from-parameter,
|
|
||||||
# bugprone-switch-missing-default-case,
|
|
||||||
# bugprone-sizeof-expression,
|
|
||||||
# bugprone-suspicious-stringview-data-usage,
|
|
||||||
# bugprone-suspicious-missing-comma,
|
|
||||||
# bugprone-pointer-arithmetic-on-polymorphic-object,
|
|
||||||
# bugprone-optional-value-conversion,
|
|
||||||
# bugprone-too-small-loop-variable,
|
|
||||||
# bugprone-unused-return-value,
|
|
||||||
# bugprone-use-after-move,
|
|
||||||
# bugprone-unhandled-self-assignment,
|
|
||||||
# bugprone-unused-raii,
|
|
||||||
#
|
|
||||||
# cppcoreguidelines-misleading-capture-default-by-value,
|
|
||||||
# cppcoreguidelines-init-variables,
|
|
||||||
# cppcoreguidelines-pro-type-member-init,
|
|
||||||
# cppcoreguidelines-pro-type-static-cast-downcast,
|
|
||||||
# cppcoreguidelines-use-default-member-init,
|
|
||||||
# cppcoreguidelines-rvalue-reference-param-not-moved,
|
|
||||||
#
|
#
|
||||||
# llvm-namespace-comment,
|
# llvm-namespace-comment,
|
||||||
# misc-const-correctness,
|
# misc-const-correctness,
|
||||||
# misc-include-cleaner,
|
# misc-include-cleaner,
|
||||||
# misc-redundant-expression,
|
# misc-redundant-expression,
|
||||||
#
|
#
|
||||||
# readability-avoid-nested-conditional-operator,
|
# readability-inconsistent-declaration-parameter-name, # in this codebase this check will break a lot of arg names
|
||||||
# readability-avoid-return-with-void-value,
|
# readability-static-accessed-through-instance, # this check is probably unnecessary. it makes the code less readable
|
||||||
# readability-braces-around-statements,
|
# readability-identifier-naming, # https://github.com/XRPLF/rippled/pull/6571
|
||||||
# readability-container-contains,
|
|
||||||
# readability-container-size-empty,
|
|
||||||
# readability-convert-member-functions-to-static,
|
|
||||||
# readability-const-return-type,
|
|
||||||
# readability-else-after-return,
|
|
||||||
# readability-implicit-bool-conversion,
|
|
||||||
# readability-inconsistent-declaration-parameter-name,
|
|
||||||
# readability-identifier-naming,
|
|
||||||
# readability-make-member-function-const,
|
|
||||||
# readability-math-missing-parentheses,
|
|
||||||
# readability-redundant-inline-specifier,
|
|
||||||
# readability-redundant-member-init,
|
|
||||||
# readability-redundant-casting,
|
|
||||||
# readability-redundant-string-init,
|
|
||||||
# readability-simplify-boolean-expr,
|
|
||||||
# readability-static-definition-in-anonymous-namespace,
|
|
||||||
# readability-suspicious-call-argument,
|
|
||||||
# readability-use-std-min-max,
|
|
||||||
# readability-static-accessed-through-instance,
|
|
||||||
#
|
#
|
||||||
# modernize-concat-nested-namespaces,
|
# modernize-concat-nested-namespaces,
|
||||||
# modernize-pass-by-value,
|
# modernize-pass-by-value,
|
||||||
@@ -149,16 +155,10 @@ Checks: "-*,
|
|||||||
# modernize-use-starts-ends-with,
|
# modernize-use-starts-ends-with,
|
||||||
# modernize-use-std-numbers,
|
# modernize-use-std-numbers,
|
||||||
# modernize-use-using,
|
# modernize-use-using,
|
||||||
#
|
|
||||||
# performance-faster-string-find,
|
|
||||||
# performance-for-range-copy,
|
|
||||||
# performance-inefficient-vector-operation,
|
|
||||||
# performance-move-const-arg,
|
|
||||||
# performance-no-automatic-move,
|
|
||||||
# ---
|
# ---
|
||||||
#
|
#
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
# 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
|
||||||
# readability-identifier-naming.StructCase: CamelCase
|
# readability-identifier-naming.StructCase: CamelCase
|
||||||
@@ -193,8 +193,9 @@ CheckOptions:
|
|||||||
# 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-unsafe-functions.ReportMoreUnsafeFunctions: true
|
||||||
# bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
|
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'
|
# 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: '^.*/(test|xrpl|xrpld)/.*\.(h|hpp)$'
|
||||||
|
ExcludeHeaderFilterRegex: '^.*/protocol_autogen/.*\.(h|hpp)$'
|
||||||
WarningsAsErrors: "*"
|
WarningsAsErrors: "*"
|
||||||
|
|||||||
@@ -1,247 +0,0 @@
|
|||||||
_help_parse: Options affecting listfile parsing
|
|
||||||
parse:
|
|
||||||
_help_additional_commands:
|
|
||||||
- Specify structure for custom cmake functions
|
|
||||||
additional_commands:
|
|
||||||
target_protobuf_sources:
|
|
||||||
pargs:
|
|
||||||
- target
|
|
||||||
- prefix
|
|
||||||
kwargs:
|
|
||||||
PROTOS: "*"
|
|
||||||
LANGUAGE: cpp
|
|
||||||
IMPORT_DIRS: "*"
|
|
||||||
GENERATE_EXTENSIONS: "*"
|
|
||||||
PLUGIN: "*"
|
|
||||||
_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: 100
|
|
||||||
_help_tab_size:
|
|
||||||
- How many spaces to tab for indent
|
|
||||||
tab_size: 4
|
|
||||||
_help_use_tabchars:
|
|
||||||
- If true, lines are indented using tab characters (utf-8
|
|
||||||
- 0x09) instead of <tab_size> space characters (utf-8 0x20).
|
|
||||||
- In cases where the layout would require a fractional tab
|
|
||||||
- character, the behavior of the fractional indentation is
|
|
||||||
- governed by <fractional_tab_policy>
|
|
||||||
use_tabchars: false
|
|
||||||
_help_fractional_tab_policy:
|
|
||||||
- If <use_tabchars> is True, then the value of this variable
|
|
||||||
- indicates how fractional indentions are handled during
|
|
||||||
- whitespace replacement. If set to 'use-space', fractional
|
|
||||||
- indentation is left as spaces (utf-8 0x20). If set to
|
|
||||||
- "`round-up` fractional indentation is replaced with a single"
|
|
||||||
- tab character (utf-8 0x09) effectively shifting the column
|
|
||||||
- to the next tabstop
|
|
||||||
fractional_tab_policy: use-space
|
|
||||||
_help_max_subgroups_hwrap:
|
|
||||||
- If an argument group contains more than this many sub-groups
|
|
||||||
- (parg or kwarg groups) then force it to a vertical layout.
|
|
||||||
max_subgroups_hwrap: 4
|
|
||||||
_help_max_pargs_hwrap:
|
|
||||||
- If a positional argument group contains more than this many
|
|
||||||
- arguments, then force it to a vertical layout.
|
|
||||||
max_pargs_hwrap: 5
|
|
||||||
_help_max_rows_cmdline:
|
|
||||||
- If a cmdline positional group consumes more than this many
|
|
||||||
- lines without nesting, then invalidate the layout (and nest)
|
|
||||||
max_rows_cmdline: 2
|
|
||||||
_help_separate_ctrl_name_with_space:
|
|
||||||
- If true, separate flow control names from their parentheses
|
|
||||||
- with a space
|
|
||||||
separate_ctrl_name_with_space: true
|
|
||||||
_help_separate_fn_name_with_space:
|
|
||||||
- If true, separate function names from parentheses with a
|
|
||||||
- space
|
|
||||||
separate_fn_name_with_space: false
|
|
||||||
_help_dangle_parens:
|
|
||||||
- If a statement is wrapped to more than one line, than dangle
|
|
||||||
- the closing parenthesis on its own line.
|
|
||||||
dangle_parens: false
|
|
||||||
_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: 18
|
|
||||||
_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: false
|
|
||||||
_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: {}
|
|
||||||
101
.gersemi/definitions.cmake
Normal file
101
.gersemi/definitions.cmake
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# 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(git_branch branch_val)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(isolate_headers target A B scope)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(create_symbolic_link target link)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(xrpl_add_test name)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
macro(exclude_from_default target_)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(exclude_if_included target_)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
function(target_protobuf_sources target prefix)
|
||||||
|
set(options APPEND_PATH DESCRIPTORS)
|
||||||
|
set(oneValueArgs
|
||||||
|
LANGUAGE
|
||||||
|
OUT_VAR
|
||||||
|
EXPORT_MACRO
|
||||||
|
TARGET
|
||||||
|
PROTOC_OUT_DIR
|
||||||
|
PLUGIN
|
||||||
|
PLUGIN_OPTIONS
|
||||||
|
PROTOC_EXE
|
||||||
|
)
|
||||||
|
set(multiValueArgs
|
||||||
|
PROTOS
|
||||||
|
IMPORT_DIRS
|
||||||
|
GENERATE_EXTENSIONS
|
||||||
|
PROTOC_OPTIONS
|
||||||
|
DEPENDENCIES
|
||||||
|
)
|
||||||
|
cmake_parse_arguments(
|
||||||
|
THIS_FUNCTION_PREFIX
|
||||||
|
"${options}"
|
||||||
|
"${oneValueArgs}"
|
||||||
|
"${multiValueArgs}"
|
||||||
|
${ARGN}
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(add_module parent name)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(setup_protocol_autogen)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(target_link_modules parent scope)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
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(add_code_coverage_to_target name scope)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(verbose_find_path variable name)
|
||||||
|
set(options
|
||||||
|
NO_CACHE
|
||||||
|
REQUIRED
|
||||||
|
OPTIONAL
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
NO_PACKAGE_ROOT_PATH
|
||||||
|
NO_CMAKE_PATH
|
||||||
|
NO_CMAKE_ENVIRONMENT_PATH
|
||||||
|
NO_SYSTEM_ENVIRONMENT_PATH
|
||||||
|
NO_CMAKE_SYSTEM_PATH
|
||||||
|
NO_CMAKE_INSTALL_PREFIX
|
||||||
|
CMAKE_FIND_ROOT_PATH_BOTH
|
||||||
|
ONLY_CMAKE_FIND_ROOT_PATH
|
||||||
|
NO_CMAKE_FIND_ROOT_PATH
|
||||||
|
)
|
||||||
|
set(oneValueArgs REGISTRY_VIEW VALIDATOR DOC)
|
||||||
|
set(multiValueArgs NAMES HINTS PATHS PATH_SUFFIXES)
|
||||||
|
cmake_parse_arguments(
|
||||||
|
THIS_FUNCTION_PREFIX
|
||||||
|
"${options}"
|
||||||
|
"${oneValueArgs}"
|
||||||
|
"${multiValueArgs}"
|
||||||
|
${ARGN}
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
1
.gersemirc
Normal file
1
.gersemirc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
definitions: [.gersemi]
|
||||||
@@ -1,16 +1,79 @@
|
|||||||
# This feature requires Git >= 2.24
|
# This feature requires Git >= 2.24
|
||||||
# To use it by default in git blame:
|
# To use it by default in git blame:
|
||||||
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||||
50760c693510894ca368e90369b0cc2dabfd07f3
|
|
||||||
e2384885f5f630c8f0ffe4bf21a169b433a16858
|
# This file is sorted in reverse chronological order, with the most recent commits at the top.
|
||||||
241b9ddde9e11beb7480600fd5ed90e1ef109b21
|
# The commits listed here are ignored by git blame, which is useful for formatting-only commits that would otherwise obscure the history of changes to a file.
|
||||||
760f16f56835663d9286bd29294d074de26a7ba6
|
|
||||||
0eebe6a5f4246fced516d52b83ec4e7f47373edd
|
# refactor: Enable remaining clang-tidy `cppcoreguidelines` checks (#6538)
|
||||||
2189cc950c0cebb89e4e2fa3b2d8817205bf7cef
|
72f4cb097f626b08b02fc3efcb4aa11cb2e7adb8
|
||||||
b9d007813378ad0ff45660dc07285b823c7e9855
|
# refactor: Rename system name from 'ripple' to 'xrpld' (#6347)
|
||||||
fe9a5365b8a52d4acc42eb27369247e6f238a4f9
|
ffea3977f0b771fe8e43a8f74e4d393d63a7afd8
|
||||||
9a93577314e6a8d4b4a8368cc9d2b15a5d8303e8
|
# refactor: Update transaction folder structure (#6483)
|
||||||
552377c76f55b403a1c876df873a23d780fcc81c
|
5865bd017f777491b4a956f9210be0c4161f5442
|
||||||
97f0747e103f13e26e45b731731059b32f7679ac
|
# chore: Use gersemi instead of ancient cmake-format (#6486)
|
||||||
b13370ac0d207217354f1fc1c29aef87769fb8a1
|
0c74270b055133a57a497b5c9fc5a75f7647b1f4
|
||||||
|
# chore: Apply clang-format width 100 (#6387)
|
||||||
|
2c1fad102353e11293e3edde1c043224e7d3e983
|
||||||
|
# chore: Set clang-format width to 100 in config file (#6387)
|
||||||
|
25cca465538a56cce501477f9e5e2c1c7ea2d84c
|
||||||
|
# chore: Set cmake-format width to 100 (#6386)
|
||||||
|
469ce9f291a4480c38d4ee3baca5136b2f053cd0
|
||||||
|
# refactor: Modularize app/tx (#6228)
|
||||||
|
0976b2b68b64972af8e6e7c497900b5bce9fe22f
|
||||||
|
# chore: Update clang-format to 21.1.8 (#6352)
|
||||||
|
958d8f375453d80bb1aa4c293b5102c045a3e4b4
|
||||||
|
# refactor: Replace include guards by '#pragma once' (#6322)
|
||||||
|
34ef577604782ca8d6e1c17df8bd7470990a52ff
|
||||||
|
# chore: Format all cmake files without comments (#6294)
|
||||||
|
fe9c8d568fcf6ac21483024e01f58962dd5c8260
|
||||||
|
# chore: Add cmake-format pre-commit hook (#6279)
|
||||||
|
a0e09187b9370805d027c611a7e9ff5a0125282a
|
||||||
|
# chore: Set ColumnLimit to 120 in clang-format (#6288)
|
||||||
|
5f638f55536def0d88b970d1018a465a238e55f4
|
||||||
|
# refactor: Fix typos in comments, configure cspell (#6164)
|
||||||
|
3c9f5b62525cb1d6ca1153eeb10433db7d7379fd
|
||||||
|
# refactor: Rename `rippled.cfg` to `xrpld.cfg` (#6098)
|
||||||
|
3d1b3a49b3601a0a7037fa0b19d5df7b5e0e2fc1
|
||||||
|
# refactor: Rename `ripple` namespace to `xrpl` (#5982)
|
||||||
|
1eb0fdac6543706b4b9ddca57fd4102928a1f871
|
||||||
|
# refactor: Rename `rippled` binary to `xrpld` (#5983)
|
||||||
|
9eb84a561ef8bb066d89f098bd9b4ac71baed67c
|
||||||
|
# refactor: Replaces secp256k1 source by Conan package (#6089)
|
||||||
|
813bc4d9491b078bb950f8255f93b02f71320478
|
||||||
|
# refactor: Remove unnecessary copyright notices already covered by LICENSE.md (#5929)
|
||||||
|
1d42c4f6de6bf01d1286fc7459b17a37a5189e88
|
||||||
|
# refactor: Rename `RIPPLE_` and `RIPPLED_` definitions to `XRPL_` (#5821)
|
||||||
|
ada83564d894829424b0f4d922b0e737e07abbf7
|
||||||
|
# refactor: Modularize shamap and nodestore (#5668)
|
||||||
|
8eb233c2ea8ad5a159be73b77f0f5e1496d547ac
|
||||||
|
# refactor: Modularise ledger (#5493)
|
||||||
|
dc8b37a52448b005153c13a7f046ad494128cf94
|
||||||
|
# chore: Update clang-format and prettier with pre-commit (#5709)
|
||||||
|
c14ce956adeabe476ad73c18d73103f347c9c613
|
||||||
|
# chore: Fix file formatting (#5718)
|
||||||
896b8c3b54a22b0497cb0d1ce95e1095f9a227ce
|
896b8c3b54a22b0497cb0d1ce95e1095f9a227ce
|
||||||
|
# chore: Reverts formatting changes to external files, adds formatting changes to proto files (#5711)
|
||||||
|
b13370ac0d207217354f1fc1c29aef87769fb8a1
|
||||||
|
# chore: Run prettier on all files (#5657)
|
||||||
|
97f0747e103f13e26e45b731731059b32f7679ac
|
||||||
|
# Reformat code with clang-format-18
|
||||||
|
552377c76f55b403a1c876df873a23d780fcc81c
|
||||||
|
# Recompute loops (#4997)
|
||||||
|
d028005aa6319338b0adae1aebf8abe113162960
|
||||||
|
# Rewrite includes (#4997)
|
||||||
|
1d23148e6dd53957fcb6205c07a5c6cd7b64d50c
|
||||||
|
# Rearrange sources (#4997)
|
||||||
|
e416ee72ca26fa0c09d2aee1b68bdfb2b7046eed
|
||||||
|
# Move CMake directory (#4997)
|
||||||
|
2e902dee53aab2a8f27f32971047bb81e022f94f
|
||||||
|
# Rewrite includes
|
||||||
|
0eebe6a5f4246fced516d52b83ec4e7f47373edd
|
||||||
|
# Format formerly .hpp files
|
||||||
|
760f16f56835663d9286bd29294d074de26a7ba6
|
||||||
|
# Rename .hpp to .h
|
||||||
|
241b9ddde9e11beb7480600fd5ed90e1ef109b21
|
||||||
|
# Consolidate external libraries
|
||||||
|
e2384885f5f630c8f0ffe4bf21a169b433a16858
|
||||||
|
# Format first-party source according to .clang-format
|
||||||
|
50760c693510894ca368e90369b0cc2dabfd07f3
|
||||||
|
|||||||
4
.github/actions/generate-version/action.yml
vendored
4
.github/actions/generate-version/action.yml
vendored
@@ -11,7 +11,7 @@ runs:
|
|||||||
steps:
|
steps:
|
||||||
# When a tag is pushed, the version is used as-is.
|
# When a tag is pushed, the version is used as-is.
|
||||||
- name: Generate version for tag event
|
- name: Generate version for tag event
|
||||||
if: ${{ github.event_name == 'tag' }}
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ github.ref_name }}
|
VERSION: ${{ github.ref_name }}
|
||||||
@@ -22,7 +22,7 @@ runs:
|
|||||||
# We use a plus sign instead of a hyphen because Conan recipe versions do
|
# We use a plus sign instead of a hyphen because Conan recipe versions do
|
||||||
# not support two hyphens.
|
# not support two hyphens.
|
||||||
- name: Generate version for non-tag event
|
- name: Generate version for non-tag event
|
||||||
if: ${{ github.event_name != 'tag' }}
|
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo 'Extracting version from BuildInfo.cpp.'
|
echo 'Extracting version from BuildInfo.cpp.'
|
||||||
|
|||||||
16
.github/pull_request_template.md
vendored
16
.github/pull_request_template.md
vendored
@@ -29,22 +29,6 @@ If a refactor, how is this better than the previous implementation?
|
|||||||
If there is a spec or design document for this feature, please link it here.
|
If there is a spec or design document for this feature, please link it here.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
### Type of Change
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Please check [x] relevant options, delete irrelevant ones.
|
|
||||||
-->
|
|
||||||
|
|
||||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
|
||||||
- [ ] New feature (non-breaking change which adds functionality)
|
|
||||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
|
||||||
- [ ] Refactor (non-breaking change that only restructures code)
|
|
||||||
- [ ] Performance (increase or change in throughput and/or latency)
|
|
||||||
- [ ] Tests (you added tests for code that already exists, or your new feature included in this PR)
|
|
||||||
- [ ] Documentation update
|
|
||||||
- [ ] Chore (no impact to binary, e.g. `.gitignore`, formatting, dropping support for older tooling)
|
|
||||||
- [ ] Release
|
|
||||||
|
|
||||||
### API Impact
|
### API Impact
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|||||||
6
.github/scripts/levelization/README.md
vendored
6
.github/scripts/levelization/README.md
vendored
@@ -70,7 +70,7 @@ that `test` code should _never_ be included in `xrpl` or `xrpld` code.)
|
|||||||
|
|
||||||
## Validation
|
## Validation
|
||||||
|
|
||||||
The [levelization](generate.sh) script takes no parameters,
|
The [levelization](generate.py) script takes no parameters,
|
||||||
reads no environment variables, and can be run from any directory,
|
reads no environment variables, and can be run from any directory,
|
||||||
as long as it is in the expected location in the rippled repo.
|
as long as it is in the expected location in the rippled repo.
|
||||||
It can be run at any time from within a checked out repo, and will
|
It can be run at any time from within a checked out repo, and will
|
||||||
@@ -104,7 +104,7 @@ It generates many files of [results](results):
|
|||||||
Github Actions workflow to test that levelization loops haven't
|
Github Actions workflow to test that levelization loops haven't
|
||||||
changed. Unfortunately, if changes are detected, it can't tell if
|
changed. Unfortunately, if changes are detected, it can't tell if
|
||||||
they are improvements or not, so if you have resolved any issues or
|
they are improvements or not, so if you have resolved any issues or
|
||||||
done anything else to improve levelization, run `levelization.sh`,
|
done anything else to improve levelization, run `generate.py`,
|
||||||
and commit the updated results.
|
and commit the updated results.
|
||||||
|
|
||||||
The `loops.txt` and `ordering.txt` files relate the modules
|
The `loops.txt` and `ordering.txt` files relate the modules
|
||||||
@@ -128,7 +128,7 @@ The committed files hide the detailed values intentionally, to
|
|||||||
prevent false alarms and merging issues, and because it's easy to
|
prevent false alarms and merging issues, and because it's easy to
|
||||||
get those details locally.
|
get those details locally.
|
||||||
|
|
||||||
1. Run `levelization.sh`
|
1. Run `generate.py`
|
||||||
2. Grep the modules in `paths.txt`.
|
2. Grep the modules in `paths.txt`.
|
||||||
- For example, if a cycle is found `A ~= B`, simply `grep -w
|
- For example, if a cycle is found `A ~= B`, simply `grep -w
|
||||||
A .github/scripts/levelization/results/paths.txt | grep -w B`
|
A .github/scripts/levelization/results/paths.txt | grep -w B`
|
||||||
|
|||||||
335
.github/scripts/levelization/generate.py
vendored
Normal file
335
.github/scripts/levelization/generate.py
vendored
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Usage: generate.py
|
||||||
|
This script takes no parameters, and can be called from any directory in the file system.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, List, Tuple, Set, Optional
|
||||||
|
|
||||||
|
# Compile regex patterns once at module level
|
||||||
|
INCLUDE_PATTERN = re.compile(r"^\s*#include.*/.*\.h")
|
||||||
|
INCLUDE_PATH_PATTERN = re.compile(r'[<"]([^>"]+)[>"]')
|
||||||
|
|
||||||
|
|
||||||
|
def dictionary_sort_key(s: str) -> str:
|
||||||
|
"""
|
||||||
|
Create a sort key that mimics 'sort -d' (dictionary order).
|
||||||
|
Dictionary order only considers blanks and alphanumeric characters.
|
||||||
|
This means punctuation like '.' is ignored during sorting.
|
||||||
|
"""
|
||||||
|
# Keep only alphanumeric characters and spaces
|
||||||
|
return "".join(c for c in s if c.isalnum() or c.isspace())
|
||||||
|
|
||||||
|
|
||||||
|
def get_level(file_path: str) -> str:
|
||||||
|
"""
|
||||||
|
Extract the level from a file path (second and third directory components).
|
||||||
|
Equivalent to bash: cut -d/ -f 2,3
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
src/xrpld/app/main.cpp -> xrpld.app
|
||||||
|
src/libxrpl/protocol/STObject.cpp -> libxrpl.protocol
|
||||||
|
include/xrpl/basics/base_uint.h -> xrpl.basics
|
||||||
|
"""
|
||||||
|
parts = file_path.split("/")
|
||||||
|
|
||||||
|
# Get fields 2 and 3 (indices 1 and 2 in 0-based indexing)
|
||||||
|
if len(parts) >= 3:
|
||||||
|
level = f"{parts[1]}/{parts[2]}"
|
||||||
|
elif len(parts) >= 2:
|
||||||
|
level = f"{parts[1]}/toplevel"
|
||||||
|
else:
|
||||||
|
level = file_path
|
||||||
|
|
||||||
|
# If the "level" indicates a file, cut off the filename
|
||||||
|
if "." in level.split("/")[-1]: # Avoid Path object creation
|
||||||
|
# Use the "toplevel" label as a workaround for `sort`
|
||||||
|
# inconsistencies between different utility versions
|
||||||
|
level = level.rsplit("/", 1)[0] + "/toplevel"
|
||||||
|
|
||||||
|
return level.replace("/", ".")
|
||||||
|
|
||||||
|
|
||||||
|
def extract_include_level(include_line: str) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Extract the include path from an #include directive.
|
||||||
|
Gets the first two directory components from the include path.
|
||||||
|
Equivalent to bash: cut -d/ -f 1,2
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
#include <xrpl/basics/base_uint.h> -> xrpl.basics
|
||||||
|
#include "xrpld/app/main/Application.h" -> xrpld.app
|
||||||
|
"""
|
||||||
|
# Remove everything before the quote or angle bracket
|
||||||
|
match = INCLUDE_PATH_PATTERN.search(include_line)
|
||||||
|
if not match:
|
||||||
|
return None
|
||||||
|
|
||||||
|
include_path = match.group(1)
|
||||||
|
parts = include_path.split("/")
|
||||||
|
|
||||||
|
# Get first two fields (indices 0 and 1)
|
||||||
|
if len(parts) >= 2:
|
||||||
|
include_level = f"{parts[0]}/{parts[1]}"
|
||||||
|
else:
|
||||||
|
include_level = include_path
|
||||||
|
|
||||||
|
# If the "includelevel" indicates a file, cut off the filename
|
||||||
|
if "." in include_level.split("/")[-1]: # Avoid Path object creation
|
||||||
|
include_level = include_level.rsplit("/", 1)[0] + "/toplevel"
|
||||||
|
|
||||||
|
return include_level.replace("/", ".")
|
||||||
|
|
||||||
|
|
||||||
|
def find_repository_directories(
|
||||||
|
start_path: Path, depth_limit: int = 10
|
||||||
|
) -> Tuple[Path, List[Path]]:
|
||||||
|
"""
|
||||||
|
Find the repository root by looking for src or include folders.
|
||||||
|
Walks up the directory tree from the start path.
|
||||||
|
"""
|
||||||
|
current = start_path.resolve()
|
||||||
|
|
||||||
|
# Walk up the directory tree
|
||||||
|
for _ in range(depth_limit): # Limit search depth to prevent infinite loops
|
||||||
|
src_path = current / "src"
|
||||||
|
include_path = current / "include"
|
||||||
|
# Check if this directory has src or include folders
|
||||||
|
has_src = src_path.exists()
|
||||||
|
has_include = include_path.exists()
|
||||||
|
|
||||||
|
if has_src or has_include:
|
||||||
|
return current, [src_path, include_path]
|
||||||
|
|
||||||
|
# Move up one level
|
||||||
|
parent = current.parent
|
||||||
|
if parent == current: # Reached filesystem root
|
||||||
|
break
|
||||||
|
current = parent
|
||||||
|
|
||||||
|
# If we couldn't find it, raise an error
|
||||||
|
raise RuntimeError(
|
||||||
|
"Could not find repository root. "
|
||||||
|
"Expected to find a directory containing 'src' and/or 'include' folders."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Change to the script's directory
|
||||||
|
script_dir = Path(__file__).parent.resolve()
|
||||||
|
os.chdir(script_dir)
|
||||||
|
|
||||||
|
# Clean up and create results directory.
|
||||||
|
results_dir = script_dir / "results"
|
||||||
|
if results_dir.exists():
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
shutil.rmtree(results_dir)
|
||||||
|
results_dir.mkdir()
|
||||||
|
|
||||||
|
# Find the repository root by searching for src and include directories.
|
||||||
|
try:
|
||||||
|
repo_root, scan_dirs = find_repository_directories(script_dir)
|
||||||
|
|
||||||
|
print(f"Found repository root: {repo_root}")
|
||||||
|
print(f"Scanning directories:")
|
||||||
|
for scan_dir in scan_dirs:
|
||||||
|
print(f" - {scan_dir.relative_to(repo_root)}")
|
||||||
|
except RuntimeError as e:
|
||||||
|
print(f"Error: {e}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("\nScanning for raw includes...")
|
||||||
|
# Find all #include directives
|
||||||
|
raw_includes: List[Tuple[str, str]] = []
|
||||||
|
rawincludes_file = results_dir / "rawincludes.txt"
|
||||||
|
|
||||||
|
# Write to file as we go to avoid storing everything in memory.
|
||||||
|
with open(rawincludes_file, "w", buffering=8192) as raw_f:
|
||||||
|
for dir_path in scan_dirs:
|
||||||
|
print(f" Scanning {dir_path.relative_to(repo_root)}...")
|
||||||
|
|
||||||
|
for file_path in dir_path.rglob("*"):
|
||||||
|
if not file_path.is_file():
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
rel_path_str = str(file_path.relative_to(repo_root))
|
||||||
|
|
||||||
|
# Read file with a large buffer for performance.
|
||||||
|
with open(
|
||||||
|
file_path,
|
||||||
|
"r",
|
||||||
|
encoding="utf-8",
|
||||||
|
errors="ignore",
|
||||||
|
buffering=8192,
|
||||||
|
) as f:
|
||||||
|
for line in f:
|
||||||
|
# Quick check before regex
|
||||||
|
if "#include" not in line or "boost" in line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if INCLUDE_PATTERN.match(line):
|
||||||
|
line_stripped = line.strip()
|
||||||
|
entry = f"{rel_path_str}:{line_stripped}\n"
|
||||||
|
print(entry, end="")
|
||||||
|
raw_f.write(entry)
|
||||||
|
raw_includes.append((rel_path_str, line_stripped))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading {file_path}: {e}", file=sys.stderr)
|
||||||
|
|
||||||
|
# Build levelization paths and count directly (no need to sort first).
|
||||||
|
print("Build levelization paths")
|
||||||
|
path_counts: Dict[Tuple[str, str], int] = defaultdict(int)
|
||||||
|
|
||||||
|
for file_path, include_line in raw_includes:
|
||||||
|
include_level = extract_include_level(include_line)
|
||||||
|
if not include_level:
|
||||||
|
continue
|
||||||
|
|
||||||
|
level = get_level(file_path)
|
||||||
|
if level != include_level:
|
||||||
|
path_counts[(level, include_level)] += 1
|
||||||
|
|
||||||
|
# Sort and deduplicate paths (using dictionary order like bash 'sort -d').
|
||||||
|
print("Sort and deduplicate paths")
|
||||||
|
|
||||||
|
paths_file = results_dir / "paths.txt"
|
||||||
|
with open(paths_file, "w") as f:
|
||||||
|
# Sort using dictionary order: only alphanumeric and spaces matter
|
||||||
|
sorted_items = sorted(
|
||||||
|
path_counts.items(),
|
||||||
|
key=lambda x: (dictionary_sort_key(x[0][0]), dictionary_sort_key(x[0][1])),
|
||||||
|
)
|
||||||
|
for (level, include_level), count in sorted_items:
|
||||||
|
line = f"{count:7} {level} {include_level}\n"
|
||||||
|
print(line.rstrip())
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
# Split into flat-file database
|
||||||
|
print("Split into flat-file database")
|
||||||
|
includes_dir = results_dir / "includes"
|
||||||
|
included_by_dir = results_dir / "included_by"
|
||||||
|
includes_dir.mkdir()
|
||||||
|
included_by_dir.mkdir()
|
||||||
|
|
||||||
|
# Batch writes by grouping data first to avoid repeated file opens.
|
||||||
|
includes_data: Dict[str, List[Tuple[str, int]]] = defaultdict(list)
|
||||||
|
included_by_data: Dict[str, List[Tuple[str, int]]] = defaultdict(list)
|
||||||
|
|
||||||
|
# Process in sorted order to match bash script behaviour (dictionary order).
|
||||||
|
sorted_items = sorted(
|
||||||
|
path_counts.items(),
|
||||||
|
key=lambda x: (dictionary_sort_key(x[0][0]), dictionary_sort_key(x[0][1])),
|
||||||
|
)
|
||||||
|
for (level, include_level), count in sorted_items:
|
||||||
|
includes_data[level].append((include_level, count))
|
||||||
|
included_by_data[include_level].append((level, count))
|
||||||
|
|
||||||
|
# Write all includes files in sorted order (dictionary order).
|
||||||
|
for level in sorted(includes_data.keys(), key=dictionary_sort_key):
|
||||||
|
entries = includes_data[level]
|
||||||
|
with open(includes_dir / level, "w") as f:
|
||||||
|
for include_level, count in entries:
|
||||||
|
line = f"{include_level} {count}\n"
|
||||||
|
print(line.rstrip())
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
# Write all included_by files in sorted order (dictionary order).
|
||||||
|
for include_level in sorted(included_by_data.keys(), key=dictionary_sort_key):
|
||||||
|
entries = included_by_data[include_level]
|
||||||
|
with open(included_by_dir / include_level, "w") as f:
|
||||||
|
for level, count in entries:
|
||||||
|
line = f"{level} {count}\n"
|
||||||
|
print(line.rstrip())
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
# Search for loops
|
||||||
|
print("Search for loops")
|
||||||
|
loops_file = results_dir / "loops.txt"
|
||||||
|
ordering_file = results_dir / "ordering.txt"
|
||||||
|
|
||||||
|
loops_found: Set[Tuple[str, str]] = set()
|
||||||
|
|
||||||
|
# Pre-load all include files into memory to avoid repeated I/O.
|
||||||
|
# This is the biggest optimisation - we were reading files repeatedly in nested loops.
|
||||||
|
# Use list of tuples to preserve file order.
|
||||||
|
includes_cache: Dict[str, List[Tuple[str, int]]] = {}
|
||||||
|
includes_lookup: Dict[str, Dict[str, int]] = {} # For fast lookup
|
||||||
|
|
||||||
|
# Note: bash script uses 'for source in *' which uses standard glob sorting,
|
||||||
|
# NOT dictionary order. So we use standard sorted() here, not dictionary_sort_key.
|
||||||
|
for include_file in sorted(includes_dir.iterdir(), key=lambda p: p.name):
|
||||||
|
if not include_file.is_file():
|
||||||
|
continue
|
||||||
|
|
||||||
|
includes_cache[include_file.name] = []
|
||||||
|
includes_lookup[include_file.name] = {}
|
||||||
|
with open(include_file, "r") as f:
|
||||||
|
for line in f:
|
||||||
|
parts = line.strip().split()
|
||||||
|
if len(parts) >= 2:
|
||||||
|
include_name = parts[0]
|
||||||
|
include_count = int(parts[1])
|
||||||
|
includes_cache[include_file.name].append(
|
||||||
|
(include_name, include_count)
|
||||||
|
)
|
||||||
|
includes_lookup[include_file.name][include_name] = include_count
|
||||||
|
|
||||||
|
with open(loops_file, "w", buffering=8192) as loops_f, open(
|
||||||
|
ordering_file, "w", buffering=8192
|
||||||
|
) as ordering_f:
|
||||||
|
|
||||||
|
# Use standard sorting to match bash glob expansion 'for source in *'.
|
||||||
|
for source in sorted(includes_cache.keys()):
|
||||||
|
source_includes = includes_cache[source]
|
||||||
|
|
||||||
|
for include, include_freq in source_includes:
|
||||||
|
# Check if include file exists and references source
|
||||||
|
if include not in includes_lookup:
|
||||||
|
continue
|
||||||
|
|
||||||
|
source_freq = includes_lookup[include].get(source)
|
||||||
|
|
||||||
|
if source_freq is not None:
|
||||||
|
# Found a loop
|
||||||
|
loop_key = tuple(sorted([source, include]))
|
||||||
|
if loop_key in loops_found:
|
||||||
|
continue
|
||||||
|
loops_found.add(loop_key)
|
||||||
|
|
||||||
|
loops_f.write(f"Loop: {source} {include}\n")
|
||||||
|
|
||||||
|
# If the counts are close, indicate that the two modules are
|
||||||
|
# on the same level, though they shouldn't be.
|
||||||
|
diff = include_freq - source_freq
|
||||||
|
if diff > 3:
|
||||||
|
loops_f.write(f" {source} > {include}\n\n")
|
||||||
|
elif diff < -3:
|
||||||
|
loops_f.write(f" {include} > {source}\n\n")
|
||||||
|
elif source_freq == include_freq:
|
||||||
|
loops_f.write(f" {include} == {source}\n\n")
|
||||||
|
else:
|
||||||
|
loops_f.write(f" {include} ~= {source}\n\n")
|
||||||
|
else:
|
||||||
|
ordering_f.write(f"{source} > {include}\n")
|
||||||
|
|
||||||
|
# Print results
|
||||||
|
print("\nOrdering:")
|
||||||
|
with open(ordering_file, "r") as f:
|
||||||
|
print(f.read(), end="")
|
||||||
|
|
||||||
|
print("\nLoops:")
|
||||||
|
with open(loops_file, "r") as f:
|
||||||
|
print(f.read(), end="")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
130
.github/scripts/levelization/generate.sh
vendored
130
.github/scripts/levelization/generate.sh
vendored
@@ -1,130 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Usage: generate.sh
|
|
||||||
# This script takes no parameters, reads no environment variables,
|
|
||||||
# and can be run from any directory, as long as it is in the expected
|
|
||||||
# location in the repo.
|
|
||||||
|
|
||||||
pushd $( dirname $0 )
|
|
||||||
|
|
||||||
if [ -v PS1 ]
|
|
||||||
then
|
|
||||||
# if the shell is interactive, clean up any flotsam before analyzing
|
|
||||||
git clean -ix
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ensure all sorting is ASCII-order consistently across platforms.
|
|
||||||
export LANG=C
|
|
||||||
|
|
||||||
rm -rfv results
|
|
||||||
mkdir results
|
|
||||||
includes="$( pwd )/results/rawincludes.txt"
|
|
||||||
pushd ../../..
|
|
||||||
echo Raw includes:
|
|
||||||
grep -r '^[ ]*#include.*/.*\.h' include src | \
|
|
||||||
grep -v boost | tee ${includes}
|
|
||||||
popd
|
|
||||||
pushd results
|
|
||||||
|
|
||||||
oldifs=${IFS}
|
|
||||||
IFS=:
|
|
||||||
mkdir includes
|
|
||||||
mkdir included_by
|
|
||||||
echo Build levelization paths
|
|
||||||
exec 3< ${includes} # open rawincludes.txt for input
|
|
||||||
while read -r -u 3 file include
|
|
||||||
do
|
|
||||||
level=$( echo ${file} | cut -d/ -f 2,3 )
|
|
||||||
# If the "level" indicates a file, cut off the filename
|
|
||||||
if [[ "${level##*.}" != "${level}" ]]
|
|
||||||
then
|
|
||||||
# Use the "toplevel" label as a workaround for `sort`
|
|
||||||
# inconsistencies between different utility versions
|
|
||||||
level="$( dirname ${level} )/toplevel"
|
|
||||||
fi
|
|
||||||
level=$( echo ${level} | tr '/' '.' )
|
|
||||||
|
|
||||||
includelevel=$( echo ${include} | sed 's/.*["<]//; s/[">].*//' | \
|
|
||||||
cut -d/ -f 1,2 )
|
|
||||||
if [[ "${includelevel##*.}" != "${includelevel}" ]]
|
|
||||||
then
|
|
||||||
# Use the "toplevel" label as a workaround for `sort`
|
|
||||||
# inconsistencies between different utility versions
|
|
||||||
includelevel="$( dirname ${includelevel} )/toplevel"
|
|
||||||
fi
|
|
||||||
includelevel=$( echo ${includelevel} | tr '/' '.' )
|
|
||||||
|
|
||||||
if [[ "$level" != "$includelevel" ]]
|
|
||||||
then
|
|
||||||
echo $level $includelevel | tee -a paths.txt
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo Sort and deduplicate paths
|
|
||||||
sort -ds paths.txt | uniq -c | tee sortedpaths.txt
|
|
||||||
mv sortedpaths.txt paths.txt
|
|
||||||
exec 3>&- #close fd 3
|
|
||||||
IFS=${oldifs}
|
|
||||||
unset oldifs
|
|
||||||
|
|
||||||
echo Split into flat-file database
|
|
||||||
exec 4<paths.txt # open paths.txt for input
|
|
||||||
while read -r -u 4 count level include
|
|
||||||
do
|
|
||||||
echo ${include} ${count} | tee -a includes/${level}
|
|
||||||
echo ${level} ${count} | tee -a included_by/${include}
|
|
||||||
done
|
|
||||||
exec 4>&- #close fd 4
|
|
||||||
|
|
||||||
loops="$( pwd )/loops.txt"
|
|
||||||
ordering="$( pwd )/ordering.txt"
|
|
||||||
pushd includes
|
|
||||||
echo Search for loops
|
|
||||||
# Redirect stdout to a file
|
|
||||||
exec 4>&1
|
|
||||||
exec 1>"${loops}"
|
|
||||||
for source in *
|
|
||||||
do
|
|
||||||
if [[ -f "$source" ]]
|
|
||||||
then
|
|
||||||
exec 5<"${source}" # open for input
|
|
||||||
while read -r -u 5 include includefreq
|
|
||||||
do
|
|
||||||
if [[ -f $include ]]
|
|
||||||
then
|
|
||||||
if grep -q -w $source $include
|
|
||||||
then
|
|
||||||
if grep -q -w "Loop: $include $source" "${loops}"
|
|
||||||
then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
sourcefreq=$( grep -w $source $include | cut -d\ -f2 )
|
|
||||||
echo "Loop: $source $include"
|
|
||||||
# If the counts are close, indicate that the two modules are
|
|
||||||
# on the same level, though they shouldn't be
|
|
||||||
if [[ $(( $includefreq - $sourcefreq )) -gt 3 ]]
|
|
||||||
then
|
|
||||||
echo -e " $source > $include\n"
|
|
||||||
elif [[ $(( $sourcefreq - $includefreq )) -gt 3 ]]
|
|
||||||
then
|
|
||||||
echo -e " $include > $source\n"
|
|
||||||
elif [[ $sourcefreq -eq $includefreq ]]
|
|
||||||
then
|
|
||||||
echo -e " $include == $source\n"
|
|
||||||
else
|
|
||||||
echo -e " $include ~= $source\n"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "$source > $include" >> "${ordering}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
exec 5>&- #close fd 5
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
exec 1>&4 #close fd 1
|
|
||||||
exec 4>&- #close fd 4
|
|
||||||
cat "${ordering}"
|
|
||||||
cat "${loops}"
|
|
||||||
popd
|
|
||||||
popd
|
|
||||||
popd
|
|
||||||
@@ -19,7 +19,9 @@ libxrpl.nodestore > xrpl.protocol
|
|||||||
libxrpl.protocol > xrpl.basics
|
libxrpl.protocol > xrpl.basics
|
||||||
libxrpl.protocol > xrpl.json
|
libxrpl.protocol > xrpl.json
|
||||||
libxrpl.protocol > xrpl.protocol
|
libxrpl.protocol > xrpl.protocol
|
||||||
|
libxrpl.protocol_autogen > xrpl.protocol_autogen
|
||||||
libxrpl.rdb > xrpl.basics
|
libxrpl.rdb > xrpl.basics
|
||||||
|
libxrpl.rdb > xrpl.core
|
||||||
libxrpl.rdb > xrpl.rdb
|
libxrpl.rdb > xrpl.rdb
|
||||||
libxrpl.resource > xrpl.basics
|
libxrpl.resource > xrpl.basics
|
||||||
libxrpl.resource > xrpl.json
|
libxrpl.resource > xrpl.json
|
||||||
@@ -89,6 +91,7 @@ test.core > xrpl.server
|
|||||||
test.csf > xrpl.basics
|
test.csf > xrpl.basics
|
||||||
test.csf > xrpld.consensus
|
test.csf > xrpld.consensus
|
||||||
test.csf > xrpl.json
|
test.csf > xrpl.json
|
||||||
|
test.csf > xrpl.ledger
|
||||||
test.csf > xrpl.protocol
|
test.csf > xrpl.protocol
|
||||||
test.json > test.jtx
|
test.json > test.jtx
|
||||||
test.json > xrpl.json
|
test.json > xrpl.json
|
||||||
@@ -107,7 +110,6 @@ test.jtx > xrpl.tx
|
|||||||
test.ledger > test.jtx
|
test.ledger > test.jtx
|
||||||
test.ledger > test.toplevel
|
test.ledger > test.toplevel
|
||||||
test.ledger > xrpl.basics
|
test.ledger > xrpl.basics
|
||||||
test.ledger > xrpld.app
|
|
||||||
test.ledger > xrpld.core
|
test.ledger > xrpld.core
|
||||||
test.ledger > xrpl.ledger
|
test.ledger > xrpl.ledger
|
||||||
test.ledger > xrpl.protocol
|
test.ledger > xrpl.protocol
|
||||||
@@ -124,6 +126,7 @@ test.overlay > xrpl.basics
|
|||||||
test.overlay > xrpld.app
|
test.overlay > xrpld.app
|
||||||
test.overlay > xrpld.overlay
|
test.overlay > xrpld.overlay
|
||||||
test.overlay > xrpld.peerfinder
|
test.overlay > xrpld.peerfinder
|
||||||
|
test.overlay > xrpl.ledger
|
||||||
test.overlay > xrpl.nodestore
|
test.overlay > xrpl.nodestore
|
||||||
test.overlay > xrpl.protocol
|
test.overlay > xrpl.protocol
|
||||||
test.overlay > xrpl.shamap
|
test.overlay > xrpl.shamap
|
||||||
@@ -134,6 +137,7 @@ test.peerfinder > xrpld.core
|
|||||||
test.peerfinder > xrpld.peerfinder
|
test.peerfinder > xrpld.peerfinder
|
||||||
test.peerfinder > xrpl.protocol
|
test.peerfinder > xrpl.protocol
|
||||||
test.protocol > test.toplevel
|
test.protocol > test.toplevel
|
||||||
|
test.protocol > test.unit_test
|
||||||
test.protocol > xrpl.basics
|
test.protocol > xrpl.basics
|
||||||
test.protocol > xrpl.json
|
test.protocol > xrpl.json
|
||||||
test.protocol > xrpl.protocol
|
test.protocol > xrpl.protocol
|
||||||
@@ -171,14 +175,16 @@ test.shamap > xrpl.shamap
|
|||||||
test.toplevel > test.csf
|
test.toplevel > test.csf
|
||||||
test.toplevel > xrpl.json
|
test.toplevel > xrpl.json
|
||||||
test.unit_test > xrpl.basics
|
test.unit_test > xrpl.basics
|
||||||
|
test.unit_test > xrpl.protocol
|
||||||
tests.libxrpl > xrpl.basics
|
tests.libxrpl > xrpl.basics
|
||||||
tests.libxrpl > xrpl.json
|
tests.libxrpl > xrpl.json
|
||||||
tests.libxrpl > xrpl.net
|
tests.libxrpl > xrpl.net
|
||||||
|
tests.libxrpl > xrpl.protocol
|
||||||
|
tests.libxrpl > xrpl.protocol_autogen
|
||||||
xrpl.conditions > xrpl.basics
|
xrpl.conditions > xrpl.basics
|
||||||
xrpl.conditions > xrpl.protocol
|
xrpl.conditions > xrpl.protocol
|
||||||
xrpl.core > xrpl.basics
|
xrpl.core > xrpl.basics
|
||||||
xrpl.core > xrpl.json
|
xrpl.core > xrpl.json
|
||||||
xrpl.core > xrpl.ledger
|
|
||||||
xrpl.core > xrpl.protocol
|
xrpl.core > xrpl.protocol
|
||||||
xrpl.json > xrpl.basics
|
xrpl.json > xrpl.basics
|
||||||
xrpl.ledger > xrpl.basics
|
xrpl.ledger > xrpl.basics
|
||||||
@@ -190,6 +196,8 @@ xrpl.nodestore > xrpl.basics
|
|||||||
xrpl.nodestore > xrpl.protocol
|
xrpl.nodestore > xrpl.protocol
|
||||||
xrpl.protocol > xrpl.basics
|
xrpl.protocol > xrpl.basics
|
||||||
xrpl.protocol > xrpl.json
|
xrpl.protocol > xrpl.json
|
||||||
|
xrpl.protocol_autogen > xrpl.json
|
||||||
|
xrpl.protocol_autogen > xrpl.protocol
|
||||||
xrpl.rdb > xrpl.basics
|
xrpl.rdb > xrpl.basics
|
||||||
xrpl.rdb > xrpl.core
|
xrpl.rdb > xrpl.core
|
||||||
xrpl.rdb > xrpl.protocol
|
xrpl.rdb > xrpl.protocol
|
||||||
@@ -227,6 +235,7 @@ xrpld.app > xrpl.shamap
|
|||||||
xrpld.app > xrpl.tx
|
xrpld.app > xrpl.tx
|
||||||
xrpld.consensus > xrpl.basics
|
xrpld.consensus > xrpl.basics
|
||||||
xrpld.consensus > xrpl.json
|
xrpld.consensus > xrpl.json
|
||||||
|
xrpld.consensus > xrpl.ledger
|
||||||
xrpld.consensus > xrpl.protocol
|
xrpld.consensus > xrpl.protocol
|
||||||
xrpld.core > xrpl.basics
|
xrpld.core > xrpl.basics
|
||||||
xrpld.core > xrpl.core
|
xrpld.core > xrpl.core
|
||||||
|
|||||||
32
.github/scripts/strategy-matrix/generate.py
vendored
32
.github/scripts/strategy-matrix/generate.py
vendored
@@ -32,13 +32,10 @@ We will further set additional CMake arguments as follows:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def generate_strategy_matrix(all: bool, config: Config, distro: str = "") -> list:
|
def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||||
configurations = []
|
configurations = []
|
||||||
os_entries = config.os
|
|
||||||
if distro:
|
|
||||||
os_entries = [o for o in os_entries if o["distro_name"] == distro]
|
|
||||||
for architecture, os, build_type, cmake_args in itertools.product(
|
for architecture, os, build_type, cmake_args in itertools.product(
|
||||||
config.architecture, os_entries, config.build_type, config.cmake_args
|
config.architecture, config.os, config.build_type, config.cmake_args
|
||||||
):
|
):
|
||||||
# The default CMake target is 'all' for Linux and MacOS and 'install'
|
# The default CMake target is 'all' for Linux and MacOS and 'install'
|
||||||
# for Windows, but it can get overridden for certain configurations.
|
# for Windows, but it can get overridden for certain configurations.
|
||||||
@@ -58,7 +55,7 @@ def generate_strategy_matrix(all: bool, config: Config, distro: str = "") -> lis
|
|||||||
# fee to 500.
|
# fee to 500.
|
||||||
# - Bookworm using GCC 15: Debug on linux/amd64, enable code
|
# - Bookworm using GCC 15: Debug on linux/amd64, enable code
|
||||||
# coverage (which will be done below).
|
# coverage (which will be done below).
|
||||||
# - Bookworm using Clang 16: Debug on linux/arm64, enable voidstar.
|
# - Bookworm using Clang 16: Debug on linux/amd64, enable voidstar.
|
||||||
# - Bookworm using Clang 17: Release on linux/amd64, set the
|
# - Bookworm using Clang 17: Release on linux/amd64, set the
|
||||||
# reference fee to 1000.
|
# reference fee to 1000.
|
||||||
# - Bookworm using Clang 20: Debug on linux/amd64.
|
# - Bookworm using Clang 20: Debug on linux/amd64.
|
||||||
@@ -81,7 +78,7 @@ def generate_strategy_matrix(all: bool, config: Config, distro: str = "") -> lis
|
|||||||
if (
|
if (
|
||||||
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-16"
|
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-16"
|
||||||
and build_type == "Debug"
|
and build_type == "Debug"
|
||||||
and architecture["platform"] == "linux/arm64"
|
and architecture["platform"] == "linux/amd64"
|
||||||
):
|
):
|
||||||
cmake_args = f"-Dvoidstar=ON {cmake_args}"
|
cmake_args = f"-Dvoidstar=ON {cmake_args}"
|
||||||
skip = False
|
skip = False
|
||||||
@@ -226,7 +223,7 @@ def generate_strategy_matrix(all: bool, config: Config, distro: str = "") -> lis
|
|||||||
if (n := os["compiler_version"]) != "":
|
if (n := os["compiler_version"]) != "":
|
||||||
config_name += f"-{n}"
|
config_name += f"-{n}"
|
||||||
config_name += (
|
config_name += (
|
||||||
f"-{architecture['platform'][architecture['platform'].find('/') + 1 :]}"
|
f"-{architecture['platform'][architecture['platform'].find('/')+1:]}"
|
||||||
)
|
)
|
||||||
config_name += f"-{build_type.lower()}"
|
config_name += f"-{build_type.lower()}"
|
||||||
if "-Dcoverage=ON" in cmake_args:
|
if "-Dcoverage=ON" in cmake_args:
|
||||||
@@ -316,32 +313,21 @@ if __name__ == "__main__":
|
|||||||
required=False,
|
required=False,
|
||||||
type=Path,
|
type=Path,
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
|
||||||
"-d",
|
|
||||||
"--distro",
|
|
||||||
help="Filter OS entries to only include those with this distro_name (e.g. 'debian', 'rhel', 'ubuntu').",
|
|
||||||
required=False,
|
|
||||||
type=str,
|
|
||||||
default="",
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
matrix = []
|
matrix = []
|
||||||
if args.config is None or args.config == "":
|
if args.config is None or args.config == "":
|
||||||
matrix += generate_strategy_matrix(
|
matrix += generate_strategy_matrix(
|
||||||
args.all, read_config(THIS_DIR / "linux.json"), args.distro
|
args.all, read_config(THIS_DIR / "linux.json")
|
||||||
)
|
)
|
||||||
matrix += generate_strategy_matrix(
|
matrix += generate_strategy_matrix(
|
||||||
args.all, read_config(THIS_DIR / "macos.json"), args.distro
|
args.all, read_config(THIS_DIR / "macos.json")
|
||||||
)
|
)
|
||||||
matrix += generate_strategy_matrix(
|
matrix += generate_strategy_matrix(
|
||||||
args.all, read_config(THIS_DIR / "windows.json"), args.distro
|
args.all, read_config(THIS_DIR / "windows.json")
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
matrix += generate_strategy_matrix(
|
matrix += generate_strategy_matrix(args.all, read_config(args.config))
|
||||||
args.all, read_config(args.config), args.distro
|
|
||||||
)
|
|
||||||
|
|
||||||
# Generate the strategy matrix.
|
# Generate the strategy matrix.
|
||||||
print(f"matrix={json.dumps({'include': matrix})}")
|
print(f"matrix={json.dumps({'include': matrix})}")
|
||||||
# print(json.dumps(matrix, indent=2))
|
|
||||||
|
|||||||
13
.github/workflows/check-pr-commits.yml
vendored
Normal file
13
.github/workflows/check-pr-commits.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
name: Check PR commits
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
# The action needs to have write permissions to post comments on the PR.
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check_commits:
|
||||||
|
uses: XRPLF/actions/.github/workflows/check-pr-commits.yml@481048b78b94ac3343d1292b4ef125a813879f2b
|
||||||
14
.github/workflows/check-pr-title.yml
vendored
Normal file
14
.github/workflows/check-pr-title.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
name: Check PR title
|
||||||
|
|
||||||
|
on:
|
||||||
|
merge_group:
|
||||||
|
types:
|
||||||
|
- checks_requested
|
||||||
|
pull_request:
|
||||||
|
types: [opened, edited, reopened, synchronize, ready_for_review]
|
||||||
|
branches: [develop]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check_title:
|
||||||
|
if: ${{ github.event.pull_request.draft != true }}
|
||||||
|
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@e2c7f400d1e85ae65dad552fd425169fbacca4a3
|
||||||
25
.github/workflows/conflicting-pr.yml
vendored
Normal file
25
.github/workflows/conflicting-pr.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
name: Label PRs with merge conflicts
|
||||||
|
|
||||||
|
on:
|
||||||
|
# So that PRs touching the same files as the push are updated.
|
||||||
|
push:
|
||||||
|
# So that the `dirtyLabel` is removed if conflicts are resolved.
|
||||||
|
# We recommend `pull_request_target` so that github secrets are available.
|
||||||
|
# In `pull_request` we wouldn't be able to change labels of fork PRs.
|
||||||
|
pull_request_target:
|
||||||
|
types: [synchronize]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
main:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check if PRs are dirty
|
||||||
|
uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3
|
||||||
|
with:
|
||||||
|
dirtyLabel: "PR: has conflicts"
|
||||||
|
repoToken: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
commentOnDirty: "This PR has conflicts, please resolve them in order for the PR to be reviewed."
|
||||||
|
commentOnClean: "All conflicts have been resolved. Assigned reviewers can now start or resume their review."
|
||||||
20
.github/workflows/on-pr.yml
vendored
20
.github/workflows/on-pr.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
|||||||
# that Github considers any skipped jobs to have passed, and in
|
# that Github considers any skipped jobs to have passed, and in
|
||||||
# turn the required checks as well.
|
# turn the required checks as well.
|
||||||
id: changes
|
id: changes
|
||||||
uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4
|
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
# These paths are unique to `on-pr.yml`.
|
# These paths are unique to `on-pr.yml`.
|
||||||
@@ -128,23 +128,12 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
os: [linux, macos, windows]
|
||||||
- os: linux
|
|
||||||
distro: debian
|
|
||||||
- os: linux
|
|
||||||
distro: rhel
|
|
||||||
- os: linux
|
|
||||||
distro: ubuntu
|
|
||||||
- os: macos
|
|
||||||
distro: ""
|
|
||||||
- os: windows
|
|
||||||
distro: ""
|
|
||||||
with:
|
with:
|
||||||
# Enable ccache only for events targeting the XRPLF repository, since
|
# Enable ccache only for events targeting the XRPLF repository, since
|
||||||
# other accounts will not have access to our remote cache storage.
|
# other accounts will not have access to our remote cache storage.
|
||||||
ccache_enabled: ${{ github.repository_owner == 'XRPLF' }}
|
ccache_enabled: ${{ github.repository_owner == 'XRPLF' }}
|
||||||
os: ${{ matrix.os }}
|
os: ${{ matrix.os }}
|
||||||
distro: ${{ matrix.distro }}
|
|
||||||
secrets:
|
secrets:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|
||||||
@@ -152,9 +141,8 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- should-run
|
- should-run
|
||||||
- build-test
|
- build-test
|
||||||
# Only run when committing to a PR that targets a release branch in the
|
# Only run when committing to a PR that targets a release branch.
|
||||||
# XRPLF repository.
|
if: ${{ github.repository == 'XRPLF/rippled' && needs.should-run.outputs.go == 'true' && github.event_name == 'pull_request' && startsWith(github.event.pull_request.base.ref, 'release') }}
|
||||||
if: ${{ github.repository_owner == 'XRPLF' && needs.should-run.outputs.go == 'true' && startsWith(github.ref, 'refs/heads/release') }}
|
|
||||||
uses: ./.github/workflows/reusable-upload-recipe.yml
|
uses: ./.github/workflows/reusable-upload-recipe.yml
|
||||||
secrets:
|
secrets:
|
||||||
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||||
|
|||||||
5
.github/workflows/on-tag.yml
vendored
5
.github/workflows/on-tag.yml
vendored
@@ -5,7 +5,7 @@ name: Tag
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "v*"
|
- "[0-9]+.[0-9]+.[0-9]*"
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -17,8 +17,7 @@ defaults:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
upload-recipe:
|
upload-recipe:
|
||||||
# Only run when a tag is pushed to the XRPLF repository.
|
if: ${{ github.repository == 'XRPLF/rippled' }}
|
||||||
if: ${{ github.repository_owner == 'XRPLF' }}
|
|
||||||
uses: ./.github/workflows/reusable-upload-recipe.yml
|
uses: ./.github/workflows/reusable-upload-recipe.yml
|
||||||
secrets:
|
secrets:
|
||||||
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||||
|
|||||||
17
.github/workflows/on-trigger.yml
vendored
17
.github/workflows/on-trigger.yml
vendored
@@ -77,17 +77,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: ${{ github.event_name == 'merge_group' }}
|
fail-fast: ${{ github.event_name == 'merge_group' }}
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
os: [linux, macos, windows]
|
||||||
- os: linux
|
|
||||||
distro: debian
|
|
||||||
- os: linux
|
|
||||||
distro: rhel
|
|
||||||
- os: linux
|
|
||||||
distro: ubuntu
|
|
||||||
- os: macos
|
|
||||||
distro: ""
|
|
||||||
- os: windows
|
|
||||||
distro: ""
|
|
||||||
with:
|
with:
|
||||||
# Enable ccache only for events targeting the XRPLF repository, since
|
# Enable ccache only for events targeting the XRPLF repository, since
|
||||||
# other accounts will not have access to our remote cache storage.
|
# other accounts will not have access to our remote cache storage.
|
||||||
@@ -96,15 +86,14 @@ jobs:
|
|||||||
# not identical to a regular compilation.
|
# not identical to a regular compilation.
|
||||||
ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !startsWith(github.ref, 'refs/heads/release') }}
|
ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !startsWith(github.ref, 'refs/heads/release') }}
|
||||||
os: ${{ matrix.os }}
|
os: ${{ matrix.os }}
|
||||||
distro: ${{ matrix.distro }}
|
|
||||||
strategy_matrix: ${{ github.event_name == 'schedule' && 'all' || 'minimal' }}
|
strategy_matrix: ${{ github.event_name == 'schedule' && 'all' || 'minimal' }}
|
||||||
secrets:
|
secrets:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|
||||||
upload-recipe:
|
upload-recipe:
|
||||||
needs: build-test
|
needs: build-test
|
||||||
# Only run when pushing to the develop branch in the XRPLF repository.
|
# Only run when pushing to the develop branch.
|
||||||
if: ${{ github.repository_owner == 'XRPLF' && github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
|
if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
|
||||||
uses: ./.github/workflows/reusable-upload-recipe.yml
|
uses: ./.github/workflows/reusable-upload-recipe.yml
|
||||||
secrets:
|
secrets:
|
||||||
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||||
|
|||||||
5
.github/workflows/pre-commit.yml
vendored
5
.github/workflows/pre-commit.yml
vendored
@@ -1,6 +1,9 @@
|
|||||||
name: Run pre-commit hooks
|
name: Run pre-commit hooks
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
merge_group:
|
||||||
|
types:
|
||||||
|
- checks_requested
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@@ -11,7 +14,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
|
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
|
||||||
run-hooks:
|
run-hooks:
|
||||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@56de1bdf19639e009639a50b8d17c28ca954f267
|
uses: XRPLF/actions/.github/workflows/pre-commit.yml@e7896f15cc60d0da1a272c77ee5c4026b424f9c7
|
||||||
with:
|
with:
|
||||||
runs_on: ubuntu-latest
|
runs_on: ubuntu-latest
|
||||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'
|
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'
|
||||||
|
|||||||
34
.github/workflows/publish-docs.yml
vendored
34
.github/workflows/publish-docs.yml
vendored
@@ -6,7 +6,6 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "develop"
|
- "develop"
|
||||||
- "release*"
|
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/publish-docs.yml"
|
- ".github/workflows/publish-docs.yml"
|
||||||
- "*.md"
|
- "*.md"
|
||||||
@@ -40,15 +39,18 @@ env:
|
|||||||
NPROC_SUBTRACT: ${{ github.event.repository.private && '1' || '2' }}
|
NPROC_SUBTRACT: ${{ github.event.repository.private && '1' || '2' }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: ghcr.io/xrplf/ci/tools-rippled-documentation:sha-a8c7be1
|
container: ghcr.io/xrplf/ci/tools-rippled-documentation:sha-a8c7be1
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
|
- name: Prepare runner
|
||||||
|
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
|
||||||
|
with:
|
||||||
|
enable_ccache: false
|
||||||
|
|
||||||
- name: Get number of processors
|
- name: Get number of processors
|
||||||
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
|
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
|
||||||
id: nproc
|
id: nproc
|
||||||
@@ -78,9 +80,23 @@ jobs:
|
|||||||
cmake -Donly_docs=ON ..
|
cmake -Donly_docs=ON ..
|
||||||
cmake --build . --target docs --parallel ${BUILD_NPROC}
|
cmake --build . --target docs --parallel ${BUILD_NPROC}
|
||||||
|
|
||||||
- name: Publish documentation
|
- name: Create documentation artifact
|
||||||
if: ${{ github.event_name == 'push' }}
|
if: ${{ github.event.repository.visibility == 'public' && github.event_name == 'push' }}
|
||||||
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
|
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
path: ${{ env.BUILD_DIR }}/docs/html
|
||||||
publish_dir: ${{ env.BUILD_DIR }}/docs/html
|
|
||||||
|
deploy:
|
||||||
|
if: ${{ github.event.repository.visibility == 'public' && github.event_name == 'push' }}
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deploy.outputs.page_url }}
|
||||||
|
steps:
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deploy
|
||||||
|
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
||||||
|
|||||||
51
.github/workflows/reusable-build-test-config.yml
vendored
51
.github/workflows/reusable-build-test-config.yml
vendored
@@ -76,7 +76,7 @@ jobs:
|
|||||||
name: ${{ inputs.config_name }}
|
name: ${{ inputs.config_name }}
|
||||||
runs-on: ${{ fromJSON(inputs.runs_on) }}
|
runs-on: ${{ fromJSON(inputs.runs_on) }}
|
||||||
container: ${{ inputs.image != '' && inputs.image || null }}
|
container: ${{ inputs.image != '' && inputs.image || null }}
|
||||||
timeout-minutes: 60
|
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 60 }}
|
||||||
env:
|
env:
|
||||||
# Use a namespace to keep the objects separate for each configuration.
|
# Use a namespace to keep the objects separate for each configuration.
|
||||||
CCACHE_NAMESPACE: ${{ inputs.config_name }}
|
CCACHE_NAMESPACE: ${{ inputs.config_name }}
|
||||||
@@ -107,7 +107,7 @@ jobs:
|
|||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Prepare runner
|
- name: Prepare runner
|
||||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
|
||||||
with:
|
with:
|
||||||
enable_ccache: ${{ inputs.ccache_enabled }}
|
enable_ccache: ${{ inputs.ccache_enabled }}
|
||||||
|
|
||||||
@@ -153,6 +153,29 @@ jobs:
|
|||||||
${CMAKE_ARGS} \
|
${CMAKE_ARGS} \
|
||||||
..
|
..
|
||||||
|
|
||||||
|
- name: Check protocol autogen files are up-to-date
|
||||||
|
env:
|
||||||
|
MESSAGE: |
|
||||||
|
|
||||||
|
The generated protocol wrapper classes are out of date.
|
||||||
|
|
||||||
|
This typically happens when your branch is behind develop and
|
||||||
|
the macro files or generator scripts have changed.
|
||||||
|
|
||||||
|
To fix this:
|
||||||
|
1. Update your branch from develop (merge or rebase)
|
||||||
|
2. Build with code generation enabled (XRPL_NO_CODEGEN=OFF)
|
||||||
|
3. Commit and push the regenerated files
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
DIFF=$(git status --porcelain -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen)
|
||||||
|
if [ -n "${DIFF}" ]; then
|
||||||
|
echo "::error::Generated protocol files are out of date"
|
||||||
|
git diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
|
||||||
|
echo "${MESSAGE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Build the binary
|
- name: Build the binary
|
||||||
working-directory: ${{ env.BUILD_DIR }}
|
working-directory: ${{ env.BUILD_DIR }}
|
||||||
env:
|
env:
|
||||||
@@ -176,8 +199,8 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload the binary (Linux)
|
- name: Upload the binary (Linux)
|
||||||
if: ${{ github.repository_owner == 'XRPLF' && runner.os == 'Linux' }}
|
if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }}
|
||||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||||
with:
|
with:
|
||||||
name: xrpld-${{ inputs.config_name }}
|
name: xrpld-${{ inputs.config_name }}
|
||||||
path: ${{ env.BUILD_DIR }}/xrpld
|
path: ${{ env.BUILD_DIR }}/xrpld
|
||||||
@@ -204,11 +227,17 @@ jobs:
|
|||||||
|
|
||||||
- name: Set sanitizer options
|
- name: Set sanitizer options
|
||||||
if: ${{ !inputs.build_only && env.SANITIZERS_ENABLED == 'true' }}
|
if: ${{ !inputs.build_only && env.SANITIZERS_ENABLED == 'true' }}
|
||||||
|
env:
|
||||||
|
CONFIG_NAME: ${{ inputs.config_name }}
|
||||||
run: |
|
run: |
|
||||||
echo "ASAN_OPTIONS=print_stacktrace=1:detect_container_overflow=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp" >> ${GITHUB_ENV}
|
ASAN_OPTS="include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-asan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp"
|
||||||
echo "TSAN_OPTIONS=second_deadlock_stack=1:halt_on_error=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >> ${GITHUB_ENV}
|
if [[ "${CONFIG_NAME}" == *gcc* ]]; then
|
||||||
echo "UBSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >> ${GITHUB_ENV}
|
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
|
||||||
echo "LSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >> ${GITHUB_ENV}
|
fi
|
||||||
|
echo "ASAN_OPTIONS=${ASAN_OPTS}" >> ${GITHUB_ENV}
|
||||||
|
echo "TSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-tsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >> ${GITHUB_ENV}
|
||||||
|
echo "UBSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >> ${GITHUB_ENV}
|
||||||
|
echo "LSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-lsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >> ${GITHUB_ENV}
|
||||||
|
|
||||||
- name: Run the separate tests
|
- name: Run the separate tests
|
||||||
if: ${{ !inputs.build_only }}
|
if: ${{ !inputs.build_only }}
|
||||||
@@ -230,6 +259,8 @@ jobs:
|
|||||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||||
run: |
|
run: |
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
# Coverage builds are slower due to instrumentation; use fewer parallel jobs to avoid flakiness
|
||||||
|
[ "$COVERAGE_ENABLED" = "true" ] && BUILD_NPROC=$(( BUILD_NPROC - 2 ))
|
||||||
./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
|
./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
|
||||||
|
|
||||||
- name: Show test failure summary
|
- name: Show test failure summary
|
||||||
@@ -266,8 +297,8 @@ jobs:
|
|||||||
--target coverage
|
--target coverage
|
||||||
|
|
||||||
- name: Upload coverage report
|
- name: Upload coverage report
|
||||||
if: ${{ github.repository_owner == 'XRPLF' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }}
|
if: ${{ github.repository == 'XRPLF/rippled' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }}
|
||||||
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
|
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
|
||||||
with:
|
with:
|
||||||
disable_search: true
|
disable_search: true
|
||||||
disable_telem: true
|
disable_telem: true
|
||||||
|
|||||||
8
.github/workflows/reusable-build-test.yml
vendored
8
.github/workflows/reusable-build-test.yml
vendored
@@ -26,12 +26,6 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
default: "minimal"
|
default: "minimal"
|
||||||
|
|
||||||
distro:
|
|
||||||
description: 'Filter to only include configs for this distro (e.g. "debian", "rhel", "ubuntu"). Leave empty for no filtering.'
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
default: ""
|
|
||||||
|
|
||||||
secrets:
|
secrets:
|
||||||
CODECOV_TOKEN:
|
CODECOV_TOKEN:
|
||||||
description: "The Codecov token to use for uploading coverage reports."
|
description: "The Codecov token to use for uploading coverage reports."
|
||||||
@@ -44,11 +38,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
os: ${{ inputs.os }}
|
os: ${{ inputs.os }}
|
||||||
strategy_matrix: ${{ inputs.strategy_matrix }}
|
strategy_matrix: ${{ inputs.strategy_matrix }}
|
||||||
distro: ${{ inputs.distro }}
|
|
||||||
|
|
||||||
# Build and test the binary for each configuration.
|
# Build and test the binary for each configuration.
|
||||||
build-test-config:
|
build-test-config:
|
||||||
name: ${{ matrix.config_name }}
|
|
||||||
needs:
|
needs:
|
||||||
- generate-matrix
|
- generate-matrix
|
||||||
uses: ./.github/workflows/reusable-build-test-config.yml
|
uses: ./.github/workflows/reusable-build-test-config.yml
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: Check levelization
|
- name: Check levelization
|
||||||
run: .github/scripts/levelization/generate.sh
|
run: python .github/scripts/levelization/generate.py
|
||||||
- name: Check for differences
|
- name: Check for differences
|
||||||
env:
|
env:
|
||||||
MESSAGE: |
|
MESSAGE: |
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
removed from loops.txt, it's probably an improvement, while if
|
removed from loops.txt, it's probably an improvement, while if
|
||||||
something was added, it's probably a regression.
|
something was added, it's probably a regression.
|
||||||
|
|
||||||
Run '.github/scripts/levelization/generate.sh' in your repo, commit
|
Run '.github/scripts/levelization/generate.py' in your repo, commit
|
||||||
and push the changes. See .github/scripts/levelization/README.md for
|
and push the changes. See .github/scripts/levelization/README.md for
|
||||||
more info.
|
more info.
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Prepare runner
|
- name: Prepare runner
|
||||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
|
||||||
with:
|
with:
|
||||||
enable_ccache: false
|
enable_ccache: false
|
||||||
|
|
||||||
@@ -83,8 +83,8 @@ jobs:
|
|||||||
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" ${TARGETS} 2>&1 | tee clang-tidy-output.txt
|
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" ${TARGETS} 2>&1 | tee clang-tidy-output.txt
|
||||||
|
|
||||||
- name: Upload clang-tidy output
|
- name: Upload clang-tidy output
|
||||||
if: steps.run_clang_tidy.outcome != 'success'
|
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
|
||||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||||
with:
|
with:
|
||||||
name: clang-tidy-results
|
name: clang-tidy-results
|
||||||
path: clang-tidy-output.txt
|
path: clang-tidy-output.txt
|
||||||
|
|||||||
6
.github/workflows/reusable-clang-tidy.yml
vendored
6
.github/workflows/reusable-clang-tidy.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Get changed C++ files
|
- name: Get changed C++ files
|
||||||
id: changed_files
|
id: changed_files
|
||||||
uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4
|
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
**/*.cpp
|
**/*.cpp
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Get changed clang-tidy configuration
|
- name: Get changed clang-tidy configuration
|
||||||
id: changed_clang_tidy
|
id: changed_clang_tidy
|
||||||
uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4
|
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
.clang-tidy
|
.clang-tidy
|
||||||
@@ -51,5 +51,5 @@ jobs:
|
|||||||
if: ${{ always() && !cancelled() && (!inputs.check_only_changed || needs.determine-files.outputs.any_cpp_changed == 'true' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
|
if: ${{ always() && !cancelled() && (!inputs.check_only_changed || needs.determine-files.outputs.any_cpp_changed == 'true' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
|
||||||
uses: ./.github/workflows/reusable-clang-tidy-files.yml
|
uses: ./.github/workflows/reusable-clang-tidy-files.yml
|
||||||
with:
|
with:
|
||||||
files: ${{ (needs.determine-files.outputs.clang_tidy_config_changed == 'true' && '') || (inputs.check_only_changed && needs.determine-files.outputs.all_changed_files || '') }}
|
files: ${{ (needs.determine-files.outputs.clang_tidy_config_changed != 'true' && inputs.check_only_changed) && needs.determine-files.outputs.all_changed_files || '' }}
|
||||||
create_issue_on_failure: ${{ inputs.create_issue_on_failure }}
|
create_issue_on_failure: ${{ inputs.create_issue_on_failure }}
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
default: "minimal"
|
default: "minimal"
|
||||||
distro:
|
|
||||||
description: 'Filter to only include configs for this distro (e.g. "debian", "rhel", "ubuntu"). Leave empty for no filtering.'
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
default: ""
|
|
||||||
outputs:
|
outputs:
|
||||||
matrix:
|
matrix:
|
||||||
description: "The generated strategy matrix."
|
description: "The generated strategy matrix."
|
||||||
@@ -47,5 +42,4 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GENERATE_CONFIG: ${{ inputs.os != '' && format('--config={0}.json', inputs.os) || '' }}
|
GENERATE_CONFIG: ${{ inputs.os != '' && format('--config={0}.json', inputs.os) || '' }}
|
||||||
GENERATE_OPTION: ${{ inputs.strategy_matrix == 'all' && '--all' || '' }}
|
GENERATE_OPTION: ${{ inputs.strategy_matrix == 'all' && '--all' || '' }}
|
||||||
GENERATE_DISTRO: ${{ inputs.distro != '' && format('--distro={0}', inputs.distro) || '' }}
|
run: ./generate.py ${GENERATE_OPTION} ${GENERATE_CONFIG} >> "${GITHUB_OUTPUT}"
|
||||||
run: ./generate.py ${GENERATE_OPTION} ${GENERATE_CONFIG} ${GENERATE_DISTRO} >> "${GITHUB_OUTPUT}"
|
|
||||||
|
|||||||
12
.github/workflows/reusable-upload-recipe.yml
vendored
12
.github/workflows/reusable-upload-recipe.yml
vendored
@@ -69,24 +69,30 @@ jobs:
|
|||||||
conan export . --version=${{ steps.version.outputs.version }}
|
conan export . --version=${{ steps.version.outputs.version }}
|
||||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }}
|
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }}
|
||||||
|
|
||||||
|
# When this workflow is triggered by a push event, it will always be when merging into the
|
||||||
|
# 'develop' branch, see on-trigger.yml.
|
||||||
- name: Upload Conan recipe (develop)
|
- name: Upload Conan recipe (develop)
|
||||||
if: ${{ github.ref == 'refs/heads/develop' }}
|
if: ${{ github.event_name == 'push' }}
|
||||||
env:
|
env:
|
||||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||||
run: |
|
run: |
|
||||||
conan export . --version=develop
|
conan export . --version=develop
|
||||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/develop
|
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/develop
|
||||||
|
|
||||||
|
# When this workflow is triggered by a pull request event, it will always be when merging into
|
||||||
|
# one of the 'release' branches, see on-pr.yml.
|
||||||
- name: Upload Conan recipe (rc)
|
- name: Upload Conan recipe (rc)
|
||||||
if: ${{ startsWith(github.ref, 'refs/heads/release') }}
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
env:
|
env:
|
||||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||||
run: |
|
run: |
|
||||||
conan export . --version=rc
|
conan export . --version=rc
|
||||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/rc
|
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/rc
|
||||||
|
|
||||||
|
# When this workflow is triggered by a push event, it will always be when tagging a final
|
||||||
|
# release, see on-tag.yml.
|
||||||
- name: Upload Conan recipe (release)
|
- name: Upload Conan recipe (release)
|
||||||
if: ${{ github.event_name == 'tag' }}
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||||
env:
|
env:
|
||||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
6
.github/workflows/upload-conan-deps.yml
vendored
6
.github/workflows/upload-conan-deps.yml
vendored
@@ -70,7 +70,7 @@ jobs:
|
|||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Prepare runner
|
- name: Prepare runner
|
||||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
|
||||||
with:
|
with:
|
||||||
enable_ccache: false
|
enable_ccache: false
|
||||||
|
|
||||||
@@ -103,11 +103,11 @@ jobs:
|
|||||||
sanitizers: ${{ matrix.sanitizers }}
|
sanitizers: ${{ matrix.sanitizers }}
|
||||||
|
|
||||||
- name: Log into Conan remote
|
- name: Log into Conan remote
|
||||||
if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
||||||
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
|
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
|
||||||
|
|
||||||
- name: Upload Conan packages
|
- name: Upload Conan packages
|
||||||
if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
||||||
env:
|
env:
|
||||||
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
|
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
|
||||||
run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION}
|
run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION}
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -71,10 +71,15 @@ DerivedData
|
|||||||
/.zed/
|
/.zed/
|
||||||
|
|
||||||
# AI tools.
|
# AI tools.
|
||||||
|
/.agent
|
||||||
|
/.agents
|
||||||
/.augment
|
/.augment
|
||||||
/.claude
|
/.claude
|
||||||
/CLAUDE.md
|
/CLAUDE.md
|
||||||
|
|
||||||
|
# Python
|
||||||
|
__pycache__
|
||||||
|
|
||||||
# Direnv's directory
|
# Direnv's directory
|
||||||
/.direnv
|
/.direnv
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ repos:
|
|||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
|
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
|
||||||
hooks:
|
hooks:
|
||||||
|
- id: check-added-large-files
|
||||||
|
args: [--maxkb=400, --enforce-all]
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: mixed-line-ending
|
- id: mixed-line-ending
|
||||||
@@ -20,33 +22,33 @@ repos:
|
|||||||
args: [--assume-in-merge]
|
args: [--assume-in-merge]
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
rev: 75ca4ad908dc4a99f57921f29b7e6c1521e10b26 # frozen: v21.1.8
|
rev: cd481d7b0bfb5c7b3090c21846317f9a8262e891 # frozen: v22.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: clang-format
|
- id: clang-format
|
||||||
args: [--style=file]
|
args: [--style=file]
|
||||||
"types_or": [c++, c, proto]
|
"types_or": [c++, c, proto]
|
||||||
|
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
|
||||||
|
|
||||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
- repo: https://github.com/BlankSpruce/gersemi
|
||||||
rev: e2c2116d86a80e72e7146a06e68b7c228afc6319 # frozen: v0.6.13
|
rev: 0.26.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: cmake-format
|
- id: gersemi
|
||||||
additional_dependencies: [PyYAML]
|
|
||||||
|
|
||||||
- repo: https://github.com/rbubley/mirrors-prettier
|
- repo: https://github.com/rbubley/mirrors-prettier
|
||||||
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
|
rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: prettier
|
- id: prettier
|
||||||
|
|
||||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||||
rev: 831207fd435b47aeffdf6af853097e64322b4d44 # frozen: v25.12.0
|
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
- repo: https://github.com/streetsidesoftware/cspell-cli
|
- repo: https://github.com/streetsidesoftware/cspell-cli
|
||||||
rev: 1cfa010f078c354f3ffb8413616280cc28f5ba21 # frozen: v9.4.0
|
rev: a42085ade523f591dca134379a595e7859986445 # frozen: v9.7.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: cspell # Spell check changed files
|
- id: cspell # Spell check changed files
|
||||||
exclude: .config/cspell.config.yaml
|
exclude: (.config/cspell.config.yaml|^include/xrpl/protocol_autogen/(transactions|ledger_entries)/)
|
||||||
- id: cspell # Spell check the commit message
|
- id: cspell # Spell check the commit message
|
||||||
name: check commit message spelling
|
name: check commit message spelling
|
||||||
args:
|
args:
|
||||||
@@ -78,5 +80,6 @@ repos:
|
|||||||
exclude: |
|
exclude: |
|
||||||
(?x)^(
|
(?x)^(
|
||||||
external/.*|
|
external/.*|
|
||||||
.github/scripts/levelization/results/.*\.txt
|
.github/scripts/levelization/results/.*\.txt|
|
||||||
|
src/tests/libxrpl/protocol_autogen/(transactions|ledger_entries)/.*
|
||||||
)$
|
)$
|
||||||
|
|||||||
@@ -22,6 +22,23 @@ API version 2 is available in `rippled` version 2.0.0 and later. See [API-VERSIO
|
|||||||
|
|
||||||
This version is supported by all `rippled` versions. For WebSocket and HTTP JSON-RPC requests, it is currently the default API version used when no `api_version` is specified.
|
This version is supported by all `rippled` versions. For WebSocket and HTTP JSON-RPC requests, it is currently the default API version used when no `api_version` is specified.
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
This section contains changes targeting a future version.
|
||||||
|
|
||||||
|
### Additions
|
||||||
|
|
||||||
|
- `server_definitions`: Added the following new sections to the response ([#6321](https://github.com/XRPLF/rippled/pull/6321)):
|
||||||
|
- `TRANSACTION_FORMATS`: Describes the fields and their optionality for each transaction type, including common fields shared across all transactions.
|
||||||
|
- `LEDGER_ENTRY_FORMATS`: Describes the fields and their optionality for each ledger entry type, including common fields shared across all ledger entries.
|
||||||
|
- `TRANSACTION_FLAGS`: Maps transaction type names to their supported flags and flag values.
|
||||||
|
- `LEDGER_ENTRY_FLAGS`: Maps ledger entry type names to their flags and flag values.
|
||||||
|
- `ACCOUNT_SET_FLAGS`: Maps AccountSet flag names (asf flags) to their numeric values.
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
- Peer Crawler: The `port` field in `overlay.active[]` now consistently returns an integer instead of a string for outbound peers. [#6318](https://github.com/XRPLF/rippled/pull/6318)
|
||||||
|
|
||||||
## XRP Ledger server version 3.1.0
|
## XRP Ledger server version 3.1.0
|
||||||
|
|
||||||
[Version 3.1.0](https://github.com/XRPLF/rippled/releases/tag/3.1.0) was released on Jan 27, 2026.
|
[Version 3.1.0](https://github.com/XRPLF/rippled/releases/tag/3.1.0) was released on Jan 27, 2026.
|
||||||
|
|||||||
77
BUILD.md
77
BUILD.md
@@ -125,9 +125,9 @@ default profile.
|
|||||||
|
|
||||||
### Patched recipes
|
### Patched recipes
|
||||||
|
|
||||||
The recipes in Conan Center occasionally need to be patched for compatibility
|
Occasionally, we need patched recipes or recipes not present in Conan Center.
|
||||||
with the latest version of `xrpld`. We maintain a fork of the Conan Center
|
We maintain a fork of the Conan Center Index
|
||||||
[here](https://github.com/XRPLF/conan-center-index/) containing the patches.
|
[here](https://github.com/XRPLF/conan-center-index/) containing the modified and newly added recipes.
|
||||||
|
|
||||||
To ensure our patched recipes are used, you must add our Conan remote at a
|
To ensure our patched recipes are used, you must add our Conan remote at a
|
||||||
higher index than the default Conan Center remote, so it is consulted first. You
|
higher index than the default Conan Center remote, so it is consulted first. You
|
||||||
@@ -137,19 +137,11 @@ can do this by running:
|
|||||||
conan remote add --index 0 xrplf https://conan.ripplex.io
|
conan remote add --index 0 xrplf https://conan.ripplex.io
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you can pull the patched recipes into the repository and use them
|
Alternatively, you can pull our recipes from the repository and export them locally:
|
||||||
locally:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Extract the version number from the lockfile.
|
|
||||||
function extract_version {
|
|
||||||
version=$(cat conan.lock | sed -nE "s@.+${1}/(.+)#.+@\1@p" | head -n1)
|
|
||||||
echo ${version}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Define which recipes to export.
|
# Define which recipes to export.
|
||||||
recipes=('ed25519' 'grpc' 'nudb' 'openssl' 'secp256k1' 'snappy' 'soci')
|
recipes=('abseil' 'ed25519' 'grpc' 'm4' 'mpt-crypto' 'nudb' 'openssl' 'secp256k1' 'snappy' 'soci' 'wasm-xrplf' 'wasmi')
|
||||||
folders=('all' 'all' 'all' '3.x.x' 'all' 'all' 'all')
|
|
||||||
|
|
||||||
# Selectively check out the recipes from our CCI fork.
|
# Selectively check out the recipes from our CCI fork.
|
||||||
cd external
|
cd external
|
||||||
@@ -158,29 +150,19 @@ cd conan-center-index
|
|||||||
git init
|
git init
|
||||||
git remote add origin git@github.com:XRPLF/conan-center-index.git
|
git remote add origin git@github.com:XRPLF/conan-center-index.git
|
||||||
git sparse-checkout init
|
git sparse-checkout init
|
||||||
for ((index = 1; index <= ${#recipes[@]}; index++)); do
|
for recipe in "${recipes[@]}"; do
|
||||||
recipe=${recipes[index]}
|
echo "Checking out recipe '${recipe}'..."
|
||||||
folder=${folders[index]}
|
git sparse-checkout add recipes/${recipe}
|
||||||
echo "Checking out recipe '${recipe}' from folder '${folder}'..."
|
|
||||||
git sparse-checkout add recipes/${recipe}/${folder}
|
|
||||||
done
|
done
|
||||||
git fetch origin master
|
git fetch origin master
|
||||||
git checkout master
|
git checkout master
|
||||||
cd ../..
|
|
||||||
|
|
||||||
# Export the recipes into the local cache.
|
./export_all.sh
|
||||||
for ((index = 1; index <= ${#recipes[@]}; index++)); do
|
cd ../../
|
||||||
recipe=${recipes[index]}
|
|
||||||
folder=${folders[index]}
|
|
||||||
version=$(extract_version ${recipe})
|
|
||||||
echo "Exporting '${recipe}/${version}' from '${recipe}/${folder}'..."
|
|
||||||
conan export --version $(extract_version ${recipe}) \
|
|
||||||
external/conan-center-index/recipes/${recipe}/${folder}
|
|
||||||
done
|
|
||||||
```
|
```
|
||||||
|
|
||||||
In the case we switch to a newer version of a dependency that still requires a
|
In the case we switch to a newer version of a dependency that still requires a
|
||||||
patch, it will be necessary for you to pull in the changes and re-export the
|
patch or add a new dependency, it will be necessary for you to pull in the changes and re-export the
|
||||||
updated dependencies with the newer version. However, if we switch to a newer
|
updated dependencies with the newer version. However, if we switch to a newer
|
||||||
version that no longer requires a patch, no action is required on your part, as
|
version that no longer requires a patch, no action is required on your part, as
|
||||||
the new recipe will be automatically pulled from the official Conan Center.
|
the new recipe will be automatically pulled from the official Conan Center.
|
||||||
@@ -189,6 +171,8 @@ the new recipe will be automatically pulled from the official Conan Center.
|
|||||||
> You might need to add `--lockfile=""` to your `conan install` command
|
> You might need to add `--lockfile=""` to your `conan install` command
|
||||||
> to avoid automatic use of the existing `conan.lock` file when you run
|
> to avoid automatic use of the existing `conan.lock` file when you run
|
||||||
> `conan export` manually on your machine
|
> `conan export` manually on your machine
|
||||||
|
>
|
||||||
|
> This is not recommended though, as you might end up using different revisions of recipes.
|
||||||
|
|
||||||
### Conan profile tweaks
|
### Conan profile tweaks
|
||||||
|
|
||||||
@@ -204,39 +188,14 @@ Possible values are ['5.0', '5.1', '6.0', '6.1', '7.0', '7.3', '8.0', '8.1',
|
|||||||
Read "http://docs.conan.io/2/knowledge/faq.html#error-invalid-setting"
|
Read "http://docs.conan.io/2/knowledge/faq.html#error-invalid-setting"
|
||||||
```
|
```
|
||||||
|
|
||||||
you need to amend the list of compiler versions in
|
you need to add your compiler to the list of compiler versions in
|
||||||
`$(conan config home)/settings.yml`, by appending the required version number(s)
|
`$(conan config home)/settings_user.yml`, by adding the required version number(s)
|
||||||
to the `version` array specific for your compiler. For example:
|
to the `version` array specific for your compiler. For example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apple-clang:
|
compiler:
|
||||||
version:
|
apple-clang:
|
||||||
[
|
version: ["17.0"]
|
||||||
"5.0",
|
|
||||||
"5.1",
|
|
||||||
"6.0",
|
|
||||||
"6.1",
|
|
||||||
"7.0",
|
|
||||||
"7.3",
|
|
||||||
"8.0",
|
|
||||||
"8.1",
|
|
||||||
"9.0",
|
|
||||||
"9.1",
|
|
||||||
"10.0",
|
|
||||||
"11.0",
|
|
||||||
"12.0",
|
|
||||||
"13",
|
|
||||||
"13.0",
|
|
||||||
"13.1",
|
|
||||||
"14",
|
|
||||||
"14.0",
|
|
||||||
"15",
|
|
||||||
"15.0",
|
|
||||||
"16",
|
|
||||||
"16.0",
|
|
||||||
"17",
|
|
||||||
"17.0",
|
|
||||||
]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Multiple compilers
|
#### Multiple compilers
|
||||||
|
|||||||
118
CMakeLists.txt
118
CMakeLists.txt
@@ -1,16 +1,16 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
if (POLICY CMP0074)
|
if(POLICY CMP0074)
|
||||||
cmake_policy(SET CMP0074 NEW)
|
cmake_policy(SET CMP0074 NEW)
|
||||||
endif ()
|
endif()
|
||||||
if (POLICY CMP0077)
|
if(POLICY CMP0077)
|
||||||
cmake_policy(SET CMP0077 NEW)
|
cmake_policy(SET CMP0077 NEW)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# Fix "unrecognized escape" issues when passing CMAKE_MODULE_PATH on Windows.
|
# Fix "unrecognized escape" issues when passing CMAKE_MODULE_PATH on Windows.
|
||||||
if (DEFINED CMAKE_MODULE_PATH)
|
if(DEFINED CMAKE_MODULE_PATH)
|
||||||
file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH)
|
file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH)
|
||||||
endif ()
|
endif()
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
project(xrpl)
|
project(xrpl)
|
||||||
@@ -21,77 +21,64 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|||||||
|
|
||||||
include(CompilationEnv)
|
include(CompilationEnv)
|
||||||
|
|
||||||
if (is_gcc)
|
if(is_gcc)
|
||||||
# GCC-specific fixes
|
# GCC-specific fixes
|
||||||
add_compile_options(-Wno-unknown-pragmas -Wno-subobject-linkage)
|
add_compile_options(-Wno-unknown-pragmas -Wno-subobject-linkage)
|
||||||
# -Wno-subobject-linkage can be removed when we upgrade GCC version to at least 13.3
|
# -Wno-subobject-linkage can be removed when we upgrade GCC version to at least 13.3
|
||||||
elseif (is_clang)
|
elseif(is_clang)
|
||||||
# Clang-specific fixes
|
# Clang-specific fixes
|
||||||
add_compile_options(-Wno-unknown-warning-option) # Ignore unknown warning options
|
add_compile_options(-Wno-unknown-warning-option) # Ignore unknown warning options
|
||||||
elseif (is_msvc)
|
elseif(is_msvc)
|
||||||
# MSVC-specific fixes
|
# MSVC-specific fixes
|
||||||
add_compile_options(/wd4068) # Ignore unknown pragmas
|
add_compile_options(/wd4068) # Ignore unknown pragmas
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# Enable ccache to speed up builds.
|
# Enable ccache to speed up builds.
|
||||||
include(Ccache)
|
include(Ccache)
|
||||||
|
|
||||||
# make GIT_COMMIT_HASH define available to all sources
|
if(thread_safety_analysis)
|
||||||
find_package(Git)
|
add_compile_options(
|
||||||
if (Git_FOUND)
|
-Wthread-safety
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git rev-parse
|
-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
|
||||||
HEAD OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE gch)
|
-DXRPL_ENABLE_THREAD_SAFETY_ANNOTATIONS
|
||||||
if (gch)
|
)
|
||||||
set(GIT_COMMIT_HASH "${gch}")
|
|
||||||
message(STATUS gch: ${GIT_COMMIT_HASH})
|
|
||||||
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git rev-parse
|
|
||||||
--abbrev-ref HEAD OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE gb)
|
|
||||||
if (gb)
|
|
||||||
set(GIT_BRANCH "${gb}")
|
|
||||||
message(STATUS gb: ${GIT_BRANCH})
|
|
||||||
add_definitions(-DGIT_BRANCH="${GIT_BRANCH}")
|
|
||||||
endif ()
|
|
||||||
endif () # git
|
|
||||||
|
|
||||||
if (thread_safety_analysis)
|
|
||||||
add_compile_options(-Wthread-safety -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
|
|
||||||
-DXRPL_ENABLE_THREAD_SAFETY_ANNOTATIONS)
|
|
||||||
add_compile_options("-stdlib=libc++")
|
add_compile_options("-stdlib=libc++")
|
||||||
add_link_options("-stdlib=libc++")
|
add_link_options("-stdlib=libc++")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
include(CMakeFuncs) # must come *after* ExternalProject b/c it overrides one function in EP
|
include(CMakeFuncs) # must come *after* ExternalProject b/c it overrides one function in EP
|
||||||
if (target)
|
if(target)
|
||||||
message(FATAL_ERROR "The target option has been removed - use native cmake options to control build"
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"The target option has been removed - use native cmake options to control build"
|
||||||
)
|
)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
include(XrplSanity)
|
include(XrplSanity)
|
||||||
include(XrplVersion)
|
include(XrplVersion)
|
||||||
include(XrplSettings)
|
include(XrplSettings)
|
||||||
# this check has to remain in the top-level cmake because of the early return statement
|
# this check has to remain in the top-level cmake because of the early return statement
|
||||||
if (packages_only)
|
if(packages_only)
|
||||||
if (NOT TARGET rpm)
|
if(NOT TARGET rpm)
|
||||||
message(FATAL_ERROR "packages_only requested, but targets were not created - is docker installed?"
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"packages_only requested, but targets were not created - is docker installed?"
|
||||||
)
|
)
|
||||||
endif ()
|
endif()
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
include(XrplCompiler)
|
include(XrplCompiler)
|
||||||
include(XrplSanitizers)
|
include(XrplSanitizers)
|
||||||
include(XrplInterface)
|
include(XrplInterface)
|
||||||
|
|
||||||
option(only_docs "Include only the docs target?" FALSE)
|
option(only_docs "Include only the docs target?" FALSE)
|
||||||
include(XrplDocs)
|
include(XrplDocs)
|
||||||
if (only_docs)
|
if(only_docs)
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
include(deps/Boost)
|
include(deps/Boost)
|
||||||
|
|
||||||
@@ -110,42 +97,45 @@ find_package(xxHash REQUIRED)
|
|||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
xrpl_libs
|
xrpl_libs
|
||||||
INTERFACE ed25519::ed25519
|
INTERFACE
|
||||||
lz4::lz4
|
ed25519::ed25519
|
||||||
OpenSSL::Crypto
|
lz4::lz4
|
||||||
OpenSSL::SSL
|
OpenSSL::Crypto
|
||||||
secp256k1::secp256k1
|
OpenSSL::SSL
|
||||||
soci::soci
|
secp256k1::secp256k1
|
||||||
SQLite::SQLite3)
|
soci::soci
|
||||||
|
SQLite::SQLite3
|
||||||
|
)
|
||||||
|
|
||||||
option(rocksdb "Enable RocksDB" ON)
|
option(rocksdb "Enable RocksDB" ON)
|
||||||
if (rocksdb)
|
if(rocksdb)
|
||||||
find_package(RocksDB REQUIRED)
|
find_package(RocksDB REQUIRED)
|
||||||
set_target_properties(RocksDB::rocksdb PROPERTIES INTERFACE_COMPILE_DEFINITIONS
|
set_target_properties(
|
||||||
XRPL_ROCKSDB_AVAILABLE=1)
|
RocksDB::rocksdb
|
||||||
|
PROPERTIES INTERFACE_COMPILE_DEFINITIONS XRPL_ROCKSDB_AVAILABLE=1
|
||||||
|
)
|
||||||
target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb)
|
target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# Work around changes to Conan recipe for now.
|
# Work around changes to Conan recipe for now.
|
||||||
if (TARGET nudb::core)
|
if(TARGET nudb::core)
|
||||||
set(nudb nudb::core)
|
set(nudb nudb::core)
|
||||||
elseif (TARGET NuDB::nudb)
|
elseif(TARGET NuDB::nudb)
|
||||||
set(nudb NuDB::nudb)
|
set(nudb NuDB::nudb)
|
||||||
else ()
|
else()
|
||||||
message(FATAL_ERROR "unknown nudb target")
|
message(FATAL_ERROR "unknown nudb target")
|
||||||
endif ()
|
endif()
|
||||||
target_link_libraries(xrpl_libs INTERFACE ${nudb})
|
target_link_libraries(xrpl_libs INTERFACE ${nudb})
|
||||||
|
|
||||||
if (coverage)
|
if(coverage)
|
||||||
include(XrplCov)
|
include(XrplCov)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
set(PROJECT_EXPORT_SET XrplExports)
|
|
||||||
include(XrplCore)
|
include(XrplCore)
|
||||||
include(XrplInstall)
|
include(XrplInstall)
|
||||||
include(XrplValidatorKeys)
|
include(XrplValidatorKeys)
|
||||||
|
|
||||||
if (tests)
|
if(tests)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
add_subdirectory(src/tests/libxrpl)
|
add_subdirectory(src/tests/libxrpl)
|
||||||
endif ()
|
endif()
|
||||||
|
|||||||
@@ -127,26 +127,6 @@ tl;dr
|
|||||||
> 6. Wrap the body at 72 characters.
|
> 6. Wrap the body at 72 characters.
|
||||||
> 7. Use the body to explain what and why vs. how.
|
> 7. Use the body to explain what and why vs. how.
|
||||||
|
|
||||||
In addition to those guidelines, please add one of the following
|
|
||||||
prefixes to the subject line if appropriate.
|
|
||||||
|
|
||||||
- `fix:` - The primary purpose is to fix an existing bug.
|
|
||||||
- `perf:` - The primary purpose is performance improvements.
|
|
||||||
- `refactor:` - The changes refactor code without affecting
|
|
||||||
functionality.
|
|
||||||
- `test:` - The changes _only_ affect unit tests.
|
|
||||||
- `docs:` - The changes _only_ affect documentation. This can
|
|
||||||
include code comments in addition to `.md` files like this one.
|
|
||||||
- `build:` - The changes _only_ affect the build process,
|
|
||||||
including CMake and/or Conan settings.
|
|
||||||
- `chore:` - Other tasks that don't affect the binary, but don't fit
|
|
||||||
any of the other cases. e.g. formatting, git settings, updating
|
|
||||||
Github Actions jobs.
|
|
||||||
|
|
||||||
Whenever possible, when updating commits after the PR is open, please
|
|
||||||
add the PR number to the end of the subject line. e.g. `test: Add
|
|
||||||
unit tests for Feature X (#1234)`.
|
|
||||||
|
|
||||||
## Pull requests
|
## Pull requests
|
||||||
|
|
||||||
In general, pull requests use `develop` as the base branch.
|
In general, pull requests use `develop` as the base branch.
|
||||||
@@ -180,6 +160,23 @@ credibility of the existing approvals is insufficient.
|
|||||||
Pull requests must be merged by [squash-and-merge][squash]
|
Pull requests must be merged by [squash-and-merge][squash]
|
||||||
to preserve a linear history for the `develop` branch.
|
to preserve a linear history for the `develop` branch.
|
||||||
|
|
||||||
|
### Type of Change
|
||||||
|
|
||||||
|
In addition to those guidelines, please start your PR title with one of the following:
|
||||||
|
|
||||||
|
- `build:` - The changes _only_ affect the build process, including CMake and/or Conan settings.
|
||||||
|
- `feat`: New feature (change which adds functionality).
|
||||||
|
- `fix:` - The primary purpose is to fix an existing bug.
|
||||||
|
- `docs:` - The changes _only_ affect documentation.
|
||||||
|
- `test:` - The changes _only_ affect unit tests.
|
||||||
|
- `ci`: Continuous Integration (changes to our CI configuration files and scripts).
|
||||||
|
- `style`: Code style (formatting).
|
||||||
|
- `refactor:` - The changes refactor code without affecting functionality.
|
||||||
|
- `perf:` - The primary purpose is performance improvements.
|
||||||
|
- `chore:` - Other tasks that don't affect the binary, but don't fit any of the other cases. e.g. `git` settings, `clang-tidy`, removing dead code, dropping support for older tooling.
|
||||||
|
|
||||||
|
First letter after the type prefix should be capitalized, and the type prefix should be followed by a colon and a space. e.g. `feat: Add support for Borrowing Protocol`.
|
||||||
|
|
||||||
### "Ready to merge"
|
### "Ready to merge"
|
||||||
|
|
||||||
A pull request should only have the "Ready to merge" label added when it
|
A pull request should only have the "Ready to merge" label added when it
|
||||||
@@ -262,6 +259,10 @@ There is a Continuous Integration job that runs clang-tidy on pull requests. The
|
|||||||
|
|
||||||
This ensures that configuration changes don't introduce new warnings across the codebase.
|
This ensures that configuration changes don't introduce new warnings across the codebase.
|
||||||
|
|
||||||
|
### Installing clang-tidy
|
||||||
|
|
||||||
|
See the [environment setup guide](./docs/build/environment.md#clang-tidy) for platform-specific installation instructions.
|
||||||
|
|
||||||
### Running clang-tidy locally
|
### Running clang-tidy locally
|
||||||
|
|
||||||
Before running clang-tidy, you must build the project to generate required files (particularly protobuf headers). Refer to [`BUILD.md`](./BUILD.md) for build instructions.
|
Before running clang-tidy, you must build the project to generate required files (particularly protobuf headers). Refer to [`BUILD.md`](./BUILD.md) for build instructions.
|
||||||
@@ -269,10 +270,15 @@ Before running clang-tidy, you must build the project to generate required files
|
|||||||
Then run clang-tidy on your local changes:
|
Then run clang-tidy on your local changes:
|
||||||
|
|
||||||
```
|
```
|
||||||
run-clang-tidy -p build src tests
|
run-clang-tidy -p build src include tests
|
||||||
```
|
```
|
||||||
|
|
||||||
This will check all source files in the `src` and `tests` directories using the compile commands from your `build` directory.
|
This will check all source files in the `src`, `include` and `tests` directories using the compile commands from your `build` directory.
|
||||||
|
If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix` to the above command:
|
||||||
|
|
||||||
|
```
|
||||||
|
run-clang-tidy -p build -fix src include tests
|
||||||
|
```
|
||||||
|
|
||||||
## Contracts and instrumentation
|
## Contracts and instrumentation
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
ISC License
|
ISC License
|
||||||
|
|
||||||
Copyright (c) 2011, Arthur Britto, David Schwartz, Jed McCaleb, Vinnie Falco, Bob Way, Eric Lombrozo, Nikolaos D. Bougalis, Howard Hinnant.
|
Copyright (c) 2011, Arthur Britto, David Schwartz, Jed McCaleb, Vinnie Falco, Bob Way, Eric Lombrozo, Nikolaos D. Bougalis, Howard Hinnant.
|
||||||
Copyright (c) 2012-2025, the XRP Ledger developers.
|
Copyright (c) 2012-present, the XRP Ledger developers.
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|||||||
@@ -1,29 +1,32 @@
|
|||||||
macro (exclude_from_default target_)
|
macro(exclude_from_default target_)
|
||||||
set_target_properties(${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
|
set_target_properties(${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||||
set_target_properties(${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
|
set_target_properties(${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
|
||||||
endmacro ()
|
endmacro()
|
||||||
|
|
||||||
macro (exclude_if_included target_)
|
macro(exclude_if_included target_)
|
||||||
get_directory_property(has_parent PARENT_DIRECTORY)
|
get_directory_property(has_parent PARENT_DIRECTORY)
|
||||||
if (has_parent)
|
if(has_parent)
|
||||||
exclude_from_default(${target_})
|
exclude_from_default(${target_})
|
||||||
endif ()
|
endif()
|
||||||
endmacro ()
|
endmacro()
|
||||||
|
|
||||||
find_package(Git)
|
find_package(Git)
|
||||||
|
|
||||||
function (git_branch branch_val)
|
function(git_branch branch_val)
|
||||||
if (NOT GIT_FOUND)
|
if(NOT GIT_FOUND)
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
set(_branch "")
|
set(_branch "")
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} "rev-parse" "--abbrev-ref" "HEAD"
|
execute_process(
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
COMMAND ${GIT_EXECUTABLE} "rev-parse" "--abbrev-ref" "HEAD"
|
||||||
RESULT_VARIABLE _git_exit_code
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
OUTPUT_VARIABLE _temp_branch
|
RESULT_VARIABLE _git_exit_code
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
|
OUTPUT_VARIABLE _temp_branch
|
||||||
if (_git_exit_code EQUAL 0)
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
if(_git_exit_code EQUAL 0)
|
||||||
set(_branch ${_temp_branch})
|
set(_branch ${_temp_branch})
|
||||||
endif ()
|
endif()
|
||||||
set(${branch_val} "${_branch}" PARENT_SCOPE)
|
set(${branch_val} "${_branch}" PARENT_SCOPE)
|
||||||
endfunction ()
|
endfunction()
|
||||||
|
|||||||
@@ -1,50 +1,62 @@
|
|||||||
find_program(CCACHE_PATH "ccache")
|
find_program(CCACHE_PATH "ccache")
|
||||||
if (NOT CCACHE_PATH)
|
if(NOT CCACHE_PATH)
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# For Linux and macOS we can use the ccache binary directly.
|
# For Linux and macOS we can use the ccache binary directly.
|
||||||
if (NOT MSVC)
|
if(NOT MSVC)
|
||||||
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PATH}")
|
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PATH}")
|
||||||
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PATH}")
|
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PATH}")
|
||||||
message(STATUS "Found ccache: ${CCACHE_PATH}")
|
message(STATUS "Found ccache: ${CCACHE_PATH}")
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# For Windows more effort is required. The code below is a modified version of
|
# For Windows more effort is required. The code below is a modified version of
|
||||||
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio#usage-with-cmake.
|
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio#usage-with-cmake.
|
||||||
if ("${CCACHE_PATH}" MATCHES "chocolatey")
|
if("${CCACHE_PATH}" MATCHES "chocolatey")
|
||||||
message(DEBUG "Ccache path: ${CCACHE_PATH}")
|
message(DEBUG "Ccache path: ${CCACHE_PATH}")
|
||||||
# Chocolatey uses a shim executable that we cannot use directly, in which case we have to find the executable it
|
# Chocolatey uses a shim executable that we cannot use directly, in which case we have to find the executable it
|
||||||
# points to. If we cannot find the target executable then we cannot use ccache.
|
# points to. If we cannot find the target executable then we cannot use ccache.
|
||||||
find_program(BASH_PATH "bash")
|
find_program(BASH_PATH "bash")
|
||||||
if (NOT BASH_PATH)
|
if(NOT BASH_PATH)
|
||||||
message(WARNING "Could not find bash.")
|
message(WARNING "Could not find bash.")
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
execute_process(COMMAND bash -c
|
execute_process(
|
||||||
"export LC_ALL='en_US.UTF-8'; ${CCACHE_PATH} --shimgen-noop | grep -oP 'path to executable: \\K.+' | head -c -1"
|
COMMAND
|
||||||
OUTPUT_VARIABLE CCACHE_PATH)
|
bash -c
|
||||||
|
"export LC_ALL='en_US.UTF-8'; ${CCACHE_PATH} --shimgen-noop | grep -oP 'path to executable: \\K.+' | head -c -1"
|
||||||
|
OUTPUT_VARIABLE CCACHE_PATH
|
||||||
|
)
|
||||||
|
|
||||||
if (NOT CCACHE_PATH)
|
if(NOT CCACHE_PATH)
|
||||||
message(WARNING "Could not find ccache target.")
|
message(WARNING "Could not find ccache target.")
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
file(TO_CMAKE_PATH "${CCACHE_PATH}" CCACHE_PATH)
|
file(TO_CMAKE_PATH "${CCACHE_PATH}" CCACHE_PATH)
|
||||||
endif ()
|
endif()
|
||||||
message(STATUS "Found ccache: ${CCACHE_PATH}")
|
message(STATUS "Found ccache: ${CCACHE_PATH}")
|
||||||
|
|
||||||
# Tell cmake to use ccache for compiling with Visual Studio.
|
# Tell cmake to use ccache for compiling with Visual Studio.
|
||||||
file(COPY_FILE ${CCACHE_PATH} ${CMAKE_BINARY_DIR}/cl.exe ONLY_IF_DIFFERENT)
|
file(COPY_FILE ${CCACHE_PATH} ${CMAKE_BINARY_DIR}/cl.exe ONLY_IF_DIFFERENT)
|
||||||
set(CMAKE_VS_GLOBALS "CLToolExe=cl.exe" "CLToolPath=${CMAKE_BINARY_DIR}" "TrackFileAccess=false"
|
set(CMAKE_VS_GLOBALS
|
||||||
"UseMultiToolTask=true")
|
"CLToolExe=cl.exe"
|
||||||
|
"CLToolPath=${CMAKE_BINARY_DIR}"
|
||||||
|
"TrackFileAccess=false"
|
||||||
|
"UseMultiToolTask=true"
|
||||||
|
)
|
||||||
|
|
||||||
# By default Visual Studio generators will use /Zi to capture debug information, which is not compatible with ccache, so
|
# By default Visual Studio generators will use /Zi to capture debug information, which is not compatible with ccache, so
|
||||||
# tell it to use /Z7 instead.
|
# tell it to use /Z7 instead.
|
||||||
if (MSVC)
|
if(MSVC)
|
||||||
foreach (var_ CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG
|
foreach(
|
||||||
CMAKE_CXX_FLAGS_RELEASE)
|
var_
|
||||||
|
CMAKE_C_FLAGS_DEBUG
|
||||||
|
CMAKE_C_FLAGS_RELEASE
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG
|
||||||
|
CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
)
|
||||||
string(REPLACE "/Zi" "/Z7" ${var_} "${${var_}}")
|
string(REPLACE "/Zi" "/Z7" ${var_} "${${var_}}")
|
||||||
endforeach ()
|
endforeach()
|
||||||
endif ()
|
endif()
|
||||||
|
|||||||
@@ -174,37 +174,45 @@ 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(COMMAND xcrun -f llvm-cov OUTPUT_VARIABLE LLVMCOV_PATH
|
execute_process(
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
COMMAND xcrun -f llvm-cov
|
||||||
else ()
|
OUTPUT_VARIABLE LLVMCOV_PATH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
else()
|
||||||
find_program(LLVMCOV_PATH llvm-cov)
|
find_program(LLVMCOV_PATH llvm-cov)
|
||||||
endif ()
|
endif()
|
||||||
if (LLVMCOV_PATH)
|
if(LLVMCOV_PATH)
|
||||||
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
|
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
|
||||||
endif ()
|
endif()
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||||
find_program(GCOV_PATH gcov)
|
find_program(GCOV_PATH gcov)
|
||||||
set(GCOV_TOOL "${GCOV_PATH}")
|
set(GCOV_TOOL "${GCOV_PATH}")
|
||||||
endif ()
|
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(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
|
message(
|
||||||
endif ()
|
FATAL_ERROR
|
||||||
elseif (NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU" AND NOT "${CMAKE_${LANG}_COMPILER_ID}"
|
"Clang version must be 3.0.0 or greater! Aborting..."
|
||||||
MATCHES "(LLVM)?[Ff]lang")
|
)
|
||||||
|
endif()
|
||||||
|
elseif(
|
||||||
|
NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
|
||||||
|
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang"
|
||||||
|
)
|
||||||
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
|
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
|
||||||
endif ()
|
endif()
|
||||||
endforeach ()
|
endforeach()
|
||||||
|
|
||||||
set(COVERAGE_COMPILER_FLAGS "-g --coverage" CACHE INTERNAL "")
|
set(COVERAGE_COMPILER_FLAGS "-g --coverage" CACHE INTERNAL "")
|
||||||
|
|
||||||
@@ -213,7 +221,7 @@ set(COVERAGE_C_COMPILER_FLAGS "")
|
|||||||
set(COVERAGE_CXX_LINKER_FLAGS "")
|
set(COVERAGE_CXX_LINKER_FLAGS "")
|
||||||
set(COVERAGE_C_LINKER_FLAGS "")
|
set(COVERAGE_C_LINKER_FLAGS "")
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
include(CheckCCompilerFlag)
|
include(CheckCCompilerFlag)
|
||||||
include(CheckLinkerFlag)
|
include(CheckLinkerFlag)
|
||||||
@@ -224,51 +232,77 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
|||||||
set(COVERAGE_C_LINKER_FLAGS ${COVERAGE_COMPILER_FLAGS})
|
set(COVERAGE_C_LINKER_FLAGS ${COVERAGE_COMPILER_FLAGS})
|
||||||
|
|
||||||
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 "${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-abs-path")
|
set(COVERAGE_CXX_COMPILER_FLAGS
|
||||||
endif ()
|
"${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-abs-path"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
|
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
|
||||||
if (HAVE_c_fprofile_abs_path)
|
if(HAVE_c_fprofile_abs_path)
|
||||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_C_COMPILER_FLAGS} -fprofile-abs-path")
|
set(COVERAGE_C_COMPILER_FLAGS
|
||||||
endif ()
|
"${COVERAGE_C_COMPILER_FLAGS} -fprofile-abs-path"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
check_linker_flag(CXX -fprofile-abs-path HAVE_cxx_linker_fprofile_abs_path)
|
check_linker_flag(CXX -fprofile-abs-path HAVE_cxx_linker_fprofile_abs_path)
|
||||||
if (HAVE_cxx_linker_fprofile_abs_path)
|
if(HAVE_cxx_linker_fprofile_abs_path)
|
||||||
set(COVERAGE_CXX_LINKER_FLAGS "${COVERAGE_CXX_LINKER_FLAGS} -fprofile-abs-path")
|
set(COVERAGE_CXX_LINKER_FLAGS
|
||||||
endif ()
|
"${COVERAGE_CXX_LINKER_FLAGS} -fprofile-abs-path"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
check_linker_flag(C -fprofile-abs-path HAVE_c_linker_fprofile_abs_path)
|
check_linker_flag(C -fprofile-abs-path HAVE_c_linker_fprofile_abs_path)
|
||||||
if (HAVE_c_linker_fprofile_abs_path)
|
if(HAVE_c_linker_fprofile_abs_path)
|
||||||
set(COVERAGE_C_LINKER_FLAGS "${COVERAGE_C_LINKER_FLAGS} -fprofile-abs-path")
|
set(COVERAGE_C_LINKER_FLAGS
|
||||||
endif ()
|
"${COVERAGE_C_LINKER_FLAGS} -fprofile-abs-path"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
check_cxx_compiler_flag(-fprofile-update=atomic HAVE_cxx_fprofile_update)
|
check_cxx_compiler_flag(-fprofile-update=atomic HAVE_cxx_fprofile_update)
|
||||||
if (HAVE_cxx_fprofile_update)
|
if(HAVE_cxx_fprofile_update)
|
||||||
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-update=atomic")
|
set(COVERAGE_CXX_COMPILER_FLAGS
|
||||||
endif ()
|
"${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-update=atomic"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
check_c_compiler_flag(-fprofile-update=atomic HAVE_c_fprofile_update)
|
check_c_compiler_flag(-fprofile-update=atomic HAVE_c_fprofile_update)
|
||||||
if (HAVE_c_fprofile_update)
|
if(HAVE_c_fprofile_update)
|
||||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_C_COMPILER_FLAGS} -fprofile-update=atomic")
|
set(COVERAGE_C_COMPILER_FLAGS
|
||||||
endif ()
|
"${COVERAGE_C_COMPILER_FLAGS} -fprofile-update=atomic"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
check_linker_flag(CXX -fprofile-update=atomic HAVE_cxx_linker_fprofile_update)
|
check_linker_flag(
|
||||||
if (HAVE_cxx_linker_fprofile_update)
|
CXX
|
||||||
set(COVERAGE_CXX_LINKER_FLAGS "${COVERAGE_CXX_LINKER_FLAGS} -fprofile-update=atomic")
|
-fprofile-update=atomic
|
||||||
endif ()
|
HAVE_cxx_linker_fprofile_update
|
||||||
|
)
|
||||||
|
if(HAVE_cxx_linker_fprofile_update)
|
||||||
|
set(COVERAGE_CXX_LINKER_FLAGS
|
||||||
|
"${COVERAGE_CXX_LINKER_FLAGS} -fprofile-update=atomic"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
check_linker_flag(C -fprofile-update=atomic HAVE_c_linker_fprofile_update)
|
check_linker_flag(C -fprofile-update=atomic HAVE_c_linker_fprofile_update)
|
||||||
if (HAVE_c_linker_fprofile_update)
|
if(HAVE_c_linker_fprofile_update)
|
||||||
set(COVERAGE_C_LINKER_FLAGS "${COVERAGE_C_LINKER_FLAGS} -fprofile-update=atomic")
|
set(COVERAGE_C_LINKER_FLAGS
|
||||||
endif ()
|
"${COVERAGE_C_LINKER_FLAGS} -fprofile-update=atomic"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
endif ()
|
get_property(
|
||||||
|
GENERATOR_IS_MULTI_CONFIG
|
||||||
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
GLOBAL
|
||||||
if (NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
|
PROPERTY 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(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)
|
||||||
|
|
||||||
# Defines a target for running and collection code coverage information
|
# Defines a target for running and collection code coverage information
|
||||||
# Builds dependencies, runs the given executable and outputs reports.
|
# Builds dependencies, runs the given executable and outputs reports.
|
||||||
@@ -292,125 +326,167 @@ endif () # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
|
|||||||
# )
|
# )
|
||||||
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
||||||
# GCVOR command.
|
# GCVOR 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(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
cmake_parse_arguments(
|
||||||
|
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 (NOT DEFINED Coverage_EXECUTABLE AND DEFINED Coverage_EXECUTABLE_ARGS)
|
if(NOT DEFINED Coverage_EXECUTABLE AND DEFINED Coverage_EXECUTABLE_ARGS)
|
||||||
message(FATAL_ERROR "EXECUTABLE_ARGS must not be set if EXECUTABLE is not set")
|
message(
|
||||||
endif ()
|
FATAL_ERROR
|
||||||
|
"EXECUTABLE_ARGS must not be set if EXECUTABLE is not set"
|
||||||
if ("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
|
|
||||||
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting..."
|
|
||||||
)
|
)
|
||||||
else ()
|
endif()
|
||||||
if ((Coverage_FORMAT STREQUAL "html-details") OR (Coverage_FORMAT STREQUAL "html-nested"))
|
|
||||||
set(GCOVR_OUTPUT_FILE ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html)
|
|
||||||
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
|
|
||||||
elseif (Coverage_FORMAT STREQUAL "html-single")
|
|
||||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
|
|
||||||
elseif ((Coverage_FORMAT STREQUAL "json-summary") OR (Coverage_FORMAT STREQUAL
|
|
||||||
"json-details")
|
|
||||||
OR (Coverage_FORMAT STREQUAL "coveralls"))
|
|
||||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
|
|
||||||
elseif (Coverage_FORMAT STREQUAL "txt")
|
|
||||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
|
|
||||||
elseif (Coverage_FORMAT STREQUAL "csv")
|
|
||||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
|
|
||||||
elseif (Coverage_FORMAT STREQUAL "lcov")
|
|
||||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.lcov)
|
|
||||||
else ()
|
|
||||||
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if ((Coverage_FORMAT STREQUAL "cobertura") OR (Coverage_FORMAT STREQUAL "xml"))
|
if("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting..."
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
if(
|
||||||
|
(Coverage_FORMAT STREQUAL "html-details")
|
||||||
|
OR (Coverage_FORMAT STREQUAL "html-nested")
|
||||||
|
)
|
||||||
|
set(GCOVR_OUTPUT_FILE
|
||||||
|
${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html
|
||||||
|
)
|
||||||
|
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
|
||||||
|
elseif(Coverage_FORMAT STREQUAL "html-single")
|
||||||
|
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
|
||||||
|
elseif(
|
||||||
|
(Coverage_FORMAT STREQUAL "json-summary")
|
||||||
|
OR (Coverage_FORMAT STREQUAL "json-details")
|
||||||
|
OR (Coverage_FORMAT STREQUAL "coveralls")
|
||||||
|
)
|
||||||
|
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
|
||||||
|
elseif(Coverage_FORMAT STREQUAL "txt")
|
||||||
|
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
|
||||||
|
elseif(Coverage_FORMAT STREQUAL "csv")
|
||||||
|
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
|
||||||
|
elseif(Coverage_FORMAT STREQUAL "lcov")
|
||||||
|
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.lcov)
|
||||||
|
else()
|
||||||
|
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(
|
||||||
|
(Coverage_FORMAT STREQUAL "cobertura")
|
||||||
|
OR (Coverage_FORMAT STREQUAL "xml")
|
||||||
|
)
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura "${GCOVR_OUTPUT_FILE}")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty)
|
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty)
|
||||||
set(Coverage_FORMAT cobertura) # overwrite xml
|
set(Coverage_FORMAT cobertura) # overwrite xml
|
||||||
elseif (Coverage_FORMAT STREQUAL "sonarqube")
|
elseif(Coverage_FORMAT STREQUAL "sonarqube")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}")
|
||||||
elseif (Coverage_FORMAT STREQUAL "jacoco")
|
elseif(Coverage_FORMAT STREQUAL "jacoco")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco "${GCOVR_OUTPUT_FILE}")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco-pretty)
|
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco-pretty)
|
||||||
elseif (Coverage_FORMAT STREQUAL "clover")
|
elseif(Coverage_FORMAT STREQUAL "clover")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --clover "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --clover "${GCOVR_OUTPUT_FILE}")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --clover-pretty)
|
list(APPEND GCOVR_ADDITIONAL_ARGS --clover-pretty)
|
||||||
elseif (Coverage_FORMAT STREQUAL "lcov")
|
elseif(Coverage_FORMAT STREQUAL "lcov")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --lcov "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --lcov "${GCOVR_OUTPUT_FILE}")
|
||||||
elseif (Coverage_FORMAT STREQUAL "json-summary")
|
elseif(Coverage_FORMAT STREQUAL "json-summary")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
|
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
|
||||||
elseif (Coverage_FORMAT STREQUAL "json-details")
|
elseif(Coverage_FORMAT STREQUAL "json-details")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --json "${GCOVR_OUTPUT_FILE}")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
|
list(APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
|
||||||
elseif (Coverage_FORMAT STREQUAL "coveralls")
|
elseif(Coverage_FORMAT STREQUAL "coveralls")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls "${GCOVR_OUTPUT_FILE}")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
|
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
|
||||||
elseif (Coverage_FORMAT STREQUAL "csv")
|
elseif(Coverage_FORMAT STREQUAL "csv")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --csv "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --csv "${GCOVR_OUTPUT_FILE}")
|
||||||
elseif (Coverage_FORMAT STREQUAL "txt")
|
elseif(Coverage_FORMAT STREQUAL "txt")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --txt "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --txt "${GCOVR_OUTPUT_FILE}")
|
||||||
elseif (Coverage_FORMAT STREQUAL "html-single")
|
elseif(Coverage_FORMAT STREQUAL "html-single")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --html "${GCOVR_OUTPUT_FILE}")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html-self-contained)
|
list(APPEND GCOVR_ADDITIONAL_ARGS --html-self-contained)
|
||||||
elseif (Coverage_FORMAT STREQUAL "html-nested")
|
elseif(Coverage_FORMAT STREQUAL "html-nested")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html-nested "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --html-nested "${GCOVR_OUTPUT_FILE}")
|
||||||
elseif (Coverage_FORMAT STREQUAL "html-details")
|
elseif(Coverage_FORMAT STREQUAL "html-details")
|
||||||
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details "${GCOVR_OUTPUT_FILE}")
|
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details "${GCOVR_OUTPUT_FILE}")
|
||||||
else ()
|
else()
|
||||||
message(FATAL_ERROR "Unsupported output style ${Coverage_FORMAT}! Aborting...")
|
message(
|
||||||
endif ()
|
FATAL_ERROR
|
||||||
|
"Unsupported output style ${Coverage_FORMAT}! Aborting..."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||||
set(GCOVR_EXCLUDES "")
|
set(GCOVR_EXCLUDES "")
|
||||||
foreach (EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
foreach(
|
||||||
if (CMAKE_VERSION VERSION_GREATER 3.4)
|
EXCLUDE
|
||||||
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
${Coverage_EXCLUDE}
|
||||||
endif ()
|
${COVERAGE_EXCLUDES}
|
||||||
|
${COVERAGE_GCOVR_EXCLUDES}
|
||||||
|
)
|
||||||
|
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||||
|
get_filename_component(
|
||||||
|
EXCLUDE
|
||||||
|
${EXCLUDE}
|
||||||
|
ABSOLUTE
|
||||||
|
BASE_DIR ${BASEDIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
||||||
endforeach ()
|
endforeach()
|
||||||
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
||||||
|
|
||||||
# Combine excludes to several -e arguments
|
# Combine excludes to several -e arguments
|
||||||
set(GCOVR_EXCLUDE_ARGS "")
|
set(GCOVR_EXCLUDE_ARGS "")
|
||||||
foreach (EXCLUDE ${GCOVR_EXCLUDES})
|
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
||||||
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
||||||
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
||||||
endforeach ()
|
endforeach()
|
||||||
|
|
||||||
# Set up commands which will be run to generate coverage data
|
# Set up commands which will be run to generate coverage data
|
||||||
# If EXECUTABLE is not set, the user is expected to run the tests manually
|
# If EXECUTABLE is not set, the user is expected to run the tests manually
|
||||||
# before running the coverage target NAME
|
# before running the coverage target NAME
|
||||||
if (DEFINED Coverage_EXECUTABLE)
|
if(DEFINED Coverage_EXECUTABLE)
|
||||||
set(GCOVR_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
|
set(GCOVR_EXEC_TESTS_CMD
|
||||||
endif ()
|
${Coverage_EXECUTABLE}
|
||||||
|
${Coverage_EXECUTABLE_ARGS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Create folder
|
# Create folder
|
||||||
if (DEFINED GCOVR_CREATE_FOLDER)
|
if(DEFINED GCOVR_CREATE_FOLDER)
|
||||||
set(GCOVR_FOLDER_CMD ${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
|
set(GCOVR_FOLDER_CMD
|
||||||
endif ()
|
${CMAKE_COMMAND}
|
||||||
|
-E
|
||||||
|
make_directory
|
||||||
|
${GCOVR_CREATE_FOLDER}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Running gcovr
|
# Running gcovr
|
||||||
set(GCOVR_CMD
|
set(GCOVR_CMD
|
||||||
@@ -422,56 +498,95 @@ function (setup_target_for_coverage_gcovr)
|
|||||||
${BASEDIR}
|
${BASEDIR}
|
||||||
${GCOVR_ADDITIONAL_ARGS}
|
${GCOVR_ADDITIONAL_ARGS}
|
||||||
${GCOVR_EXCLUDE_ARGS}
|
${GCOVR_EXCLUDE_ARGS}
|
||||||
--object-directory=${PROJECT_BINARY_DIR})
|
--object-directory=${PROJECT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
if (CODE_COVERAGE_VERBOSE)
|
if(CODE_COVERAGE_VERBOSE)
|
||||||
message(STATUS "Executed command report")
|
message(STATUS "Executed command report")
|
||||||
|
|
||||||
if (NOT "${GCOVR_EXEC_TESTS_CMD}" STREQUAL "")
|
if(NOT "${GCOVR_EXEC_TESTS_CMD}" STREQUAL "")
|
||||||
message(STATUS "Command to run tests: ")
|
message(STATUS "Command to run tests: ")
|
||||||
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
|
string(
|
||||||
|
REPLACE ";"
|
||||||
|
" "
|
||||||
|
GCOVR_EXEC_TESTS_CMD_SPACED
|
||||||
|
"${GCOVR_EXEC_TESTS_CMD}"
|
||||||
|
)
|
||||||
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
|
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (NOT "${GCOVR_FOLDER_CMD}" STREQUAL "")
|
if(NOT "${GCOVR_FOLDER_CMD}" STREQUAL "")
|
||||||
message(STATUS "Command to create a folder: ")
|
message(STATUS "Command to create a folder: ")
|
||||||
string(REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD}")
|
string(
|
||||||
|
REPLACE ";"
|
||||||
|
" "
|
||||||
|
GCOVR_FOLDER_CMD_SPACED
|
||||||
|
"${GCOVR_FOLDER_CMD}"
|
||||||
|
)
|
||||||
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
|
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
message(STATUS "Command to generate gcovr coverage data: ")
|
message(STATUS "Command to generate gcovr coverage data: ")
|
||||||
string(REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD}")
|
string(REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD}")
|
||||||
message(STATUS "${GCOVR_CMD_SPACED}")
|
message(STATUS "${GCOVR_CMD_SPACED}")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
add_custom_target(${Coverage_NAME}
|
add_custom_target(
|
||||||
COMMAND ${GCOVR_EXEC_TESTS_CMD}
|
${Coverage_NAME}
|
||||||
COMMAND ${GCOVR_FOLDER_CMD}
|
COMMAND ${GCOVR_EXEC_TESTS_CMD}
|
||||||
COMMAND ${GCOVR_CMD}
|
COMMAND ${GCOVR_FOLDER_CMD}
|
||||||
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
|
COMMAND ${GCOVR_CMD}
|
||||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
|
||||||
DEPENDS ${Coverage_DEPENDENCIES}
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
VERBATIM # Protect arguments to commands
|
DEPENDS ${Coverage_DEPENDENCIES}
|
||||||
COMMENT "Running gcovr to produce code coverage report.")
|
VERBATIM # Protect arguments to commands
|
||||||
|
COMMENT "Running gcovr to produce code coverage report."
|
||||||
|
)
|
||||||
|
|
||||||
# Show info where to find the report
|
# Show info where to find the report
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${Coverage_NAME} POST_BUILD COMMAND echo
|
TARGET ${Coverage_NAME}
|
||||||
COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
|
POST_BUILD
|
||||||
|
COMMAND echo
|
||||||
|
COMMENT
|
||||||
|
"Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
|
||||||
)
|
)
|
||||||
endfunction () # setup_target_for_coverage_gcovr
|
endfunction() # setup_target_for_coverage_gcovr
|
||||||
|
|
||||||
function (add_code_coverage_to_target name scope)
|
function(add_code_coverage_to_target name scope)
|
||||||
separate_arguments(COVERAGE_CXX_COMPILER_FLAGS NATIVE_COMMAND "${COVERAGE_CXX_COMPILER_FLAGS}")
|
separate_arguments(
|
||||||
separate_arguments(COVERAGE_C_COMPILER_FLAGS NATIVE_COMMAND "${COVERAGE_C_COMPILER_FLAGS}")
|
COVERAGE_CXX_COMPILER_FLAGS
|
||||||
separate_arguments(COVERAGE_CXX_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_CXX_LINKER_FLAGS}")
|
NATIVE_COMMAND
|
||||||
separate_arguments(COVERAGE_C_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_C_LINKER_FLAGS}")
|
"${COVERAGE_CXX_COMPILER_FLAGS}"
|
||||||
|
)
|
||||||
|
separate_arguments(
|
||||||
|
COVERAGE_C_COMPILER_FLAGS
|
||||||
|
NATIVE_COMMAND
|
||||||
|
"${COVERAGE_C_COMPILER_FLAGS}"
|
||||||
|
)
|
||||||
|
separate_arguments(
|
||||||
|
COVERAGE_CXX_LINKER_FLAGS
|
||||||
|
NATIVE_COMMAND
|
||||||
|
"${COVERAGE_CXX_LINKER_FLAGS}"
|
||||||
|
)
|
||||||
|
separate_arguments(
|
||||||
|
COVERAGE_C_LINKER_FLAGS
|
||||||
|
NATIVE_COMMAND
|
||||||
|
"${COVERAGE_C_LINKER_FLAGS}"
|
||||||
|
)
|
||||||
|
|
||||||
# Add compiler options to the target
|
# Add compiler options to the target
|
||||||
target_compile_options(
|
target_compile_options(
|
||||||
${name} ${scope} $<$<COMPILE_LANGUAGE:CXX>:${COVERAGE_CXX_COMPILER_FLAGS}>
|
${name}
|
||||||
$<$<COMPILE_LANGUAGE:C>:${COVERAGE_C_COMPILER_FLAGS}>)
|
${scope}
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:${COVERAGE_CXX_COMPILER_FLAGS}>
|
||||||
|
$<$<COMPILE_LANGUAGE:C>:${COVERAGE_C_COMPILER_FLAGS}>
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(${name} ${scope} $<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS}>
|
target_link_libraries(
|
||||||
$<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS}>)
|
${name}
|
||||||
endfunction () # add_code_coverage_to_target
|
${scope}
|
||||||
|
$<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS}>
|
||||||
|
$<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS}>
|
||||||
|
)
|
||||||
|
endfunction() # add_code_coverage_to_target
|
||||||
|
|||||||
@@ -14,20 +14,20 @@ set(is_gcc FALSE)
|
|||||||
set(is_msvc FALSE)
|
set(is_msvc FALSE)
|
||||||
set(is_xcode FALSE)
|
set(is_xcode FALSE)
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # Clang or AppleClang
|
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # Clang or AppleClang
|
||||||
set(is_clang TRUE)
|
set(is_clang TRUE)
|
||||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
set(is_gcc TRUE)
|
set(is_gcc TRUE)
|
||||||
elseif (MSVC)
|
elseif(MSVC)
|
||||||
set(is_msvc TRUE)
|
set(is_msvc TRUE)
|
||||||
else ()
|
else()
|
||||||
message(FATAL_ERROR "Unsupported C++ compiler: ${CMAKE_CXX_COMPILER_ID}")
|
message(FATAL_ERROR "Unsupported C++ compiler: ${CMAKE_CXX_COMPILER_ID}")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# Xcode generator detection
|
# Xcode generator detection
|
||||||
if (CMAKE_GENERATOR STREQUAL "Xcode")
|
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||||
set(is_xcode TRUE)
|
set(is_xcode TRUE)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# Operating system detection
|
# Operating system detection
|
||||||
@@ -36,23 +36,23 @@ set(is_linux FALSE)
|
|||||||
set(is_windows FALSE)
|
set(is_windows FALSE)
|
||||||
set(is_macos FALSE)
|
set(is_macos FALSE)
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
set(is_linux TRUE)
|
set(is_linux TRUE)
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
set(is_windows TRUE)
|
set(is_windows TRUE)
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
set(is_macos TRUE)
|
set(is_macos TRUE)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# Architecture
|
# Architecture
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
set(is_amd64 FALSE)
|
set(is_amd64 FALSE)
|
||||||
set(is_arm64 FALSE)
|
set(is_arm64 FALSE)
|
||||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
|
||||||
set(is_amd64 TRUE)
|
set(is_amd64 TRUE)
|
||||||
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
|
||||||
set(is_arm64 TRUE)
|
set(is_arm64 TRUE)
|
||||||
else ()
|
else()
|
||||||
message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||||
endif ()
|
endif()
|
||||||
|
|||||||
28
cmake/GitInfo.cmake
Normal file
28
cmake/GitInfo.cmake
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
include_guard()
|
||||||
|
|
||||||
|
set(GIT_BUILD_BRANCH "")
|
||||||
|
set(GIT_COMMIT_HASH "")
|
||||||
|
|
||||||
|
find_package(Git)
|
||||||
|
if(NOT Git_FOUND)
|
||||||
|
message(WARNING "Git not found. Git branch and commit hash will be empty.")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GIT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
${GIT_EXECUTABLE} --git-dir=${GIT_DIRECTORY} rev-parse --abbrev-ref HEAD
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
OUTPUT_VARIABLE GIT_BUILD_BRANCH
|
||||||
|
)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GIT_EXECUTABLE} --git-dir=${GIT_DIRECTORY} rev-parse HEAD
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||||
|
)
|
||||||
|
|
||||||
|
message(STATUS "Git branch: ${GIT_BUILD_BRANCH}")
|
||||||
|
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}")
|
||||||
@@ -1,13 +1,22 @@
|
|||||||
include(isolate_headers)
|
include(isolate_headers)
|
||||||
|
|
||||||
function (xrpl_add_test name)
|
function(xrpl_add_test name)
|
||||||
set(target ${PROJECT_NAME}.test.${name})
|
set(target ${PROJECT_NAME}.test.${name})
|
||||||
|
|
||||||
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
|
file(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp")
|
GLOB_RECURSE sources
|
||||||
|
CONFIGURE_DEPENDS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
|
||||||
|
)
|
||||||
add_executable(${target} ${ARGN} ${sources})
|
add_executable(${target} ${ARGN} ${sources})
|
||||||
|
|
||||||
isolate_headers(${target} "${CMAKE_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}/tests/${name}" PRIVATE)
|
isolate_headers(
|
||||||
|
${target}
|
||||||
|
"${CMAKE_SOURCE_DIR}"
|
||||||
|
"${CMAKE_SOURCE_DIR}/tests/${name}"
|
||||||
|
PRIVATE
|
||||||
|
)
|
||||||
|
|
||||||
add_test(NAME ${target} COMMAND ${target})
|
add_test(NAME ${target} COMMAND ${target})
|
||||||
endfunction ()
|
endfunction()
|
||||||
|
|||||||
@@ -14,33 +14,42 @@ include(XrplSanitizers)
|
|||||||
# add a single global dependency on this interface lib
|
# add a single global dependency on this interface lib
|
||||||
link_libraries(Xrpl::common)
|
link_libraries(Xrpl::common)
|
||||||
# Respect CMAKE_POSITION_INDEPENDENT_CODE setting (may be set by Conan toolchain)
|
# Respect CMAKE_POSITION_INDEPENDENT_CODE setting (may be set by Conan toolchain)
|
||||||
if (NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
|
if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
endif ()
|
endif()
|
||||||
set_target_properties(common PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE
|
set_target_properties(
|
||||||
${CMAKE_POSITION_INDEPENDENT_CODE})
|
common
|
||||||
|
PROPERTIES
|
||||||
|
INTERFACE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE}
|
||||||
|
)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
target_compile_definitions(
|
target_compile_definitions(
|
||||||
common
|
common
|
||||||
INTERFACE $<$<CONFIG:Debug>:DEBUG
|
INTERFACE
|
||||||
_DEBUG>
|
$<$<CONFIG:Debug>:DEBUG
|
||||||
#[===[
|
_DEBUG>
|
||||||
|
#[===[
|
||||||
NOTE: CMAKE release builds already have NDEBUG defined, so no need to add it
|
NOTE: CMAKE release builds already have NDEBUG defined, so no need to add it
|
||||||
explicitly except for the special case of (profile ON) and (assert OFF).
|
explicitly except for the special case of (profile ON) and (assert OFF).
|
||||||
Presumably this is because we don't want profile builds asserting unless
|
Presumably this is because we don't want profile builds asserting unless
|
||||||
asserts were specifically requested.
|
asserts were specifically requested.
|
||||||
]===]
|
]===]
|
||||||
$<$<AND:$<BOOL:${profile}>,$<NOT:$<BOOL:${assert}>>>:NDEBUG>
|
$<$<AND:$<BOOL:${profile}>,$<NOT:$<BOOL:${assert}>>>:NDEBUG>
|
||||||
# TODO: Remove once we have migrated functions from OpenSSL 1.x to 3.x.
|
# TODO: Remove once we have migrated functions from OpenSSL 1.x to 3.x.
|
||||||
OPENSSL_SUPPRESS_DEPRECATED)
|
OPENSSL_SUPPRESS_DEPRECATED
|
||||||
|
)
|
||||||
|
|
||||||
if (MSVC)
|
if(MSVC)
|
||||||
# remove existing exception flag since we set it to -EHa
|
# remove existing exception flag since we set it to -EHa
|
||||||
string(REGEX REPLACE "[-/]EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
string(REGEX REPLACE "[-/]EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||||
|
|
||||||
foreach (var_ CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG
|
foreach(
|
||||||
CMAKE_CXX_FLAGS_RELEASE)
|
var_
|
||||||
|
CMAKE_C_FLAGS_DEBUG
|
||||||
|
CMAKE_C_FLAGS_RELEASE
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG
|
||||||
|
CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
)
|
||||||
# also remove dynamic runtime
|
# also remove dynamic runtime
|
||||||
string(REGEX REPLACE "[-/]MD[d]*" " " ${var_} "${${var_}}")
|
string(REGEX REPLACE "[-/]MD[d]*" " " ${var_} "${${var_}}")
|
||||||
|
|
||||||
@@ -48,120 +57,143 @@ if (MSVC)
|
|||||||
string(REPLACE "/ZI" "/Zi" ${var_} "${${var_}}")
|
string(REPLACE "/ZI" "/Zi" ${var_} "${${var_}}")
|
||||||
|
|
||||||
# omit debug info completely under CI (not needed)
|
# omit debug info completely under CI (not needed)
|
||||||
if (is_ci)
|
if(is_ci)
|
||||||
string(REPLACE "/Zi" " " ${var_} "${${var_}}")
|
string(REPLACE "/Zi" " " ${var_} "${${var_}}")
|
||||||
string(REPLACE "/Z7" " " ${var_} "${${var_}}")
|
string(REPLACE "/Z7" " " ${var_} "${${var_}}")
|
||||||
endif ()
|
endif()
|
||||||
endforeach ()
|
endforeach()
|
||||||
|
|
||||||
target_compile_options(
|
target_compile_options(
|
||||||
common
|
common
|
||||||
INTERFACE # Increase object file max size
|
INTERFACE # Increase object file max size
|
||||||
-bigobj
|
-bigobj
|
||||||
# Floating point behavior
|
# Floating point behavior
|
||||||
-fp:precise
|
-fp:precise
|
||||||
# __cdecl calling convention
|
# __cdecl calling convention
|
||||||
-Gd
|
-Gd
|
||||||
# Minimal rebuild: disabled
|
# Minimal rebuild: disabled
|
||||||
-Gm-
|
-Gm-
|
||||||
# Function level linking: disabled
|
# Function level linking: disabled
|
||||||
-Gy-
|
-Gy-
|
||||||
# Multiprocessor compilation
|
# Multiprocessor compilation
|
||||||
-MP
|
-MP
|
||||||
# pragma omp: disabled
|
# pragma omp: disabled
|
||||||
-openmp-
|
-openmp-
|
||||||
# No error reporting to Internet
|
# No error reporting to Internet
|
||||||
-errorReport:none
|
-errorReport:none
|
||||||
# Suppress login banner
|
# Suppress login banner
|
||||||
-nologo
|
-nologo
|
||||||
# Disable signed/unsigned comparison warnings
|
# Disable signed/unsigned comparison warnings
|
||||||
-wd4018
|
-wd4018
|
||||||
# Disable float to int possible loss of data warnings
|
# Disable float to int possible loss of data warnings
|
||||||
-wd4244
|
-wd4244
|
||||||
# Disable size_t to T possible loss of data warnings
|
# Disable size_t to T possible loss of data warnings
|
||||||
-wd4267
|
-wd4267
|
||||||
# Disable C4800(int to bool performance)
|
# Disable C4800(int to bool performance)
|
||||||
-wd4800
|
-wd4800
|
||||||
# Decorated name length exceeded, name was truncated
|
# Decorated name length exceeded, name was truncated
|
||||||
-wd4503
|
-wd4503
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:
|
$<$<COMPILE_LANGUAGE:CXX>:
|
||||||
-EHa
|
-EHa
|
||||||
-GR
|
-GR
|
||||||
>
|
>
|
||||||
$<$<CONFIG:Release>:-Ox>
|
$<$<CONFIG:Release>:-Ox>
|
||||||
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:
|
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:
|
||||||
-GS
|
-GS
|
||||||
-Zc:forScope
|
-Zc:forScope
|
||||||
>
|
>
|
||||||
# static runtime
|
# static runtime
|
||||||
$<$<CONFIG:Debug>:-MTd>
|
$<$<CONFIG:Debug>:-MTd>
|
||||||
$<$<NOT:$<CONFIG:Debug>>:-MT>
|
$<$<NOT:$<CONFIG:Debug>>:-MT>
|
||||||
$<$<BOOL:${werr}>:-WX>)
|
$<$<BOOL:${werr}>:-WX>
|
||||||
|
)
|
||||||
target_compile_definitions(
|
target_compile_definitions(
|
||||||
common
|
common
|
||||||
INTERFACE _WIN32_WINNT=0x6000
|
INTERFACE
|
||||||
_SCL_SECURE_NO_WARNINGS
|
_WIN32_WINNT=0x6000
|
||||||
_CRT_SECURE_NO_WARNINGS
|
_SCL_SECURE_NO_WARNINGS
|
||||||
WIN32_CONSOLE
|
_CRT_SECURE_NO_WARNINGS
|
||||||
WIN32_LEAN_AND_MEAN
|
WIN32_CONSOLE
|
||||||
NOMINMAX
|
WIN32_LEAN_AND_MEAN
|
||||||
# TODO: Resolve these warnings, don't just silence them
|
NOMINMAX
|
||||||
_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
|
# TODO: Resolve these warnings, don't just silence them
|
||||||
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:_CRTDBG_MAP_ALLOC>)
|
_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
|
||||||
|
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>,$<NOT:$<BOOL:${is_ci}>>>:_CRTDBG_MAP_ALLOC>
|
||||||
|
)
|
||||||
target_link_libraries(common INTERFACE -errorreport:none -machine:X64)
|
target_link_libraries(common INTERFACE -errorreport:none -machine:X64)
|
||||||
else ()
|
else()
|
||||||
target_compile_options(
|
target_compile_options(
|
||||||
common
|
common
|
||||||
INTERFACE -Wall
|
INTERFACE
|
||||||
-Wdeprecated
|
-Wall
|
||||||
$<$<BOOL:${is_clang}>:-Wno-deprecated-declarations>
|
-Wdeprecated
|
||||||
$<$<BOOL:${wextra}>:-Wextra
|
$<$<BOOL:${is_clang}>:-Wno-deprecated-declarations>
|
||||||
-Wno-unused-parameter>
|
$<$<BOOL:${wextra}>:-Wextra
|
||||||
$<$<BOOL:${werr}>:-Werror>
|
-Wno-unused-parameter>
|
||||||
-fstack-protector
|
$<$<BOOL:${werr}>:-Werror>
|
||||||
-Wno-sign-compare
|
-fstack-protector
|
||||||
-Wno-unused-but-set-variable
|
-Wno-sign-compare
|
||||||
$<$<NOT:$<CONFIG:Debug>>:-fno-strict-aliasing>
|
-Wno-unused-but-set-variable
|
||||||
# tweak gcc optimization for debug
|
$<$<NOT:$<CONFIG:Debug>>:-fno-strict-aliasing>
|
||||||
$<$<AND:$<BOOL:${is_gcc}>,$<CONFIG:Debug>>:-O0>
|
# tweak gcc optimization for debug
|
||||||
# Add debug symbols to release config
|
$<$<AND:$<BOOL:${is_gcc}>,$<CONFIG:Debug>>:-O0>
|
||||||
$<$<CONFIG:Release>:-g>)
|
# Add debug symbols to release config
|
||||||
|
$<$<CONFIG:Release>:-g>
|
||||||
|
)
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
common
|
common
|
||||||
INTERFACE -rdynamic
|
INTERFACE
|
||||||
$<$<BOOL:${is_linux}>:-Wl,-z,relro,-z,now,--build-id>
|
-rdynamic
|
||||||
# link to static libc/c++ iff: * static option set and * NOT APPLE (AppleClang does not support static
|
$<$<BOOL:${is_linux}>:-Wl,-z,relro,-z,now,--build-id>
|
||||||
# libc/c++) and * NOT SANITIZERS (sanitizers typically don't work with static libc/c++)
|
# link to static libc/c++ iff: * static option set and * NOT APPLE (AppleClang does not support static
|
||||||
$<$<AND:$<BOOL:${static}>,$<NOT:$<BOOL:${APPLE}>>,$<NOT:$<BOOL:${SANITIZERS_ENABLED}>>>:
|
# libc/c++) and * NOT SANITIZERS (sanitizers typically don't work with static libc/c++)
|
||||||
-static-libstdc++
|
$<$<AND:$<BOOL:${static}>,$<NOT:$<BOOL:${APPLE}>>,$<NOT:$<BOOL:${SANITIZERS_ENABLED}>>>:
|
||||||
-static-libgcc
|
-static-libstdc++
|
||||||
>)
|
-static-libgcc
|
||||||
endif ()
|
>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Antithesis instrumentation will only be built and deployed using machines running Linux.
|
# Antithesis instrumentation will only be built and deployed using machines running Linux.
|
||||||
if (voidstar)
|
if(voidstar)
|
||||||
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
message(FATAL_ERROR "Antithesis instrumentation requires Debug build type, aborting...")
|
message(
|
||||||
elseif (NOT is_linux)
|
FATAL_ERROR
|
||||||
message(FATAL_ERROR "Antithesis instrumentation requires Linux, aborting...")
|
"Antithesis instrumentation requires Debug build type, aborting..."
|
||||||
elseif (NOT (is_clang AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0))
|
|
||||||
message(FATAL_ERROR "Antithesis instrumentation requires Clang version 16 or later, aborting..."
|
|
||||||
)
|
)
|
||||||
endif ()
|
elseif(NOT is_linux)
|
||||||
endif ()
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Antithesis instrumentation requires Linux, aborting..."
|
||||||
|
)
|
||||||
|
elseif(
|
||||||
|
NOT (is_clang AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)
|
||||||
|
)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Antithesis instrumentation requires Clang version 16 or later, aborting..."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (use_mold)
|
if(use_mold)
|
||||||
# use mold linker if available
|
# use mold linker if available
|
||||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=mold -Wl,--version ERROR_QUIET
|
execute_process(
|
||||||
OUTPUT_VARIABLE LD_VERSION)
|
COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=mold -Wl,--version
|
||||||
if ("${LD_VERSION}" MATCHES "mold")
|
ERROR_QUIET
|
||||||
|
OUTPUT_VARIABLE LD_VERSION
|
||||||
|
)
|
||||||
|
if("${LD_VERSION}" MATCHES "mold")
|
||||||
target_link_libraries(common INTERFACE -fuse-ld=mold)
|
target_link_libraries(common INTERFACE -fuse-ld=mold)
|
||||||
endif ()
|
endif()
|
||||||
unset(LD_VERSION)
|
unset(LD_VERSION)
|
||||||
elseif (use_gold AND is_gcc)
|
elseif(use_gold AND is_gcc)
|
||||||
# use gold linker if available
|
# use gold linker if available
|
||||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET
|
execute_process(
|
||||||
OUTPUT_VARIABLE LD_VERSION)
|
COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_VARIABLE LD_VERSION
|
||||||
|
)
|
||||||
#[=========================================================[
|
#[=========================================================[
|
||||||
NOTE: THE gold linker inserts -rpath as DT_RUNPATH by
|
NOTE: THE gold linker inserts -rpath as DT_RUNPATH by
|
||||||
default instead of DT_RPATH, so you might have slightly
|
default instead of DT_RPATH, so you might have slightly
|
||||||
@@ -175,32 +207,37 @@ elseif (use_gold AND is_gcc)
|
|||||||
disabling would be to figure out all the settings
|
disabling would be to figure out all the settings
|
||||||
required to make gold play nicely with jemalloc.
|
required to make gold play nicely with jemalloc.
|
||||||
#]=========================================================]
|
#]=========================================================]
|
||||||
if (("${LD_VERSION}" MATCHES "GNU gold") AND (NOT jemalloc))
|
if(("${LD_VERSION}" MATCHES "GNU gold") AND (NOT jemalloc))
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
common
|
common
|
||||||
INTERFACE -fuse-ld=gold
|
INTERFACE
|
||||||
-Wl,--no-as-needed
|
-fuse-ld=gold
|
||||||
#[=========================================================[
|
-Wl,--no-as-needed
|
||||||
|
#[=========================================================[
|
||||||
see https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/1253638/comments/5
|
see https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/1253638/comments/5
|
||||||
DT_RUNPATH does not work great for transitive
|
DT_RUNPATH does not work great for transitive
|
||||||
dependencies (of which boost has a few) - so just
|
dependencies (of which boost has a few) - so just
|
||||||
switch to DT_RPATH if doing dynamic linking with gold
|
switch to DT_RPATH if doing dynamic linking with gold
|
||||||
#]=========================================================]
|
#]=========================================================]
|
||||||
$<$<NOT:$<BOOL:${static}>>:-Wl,--disable-new-dtags>)
|
$<$<NOT:$<BOOL:${static}>>:-Wl,--disable-new-dtags>
|
||||||
endif ()
|
)
|
||||||
|
endif()
|
||||||
unset(LD_VERSION)
|
unset(LD_VERSION)
|
||||||
elseif (use_lld)
|
elseif(use_lld)
|
||||||
# use lld linker if available
|
# use lld linker if available
|
||||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=lld -Wl,--version ERROR_QUIET
|
execute_process(
|
||||||
OUTPUT_VARIABLE LD_VERSION)
|
COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=lld -Wl,--version
|
||||||
if ("${LD_VERSION}" MATCHES "LLD")
|
ERROR_QUIET
|
||||||
|
OUTPUT_VARIABLE LD_VERSION
|
||||||
|
)
|
||||||
|
if("${LD_VERSION}" MATCHES "LLD")
|
||||||
target_link_libraries(common INTERFACE -fuse-ld=lld)
|
target_link_libraries(common INTERFACE -fuse-ld=lld)
|
||||||
endif ()
|
endif()
|
||||||
unset(LD_VERSION)
|
unset(LD_VERSION)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (assert)
|
if(assert)
|
||||||
foreach (var_ CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE)
|
foreach(var_ CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE)
|
||||||
string(REGEX REPLACE "[-/]DNDEBUG" "" ${var_} "${${var_}}")
|
string(REGEX REPLACE "[-/]DNDEBUG" "" ${var_} "${${var_}}")
|
||||||
endforeach ()
|
endforeach()
|
||||||
endif ()
|
endif()
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
include(CMakeFindDependencyMacro)
|
|
||||||
# need to represent system dependencies of the lib here
|
|
||||||
#[=========================================================[
|
|
||||||
Boost
|
|
||||||
#]=========================================================]
|
|
||||||
if (static OR APPLE OR MSVC)
|
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
|
||||||
endif ()
|
|
||||||
set(Boost_USE_MULTITHREADED ON)
|
|
||||||
if (static OR MSVC)
|
|
||||||
set(Boost_USE_STATIC_RUNTIME ON)
|
|
||||||
else ()
|
|
||||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
|
||||||
endif ()
|
|
||||||
find_dependency(Boost
|
|
||||||
COMPONENTS
|
|
||||||
chrono
|
|
||||||
container
|
|
||||||
context
|
|
||||||
coroutine
|
|
||||||
date_time
|
|
||||||
filesystem
|
|
||||||
program_options
|
|
||||||
regex
|
|
||||||
system
|
|
||||||
thread)
|
|
||||||
#[=========================================================[
|
|
||||||
OpenSSL
|
|
||||||
#]=========================================================]
|
|
||||||
if (NOT DEFINED OPENSSL_ROOT_DIR)
|
|
||||||
if (DEFINED ENV{OPENSSL_ROOT})
|
|
||||||
set(OPENSSL_ROOT_DIR $ENV{OPENSSL_ROOT})
|
|
||||||
elseif (APPLE)
|
|
||||||
find_program(homebrew brew)
|
|
||||||
if (homebrew)
|
|
||||||
execute_process(COMMAND ${homebrew} --prefix openssl OUTPUT_VARIABLE OPENSSL_ROOT_DIR
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
file(TO_CMAKE_PATH "${OPENSSL_ROOT_DIR}" OPENSSL_ROOT_DIR)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (static OR APPLE OR MSVC)
|
|
||||||
set(OPENSSL_USE_STATIC_LIBS ON)
|
|
||||||
endif ()
|
|
||||||
set(OPENSSL_MSVC_STATIC_RT ON)
|
|
||||||
find_dependency(OpenSSL REQUIRED)
|
|
||||||
find_dependency(ZLIB)
|
|
||||||
find_dependency(date)
|
|
||||||
if (TARGET ZLIB::ZLIB)
|
|
||||||
set_target_properties(OpenSSL::Crypto PROPERTIES INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
|
|
||||||
endif ()
|
|
||||||
@@ -10,25 +10,44 @@ include(target_protobuf_sources)
|
|||||||
# so we just build them as a separate library.
|
# so we just build them as a separate library.
|
||||||
add_library(xrpl.libpb)
|
add_library(xrpl.libpb)
|
||||||
set_target_properties(xrpl.libpb PROPERTIES UNITY_BUILD OFF)
|
set_target_properties(xrpl.libpb PROPERTIES UNITY_BUILD OFF)
|
||||||
target_protobuf_sources(xrpl.libpb xrpl/proto LANGUAGE cpp IMPORT_DIRS include/xrpl/proto
|
target_protobuf_sources(
|
||||||
PROTOS include/xrpl/proto/xrpl.proto)
|
xrpl.libpb
|
||||||
|
xrpl/proto
|
||||||
|
LANGUAGE cpp
|
||||||
|
IMPORT_DIRS include/xrpl/proto
|
||||||
|
PROTOS include/xrpl/proto/xrpl.proto
|
||||||
|
)
|
||||||
|
|
||||||
file(GLOB_RECURSE protos "include/xrpl/proto/org/*.proto")
|
file(GLOB_RECURSE protos "include/xrpl/proto/org/*.proto")
|
||||||
target_protobuf_sources(xrpl.libpb xrpl/proto LANGUAGE cpp IMPORT_DIRS include/xrpl/proto
|
|
||||||
PROTOS "${protos}")
|
|
||||||
target_protobuf_sources(
|
target_protobuf_sources(
|
||||||
xrpl.libpb xrpl/proto
|
xrpl.libpb
|
||||||
|
xrpl/proto
|
||||||
|
LANGUAGE cpp
|
||||||
|
IMPORT_DIRS include/xrpl/proto
|
||||||
|
PROTOS "${protos}"
|
||||||
|
)
|
||||||
|
target_protobuf_sources(
|
||||||
|
xrpl.libpb
|
||||||
|
xrpl/proto
|
||||||
LANGUAGE grpc
|
LANGUAGE grpc
|
||||||
IMPORT_DIRS include/xrpl/proto
|
IMPORT_DIRS include/xrpl/proto
|
||||||
PROTOS "${protos}"
|
PROTOS "${protos}"
|
||||||
PLUGIN protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>
|
PLUGIN protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>
|
||||||
GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc)
|
GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc
|
||||||
|
)
|
||||||
|
|
||||||
target_compile_options(
|
target_compile_options(
|
||||||
xrpl.libpb
|
xrpl.libpb
|
||||||
PUBLIC $<$<BOOL:${is_msvc}>:-wd4996> $<$<BOOL:${is_xcode}>:
|
PUBLIC
|
||||||
--system-header-prefix="google/protobuf" -Wno-deprecated-dynamic-exception-spec >
|
$<$<BOOL:${is_msvc}>:-wd4996>
|
||||||
PRIVATE $<$<BOOL:${is_msvc}>:-wd4065> $<$<NOT:$<BOOL:${is_msvc}>>:-Wno-deprecated-declarations>)
|
$<$<BOOL:${is_xcode}>:
|
||||||
|
--system-header-prefix="google/protobuf"
|
||||||
|
-Wno-deprecated-dynamic-exception-spec
|
||||||
|
>
|
||||||
|
PRIVATE
|
||||||
|
$<$<BOOL:${is_msvc}>:-wd4065>
|
||||||
|
$<$<NOT:$<BOOL:${is_msvc}>>:-Wno-deprecated-declarations>
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(xrpl.libpb PUBLIC protobuf::libprotobuf gRPC::grpc++)
|
target_link_libraries(xrpl.libpb PUBLIC protobuf::libprotobuf gRPC::grpc++)
|
||||||
|
|
||||||
@@ -37,19 +56,21 @@ add_library(xrpl.imports.main INTERFACE)
|
|||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
xrpl.imports.main
|
xrpl.imports.main
|
||||||
INTERFACE absl::random_random
|
INTERFACE
|
||||||
date::date
|
absl::random_random
|
||||||
ed25519::ed25519
|
date::date
|
||||||
LibArchive::LibArchive
|
ed25519::ed25519
|
||||||
OpenSSL::Crypto
|
LibArchive::LibArchive
|
||||||
Xrpl::boost
|
OpenSSL::Crypto
|
||||||
Xrpl::libs
|
Xrpl::boost
|
||||||
Xrpl::opts
|
Xrpl::libs
|
||||||
Xrpl::syslibs
|
Xrpl::opts
|
||||||
secp256k1::secp256k1
|
Xrpl::syslibs
|
||||||
xrpl.libpb
|
secp256k1::secp256k1
|
||||||
xxHash::xxhash
|
xrpl.libpb
|
||||||
$<$<BOOL:${voidstar}>:antithesis-sdk-cpp>)
|
xxHash::xxhash
|
||||||
|
$<$<BOOL:${voidstar}>:antithesis-sdk-cpp>
|
||||||
|
)
|
||||||
|
|
||||||
include(add_module)
|
include(add_module)
|
||||||
include(target_link_modules)
|
include(target_link_modules)
|
||||||
@@ -58,6 +79,16 @@ include(target_link_modules)
|
|||||||
add_module(xrpl beast)
|
add_module(xrpl beast)
|
||||||
target_link_libraries(xrpl.libxrpl.beast PUBLIC xrpl.imports.main)
|
target_link_libraries(xrpl.libxrpl.beast PUBLIC xrpl.imports.main)
|
||||||
|
|
||||||
|
include(GitInfo)
|
||||||
|
add_module(xrpl git)
|
||||||
|
target_compile_definitions(
|
||||||
|
xrpl.libxrpl.git
|
||||||
|
PRIVATE
|
||||||
|
GIT_COMMIT_HASH="${GIT_COMMIT_HASH}"
|
||||||
|
GIT_BUILD_BRANCH="${GIT_BUILD_BRANCH}"
|
||||||
|
)
|
||||||
|
target_link_libraries(xrpl.libxrpl.git PUBLIC xrpl.imports.main)
|
||||||
|
|
||||||
# Level 02
|
# Level 02
|
||||||
add_module(xrpl basics)
|
add_module(xrpl basics)
|
||||||
target_link_libraries(xrpl.libxrpl.basics PUBLIC xrpl.libxrpl.beast)
|
target_link_libraries(xrpl.libxrpl.basics PUBLIC xrpl.libxrpl.beast)
|
||||||
@@ -71,36 +102,81 @@ target_link_libraries(xrpl.libxrpl.crypto PUBLIC xrpl.libxrpl.basics)
|
|||||||
|
|
||||||
# Level 04
|
# Level 04
|
||||||
add_module(xrpl protocol)
|
add_module(xrpl protocol)
|
||||||
target_link_libraries(xrpl.libxrpl.protocol PUBLIC xrpl.libxrpl.crypto xrpl.libxrpl.json)
|
target_link_libraries(
|
||||||
|
xrpl.libxrpl.protocol
|
||||||
|
PUBLIC xrpl.libxrpl.crypto xrpl.libxrpl.git xrpl.libxrpl.json
|
||||||
|
)
|
||||||
|
|
||||||
# Level 05
|
# Level 05
|
||||||
add_module(xrpl core)
|
## Set up code generation for protocol_autogen module.
|
||||||
target_link_libraries(xrpl.libxrpl.core PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json
|
## Generation runs at configure time (when the stamp is stale),
|
||||||
xrpl.libxrpl.protocol)
|
## so generated files are always present before add_module GLOBs them.
|
||||||
|
include(XrplProtocolAutogen)
|
||||||
|
setup_protocol_autogen()
|
||||||
|
|
||||||
|
add_module(xrpl protocol_autogen)
|
||||||
|
target_link_libraries(
|
||||||
|
xrpl.libxrpl.protocol_autogen
|
||||||
|
PUBLIC xrpl.libxrpl.protocol
|
||||||
|
)
|
||||||
|
|
||||||
# Level 06
|
# Level 06
|
||||||
|
add_module(xrpl core)
|
||||||
|
target_link_libraries(
|
||||||
|
xrpl.libxrpl.core
|
||||||
|
PUBLIC
|
||||||
|
xrpl.libxrpl.basics
|
||||||
|
xrpl.libxrpl.json
|
||||||
|
xrpl.libxrpl.protocol
|
||||||
|
xrpl.libxrpl.protocol_autogen
|
||||||
|
)
|
||||||
|
|
||||||
|
# Level 07
|
||||||
add_module(xrpl resource)
|
add_module(xrpl resource)
|
||||||
target_link_libraries(xrpl.libxrpl.resource PUBLIC xrpl.libxrpl.protocol)
|
target_link_libraries(xrpl.libxrpl.resource PUBLIC xrpl.libxrpl.protocol)
|
||||||
|
|
||||||
# Level 07
|
# Level 08
|
||||||
add_module(xrpl net)
|
add_module(xrpl net)
|
||||||
target_link_libraries(xrpl.libxrpl.net PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json
|
target_link_libraries(
|
||||||
xrpl.libxrpl.protocol xrpl.libxrpl.resource)
|
xrpl.libxrpl.net
|
||||||
|
PUBLIC
|
||||||
|
xrpl.libxrpl.basics
|
||||||
|
xrpl.libxrpl.json
|
||||||
|
xrpl.libxrpl.protocol
|
||||||
|
xrpl.libxrpl.resource
|
||||||
|
)
|
||||||
|
|
||||||
add_module(xrpl nodestore)
|
add_module(xrpl nodestore)
|
||||||
target_link_libraries(xrpl.libxrpl.nodestore PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json
|
target_link_libraries(
|
||||||
xrpl.libxrpl.protocol)
|
xrpl.libxrpl.nodestore
|
||||||
|
PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol
|
||||||
|
)
|
||||||
|
|
||||||
add_module(xrpl shamap)
|
add_module(xrpl shamap)
|
||||||
target_link_libraries(xrpl.libxrpl.shamap PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.crypto
|
target_link_libraries(
|
||||||
xrpl.libxrpl.protocol xrpl.libxrpl.nodestore)
|
xrpl.libxrpl.shamap
|
||||||
|
PUBLIC
|
||||||
|
xrpl.libxrpl.basics
|
||||||
|
xrpl.libxrpl.crypto
|
||||||
|
xrpl.libxrpl.protocol
|
||||||
|
xrpl.libxrpl.nodestore
|
||||||
|
)
|
||||||
|
|
||||||
add_module(xrpl rdb)
|
add_module(xrpl rdb)
|
||||||
target_link_libraries(xrpl.libxrpl.rdb PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.core)
|
target_link_libraries(
|
||||||
|
xrpl.libxrpl.rdb
|
||||||
|
PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.core
|
||||||
|
)
|
||||||
|
|
||||||
add_module(xrpl server)
|
add_module(xrpl server)
|
||||||
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol xrpl.libxrpl.core
|
target_link_libraries(
|
||||||
xrpl.libxrpl.rdb xrpl.libxrpl.resource)
|
xrpl.libxrpl.server
|
||||||
|
PUBLIC
|
||||||
|
xrpl.libxrpl.protocol
|
||||||
|
xrpl.libxrpl.core
|
||||||
|
xrpl.libxrpl.rdb
|
||||||
|
xrpl.libxrpl.resource
|
||||||
|
)
|
||||||
|
|
||||||
add_module(xrpl conditions)
|
add_module(xrpl conditions)
|
||||||
target_link_libraries(xrpl.libxrpl.conditions PUBLIC xrpl.libxrpl.server)
|
target_link_libraries(xrpl.libxrpl.conditions PUBLIC xrpl.libxrpl.server)
|
||||||
@@ -108,13 +184,16 @@ target_link_libraries(xrpl.libxrpl.conditions PUBLIC xrpl.libxrpl.server)
|
|||||||
add_module(xrpl ledger)
|
add_module(xrpl ledger)
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
xrpl.libxrpl.ledger
|
xrpl.libxrpl.ledger
|
||||||
PUBLIC xrpl.libxrpl.basics
|
PUBLIC
|
||||||
xrpl.libxrpl.json
|
xrpl.libxrpl.basics
|
||||||
xrpl.libxrpl.protocol
|
xrpl.libxrpl.json
|
||||||
xrpl.libxrpl.rdb
|
xrpl.libxrpl.protocol
|
||||||
xrpl.libxrpl.server
|
xrpl.libxrpl.protocol_autogen
|
||||||
xrpl.libxrpl.shamap
|
xrpl.libxrpl.rdb
|
||||||
xrpl.libxrpl.conditions)
|
xrpl.libxrpl.server
|
||||||
|
xrpl.libxrpl.shamap
|
||||||
|
xrpl.libxrpl.conditions
|
||||||
|
)
|
||||||
|
|
||||||
add_module(xrpl tx)
|
add_module(xrpl tx)
|
||||||
target_link_libraries(xrpl.libxrpl.tx PUBLIC xrpl.libxrpl.ledger)
|
target_link_libraries(xrpl.libxrpl.tx PUBLIC xrpl.libxrpl.ledger)
|
||||||
@@ -124,7 +203,11 @@ set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
|
|||||||
|
|
||||||
add_library(xrpl::libxrpl ALIAS xrpl.libxrpl)
|
add_library(xrpl::libxrpl ALIAS xrpl.libxrpl)
|
||||||
|
|
||||||
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/libxrpl/*.cpp")
|
file(
|
||||||
|
GLOB_RECURSE sources
|
||||||
|
CONFIGURE_DEPENDS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/libxrpl/*.cpp"
|
||||||
|
)
|
||||||
target_sources(xrpl.libxrpl PRIVATE ${sources})
|
target_sources(xrpl.libxrpl PRIVATE ${sources})
|
||||||
|
|
||||||
target_link_modules(
|
target_link_modules(
|
||||||
@@ -135,16 +218,19 @@ target_link_modules(
|
|||||||
conditions
|
conditions
|
||||||
core
|
core
|
||||||
crypto
|
crypto
|
||||||
|
git
|
||||||
json
|
json
|
||||||
ledger
|
ledger
|
||||||
net
|
net
|
||||||
nodestore
|
nodestore
|
||||||
protocol
|
protocol
|
||||||
|
protocol_autogen
|
||||||
rdb
|
rdb
|
||||||
resource
|
resource
|
||||||
server
|
server
|
||||||
shamap
|
shamap
|
||||||
tx)
|
tx
|
||||||
|
)
|
||||||
|
|
||||||
# All headers in libxrpl are in modules.
|
# All headers in libxrpl are in modules.
|
||||||
# Uncomment this stanza if you have not yet moved new headers into a module.
|
# Uncomment this stanza if you have not yet moved new headers into a module.
|
||||||
@@ -155,34 +241,51 @@ target_link_modules(
|
|||||||
# $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
# $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||||
# $<INSTALL_INTERFACE:include>)
|
# $<INSTALL_INTERFACE:include>)
|
||||||
|
|
||||||
if (xrpld)
|
if(xrpld)
|
||||||
add_executable(xrpld)
|
add_executable(xrpld)
|
||||||
if (tests)
|
if(tests)
|
||||||
target_compile_definitions(xrpld PUBLIC ENABLE_TESTS)
|
target_compile_definitions(xrpld PUBLIC ENABLE_TESTS)
|
||||||
target_compile_definitions(xrpld PRIVATE UNIT_TEST_REFERENCE_FEE=${UNIT_TEST_REFERENCE_FEE})
|
target_compile_definitions(
|
||||||
endif ()
|
xrpld
|
||||||
target_include_directories(xrpld PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
|
PRIVATE UNIT_TEST_REFERENCE_FEE=${UNIT_TEST_REFERENCE_FEE}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
target_include_directories(
|
||||||
|
xrpld
|
||||||
|
PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||||
|
)
|
||||||
|
|
||||||
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/xrpld/*.cpp")
|
file(
|
||||||
|
GLOB_RECURSE sources
|
||||||
|
CONFIGURE_DEPENDS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/xrpld/*.cpp"
|
||||||
|
)
|
||||||
target_sources(xrpld PRIVATE ${sources})
|
target_sources(xrpld PRIVATE ${sources})
|
||||||
|
|
||||||
if (tests)
|
if(tests)
|
||||||
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/test/*.cpp")
|
file(
|
||||||
|
GLOB_RECURSE sources
|
||||||
|
CONFIGURE_DEPENDS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/test/*.cpp"
|
||||||
|
)
|
||||||
target_sources(xrpld PRIVATE ${sources})
|
target_sources(xrpld PRIVATE ${sources})
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(xrpld Xrpl::boost Xrpl::opts Xrpl::libs xrpl.libxrpl)
|
target_link_libraries(xrpld Xrpl::boost Xrpl::opts Xrpl::libs xrpl.libxrpl)
|
||||||
exclude_if_included(xrpld)
|
exclude_if_included(xrpld)
|
||||||
# define a macro for tests that might need to
|
# define a macro for tests that might need to
|
||||||
# be excluded or run differently in CI environment
|
# be excluded or run differently in CI environment
|
||||||
if (is_ci)
|
if(is_ci)
|
||||||
target_compile_definitions(xrpld PRIVATE XRPL_RUNNING_IN_CI)
|
target_compile_definitions(xrpld PRIVATE XRPL_RUNNING_IN_CI)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (voidstar)
|
if(voidstar)
|
||||||
target_compile_options(xrpld PRIVATE -fsanitize-coverage=trace-pc-guard)
|
target_compile_options(xrpld PRIVATE -fsanitize-coverage=trace-pc-guard)
|
||||||
# xrpld requires access to antithesis-sdk-cpp implementation file
|
# xrpld requires access to antithesis-sdk-cpp implementation file
|
||||||
# antithesis_instrumentation.h, which is not exported as INTERFACE
|
# antithesis_instrumentation.h, which is not exported as INTERFACE
|
||||||
target_include_directories(xrpld PRIVATE ${CMAKE_SOURCE_DIR}/external/antithesis-sdk)
|
target_include_directories(
|
||||||
endif ()
|
xrpld
|
||||||
endif ()
|
PRIVATE ${CMAKE_SOURCE_DIR}/external/antithesis-sdk
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -2,14 +2,17 @@
|
|||||||
coverage report target
|
coverage report target
|
||||||
#]===================================================================]
|
#]===================================================================]
|
||||||
|
|
||||||
if (NOT coverage)
|
if(NOT coverage)
|
||||||
message(FATAL_ERROR "Code coverage not enabled! Aborting ...")
|
message(FATAL_ERROR "Code coverage not enabled! Aborting ...")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||||
message(WARNING "Code coverage on Windows is not supported, ignoring 'coverage' flag")
|
message(
|
||||||
|
WARNING
|
||||||
|
"Code coverage on Windows is not supported, ignoring 'coverage' flag"
|
||||||
|
)
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
include(ProcessorCount)
|
include(ProcessorCount)
|
||||||
ProcessorCount(PROCESSOR_COUNT)
|
ProcessorCount(PROCESSOR_COUNT)
|
||||||
@@ -21,32 +24,30 @@ include(CodeCoverage)
|
|||||||
# `CodeCoverage.cmake`)
|
# `CodeCoverage.cmake`)
|
||||||
|
|
||||||
set(GCOVR_ADDITIONAL_ARGS ${coverage_extra_args})
|
set(GCOVR_ADDITIONAL_ARGS ${coverage_extra_args})
|
||||||
if (NOT GCOVR_ADDITIONAL_ARGS STREQUAL "")
|
if(NOT GCOVR_ADDITIONAL_ARGS STREQUAL "")
|
||||||
separate_arguments(GCOVR_ADDITIONAL_ARGS)
|
separate_arguments(GCOVR_ADDITIONAL_ARGS)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
list(APPEND
|
list(
|
||||||
GCOVR_ADDITIONAL_ARGS
|
APPEND GCOVR_ADDITIONAL_ARGS
|
||||||
--exclude-throw-branches
|
--exclude-throw-branches
|
||||||
--exclude-noncode-lines
|
--exclude-noncode-lines
|
||||||
--exclude-unreachable-branches
|
--exclude-unreachable-branches
|
||||||
-s
|
-s
|
||||||
-j
|
-j
|
||||||
${PROCESSOR_COUNT})
|
${PROCESSOR_COUNT}
|
||||||
|
)
|
||||||
|
|
||||||
setup_target_for_coverage_gcovr(
|
setup_target_for_coverage_gcovr(
|
||||||
NAME
|
NAME coverage
|
||||||
coverage
|
FORMAT ${coverage_format}
|
||||||
FORMAT
|
|
||||||
${coverage_format}
|
|
||||||
EXCLUDE
|
EXCLUDE
|
||||||
"src/test"
|
"src/test"
|
||||||
"src/tests"
|
"src/tests"
|
||||||
"include/xrpl/beast/test"
|
"include/xrpl/beast/test"
|
||||||
"include/xrpl/beast/unit_test"
|
"include/xrpl/beast/unit_test"
|
||||||
"${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
|
"${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
|
||||||
DEPENDENCIES
|
DEPENDENCIES xrpld xrpl.tests
|
||||||
xrpld
|
)
|
||||||
xrpl.tests)
|
|
||||||
|
|
||||||
add_code_coverage_to_target(opts INTERFACE)
|
add_code_coverage_to_target(opts INTERFACE)
|
||||||
|
|||||||
@@ -2,71 +2,90 @@
|
|||||||
docs target (optional)
|
docs target (optional)
|
||||||
#]===================================================================]
|
#]===================================================================]
|
||||||
|
|
||||||
if (NOT only_docs)
|
if(NOT only_docs)
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
find_package(Doxygen)
|
find_package(Doxygen)
|
||||||
if (NOT TARGET Doxygen::doxygen)
|
if(NOT TARGET Doxygen::doxygen)
|
||||||
message(STATUS "doxygen executable not found -- skipping docs target")
|
message(STATUS "doxygen executable not found -- skipping docs target")
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
set(doxygen_output_directory "${CMAKE_BINARY_DIR}/docs")
|
set(doxygen_output_directory "${CMAKE_BINARY_DIR}/docs")
|
||||||
set(doxygen_include_path "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
set(doxygen_include_path "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||||
set(doxygen_index_file "${doxygen_output_directory}/html/index.html")
|
set(doxygen_index_file "${doxygen_output_directory}/html/index.html")
|
||||||
set(doxyfile "${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile")
|
set(doxyfile "${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile")
|
||||||
|
|
||||||
file(GLOB_RECURSE
|
file(
|
||||||
doxygen_input
|
GLOB_RECURSE doxygen_input
|
||||||
docs/*.md
|
docs/*.md
|
||||||
include/*.h
|
include/*.h
|
||||||
include/*.cpp
|
include/*.cpp
|
||||||
include/*.md
|
include/*.md
|
||||||
src/*.h
|
src/*.h
|
||||||
src/*.cpp
|
src/*.cpp
|
||||||
src/*.md
|
src/*.md
|
||||||
Builds/*.md
|
Builds/*.md
|
||||||
*.md)
|
*.md
|
||||||
|
)
|
||||||
list(APPEND doxygen_input external/README.md)
|
list(APPEND doxygen_input external/README.md)
|
||||||
set(dependencies "${doxygen_input}" "${doxyfile}")
|
set(dependencies "${doxygen_input}" "${doxyfile}")
|
||||||
|
|
||||||
function (verbose_find_path variable name)
|
function(verbose_find_path variable name)
|
||||||
# find_path sets a CACHE variable, so don't try using a "local" variable.
|
# find_path sets a CACHE variable, so don't try using a "local" variable.
|
||||||
find_path(${variable} "${name}" ${ARGN})
|
find_path(${variable} "${name}" ${ARGN})
|
||||||
if (NOT ${variable})
|
if(NOT ${variable})
|
||||||
message(NOTICE "could not find ${name}")
|
message(NOTICE "could not find ${name}")
|
||||||
else ()
|
else()
|
||||||
message(STATUS "found ${name}: ${${variable}}/${name}")
|
message(STATUS "found ${name}: ${${variable}}/${name}")
|
||||||
endif ()
|
endif()
|
||||||
endfunction ()
|
endfunction()
|
||||||
|
|
||||||
verbose_find_path(doxygen_plantuml_jar_path plantuml.jar PATH_SUFFIXES share/plantuml)
|
verbose_find_path(
|
||||||
|
doxygen_plantuml_jar_path
|
||||||
|
plantuml.jar
|
||||||
|
PATH_SUFFIXES share/plantuml
|
||||||
|
)
|
||||||
verbose_find_path(doxygen_dot_path dot)
|
verbose_find_path(doxygen_dot_path dot)
|
||||||
|
|
||||||
# https://en.cppreference.com/w/Cppreference:Archives
|
# https://en.cppreference.com/w/Cppreference:Archives
|
||||||
# https://stackoverflow.com/questions/60822559/how-to-move-a-file-download-from-configure-step-to-build-step
|
# https://stackoverflow.com/questions/60822559/how-to-move-a-file-download-from-configure-step-to-build-step
|
||||||
set(download_script "${CMAKE_BINARY_DIR}/docs/download-cppreference.cmake")
|
set(download_script "${CMAKE_BINARY_DIR}/docs/download-cppreference.cmake")
|
||||||
file(WRITE "${download_script}"
|
file(
|
||||||
"file(DOWNLOAD \
|
WRITE "${download_script}"
|
||||||
|
"file(DOWNLOAD \
|
||||||
https://github.com/PeterFeicht/cppreference-doc/releases/download/v20250209/html-book-20250209.zip \
|
https://github.com/PeterFeicht/cppreference-doc/releases/download/v20250209/html-book-20250209.zip \
|
||||||
${CMAKE_BINARY_DIR}/docs/cppreference.zip \
|
${CMAKE_BINARY_DIR}/docs/cppreference.zip \
|
||||||
EXPECTED_HASH MD5=bda585f72fbca4b817b29a3d5746567b \
|
EXPECTED_HASH MD5=bda585f72fbca4b817b29a3d5746567b \
|
||||||
)\n \
|
)\n \
|
||||||
execute_process( \
|
execute_process( \
|
||||||
COMMAND \"${CMAKE_COMMAND}\" -E tar -xf cppreference.zip \
|
COMMAND \"${CMAKE_COMMAND}\" -E tar -xf cppreference.zip \
|
||||||
)\n")
|
)\n"
|
||||||
|
)
|
||||||
set(tagfile "${CMAKE_BINARY_DIR}/docs/cppreference-doxygen-web.tag.xml")
|
set(tagfile "${CMAKE_BINARY_DIR}/docs/cppreference-doxygen-web.tag.xml")
|
||||||
add_custom_command(OUTPUT "${tagfile}" COMMAND "${CMAKE_COMMAND}" -P "${download_script}"
|
add_custom_command(
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/docs")
|
OUTPUT "${tagfile}"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -P "${download_script}"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/docs"
|
||||||
|
)
|
||||||
set(doxygen_tagfiles "${tagfile}=http://en.cppreference.com/w/")
|
set(doxygen_tagfiles "${tagfile}=http://en.cppreference.com/w/")
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT "${doxygen_index_file}"
|
OUTPUT "${doxygen_index_file}"
|
||||||
COMMAND "${CMAKE_COMMAND}" -E env "DOXYGEN_OUTPUT_DIRECTORY=${doxygen_output_directory}"
|
COMMAND
|
||||||
"DOXYGEN_INCLUDE_PATH=${doxygen_include_path}" "DOXYGEN_TAGFILES=${doxygen_tagfiles}"
|
"${CMAKE_COMMAND}" -E env
|
||||||
"DOXYGEN_PLANTUML_JAR_PATH=${doxygen_plantuml_jar_path}"
|
"DOXYGEN_OUTPUT_DIRECTORY=${doxygen_output_directory}"
|
||||||
"DOXYGEN_DOT_PATH=${doxygen_dot_path}" "${DOXYGEN_EXECUTABLE}" "${doxyfile}"
|
"DOXYGEN_INCLUDE_PATH=${doxygen_include_path}"
|
||||||
|
"DOXYGEN_TAGFILES=${doxygen_tagfiles}"
|
||||||
|
"DOXYGEN_PLANTUML_JAR_PATH=${doxygen_plantuml_jar_path}"
|
||||||
|
"DOXYGEN_DOT_PATH=${doxygen_dot_path}" "${DOXYGEN_EXECUTABLE}"
|
||||||
|
"${doxyfile}"
|
||||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
DEPENDS "${dependencies}" "${tagfile}")
|
DEPENDS "${dependencies}" "${tagfile}"
|
||||||
add_custom_target(docs DEPENDS "${doxygen_index_file}" SOURCES "${dependencies}")
|
)
|
||||||
|
add_custom_target(
|
||||||
|
docs
|
||||||
|
DEPENDS "${doxygen_index_file}"
|
||||||
|
SOURCES "${dependencies}"
|
||||||
|
)
|
||||||
|
|||||||
@@ -2,77 +2,38 @@
|
|||||||
install stuff
|
install stuff
|
||||||
#]===================================================================]
|
#]===================================================================]
|
||||||
|
|
||||||
include(create_symbolic_link)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
# If no suffix is defined for executables (e.g. Windows uses .exe but Linux
|
if(is_root_project AND TARGET xrpld)
|
||||||
# and macOS use none), then explicitly set it to the empty string.
|
install(
|
||||||
if (NOT DEFINED suffix)
|
TARGETS xrpld
|
||||||
set(suffix "")
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
|
||||||
endif ()
|
)
|
||||||
|
|
||||||
install(TARGETS common
|
install(
|
||||||
opts
|
FILES "${CMAKE_CURRENT_SOURCE_DIR}/cfg/xrpld-example.cfg"
|
||||||
xrpl_boost
|
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/xrpld"
|
||||||
xrpl_libs
|
RENAME xrpld.cfg
|
||||||
xrpl_syslibs
|
COMPONENT runtime
|
||||||
xrpl.imports.main
|
)
|
||||||
xrpl.libpb
|
|
||||||
xrpl.libxrpl
|
|
||||||
xrpl.libxrpl.basics
|
|
||||||
xrpl.libxrpl.beast
|
|
||||||
xrpl.libxrpl.conditions
|
|
||||||
xrpl.libxrpl.core
|
|
||||||
xrpl.libxrpl.crypto
|
|
||||||
xrpl.libxrpl.json
|
|
||||||
xrpl.libxrpl.rdb
|
|
||||||
xrpl.libxrpl.ledger
|
|
||||||
xrpl.libxrpl.net
|
|
||||||
xrpl.libxrpl.nodestore
|
|
||||||
xrpl.libxrpl.protocol
|
|
||||||
xrpl.libxrpl.resource
|
|
||||||
xrpl.libxrpl.server
|
|
||||||
xrpl.libxrpl.shamap
|
|
||||||
xrpl.libxrpl.tx
|
|
||||||
antithesis-sdk-cpp
|
|
||||||
EXPORT XrplExports
|
|
||||||
LIBRARY DESTINATION lib
|
|
||||||
ARCHIVE DESTINATION lib
|
|
||||||
RUNTIME DESTINATION bin
|
|
||||||
INCLUDES
|
|
||||||
DESTINATION include)
|
|
||||||
|
|
||||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl"
|
install(
|
||||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
FILES "${CMAKE_CURRENT_SOURCE_DIR}/cfg/validators-example.txt"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/xrpld"
|
||||||
|
RENAME validators.txt
|
||||||
|
COMPONENT runtime
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
install(EXPORT XrplExports FILE XrplTargets.cmake NAMESPACE Xrpl:: DESTINATION lib/cmake/xrpl)
|
install(
|
||||||
include(CMakePackageConfigHelpers)
|
TARGETS xrpl.libpb xrpl.libxrpl
|
||||||
write_basic_package_version_file(XrplConfigVersion.cmake VERSION ${xrpld_version}
|
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT development
|
||||||
COMPATIBILITY SameMajorVersion)
|
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT development
|
||||||
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT development
|
||||||
|
)
|
||||||
|
|
||||||
if (is_root_project AND TARGET xrpld)
|
install(
|
||||||
install(TARGETS xrpld RUNTIME DESTINATION bin)
|
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl"
|
||||||
set_target_properties(xrpld PROPERTIES INSTALL_RPATH_USE_LINK_PATH ON)
|
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
# sample configs should not overwrite existing files
|
COMPONENT development
|
||||||
# install if-not-exists workaround as suggested by
|
)
|
||||||
# https://cmake.org/Bug/view.php?id=12646
|
|
||||||
install(CODE "
|
|
||||||
macro (copy_if_not_exists SRC DEST NEWNAME)
|
|
||||||
if (NOT EXISTS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}/\${NEWNAME}\")
|
|
||||||
file (INSTALL FILE_PERMISSIONS OWNER_READ OWNER_WRITE DESTINATION \"\${CMAKE_INSTALL_PREFIX}/\${DEST}\" FILES \"\${SRC}\" RENAME \"\${NEWNAME}\")
|
|
||||||
else ()
|
|
||||||
message (\"-- Skipping : \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}/\${NEWNAME}\")
|
|
||||||
endif ()
|
|
||||||
endmacro()
|
|
||||||
copy_if_not_exists(\"${CMAKE_CURRENT_SOURCE_DIR}/cfg/xrpld-example.cfg\" etc xrpld.cfg)
|
|
||||||
copy_if_not_exists(\"${CMAKE_CURRENT_SOURCE_DIR}/cfg/validators-example.txt\" etc validators.txt)
|
|
||||||
")
|
|
||||||
install(CODE "
|
|
||||||
set(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\")
|
|
||||||
include(create_symbolic_link)
|
|
||||||
create_symbolic_link(xrpld${suffix} \
|
|
||||||
\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/rippled${suffix})
|
|
||||||
")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/XrplConfig.cmake
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/XrplConfigVersion.cmake DESTINATION lib/cmake/xrpl)
|
|
||||||
|
|||||||
@@ -5,47 +5,55 @@
|
|||||||
include(CompilationEnv)
|
include(CompilationEnv)
|
||||||
|
|
||||||
# Set defaults for optional variables to avoid uninitialized variable warnings
|
# Set defaults for optional variables to avoid uninitialized variable warnings
|
||||||
if (NOT DEFINED voidstar)
|
if(NOT DEFINED voidstar)
|
||||||
set(voidstar OFF)
|
set(voidstar OFF)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
add_library(opts INTERFACE)
|
add_library(opts INTERFACE)
|
||||||
add_library(Xrpl::opts ALIAS opts)
|
add_library(Xrpl::opts ALIAS opts)
|
||||||
target_compile_definitions(
|
target_compile_definitions(
|
||||||
opts
|
opts
|
||||||
INTERFACE BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS
|
INTERFACE
|
||||||
BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT
|
BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS
|
||||||
BOOST_CONTAINER_FWD_BAD_DEQUE
|
BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT
|
||||||
HAS_UNCAUGHT_EXCEPTIONS=1
|
BOOST_CONTAINER_FWD_BAD_DEQUE
|
||||||
$<$<BOOL:${boost_show_deprecated}>:
|
HAS_UNCAUGHT_EXCEPTIONS=1
|
||||||
BOOST_ASIO_NO_DEPRECATED
|
$<$<BOOL:${boost_show_deprecated}>:
|
||||||
BOOST_FILESYSTEM_NO_DEPRECATED
|
BOOST_ASIO_NO_DEPRECATED
|
||||||
>
|
BOOST_FILESYSTEM_NO_DEPRECATED
|
||||||
$<$<NOT:$<BOOL:${boost_show_deprecated}>>:
|
>
|
||||||
BOOST_COROUTINES_NO_DEPRECATION_WARNING
|
$<$<NOT:$<BOOL:${boost_show_deprecated}>>:
|
||||||
BOOST_BEAST_ALLOW_DEPRECATED
|
BOOST_COROUTINES2_NO_DEPRECATION_WARNING
|
||||||
BOOST_FILESYSTEM_DEPRECATED
|
BOOST_BEAST_ALLOW_DEPRECATED
|
||||||
>
|
BOOST_FILESYSTEM_DEPRECATED
|
||||||
$<$<BOOL:${beast_no_unit_test_inline}>:BEAST_NO_UNIT_TEST_INLINE=1>
|
>
|
||||||
$<$<BOOL:${beast_disable_autolink}>:BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES=1>
|
$<$<BOOL:${beast_no_unit_test_inline}>:BEAST_NO_UNIT_TEST_INLINE=1>
|
||||||
$<$<BOOL:${single_io_service_thread}>:XRPL_SINGLE_IO_SERVICE_THREAD=1>
|
$<$<BOOL:${beast_disable_autolink}>:BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES=1>
|
||||||
$<$<BOOL:${voidstar}>:ENABLE_VOIDSTAR>)
|
$<$<BOOL:${single_io_service_thread}>:XRPL_SINGLE_IO_SERVICE_THREAD=1>
|
||||||
|
$<$<BOOL:${voidstar}>:ENABLE_VOIDSTAR>
|
||||||
|
)
|
||||||
target_compile_options(
|
target_compile_options(
|
||||||
opts
|
opts
|
||||||
INTERFACE $<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
|
INTERFACE
|
||||||
$<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized>
|
$<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
|
||||||
$<$<BOOL:${perf}>:-fno-omit-frame-pointer>
|
$<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized>
|
||||||
$<$<BOOL:${profile}>:-pg>
|
$<$<BOOL:${perf}>:-fno-omit-frame-pointer>
|
||||||
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
|
$<$<BOOL:${profile}>:-pg>
|
||||||
|
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(opts INTERFACE $<$<BOOL:${profile}>:-pg>
|
target_link_libraries(
|
||||||
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
|
opts
|
||||||
|
INTERFACE
|
||||||
|
$<$<BOOL:${profile}>:-pg>
|
||||||
|
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>
|
||||||
|
)
|
||||||
|
|
||||||
if (jemalloc)
|
if(jemalloc)
|
||||||
find_package(jemalloc REQUIRED)
|
find_package(jemalloc REQUIRED)
|
||||||
target_compile_definitions(opts INTERFACE PROFILE_JEMALLOC)
|
target_compile_definitions(opts INTERFACE PROFILE_JEMALLOC)
|
||||||
target_link_libraries(opts INTERFACE jemalloc::jemalloc)
|
target_link_libraries(opts INTERFACE jemalloc::jemalloc)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
#[===================================================================[
|
#[===================================================================[
|
||||||
xrpld transitive library deps via an interface library
|
xrpld transitive library deps via an interface library
|
||||||
@@ -55,31 +63,33 @@ add_library(xrpl_syslibs INTERFACE)
|
|||||||
add_library(Xrpl::syslibs ALIAS xrpl_syslibs)
|
add_library(Xrpl::syslibs ALIAS xrpl_syslibs)
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
xrpl_syslibs
|
xrpl_syslibs
|
||||||
INTERFACE $<$<BOOL:${is_msvc}>:
|
INTERFACE
|
||||||
legacy_stdio_definitions.lib
|
$<$<BOOL:${is_msvc}>:
|
||||||
Shlwapi
|
legacy_stdio_definitions.lib
|
||||||
kernel32
|
Shlwapi
|
||||||
user32
|
kernel32
|
||||||
gdi32
|
user32
|
||||||
winspool
|
gdi32
|
||||||
comdlg32
|
winspool
|
||||||
advapi32
|
comdlg32
|
||||||
shell32
|
advapi32
|
||||||
ole32
|
shell32
|
||||||
oleaut32
|
ole32
|
||||||
uuid
|
oleaut32
|
||||||
odbc32
|
uuid
|
||||||
odbccp32
|
odbc32
|
||||||
crypt32
|
odbccp32
|
||||||
>
|
crypt32
|
||||||
$<$<NOT:$<BOOL:${is_msvc}>>:dl>
|
>
|
||||||
$<$<NOT:$<OR:$<BOOL:${is_msvc}>,$<BOOL:${is_macos}>>>:rt>)
|
$<$<NOT:$<BOOL:${is_msvc}>>:dl>
|
||||||
|
$<$<NOT:$<OR:$<BOOL:${is_msvc}>,$<BOOL:${is_macos}>>>:rt>
|
||||||
|
)
|
||||||
|
|
||||||
if (NOT is_msvc)
|
if(NOT is_msvc)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
target_link_libraries(xrpl_syslibs INTERFACE Threads::Threads)
|
target_link_libraries(xrpl_syslibs INTERFACE Threads::Threads)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
add_library(xrpl_libs INTERFACE)
|
add_library(xrpl_libs INTERFACE)
|
||||||
add_library(Xrpl::libs ALIAS xrpl_libs)
|
add_library(Xrpl::libs ALIAS xrpl_libs)
|
||||||
|
|||||||
294
cmake/XrplProtocolAutogen.cmake
Normal file
294
cmake/XrplProtocolAutogen.cmake
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
#[===================================================================[
|
||||||
|
Protocol Autogen - Code generation for protocol wrapper classes
|
||||||
|
#]===================================================================]
|
||||||
|
|
||||||
|
# Options for code generation
|
||||||
|
option(
|
||||||
|
XRPL_NO_CODEGEN
|
||||||
|
"Disable code generation (use pre-generated files from repository)"
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
set(CODEGEN_VENV_DIR
|
||||||
|
""
|
||||||
|
CACHE PATH
|
||||||
|
"Path to Python virtual environment for code generation. If provided, automatic venv setup is skipped."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Function to set up code generation for protocol_autogen module
|
||||||
|
function(setup_protocol_autogen)
|
||||||
|
# Directory paths
|
||||||
|
set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol/detail")
|
||||||
|
set(AUTOGEN_HEADER_DIR
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol_autogen"
|
||||||
|
)
|
||||||
|
set(AUTOGEN_TEST_DIR
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/tests/libxrpl/protocol_autogen"
|
||||||
|
)
|
||||||
|
set(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/scripts/codegen")
|
||||||
|
|
||||||
|
# Input macro files
|
||||||
|
set(TRANSACTIONS_MACRO "${MACRO_DIR}/transactions.macro")
|
||||||
|
set(LEDGER_ENTRIES_MACRO "${MACRO_DIR}/ledger_entries.macro")
|
||||||
|
set(SFIELDS_MACRO "${MACRO_DIR}/sfields.macro")
|
||||||
|
|
||||||
|
# Python scripts and templates
|
||||||
|
set(GENERATE_TX_SCRIPT "${SCRIPTS_DIR}/generate_tx_classes.py")
|
||||||
|
set(GENERATE_LEDGER_SCRIPT "${SCRIPTS_DIR}/generate_ledger_classes.py")
|
||||||
|
set(REQUIREMENTS_FILE "${SCRIPTS_DIR}/requirements.txt")
|
||||||
|
set(MACRO_PARSER_COMMON "${SCRIPTS_DIR}/macro_parser_common.py")
|
||||||
|
set(TX_TEMPLATE "${SCRIPTS_DIR}/templates/Transaction.h.mako")
|
||||||
|
set(TX_TEST_TEMPLATE "${SCRIPTS_DIR}/templates/TransactionTests.cpp.mako")
|
||||||
|
set(LEDGER_TEMPLATE "${SCRIPTS_DIR}/templates/LedgerEntry.h.mako")
|
||||||
|
set(LEDGER_TEST_TEMPLATE
|
||||||
|
"${SCRIPTS_DIR}/templates/LedgerEntryTests.cpp.mako"
|
||||||
|
)
|
||||||
|
set(UPDATE_STAMP_SCRIPT "${SCRIPTS_DIR}/update_codegen_stamp.py")
|
||||||
|
|
||||||
|
# Check if code generation is disabled
|
||||||
|
if(XRPL_NO_CODEGEN)
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"Protocol autogen: Code generation is disabled (XRPL_NO_CODEGEN=ON). "
|
||||||
|
"Generated files may be out of date."
|
||||||
|
)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Create output directories
|
||||||
|
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/transactions")
|
||||||
|
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/ledger_entries")
|
||||||
|
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/ledger_entries")
|
||||||
|
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/transactions")
|
||||||
|
|
||||||
|
# === Stamp file check ===
|
||||||
|
# All input files whose content affects code generation output.
|
||||||
|
set(STAMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/scripts/codegen/.codegen_stamp")
|
||||||
|
set(ALL_INPUT_FILES
|
||||||
|
"${TRANSACTIONS_MACRO}"
|
||||||
|
"${LEDGER_ENTRIES_MACRO}"
|
||||||
|
"${SFIELDS_MACRO}"
|
||||||
|
"${GENERATE_TX_SCRIPT}"
|
||||||
|
"${GENERATE_LEDGER_SCRIPT}"
|
||||||
|
"${REQUIREMENTS_FILE}"
|
||||||
|
"${MACRO_PARSER_COMMON}"
|
||||||
|
"${TX_TEMPLATE}"
|
||||||
|
"${TX_TEST_TEMPLATE}"
|
||||||
|
"${LEDGER_TEMPLATE}"
|
||||||
|
"${LEDGER_TEST_TEMPLATE}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Tell CMake to reconfigure automatically when any input file changes.
|
||||||
|
# The reconfigure itself is cheap — it runs the stamp check below
|
||||||
|
# which only invokes stdlib Python (no venv needed).
|
||||||
|
set_property(
|
||||||
|
DIRECTORY
|
||||||
|
APPEND
|
||||||
|
PROPERTY CMAKE_CONFIGURE_DEPENDS ${ALL_INPUT_FILES}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find Python3 (needed for stamp check; no venv required).
|
||||||
|
if(NOT Python3_EXECUTABLE)
|
||||||
|
find_package(Python3 COMPONENTS Interpreter QUIET)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT Python3_EXECUTABLE)
|
||||||
|
# Try finding python3 executable directly
|
||||||
|
find_program(Python3_EXECUTABLE NAMES python3 python)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT Python3_EXECUTABLE)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Python3 not found. Code generation cannot proceed.\n"
|
||||||
|
"Please install Python 3, or set -DXRPL_NO_CODEGEN=ON to use existing generated files."
|
||||||
|
)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check whether the stamp is up-to-date (stdlib-only, no venv).
|
||||||
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
${Python3_EXECUTABLE} "${UPDATE_STAMP_SCRIPT}" --check
|
||||||
|
"${STAMP_FILE}" ${ALL_INPUT_FILES}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE STAMP_CHECK_RESULT
|
||||||
|
)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Fast path: stamp matches — generated files are up to date.
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
if(STAMP_CHECK_RESULT EQUAL 0)
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"Protocol autogen: inputs unchanged (stamp matches), skipping generation"
|
||||||
|
)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Slow path: stamp mismatch — run generation at configure time.
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"Protocol autogen: inputs changed, running code generation..."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set up Python virtual environment for code generation.
|
||||||
|
if(CODEGEN_VENV_DIR)
|
||||||
|
# User-provided venv - skip automatic setup.
|
||||||
|
set(VENV_DIR "${CODEGEN_VENV_DIR}")
|
||||||
|
message(STATUS "Using user-provided Python venv: ${VENV_DIR}")
|
||||||
|
else()
|
||||||
|
# Use default venv in build directory.
|
||||||
|
set(VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/codegen_venv")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine the Python/pip executables inside the venv.
|
||||||
|
if(WIN32)
|
||||||
|
set(VENV_PYTHON "${VENV_DIR}/Scripts/python.exe")
|
||||||
|
set(VENV_PIP "${VENV_DIR}/Scripts/pip.exe")
|
||||||
|
else()
|
||||||
|
set(VENV_PYTHON "${VENV_DIR}/bin/python")
|
||||||
|
set(VENV_PIP "${VENV_DIR}/bin/pip")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Create or update the virtual environment if needed.
|
||||||
|
if(NOT CODEGEN_VENV_DIR)
|
||||||
|
# Check if venv needs to be created or updated.
|
||||||
|
set(VENV_NEEDS_UPDATE FALSE)
|
||||||
|
if(NOT EXISTS "${VENV_PYTHON}")
|
||||||
|
set(VENV_NEEDS_UPDATE TRUE)
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"Creating Python virtual environment for code generation..."
|
||||||
|
)
|
||||||
|
elseif(
|
||||||
|
"${REQUIREMENTS_FILE}"
|
||||||
|
IS_NEWER_THAN
|
||||||
|
"${VENV_DIR}/.requirements_installed"
|
||||||
|
)
|
||||||
|
set(VENV_NEEDS_UPDATE TRUE)
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"Updating Python virtual environment (requirements changed)..."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Create/update virtual environment if needed.
|
||||||
|
if(VENV_NEEDS_UPDATE)
|
||||||
|
# Create the venv.
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"Setting up Python virtual environment at ${VENV_DIR}"
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -m venv "${VENV_DIR}"
|
||||||
|
RESULT_VARIABLE VENV_RESULT
|
||||||
|
ERROR_VARIABLE VENV_ERROR
|
||||||
|
)
|
||||||
|
if(NOT VENV_RESULT EQUAL 0)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Failed to create virtual environment: ${VENV_ERROR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Warn if pip is configured with a non-default index (may need VPN).
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${VENV_PIP} config get global.index-url
|
||||||
|
OUTPUT_VARIABLE PIP_INDEX_URL
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
|
||||||
|
# Default PyPI URL
|
||||||
|
set(DEFAULT_PIP_INDEX "https://pypi.org/simple")
|
||||||
|
|
||||||
|
# Show warning if using non-default index
|
||||||
|
if(PIP_INDEX_URL AND NOT PIP_INDEX_URL STREQUAL "")
|
||||||
|
if(NOT PIP_INDEX_URL STREQUAL DEFAULT_PIP_INDEX)
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"Private pip index URL detected: ${PIP_INDEX_URL}\n"
|
||||||
|
"You may need to connect to VPN to access this URL."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Install dependencies.
|
||||||
|
message(STATUS "Installing Python dependencies...")
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${VENV_PIP} install --upgrade pip
|
||||||
|
RESULT_VARIABLE PIP_UPGRADE_RESULT
|
||||||
|
OUTPUT_QUIET
|
||||||
|
ERROR_VARIABLE PIP_UPGRADE_ERROR
|
||||||
|
)
|
||||||
|
if(NOT PIP_UPGRADE_RESULT EQUAL 0)
|
||||||
|
message(WARNING "Failed to upgrade pip: ${PIP_UPGRADE_ERROR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${VENV_PIP} install -r "${REQUIREMENTS_FILE}"
|
||||||
|
RESULT_VARIABLE PIP_INSTALL_RESULT
|
||||||
|
ERROR_VARIABLE PIP_INSTALL_ERROR
|
||||||
|
)
|
||||||
|
if(NOT PIP_INSTALL_RESULT EQUAL 0)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Failed to install Python dependencies: ${PIP_INSTALL_ERROR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Mark requirements as installed.
|
||||||
|
file(TOUCH "${VENV_DIR}/.requirements_installed")
|
||||||
|
message(STATUS "Python virtual environment ready")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Generate transaction classes.
|
||||||
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
${VENV_PYTHON} "${GENERATE_TX_SCRIPT}" "${TRANSACTIONS_MACRO}"
|
||||||
|
--header-dir "${AUTOGEN_HEADER_DIR}/transactions" --test-dir
|
||||||
|
"${AUTOGEN_TEST_DIR}/transactions" --sfields-macro
|
||||||
|
"${SFIELDS_MACRO}"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE TX_RESULT
|
||||||
|
ERROR_VARIABLE TX_ERROR
|
||||||
|
)
|
||||||
|
if(NOT TX_RESULT EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Transaction code generation failed:\n${TX_ERROR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Generate ledger entry classes.
|
||||||
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
${VENV_PYTHON} "${GENERATE_LEDGER_SCRIPT}" "${LEDGER_ENTRIES_MACRO}"
|
||||||
|
--header-dir "${AUTOGEN_HEADER_DIR}/ledger_entries" --test-dir
|
||||||
|
"${AUTOGEN_TEST_DIR}/ledger_entries" --sfields-macro
|
||||||
|
"${SFIELDS_MACRO}"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE LEDGER_RESULT
|
||||||
|
ERROR_VARIABLE LEDGER_ERROR
|
||||||
|
)
|
||||||
|
if(NOT LEDGER_RESULT EQUAL 0)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Ledger entry code generation failed:\n${LEDGER_ERROR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Update the stamp file so subsequent configures skip generation.
|
||||||
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
${Python3_EXECUTABLE} "${UPDATE_STAMP_SCRIPT}" --update
|
||||||
|
"${STAMP_FILE}" ${ALL_INPUT_FILES}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE STAMP_RESULT
|
||||||
|
)
|
||||||
|
if(NOT STAMP_RESULT EQUAL 0)
|
||||||
|
message(WARNING "Failed to update codegen stamp file")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Protocol autogen: code generation complete")
|
||||||
|
endfunction()
|
||||||
@@ -44,23 +44,26 @@ include(CompilationEnv)
|
|||||||
|
|
||||||
# Read environment variable
|
# Read environment variable
|
||||||
set(SANITIZERS "")
|
set(SANITIZERS "")
|
||||||
if (DEFINED ENV{SANITIZERS})
|
if(DEFINED ENV{SANITIZERS})
|
||||||
set(SANITIZERS "$ENV{SANITIZERS}")
|
set(SANITIZERS "$ENV{SANITIZERS}")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# Set SANITIZERS_ENABLED flag for use in other modules
|
# Set SANITIZERS_ENABLED flag for use in other modules
|
||||||
if (SANITIZERS MATCHES "address|thread|undefinedbehavior")
|
if(SANITIZERS MATCHES "address|thread|undefinedbehavior")
|
||||||
set(SANITIZERS_ENABLED TRUE)
|
set(SANITIZERS_ENABLED TRUE)
|
||||||
else ()
|
else()
|
||||||
set(SANITIZERS_ENABLED FALSE)
|
set(SANITIZERS_ENABLED FALSE)
|
||||||
return()
|
return()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# Sanitizers are not supported on Windows/MSVC
|
# Sanitizers are not supported on Windows/MSVC
|
||||||
if (is_msvc)
|
if(is_msvc)
|
||||||
message(FATAL_ERROR "Sanitizers are not supported on Windows/MSVC. "
|
message(
|
||||||
"Please unset the SANITIZERS environment variable.")
|
FATAL_ERROR
|
||||||
endif ()
|
"Sanitizers are not supported on Windows/MSVC. "
|
||||||
|
"Please unset the SANITIZERS environment variable."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
message(STATUS "Configuring sanitizers: ${SANITIZERS}")
|
message(STATUS "Configuring sanitizers: ${SANITIZERS}")
|
||||||
|
|
||||||
@@ -74,24 +77,30 @@ set(san_list "${SANITIZERS}")
|
|||||||
string(REPLACE "," ";" san_list "${san_list}")
|
string(REPLACE "," ";" san_list "${san_list}")
|
||||||
separate_arguments(san_list)
|
separate_arguments(san_list)
|
||||||
|
|
||||||
foreach (san IN LISTS san_list)
|
foreach(san IN LISTS san_list)
|
||||||
if (san STREQUAL "address")
|
if(san STREQUAL "address")
|
||||||
set(enable_asan TRUE)
|
set(enable_asan TRUE)
|
||||||
elseif (san STREQUAL "thread")
|
elseif(san STREQUAL "thread")
|
||||||
set(enable_tsan TRUE)
|
set(enable_tsan TRUE)
|
||||||
elseif (san STREQUAL "undefinedbehavior")
|
elseif(san STREQUAL "undefinedbehavior")
|
||||||
set(enable_ubsan TRUE)
|
set(enable_ubsan TRUE)
|
||||||
else ()
|
else()
|
||||||
message(FATAL_ERROR "Unsupported sanitizer type: ${san}"
|
message(
|
||||||
"Supported: address, thread, undefinedbehavior and their combinations.")
|
FATAL_ERROR
|
||||||
endif ()
|
"Unsupported sanitizer type: ${san}"
|
||||||
endforeach ()
|
"Supported: address, thread, undefinedbehavior and their combinations."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
# Validate sanitizer compatibility
|
# Validate sanitizer compatibility
|
||||||
if (enable_asan AND enable_tsan)
|
if(enable_asan AND enable_tsan)
|
||||||
message(FATAL_ERROR "AddressSanitizer and ThreadSanitizer are incompatible and cannot be enabled simultaneously. "
|
message(
|
||||||
"Use 'address' or 'thread', optionally with 'undefinedbehavior'.")
|
FATAL_ERROR
|
||||||
endif ()
|
"AddressSanitizer and ThreadSanitizer are incompatible and cannot be enabled simultaneously. "
|
||||||
|
"Use 'address' or 'thread', optionally with 'undefinedbehavior'."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Frame pointer is required for meaningful stack traces. Sanitizers recommend minimum of -O1 for reasonable performance
|
# Frame pointer is required for meaningful stack traces. Sanitizers recommend minimum of -O1 for reasonable performance
|
||||||
set(SANITIZERS_COMPILE_FLAGS "-fno-omit-frame-pointer" "-O1")
|
set(SANITIZERS_COMPILE_FLAGS "-fno-omit-frame-pointer" "-O1")
|
||||||
@@ -99,66 +108,79 @@ set(SANITIZERS_COMPILE_FLAGS "-fno-omit-frame-pointer" "-O1")
|
|||||||
# Build the sanitizer flags list
|
# Build the sanitizer flags list
|
||||||
set(SANITIZER_TYPES)
|
set(SANITIZER_TYPES)
|
||||||
|
|
||||||
if (enable_asan)
|
if(enable_asan)
|
||||||
list(APPEND SANITIZER_TYPES "address")
|
list(APPEND SANITIZER_TYPES "address")
|
||||||
elseif (enable_tsan)
|
elseif(enable_tsan)
|
||||||
list(APPEND SANITIZER_TYPES "thread")
|
list(APPEND SANITIZER_TYPES "thread")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (enable_ubsan)
|
if(enable_ubsan)
|
||||||
# UB sanitizer flags
|
# UB sanitizer flags
|
||||||
list(APPEND SANITIZER_TYPES "undefined" "float-divide-by-zero")
|
list(APPEND SANITIZER_TYPES "undefined" "float-divide-by-zero")
|
||||||
if (is_clang)
|
if(is_clang)
|
||||||
# Clang supports additional UB checks. More info here
|
# Clang supports additional UB checks. More info here
|
||||||
# https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
|
# https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
|
||||||
list(APPEND SANITIZER_TYPES "unsigned-integer-overflow")
|
list(APPEND SANITIZER_TYPES "unsigned-integer-overflow")
|
||||||
endif ()
|
endif()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# Configure code model for GCC on amd64 Use large code model for ASAN to avoid relocation errors Use medium code model
|
# Configure code model for GCC on amd64 Use large code model for ASAN to avoid relocation errors Use medium code model
|
||||||
# for TSAN (large is not compatible with TSAN)
|
# for TSAN (large is not compatible with TSAN)
|
||||||
set(SANITIZERS_RELOCATION_FLAGS)
|
set(SANITIZERS_RELOCATION_FLAGS)
|
||||||
|
|
||||||
# Compiler-specific configuration
|
# Compiler-specific configuration
|
||||||
if (is_gcc)
|
if(is_gcc)
|
||||||
# Disable mold, gold and lld linkers for GCC with sanitizers Use default linker (bfd/ld) which is more lenient with
|
# Disable mold, gold and lld linkers for GCC with sanitizers Use default linker (bfd/ld) which is more lenient with
|
||||||
# mixed code models This is needed since the size of instrumented binary exceeds the limits set by mold, lld and
|
# mixed code models This is needed since the size of instrumented binary exceeds the limits set by mold, lld and
|
||||||
# gold linkers
|
# gold linkers
|
||||||
set(use_mold OFF CACHE BOOL "Use mold linker" FORCE)
|
set(use_mold OFF CACHE BOOL "Use mold linker" FORCE)
|
||||||
set(use_gold OFF CACHE BOOL "Use gold linker" FORCE)
|
set(use_gold OFF CACHE BOOL "Use gold linker" FORCE)
|
||||||
set(use_lld OFF CACHE BOOL "Use lld linker" FORCE)
|
set(use_lld OFF CACHE BOOL "Use lld linker" FORCE)
|
||||||
message(STATUS " Disabled mold, gold, and lld linkers for GCC with sanitizers")
|
message(
|
||||||
|
STATUS
|
||||||
|
" Disabled mold, gold, and lld linkers for GCC with sanitizers"
|
||||||
|
)
|
||||||
|
|
||||||
# Suppress false positive warnings in GCC with stringop-overflow
|
# Suppress false positive warnings in GCC with stringop-overflow
|
||||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-stringop-overflow")
|
list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-stringop-overflow")
|
||||||
|
|
||||||
if (is_amd64 AND enable_asan)
|
if(is_amd64 AND enable_asan)
|
||||||
message(STATUS " Using large code model (-mcmodel=large)")
|
message(STATUS " Using large code model (-mcmodel=large)")
|
||||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=large")
|
list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=large")
|
||||||
list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=large")
|
list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=large")
|
||||||
elseif (enable_tsan)
|
elseif(enable_tsan)
|
||||||
# GCC doesn't support atomic_thread_fence with tsan. Suppress warnings.
|
# GCC doesn't support atomic_thread_fence with tsan. Suppress warnings.
|
||||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-tsan")
|
list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-tsan")
|
||||||
message(STATUS " Using medium code model (-mcmodel=medium)")
|
message(STATUS " Using medium code model (-mcmodel=medium)")
|
||||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=medium")
|
list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=medium")
|
||||||
list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=medium")
|
list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=medium")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# Join sanitizer flags with commas for -fsanitize option
|
# Join sanitizer flags with commas for -fsanitize option
|
||||||
list(JOIN SANITIZER_TYPES "," SANITIZER_TYPES_STR)
|
list(JOIN SANITIZER_TYPES "," SANITIZER_TYPES_STR)
|
||||||
|
|
||||||
# Add sanitizer to compile and link flags
|
# Add sanitizer to compile and link flags
|
||||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
|
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
|
||||||
set(SANITIZERS_LINK_FLAGS "${SANITIZERS_RELOCATION_FLAGS}" "-fsanitize=${SANITIZER_TYPES_STR}")
|
set(SANITIZERS_LINK_FLAGS
|
||||||
|
"${SANITIZERS_RELOCATION_FLAGS}"
|
||||||
elseif (is_clang)
|
"-fsanitize=${SANITIZER_TYPES_STR}"
|
||||||
|
)
|
||||||
|
elseif(is_clang)
|
||||||
# Add ignorelist for Clang (GCC doesn't support this) Use CMAKE_SOURCE_DIR to get the path to the ignorelist
|
# Add ignorelist for Clang (GCC doesn't support this) Use CMAKE_SOURCE_DIR to get the path to the ignorelist
|
||||||
set(IGNORELIST_PATH "${CMAKE_SOURCE_DIR}/sanitizers/suppressions/sanitizer-ignorelist.txt")
|
set(IGNORELIST_PATH
|
||||||
if (NOT EXISTS "${IGNORELIST_PATH}")
|
"${CMAKE_SOURCE_DIR}/sanitizers/suppressions/sanitizer-ignorelist.txt"
|
||||||
message(FATAL_ERROR "Sanitizer ignorelist not found: ${IGNORELIST_PATH}")
|
)
|
||||||
endif ()
|
if(NOT EXISTS "${IGNORELIST_PATH}")
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"Sanitizer ignorelist not found: ${IGNORELIST_PATH}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize-ignorelist=${IGNORELIST_PATH}")
|
list(
|
||||||
|
APPEND SANITIZERS_COMPILE_FLAGS
|
||||||
|
"-fsanitize-ignorelist=${IGNORELIST_PATH}"
|
||||||
|
)
|
||||||
message(STATUS " Using sanitizer ignorelist: ${IGNORELIST_PATH}")
|
message(STATUS " Using sanitizer ignorelist: ${IGNORELIST_PATH}")
|
||||||
|
|
||||||
# Join sanitizer flags with commas for -fsanitize option
|
# Join sanitizer flags with commas for -fsanitize option
|
||||||
@@ -167,31 +189,35 @@ elseif (is_clang)
|
|||||||
# Add sanitizer to compile and link flags
|
# Add sanitizer to compile and link flags
|
||||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
|
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
|
||||||
set(SANITIZERS_LINK_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
|
set(SANITIZERS_LINK_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
message(STATUS " Compile flags: ${SANITIZERS_COMPILE_FLAGS}")
|
message(STATUS " Compile flags: ${SANITIZERS_COMPILE_FLAGS}")
|
||||||
message(STATUS " Link flags: ${SANITIZERS_LINK_FLAGS}")
|
message(STATUS " Link flags: ${SANITIZERS_LINK_FLAGS}")
|
||||||
|
|
||||||
# Apply the sanitizer flags to the 'common' interface library This is the same library used by XrplCompiler.cmake
|
# Apply the sanitizer flags to the 'common' interface library This is the same library used by XrplCompiler.cmake
|
||||||
target_compile_options(common INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${SANITIZERS_COMPILE_FLAGS}>
|
target_compile_options(
|
||||||
$<$<COMPILE_LANGUAGE:C>:${SANITIZERS_COMPILE_FLAGS}>)
|
common
|
||||||
|
INTERFACE
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:${SANITIZERS_COMPILE_FLAGS}>
|
||||||
|
$<$<COMPILE_LANGUAGE:C>:${SANITIZERS_COMPILE_FLAGS}>
|
||||||
|
)
|
||||||
|
|
||||||
# Apply linker flags
|
# Apply linker flags
|
||||||
target_link_options(common INTERFACE ${SANITIZERS_LINK_FLAGS})
|
target_link_options(common INTERFACE ${SANITIZERS_LINK_FLAGS})
|
||||||
|
|
||||||
# Define SANITIZERS macro for BuildInfo.cpp
|
# Define SANITIZERS macro for BuildInfo.cpp
|
||||||
set(sanitizers_list)
|
set(sanitizers_list)
|
||||||
if (enable_asan)
|
if(enable_asan)
|
||||||
list(APPEND sanitizers_list "ASAN")
|
list(APPEND sanitizers_list "ASAN")
|
||||||
endif ()
|
endif()
|
||||||
if (enable_tsan)
|
if(enable_tsan)
|
||||||
list(APPEND sanitizers_list "TSAN")
|
list(APPEND sanitizers_list "TSAN")
|
||||||
endif ()
|
endif()
|
||||||
if (enable_ubsan)
|
if(enable_ubsan)
|
||||||
list(APPEND sanitizers_list "UBSAN")
|
list(APPEND sanitizers_list "UBSAN")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (sanitizers_list)
|
if(sanitizers_list)
|
||||||
list(JOIN sanitizers_list "." sanitizers_str)
|
list(JOIN sanitizers_list "." sanitizers_str)
|
||||||
target_compile_definitions(common INTERFACE SANITIZERS=${sanitizers_str})
|
target_compile_definitions(common INTERFACE SANITIZERS=${sanitizers_str})
|
||||||
endif ()
|
endif()
|
||||||
|
|||||||
@@ -7,40 +7,56 @@ include(CompilationEnv)
|
|||||||
get_property(is_multiconfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
get_property(is_multiconfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
|
|
||||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
|
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
|
||||||
if (NOT is_multiconfig)
|
if(NOT is_multiconfig)
|
||||||
if (NOT CMAKE_BUILD_TYPE)
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
message(STATUS "Build type not specified - defaulting to Release")
|
message(STATUS "Build type not specified - defaulting to Release")
|
||||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "build type" FORCE)
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "build type" FORCE)
|
||||||
elseif (NOT (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL Release))
|
elseif(
|
||||||
|
NOT (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL Release)
|
||||||
|
)
|
||||||
# for simplicity, these are the only two config types we care about. Limiting the build types simplifies dealing
|
# for simplicity, these are the only two config types we care about. Limiting the build types simplifies dealing
|
||||||
# with external project builds especially
|
# with external project builds especially
|
||||||
message(FATAL_ERROR " *** Only Debug or Release build types are currently supported ***")
|
message(
|
||||||
endif ()
|
FATAL_ERROR
|
||||||
endif ()
|
" *** Only Debug or Release build types are currently supported ***"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (is_clang) # both Clang and AppleClang
|
if(is_clang) # both Clang and AppleClang
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS
|
if(
|
||||||
16.0)
|
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang"
|
||||||
|
AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0
|
||||||
|
)
|
||||||
message(FATAL_ERROR "This project requires clang 16 or later")
|
message(FATAL_ERROR "This project requires clang 16 or later")
|
||||||
endif ()
|
endif()
|
||||||
elseif (is_gcc)
|
elseif(is_gcc)
|
||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
|
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
|
||||||
message(FATAL_ERROR "This project requires GCC 12 or later")
|
message(FATAL_ERROR "This project requires GCC 12 or later")
|
||||||
endif ()
|
endif()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# check for in-source build and fail
|
# check for in-source build and fail
|
||||||
if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||||
message(FATAL_ERROR "Builds (in-source) are not allowed in "
|
message(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}. Please remove CMakeCache.txt and the CMakeFiles "
|
FATAL_ERROR
|
||||||
"directory from ${CMAKE_CURRENT_SOURCE_DIR} and try building in a separate directory."
|
"Builds (in-source) are not allowed in "
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}. Please remove CMakeCache.txt and the CMakeFiles "
|
||||||
|
"directory from ${CMAKE_CURRENT_SOURCE_DIR} and try building in a separate directory."
|
||||||
)
|
)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (MSVC AND CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
|
if(MSVC AND CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
|
||||||
message(FATAL_ERROR "Visual Studio 32-bit build is not supported.")
|
message(FATAL_ERROR "Visual Studio 32-bit build is not supported.")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (APPLE AND NOT HOMEBREW)
|
if(voidstar AND NOT is_amd64)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"The voidstar library only supported on amd64/x86_64. Detected archictecture was: ${CMAKE_SYSTEM_PROCESSOR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE AND NOT HOMEBREW)
|
||||||
find_program(HOMEBREW brew)
|
find_program(HOMEBREW brew)
|
||||||
endif ()
|
endif()
|
||||||
|
|||||||
@@ -5,59 +5,67 @@
|
|||||||
include(CompilationEnv)
|
include(CompilationEnv)
|
||||||
|
|
||||||
set(is_ci FALSE)
|
set(is_ci FALSE)
|
||||||
if (DEFINED ENV{CI})
|
if(DEFINED ENV{CI})
|
||||||
if ("$ENV{CI}" STREQUAL "true")
|
if("$ENV{CI}" STREQUAL "true")
|
||||||
set(is_ci TRUE)
|
set(is_ci TRUE)
|
||||||
endif ()
|
endif()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
get_directory_property(has_parent PARENT_DIRECTORY)
|
get_directory_property(has_parent PARENT_DIRECTORY)
|
||||||
if (has_parent)
|
if(has_parent)
|
||||||
set(is_root_project OFF)
|
set(is_root_project OFF)
|
||||||
else ()
|
else()
|
||||||
set(is_root_project ON)
|
set(is_root_project ON)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
option(assert "Enables asserts, even in release builds" OFF)
|
option(assert "Enables asserts, even in release builds" OFF)
|
||||||
|
|
||||||
option(xrpld "Build xrpld" ON)
|
option(xrpld "Build xrpld" ON)
|
||||||
|
|
||||||
option(tests "Build tests" ON)
|
option(tests "Build tests" ON)
|
||||||
if (tests)
|
if(tests)
|
||||||
# This setting allows making a separate workflow to test fees other than default 10
|
# This setting allows making a separate workflow to test fees other than default 10
|
||||||
if (NOT UNIT_TEST_REFERENCE_FEE)
|
if(NOT UNIT_TEST_REFERENCE_FEE)
|
||||||
set(UNIT_TEST_REFERENCE_FEE "10" CACHE STRING "")
|
set(UNIT_TEST_REFERENCE_FEE "10" CACHE STRING "")
|
||||||
endif ()
|
endif()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
option(unity "Creates a build using UNITY support in cmake." OFF)
|
option(unity "Creates a build using UNITY support in cmake." OFF)
|
||||||
if (unity)
|
if(unity)
|
||||||
if (NOT is_ci)
|
if(NOT is_ci)
|
||||||
set(CMAKE_UNITY_BUILD_BATCH_SIZE 15 CACHE STRING "")
|
set(CMAKE_UNITY_BUILD_BATCH_SIZE 15 CACHE STRING "")
|
||||||
endif ()
|
endif()
|
||||||
set(CMAKE_UNITY_BUILD ON CACHE BOOL "Do a unity build")
|
set(CMAKE_UNITY_BUILD ON CACHE BOOL "Do a unity build")
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (is_clang AND is_linux)
|
if(is_clang AND is_linux)
|
||||||
option(voidstar "Enable Antithesis instrumentation." OFF)
|
option(voidstar "Enable Antithesis instrumentation." OFF)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (is_gcc OR is_clang)
|
if(is_gcc OR is_clang)
|
||||||
include(ProcessorCount)
|
include(ProcessorCount)
|
||||||
ProcessorCount(PROCESSOR_COUNT)
|
ProcessorCount(PROCESSOR_COUNT)
|
||||||
|
|
||||||
option(coverage "Generates coverage info." OFF)
|
option(coverage "Generates coverage info." OFF)
|
||||||
option(profile "Add profiling flags" OFF)
|
option(profile "Add profiling flags" OFF)
|
||||||
set(coverage_format "html-details" CACHE STRING "Output format of the coverage report.")
|
set(coverage_format
|
||||||
set(coverage_extra_args "" CACHE STRING "Additional arguments to pass to gcovr.")
|
"html-details"
|
||||||
|
CACHE STRING
|
||||||
|
"Output format of the coverage report."
|
||||||
|
)
|
||||||
|
set(coverage_extra_args
|
||||||
|
""
|
||||||
|
CACHE STRING
|
||||||
|
"Additional arguments to pass to gcovr."
|
||||||
|
)
|
||||||
option(wextra "compile with extra gcc/clang warnings enabled" ON)
|
option(wextra "compile with extra gcc/clang warnings enabled" ON)
|
||||||
else ()
|
else()
|
||||||
set(profile OFF CACHE BOOL "gcc/clang only" FORCE)
|
set(profile OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||||
set(coverage OFF CACHE BOOL "gcc/clang only" FORCE)
|
set(coverage OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||||
set(wextra OFF CACHE BOOL "gcc/clang only" FORCE)
|
set(wextra OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (is_linux AND NOT SANITIZER)
|
if(is_linux AND NOT SANITIZER)
|
||||||
option(BUILD_SHARED_LIBS "build shared xrpl libraries" OFF)
|
option(BUILD_SHARED_LIBS "build shared xrpl libraries" OFF)
|
||||||
option(static "link protobuf, openssl, libc++, and boost statically" ON)
|
option(static "link protobuf, openssl, libc++, and boost statically" ON)
|
||||||
option(perf "Enables flags that assist with perf recording" OFF)
|
option(perf "Enables flags that assist with perf recording" OFF)
|
||||||
@@ -65,53 +73,83 @@ if (is_linux AND NOT SANITIZER)
|
|||||||
option(use_mold "enables detection of mold (binutils) linker" ON)
|
option(use_mold "enables detection of mold (binutils) linker" ON)
|
||||||
# Set a default value for the log flag based on the build type. This provides a sensible default (on for debug, off
|
# Set a default value for the log flag based on the build type. This provides a sensible default (on for debug, off
|
||||||
# for release) while still allowing the user to override it for any build.
|
# for release) while still allowing the user to override it for any build.
|
||||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
set(TRUNCATED_LOGS_DEFAULT ON)
|
set(TRUNCATED_LOGS_DEFAULT ON)
|
||||||
else ()
|
else()
|
||||||
set(TRUNCATED_LOGS_DEFAULT OFF)
|
set(TRUNCATED_LOGS_DEFAULT OFF)
|
||||||
endif ()
|
endif()
|
||||||
option(TRUNCATED_THREAD_NAME_LOGS "Show warnings about truncated thread names on Linux."
|
option(
|
||||||
${TRUNCATED_LOGS_DEFAULT})
|
TRUNCATED_THREAD_NAME_LOGS
|
||||||
if (TRUNCATED_THREAD_NAME_LOGS)
|
"Show warnings about truncated thread names on Linux."
|
||||||
|
${TRUNCATED_LOGS_DEFAULT}
|
||||||
|
)
|
||||||
|
if(TRUNCATED_THREAD_NAME_LOGS)
|
||||||
add_compile_definitions(TRUNCATED_THREAD_NAME_LOGS)
|
add_compile_definitions(TRUNCATED_THREAD_NAME_LOGS)
|
||||||
endif ()
|
endif()
|
||||||
else ()
|
else()
|
||||||
# we are not ready to allow shared-libs on windows because it would require export declarations. On macos it's more
|
# we are not ready to allow shared-libs on windows because it would require export declarations. On macos it's more
|
||||||
# feasible, but static openssl produces odd linker errors, thus we disable shared lib builds for now.
|
# feasible, but static openssl produces odd linker errors, thus we disable shared lib builds for now.
|
||||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "build shared xrpl libraries - OFF for win/macos" FORCE)
|
set(BUILD_SHARED_LIBS
|
||||||
|
OFF
|
||||||
|
CACHE BOOL
|
||||||
|
"build shared xrpl libraries - OFF for win/macos"
|
||||||
|
FORCE
|
||||||
|
)
|
||||||
set(static ON CACHE BOOL "static link, linux only. ON for WIN/macos" FORCE)
|
set(static ON CACHE BOOL "static link, linux only. ON for WIN/macos" FORCE)
|
||||||
set(perf OFF CACHE BOOL "perf flags, linux only" FORCE)
|
set(perf OFF CACHE BOOL "perf flags, linux only" FORCE)
|
||||||
set(use_gold OFF CACHE BOOL "gold linker, linux only" FORCE)
|
set(use_gold OFF CACHE BOOL "gold linker, linux only" FORCE)
|
||||||
set(use_mold OFF CACHE BOOL "mold linker, linux only" FORCE)
|
set(use_mold OFF CACHE BOOL "mold linker, linux only" FORCE)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (is_clang)
|
if(is_clang)
|
||||||
option(use_lld "enables detection of lld linker" ON)
|
option(use_lld "enables detection of lld linker" ON)
|
||||||
else ()
|
else()
|
||||||
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
|
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
option(jemalloc "Enables jemalloc for heap profiling" OFF)
|
option(jemalloc "Enables jemalloc for heap profiling" OFF)
|
||||||
option(werr "treat warnings as errors" OFF)
|
option(werr "treat warnings as errors" OFF)
|
||||||
option(local_protobuf
|
option(
|
||||||
"Force a local build of protobuf instead of looking for an installed version." OFF)
|
local_protobuf
|
||||||
option(local_grpc "Force a local build of gRPC instead of looking for an installed version." OFF)
|
"Force a local build of protobuf instead of looking for an installed version."
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
local_grpc
|
||||||
|
"Force a local build of gRPC instead of looking for an installed version."
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
|
||||||
# the remaining options are obscure and rarely used
|
# the remaining options are obscure and rarely used
|
||||||
option(beast_no_unit_test_inline
|
option(
|
||||||
"Prevents unit test definitions from being inserted into global table" OFF)
|
beast_no_unit_test_inline
|
||||||
option(single_io_service_thread "Restricts the number of threads calling io_context::run to one. \
|
"Prevents unit test definitions from being inserted into global table"
|
||||||
This can be useful when debugging." OFF)
|
OFF
|
||||||
option(boost_show_deprecated "Allow boost to fail on deprecated usage. Only useful if you're trying\
|
)
|
||||||
to find deprecated calls." OFF)
|
option(
|
||||||
|
single_io_service_thread
|
||||||
|
"Restricts the number of threads calling io_context::run to one. \
|
||||||
|
This can be useful when debugging."
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
boost_show_deprecated
|
||||||
|
"Allow boost to fail on deprecated usage. Only useful if you're trying\
|
||||||
|
to find deprecated calls."
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if(WIN32)
|
||||||
option(beast_disable_autolink "Disables autolinking of system libraries on WIN32" OFF)
|
option(
|
||||||
else ()
|
beast_disable_autolink
|
||||||
|
"Disables autolinking of system libraries on WIN32"
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
else()
|
||||||
set(beast_disable_autolink OFF CACHE BOOL "WIN32 only" FORCE)
|
set(beast_disable_autolink OFF CACHE BOOL "WIN32 only" FORCE)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (coverage)
|
if(coverage)
|
||||||
message(STATUS "coverage build requested - forcing Debug build")
|
message(STATUS "coverage build requested - forcing Debug build")
|
||||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
|
||||||
endif ()
|
endif()
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
option(validator_keys
|
option(
|
||||||
"Enables building of validator-keys tool as a separate target (imported via FetchContent)"
|
validator_keys
|
||||||
OFF)
|
"Enables building of validator-keys tool as a separate target (imported via FetchContent)"
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
|
||||||
if (validator_keys)
|
if(validator_keys)
|
||||||
git_branch(current_branch)
|
git_branch(current_branch)
|
||||||
# default to tracking VK master branch unless we are on release
|
# default to tracking VK master branch unless we are on release
|
||||||
if (NOT (current_branch STREQUAL "release"))
|
if(NOT (current_branch STREQUAL "release"))
|
||||||
set(current_branch "master")
|
set(current_branch "master")
|
||||||
endif ()
|
endif()
|
||||||
message(STATUS "Tracking ValidatorKeys branch: ${current_branch}")
|
message(STATUS "Tracking ValidatorKeys branch: ${current_branch}")
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
validator_keys GIT_REPOSITORY https://github.com/ripple/validator-keys-tool.git
|
validator_keys
|
||||||
GIT_TAG "${current_branch}")
|
GIT_REPOSITORY https://github.com/ripple/validator-keys-tool.git
|
||||||
|
GIT_TAG "${current_branch}"
|
||||||
|
)
|
||||||
FetchContent_MakeAvailable(validator_keys)
|
FetchContent_MakeAvailable(validator_keys)
|
||||||
set_target_properties(validator-keys PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
set_target_properties(
|
||||||
|
validator-keys
|
||||||
|
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
|
)
|
||||||
install(TARGETS validator-keys RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install(TARGETS validator-keys RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
endif ()
|
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
#]===================================================================]
|
#]===================================================================]
|
||||||
|
|
||||||
file(STRINGS src/libxrpl/protocol/BuildInfo.cpp BUILD_INFO)
|
file(STRINGS src/libxrpl/protocol/BuildInfo.cpp BUILD_INFO)
|
||||||
foreach (line_ ${BUILD_INFO})
|
foreach(line_ ${BUILD_INFO})
|
||||||
if (line_ MATCHES "versionString[ ]*=[ ]*\"(.+)\"")
|
if(line_ MATCHES "versionString[ ]*=[ ]*\"(.+)\"")
|
||||||
set(xrpld_version ${CMAKE_MATCH_1})
|
set(xrpld_version ${CMAKE_MATCH_1})
|
||||||
endif ()
|
endif()
|
||||||
endforeach ()
|
endforeach()
|
||||||
if (xrpld_version)
|
if(xrpld_version)
|
||||||
message(STATUS "xrpld version: ${xrpld_version}")
|
message(STATUS "xrpld version: ${xrpld_version}")
|
||||||
else ()
|
else()
|
||||||
message(FATAL_ERROR "unable to determine xrpld version")
|
message(FATAL_ERROR "unable to determine xrpld version")
|
||||||
endif ()
|
endif()
|
||||||
|
|||||||
@@ -12,15 +12,29 @@ include(isolate_headers)
|
|||||||
# add_module(parent a)
|
# add_module(parent a)
|
||||||
# add_module(parent b)
|
# add_module(parent b)
|
||||||
# target_link_libraries(project.libparent.b PUBLIC project.libparent.a)
|
# target_link_libraries(project.libparent.b PUBLIC project.libparent.a)
|
||||||
function (add_module parent name)
|
function(add_module parent name)
|
||||||
set(target ${PROJECT_NAME}.lib${parent}.${name})
|
set(target ${PROJECT_NAME}.lib${parent}.${name})
|
||||||
add_library(${target} OBJECT)
|
add_library(${target} OBJECT)
|
||||||
file(GLOB_RECURSE sources CONFIGURE_DEPENDS
|
file(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}/*.cpp")
|
GLOB_RECURSE sources
|
||||||
|
CONFIGURE_DEPENDS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}/*.cpp"
|
||||||
|
)
|
||||||
target_sources(${target} PRIVATE ${sources})
|
target_sources(${target} PRIVATE ${sources})
|
||||||
target_include_directories(${target} PUBLIC "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
target_include_directories(
|
||||||
isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
${target}
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/${parent}/${name}" PUBLIC)
|
PUBLIC "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||||
isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/src"
|
)
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}" PRIVATE)
|
isolate_headers(
|
||||||
endfunction ()
|
${target}
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/${parent}/${name}"
|
||||||
|
PUBLIC
|
||||||
|
)
|
||||||
|
isolate_headers(
|
||||||
|
${target}
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}"
|
||||||
|
PRIVATE
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
# file(CREATE_SYMLINK) only works on Windows with administrator privileges. https://stackoverflow.com/a/61244115/618906
|
# file(CREATE_SYMLINK) only works on Windows with administrator privileges. https://stackoverflow.com/a/61244115/618906
|
||||||
function (create_symbolic_link target link)
|
function(create_symbolic_link target link)
|
||||||
if (WIN32)
|
if(WIN32)
|
||||||
if (NOT IS_SYMLINK "${link}")
|
if(NOT IS_SYMLINK "${link}")
|
||||||
if (NOT IS_ABSOLUTE "${target}")
|
if(NOT IS_ABSOLUTE "${target}")
|
||||||
# Relative links work do not work on Windows.
|
# Relative links work do not work on Windows.
|
||||||
set(target "${link}/../${target}")
|
set(target "${link}/../${target}")
|
||||||
endif ()
|
endif()
|
||||||
file(TO_NATIVE_PATH "${target}" target)
|
file(TO_NATIVE_PATH "${target}" target)
|
||||||
file(TO_NATIVE_PATH "${link}" link)
|
file(TO_NATIVE_PATH "${link}" link)
|
||||||
execute_process(COMMAND cmd.exe /c mklink /J "${link}" "${target}")
|
execute_process(
|
||||||
endif ()
|
COMMAND cmd.exe /c mklink /J "${link}" "${target}"
|
||||||
else ()
|
)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
file(CREATE_LINK "${target}" "${link}" SYMBOLIC)
|
file(CREATE_LINK "${target}" "${link}" SYMBOLIC)
|
||||||
endif ()
|
endif()
|
||||||
if (NOT IS_SYMLINK "${link}")
|
if(NOT IS_SYMLINK "${link}")
|
||||||
message(ERROR "failed to create symlink: <${link}>")
|
message(ERROR "failed to create symlink: <${link}>")
|
||||||
endif ()
|
endif()
|
||||||
endfunction ()
|
endfunction()
|
||||||
|
|||||||
@@ -1,45 +1,63 @@
|
|||||||
include(CompilationEnv)
|
include(CompilationEnv)
|
||||||
include(XrplSanitizers)
|
include(XrplSanitizers)
|
||||||
|
|
||||||
find_package(Boost REQUIRED
|
find_package(
|
||||||
COMPONENTS chrono
|
Boost
|
||||||
container
|
REQUIRED
|
||||||
coroutine
|
COMPONENTS
|
||||||
date_time
|
chrono
|
||||||
filesystem
|
container
|
||||||
json
|
context
|
||||||
program_options
|
date_time
|
||||||
regex
|
filesystem
|
||||||
system
|
json
|
||||||
thread)
|
program_options
|
||||||
|
regex
|
||||||
|
system
|
||||||
|
thread
|
||||||
|
)
|
||||||
|
|
||||||
add_library(xrpl_boost INTERFACE)
|
add_library(xrpl_boost INTERFACE)
|
||||||
add_library(Xrpl::boost ALIAS xrpl_boost)
|
add_library(Xrpl::boost ALIAS xrpl_boost)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
xrpl_boost
|
xrpl_boost
|
||||||
INTERFACE Boost::headers
|
INTERFACE
|
||||||
Boost::chrono
|
Boost::headers
|
||||||
Boost::container
|
Boost::chrono
|
||||||
Boost::coroutine
|
Boost::container
|
||||||
Boost::date_time
|
Boost::context
|
||||||
Boost::filesystem
|
Boost::date_time
|
||||||
Boost::json
|
Boost::filesystem
|
||||||
Boost::process
|
Boost::json
|
||||||
Boost::program_options
|
Boost::process
|
||||||
Boost::regex
|
Boost::program_options
|
||||||
Boost::thread)
|
Boost::regex
|
||||||
if (Boost_COMPILER)
|
Boost::thread
|
||||||
|
)
|
||||||
|
if(Boost_COMPILER)
|
||||||
target_link_libraries(xrpl_boost INTERFACE Boost::disable_autolinking)
|
target_link_libraries(xrpl_boost INTERFACE Boost::disable_autolinking)
|
||||||
endif ()
|
endif()
|
||||||
if (SANITIZERS_ENABLED AND is_clang)
|
|
||||||
# TODO: gcc does not support -fsanitize-blacklist...can we do something else for gcc ?
|
# GCC 14+ has a false positive -Wuninitialized warning in Boost.Coroutine2's
|
||||||
if (NOT Boost_INCLUDE_DIRS AND TARGET Boost::headers)
|
# state.hpp when compiled with -O3. This is due to GCC's intentional behavior
|
||||||
get_target_property(Boost_INCLUDE_DIRS Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
|
# change (Bug #98871, #119388) where warnings from inlined system header code
|
||||||
endif ()
|
# are no longer suppressed by -isystem. The warning occurs in operator|= in
|
||||||
message(STATUS "Adding [${Boost_INCLUDE_DIRS}] to sanitizer blacklist")
|
# boost/coroutine2/detail/state.hpp when inlined from push_control_block::destroy().
|
||||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt "src:${Boost_INCLUDE_DIRS}/*")
|
# See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119388
|
||||||
target_compile_options(
|
if(is_gcc AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14)
|
||||||
opts INTERFACE # ignore boost headers for sanitizing
|
target_compile_options(xrpl_boost INTERFACE -Wno-uninitialized)
|
||||||
-fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt)
|
endif()
|
||||||
endif ()
|
|
||||||
|
# Boost.Context's ucontext backend has ASAN fiber-switching annotations
|
||||||
|
# (start/finish_switch_fiber) that are compiled in when BOOST_USE_ASAN is defined.
|
||||||
|
# This tells ASAN about coroutine stack switches, preventing false positive
|
||||||
|
# stack-use-after-scope errors. BOOST_USE_UCONTEXT ensures the ucontext backend
|
||||||
|
# is selected (fcontext does not support ASAN annotations).
|
||||||
|
# These defines must match what Boost was compiled with (see conan/profiles/sanitizers).
|
||||||
|
if(enable_asan)
|
||||||
|
target_compile_definitions(
|
||||||
|
xrpl_boost
|
||||||
|
INTERFACE BOOST_USE_ASAN BOOST_USE_UCONTEXT
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ include(create_symbolic_link)
|
|||||||
# `${CMAKE_CURRENT_BINARY_DIR}/include/${target}`.
|
# `${CMAKE_CURRENT_BINARY_DIR}/include/${target}`.
|
||||||
#
|
#
|
||||||
# isolate_headers(target A B scope)
|
# isolate_headers(target A B scope)
|
||||||
function (isolate_headers target A B scope)
|
function(isolate_headers target A B scope)
|
||||||
file(RELATIVE_PATH C "${A}" "${B}")
|
file(RELATIVE_PATH C "${A}" "${B}")
|
||||||
set(X "${CMAKE_CURRENT_BINARY_DIR}/modules/${target}")
|
set(X "${CMAKE_CURRENT_BINARY_DIR}/modules/${target}")
|
||||||
set(Y "${X}/${C}")
|
set(Y "${X}/${C}")
|
||||||
@@ -45,4 +45,4 @@ function (isolate_headers target A B scope)
|
|||||||
file(MAKE_DIRECTORY "${parent}")
|
file(MAKE_DIRECTORY "${parent}")
|
||||||
create_symbolic_link("${B}" "${Y}")
|
create_symbolic_link("${B}" "${Y}")
|
||||||
target_include_directories(${target} ${scope} "$<BUILD_INTERFACE:${X}>")
|
target_include_directories(${target} ${scope} "$<BUILD_INTERFACE:${X}>")
|
||||||
endfunction ()
|
endfunction()
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
# target_link_libraries(project.libparent.b PUBLIC project.libparent.a)
|
# target_link_libraries(project.libparent.b PUBLIC project.libparent.a)
|
||||||
# add_library(project.libparent)
|
# add_library(project.libparent)
|
||||||
# target_link_modules(parent PUBLIC a b)
|
# target_link_modules(parent PUBLIC a b)
|
||||||
function (target_link_modules parent scope)
|
function(target_link_modules parent scope)
|
||||||
set(library ${PROJECT_NAME}.lib${parent})
|
set(library ${PROJECT_NAME}.lib${parent})
|
||||||
foreach (name ${ARGN})
|
foreach(name ${ARGN})
|
||||||
set(module ${library}.${name})
|
set(module ${library}.${name})
|
||||||
get_target_property(sources ${library} SOURCES)
|
get_target_property(sources ${library} SOURCES)
|
||||||
list(LENGTH sources before)
|
list(LENGTH sources before)
|
||||||
@@ -17,8 +17,11 @@ function (target_link_modules parent scope)
|
|||||||
list(REMOVE_ITEM sources ${dupes})
|
list(REMOVE_ITEM sources ${dupes})
|
||||||
list(LENGTH sources after)
|
list(LENGTH sources after)
|
||||||
math(EXPR actual "${before} - ${after}")
|
math(EXPR actual "${before} - ${after}")
|
||||||
message(STATUS "${module} with ${expected} sources took ${actual} sources from ${library}")
|
message(
|
||||||
|
STATUS
|
||||||
|
"${module} with ${expected} sources took ${actual} sources from ${library}"
|
||||||
|
)
|
||||||
set_target_properties(${library} PROPERTIES SOURCES "${sources}")
|
set_target_properties(${library} PROPERTIES SOURCES "${sources}")
|
||||||
target_link_libraries(${library} ${scope} ${module})
|
target_link_libraries(${library} ${scope} ${module})
|
||||||
endforeach ()
|
endforeach()
|
||||||
endfunction ()
|
endfunction()
|
||||||
|
|||||||
@@ -35,20 +35,31 @@ find_package(Protobuf REQUIRED)
|
|||||||
# This prefix should appear at the start of all your consumer includes.
|
# This prefix should appear at the start of all your consumer includes.
|
||||||
# ARGN:
|
# ARGN:
|
||||||
# A list of .proto files.
|
# A list of .proto files.
|
||||||
function (target_protobuf_sources target prefix)
|
function(target_protobuf_sources target prefix)
|
||||||
set(dir "${CMAKE_CURRENT_BINARY_DIR}/pb-${target}")
|
set(dir "${CMAKE_CURRENT_BINARY_DIR}/pb-${target}")
|
||||||
file(MAKE_DIRECTORY "${dir}/${prefix}")
|
file(MAKE_DIRECTORY "${dir}/${prefix}")
|
||||||
|
|
||||||
protobuf_generate(TARGET ${target} PROTOC_OUT_DIR "${dir}/${prefix}" "${ARGN}")
|
protobuf_generate(
|
||||||
|
TARGET ${target}
|
||||||
|
PROTOC_OUT_DIR "${dir}/${prefix}"
|
||||||
|
"${ARGN}"
|
||||||
|
)
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
${target} SYSTEM
|
${target}
|
||||||
|
SYSTEM
|
||||||
PUBLIC # Allows #include <package/path/to/file.proto> used by consumer files.
|
PUBLIC # Allows #include <package/path/to/file.proto> used by consumer files.
|
||||||
$<BUILD_INTERFACE:${dir}>
|
$<BUILD_INTERFACE:${dir}>
|
||||||
# Allows #include "path/to/file.proto" used by generated files.
|
# Allows #include "path/to/file.proto" used by generated files.
|
||||||
$<BUILD_INTERFACE:${dir}/${prefix}>
|
$<BUILD_INTERFACE:${dir}/${prefix}>
|
||||||
# Allows #include <package/path/to/file.proto> used by consumer files.
|
# Allows #include <package/path/to/file.proto> used by consumer files.
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
# Allows #include "path/to/file.proto" used by generated files.
|
# Allows #include "path/to/file.proto" used by generated files.
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${prefix}>)
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${prefix}>
|
||||||
install(DIRECTORY ${dir}/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h")
|
)
|
||||||
endfunction ()
|
install(
|
||||||
|
DIRECTORY ${dir}/
|
||||||
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.h"
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|||||||
45
conan.lock
45
conan.lock
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"version": "0.5",
|
"version": "0.5",
|
||||||
"requires": [
|
"requires": [
|
||||||
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
|
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
|
||||||
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
|
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
|
||||||
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926",
|
"sqlite3/3.51.0#66aa11eabd0e34954c5c1c061ad44abe%1763899256.358",
|
||||||
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1765850149.46",
|
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
|
||||||
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
|
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
|
||||||
"secp256k1/0.7.1#3a61e95e220062ef32c48d019e9c81f7%1770306721.686",
|
"secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
|
||||||
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
|
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
|
||||||
"re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103",
|
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1774398111.888",
|
||||||
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038",
|
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1773224203.27",
|
||||||
"openssl/3.5.5#05a4ac5b7323f7a329b2db1391d9941f%1769599205.414",
|
"openssl/3.6.1#e6399de266349245a4542fc5f6c71552%1774458290.139",
|
||||||
"nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32",
|
"nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32",
|
||||||
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
|
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
|
||||||
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
|
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
|
||||||
@@ -18,27 +18,26 @@
|
|||||||
"libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736",
|
"libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736",
|
||||||
"jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244",
|
"jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244",
|
||||||
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
|
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
|
||||||
"grpc/1.72.0#f244a57bff01e708c55a1100b12e1589%1765850193.734",
|
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1772623605.068",
|
||||||
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
|
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
|
||||||
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
|
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
|
||||||
"c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336",
|
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
|
||||||
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
|
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
|
||||||
"boost/1.90.0#d5e8defe7355494953be18524a7f135b%1769454080.269",
|
"boost/1.90.0#d5e8defe7355494953be18524a7f135b%1769454080.269",
|
||||||
"abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993"
|
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
|
||||||
],
|
],
|
||||||
"build_requires": [
|
"build_requires": [
|
||||||
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
|
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
|
||||||
"strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1765850165.196",
|
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964",
|
||||||
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038",
|
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1773224203.27",
|
||||||
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
|
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
|
||||||
"msys2/cci.latest#eea83308ad7e9023f7318c60d5a9e6cb%1770199879.083",
|
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
|
||||||
"m4/1.4.19#70dc8bbb33e981d119d2acc0175cf381%1763158052.846",
|
"m4/1.4.19#5d7a4994e5875d76faf7acf3ed056036%1774365463.87",
|
||||||
"cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1765850153.937",
|
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
|
||||||
"cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479",
|
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
|
||||||
"b2/5.3.3#107c15377719889654eb9a162a673975%1765850144.355",
|
|
||||||
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
|
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
|
||||||
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
|
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
|
||||||
"abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993"
|
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
|
||||||
],
|
],
|
||||||
"python_requires": [],
|
"python_requires": [],
|
||||||
"overrides": {
|
"overrides": {
|
||||||
@@ -46,14 +45,14 @@
|
|||||||
null,
|
null,
|
||||||
"boost/1.90.0"
|
"boost/1.90.0"
|
||||||
],
|
],
|
||||||
"protobuf/5.27.0": [
|
"protobuf/[>=5.27.0 <7]": [
|
||||||
"protobuf/6.32.1"
|
"protobuf/6.33.5"
|
||||||
],
|
],
|
||||||
"lz4/1.9.4": [
|
"lz4/1.9.4": [
|
||||||
"lz4/1.10.0"
|
"lz4/1.10.0"
|
||||||
],
|
],
|
||||||
"sqlite3/3.44.2": [
|
"sqlite3/[>=3.44 <4]": [
|
||||||
"sqlite3/3.49.1"
|
"sqlite3/3.51.0"
|
||||||
],
|
],
|
||||||
"boost/1.83.0": [
|
"boost/1.83.0": [
|
||||||
"boost/1.90.0"
|
"boost/1.90.0"
|
||||||
|
|||||||
@@ -7,16 +7,21 @@ include(default)
|
|||||||
{% if compiler == "gcc" %}
|
{% if compiler == "gcc" %}
|
||||||
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
|
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
|
||||||
{% set sanitizer_list = [] %}
|
{% set sanitizer_list = [] %}
|
||||||
|
{% set defines = [] %}
|
||||||
{% set model_code = "" %}
|
{% set model_code = "" %}
|
||||||
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1", "-Wno-stringop-overflow"] %}
|
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1", "-Wno-stringop-overflow"] %}
|
||||||
|
|
||||||
{% if "address" in sanitizers %}
|
{% if "address" in sanitizers %}
|
||||||
{% set _ = sanitizer_list.append("address") %}
|
{% set _ = sanitizer_list.append("address") %}
|
||||||
{% set model_code = "-mcmodel=large" %}
|
{% set model_code = "-mcmodel=large" %}
|
||||||
|
{% set _ = defines.append("BOOST_USE_ASAN")%}
|
||||||
|
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||||
{% elif "thread" in sanitizers %}
|
{% elif "thread" in sanitizers %}
|
||||||
{% set _ = sanitizer_list.append("thread") %}
|
{% set _ = sanitizer_list.append("thread") %}
|
||||||
{% set model_code = "-mcmodel=medium" %}
|
{% set model_code = "-mcmodel=medium" %}
|
||||||
{% set _ = extra_cxxflags.append("-Wno-tsan") %}
|
{% set _ = extra_cxxflags.append("-Wno-tsan") %}
|
||||||
|
{% set _ = defines.append("BOOST_USE_TSAN")%}
|
||||||
|
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if "undefinedbehavior" in sanitizers %}
|
{% if "undefinedbehavior" in sanitizers %}
|
||||||
@@ -29,16 +34,22 @@ include(default)
|
|||||||
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
|
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
|
||||||
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
|
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
|
||||||
tools.build:exelinkflags+=['{{sanitizer_flags}}']
|
tools.build:exelinkflags+=['{{sanitizer_flags}}']
|
||||||
|
tools.build:defines+={{defines}}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% elif compiler == "apple-clang" or compiler == "clang" %}
|
{% elif compiler == "apple-clang" or compiler == "clang" %}
|
||||||
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
|
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
|
||||||
{% set sanitizer_list = [] %}
|
{% set sanitizer_list = [] %}
|
||||||
|
{% set defines = [] %}
|
||||||
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1"] %}
|
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1"] %}
|
||||||
|
|
||||||
{% if "address" in sanitizers %}
|
{% if "address" in sanitizers %}
|
||||||
{% set _ = sanitizer_list.append("address") %}
|
{% set _ = sanitizer_list.append("address") %}
|
||||||
|
{% set _ = defines.append("BOOST_USE_ASAN")%}
|
||||||
|
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||||
{% elif "thread" in sanitizers %}
|
{% elif "thread" in sanitizers %}
|
||||||
{% set _ = sanitizer_list.append("thread") %}
|
{% set _ = sanitizer_list.append("thread") %}
|
||||||
|
{% set _ = defines.append("BOOST_USE_TSAN")%}
|
||||||
|
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if "undefinedbehavior" in sanitizers %}
|
{% if "undefinedbehavior" in sanitizers %}
|
||||||
@@ -52,8 +63,24 @@ include(default)
|
|||||||
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
|
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
|
||||||
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
|
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
|
||||||
tools.build:exelinkflags+=['{{sanitizer_flags}}']
|
tools.build:exelinkflags+=['{{sanitizer_flags}}']
|
||||||
|
tools.build:defines+={{defines}}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"]
|
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]
|
||||||
|
|
||||||
|
[options]
|
||||||
|
{% if sanitizers %}
|
||||||
|
{% if "address" in sanitizers %}
|
||||||
|
# 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
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|||||||
33
conanfile.py
33
conanfile.py
@@ -1,9 +1,9 @@
|
|||||||
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
|
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
|
||||||
|
|
||||||
from conan import ConanFile
|
from conan import ConanFile
|
||||||
from conan import __version__ as conan_version
|
|
||||||
|
|
||||||
|
|
||||||
class Xrpl(ConanFile):
|
class Xrpl(ConanFile):
|
||||||
@@ -29,10 +29,10 @@ class Xrpl(ConanFile):
|
|||||||
|
|
||||||
requires = [
|
requires = [
|
||||||
"ed25519/2015.03",
|
"ed25519/2015.03",
|
||||||
"grpc/1.72.0",
|
"grpc/1.78.1",
|
||||||
"libarchive/3.8.1",
|
"libarchive/3.8.1",
|
||||||
"nudb/2.0.9",
|
"nudb/2.0.9",
|
||||||
"openssl/3.5.5",
|
"openssl/3.6.1",
|
||||||
"secp256k1/0.7.1",
|
"secp256k1/0.7.1",
|
||||||
"soci/4.0.3",
|
"soci/4.0.3",
|
||||||
"zlib/1.3.1",
|
"zlib/1.3.1",
|
||||||
@@ -43,7 +43,7 @@ class Xrpl(ConanFile):
|
|||||||
]
|
]
|
||||||
|
|
||||||
tool_requires = [
|
tool_requires = [
|
||||||
"protobuf/6.32.1",
|
"protobuf/6.33.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
default_options = {
|
default_options = {
|
||||||
@@ -57,6 +57,9 @@ class Xrpl(ConanFile):
|
|||||||
"tests": False,
|
"tests": False,
|
||||||
"unity": False,
|
"unity": False,
|
||||||
"xrpld": False,
|
"xrpld": False,
|
||||||
|
"boost/*:without_context": False,
|
||||||
|
"boost/*:without_coroutine": True,
|
||||||
|
"boost/*:without_coroutine2": False,
|
||||||
"date/*:header_only": True,
|
"date/*:header_only": True,
|
||||||
"ed25519/*:shared": False,
|
"ed25519/*:shared": False,
|
||||||
"grpc/*:shared": False,
|
"grpc/*:shared": False,
|
||||||
@@ -126,21 +129,23 @@ class Xrpl(ConanFile):
|
|||||||
if self.settings.compiler in ["clang", "gcc"]:
|
if self.settings.compiler in ["clang", "gcc"]:
|
||||||
self.options["boost"].without_cobalt = True
|
self.options["boost"].without_cobalt = True
|
||||||
|
|
||||||
|
# Check if environment variable exists
|
||||||
|
if "SANITIZERS" in os.environ:
|
||||||
|
sanitizers = os.environ["SANITIZERS"]
|
||||||
|
if "address" in sanitizers.lower():
|
||||||
|
self.default_options["fPIC"] = False
|
||||||
|
|
||||||
def requirements(self):
|
def requirements(self):
|
||||||
# Conan 2 requires transitive headers to be specified
|
self.requires("boost/1.90.0", force=True, transitive_headers=True)
|
||||||
transitive_headers_opt = (
|
self.requires("date/3.0.4", transitive_headers=True)
|
||||||
{"transitive_headers": True} if conan_version.split(".")[0] == "2" else {}
|
|
||||||
)
|
|
||||||
self.requires("boost/1.90.0", force=True, **transitive_headers_opt)
|
|
||||||
self.requires("date/3.0.4", **transitive_headers_opt)
|
|
||||||
self.requires("lz4/1.10.0", force=True)
|
self.requires("lz4/1.10.0", force=True)
|
||||||
self.requires("protobuf/6.32.1", force=True)
|
self.requires("protobuf/6.33.5", force=True)
|
||||||
self.requires("sqlite3/3.49.1", force=True)
|
self.requires("sqlite3/3.51.0", force=True)
|
||||||
if self.options.jemalloc:
|
if self.options.jemalloc:
|
||||||
self.requires("jemalloc/5.3.0")
|
self.requires("jemalloc/5.3.0")
|
||||||
if self.options.rocksdb:
|
if self.options.rocksdb:
|
||||||
self.requires("rocksdb/10.5.1")
|
self.requires("rocksdb/10.5.1")
|
||||||
self.requires("xxhash/0.8.3", **transitive_headers_opt)
|
self.requires("xxhash/0.8.3", transitive_headers=True)
|
||||||
|
|
||||||
exports_sources = (
|
exports_sources = (
|
||||||
"CMakeLists.txt",
|
"CMakeLists.txt",
|
||||||
@@ -196,7 +201,7 @@ class Xrpl(ConanFile):
|
|||||||
"boost::headers",
|
"boost::headers",
|
||||||
"boost::chrono",
|
"boost::chrono",
|
||||||
"boost::container",
|
"boost::container",
|
||||||
"boost::coroutine",
|
"boost::context",
|
||||||
"boost::date_time",
|
"boost::date_time",
|
||||||
"boost::filesystem",
|
"boost::filesystem",
|
||||||
"boost::json",
|
"boost::json",
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ words:
|
|||||||
- endmacro
|
- endmacro
|
||||||
- exceptioned
|
- exceptioned
|
||||||
- Falco
|
- Falco
|
||||||
|
- fcontext
|
||||||
- finalizers
|
- finalizers
|
||||||
- firewalled
|
- firewalled
|
||||||
- fmtdur
|
- fmtdur
|
||||||
@@ -111,6 +112,7 @@ words:
|
|||||||
- gpgcheck
|
- gpgcheck
|
||||||
- gpgkey
|
- gpgkey
|
||||||
- hotwallet
|
- hotwallet
|
||||||
|
- hwaddress
|
||||||
- hwrap
|
- hwrap
|
||||||
- ifndef
|
- ifndef
|
||||||
- inequation
|
- inequation
|
||||||
@@ -176,6 +178,8 @@ words:
|
|||||||
- nixfmt
|
- nixfmt
|
||||||
- nixos
|
- nixos
|
||||||
- nixpkgs
|
- nixpkgs
|
||||||
|
- NOLINT
|
||||||
|
- NOLINTNEXTLINE
|
||||||
- nonxrp
|
- nonxrp
|
||||||
- noripple
|
- noripple
|
||||||
- nudb
|
- nudb
|
||||||
@@ -202,6 +206,7 @@ words:
|
|||||||
- ptrs
|
- ptrs
|
||||||
- pushd
|
- pushd
|
||||||
- pyenv
|
- pyenv
|
||||||
|
- pyparsing
|
||||||
- qalloc
|
- qalloc
|
||||||
- queuable
|
- queuable
|
||||||
- Raphson
|
- Raphson
|
||||||
@@ -227,6 +232,7 @@ words:
|
|||||||
- seqit
|
- seqit
|
||||||
- sf
|
- sf
|
||||||
- SFIELD
|
- SFIELD
|
||||||
|
- sfields
|
||||||
- shamap
|
- shamap
|
||||||
- shamapitem
|
- shamapitem
|
||||||
- sidechain
|
- sidechain
|
||||||
@@ -291,6 +297,7 @@ words:
|
|||||||
- venv
|
- venv
|
||||||
- vfalco
|
- vfalco
|
||||||
- vinnie
|
- vinnie
|
||||||
|
- wasmi
|
||||||
- wextra
|
- wextra
|
||||||
- wptr
|
- wptr
|
||||||
- writeme
|
- writeme
|
||||||
|
|||||||
29
docs/build/environment.md
vendored
29
docs/build/environment.md
vendored
@@ -109,3 +109,32 @@ Install CMake with Homebrew too:
|
|||||||
```
|
```
|
||||||
brew install cmake
|
brew install cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Clang-tidy
|
||||||
|
|
||||||
|
Clang-tidy is required to run static analysis checks locally (see [CONTRIBUTING.md](../../CONTRIBUTING.md)).
|
||||||
|
It is not required to build the project. Currently this project uses clang-tidy version 21.
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
LLVM 21 is not available in the default Debian 12 (Bookworm) repositories.
|
||||||
|
Install it using the official LLVM apt installer:
|
||||||
|
|
||||||
|
```
|
||||||
|
wget https://apt.llvm.org/llvm.sh
|
||||||
|
chmod +x llvm.sh
|
||||||
|
sudo ./llvm.sh 21
|
||||||
|
sudo apt install --yes clang-tidy-21
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use `run-clang-tidy-21` when running clang-tidy locally.
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
Install LLVM 21 via Homebrew:
|
||||||
|
|
||||||
|
```
|
||||||
|
brew install llvm@21
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use `run-clang-tidy` from the LLVM 21 Homebrew prefix when running clang-tidy locally.
|
||||||
|
|||||||
8
docs/build/sanitizers.md
vendored
8
docs/build/sanitizers.md
vendored
@@ -89,8 +89,8 @@ cmake --build . --parallel 4
|
|||||||
**IMPORTANT**: ASAN with Boost produces many false positives. Use these options:
|
**IMPORTANT**: ASAN with Boost produces many false positives. Use these options:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export ASAN_OPTIONS="print_stacktrace=1:detect_container_overflow=0:suppressions=path/to/asan.supp:halt_on_error=0:log_path=asan.log"
|
export ASAN_OPTIONS="include=sanitizers/suppressions/runtime-asan-options.txt:suppressions=sanitizers/suppressions/asan.supp"
|
||||||
export LSAN_OPTIONS="suppressions=path/to/lsan.supp:halt_on_error=0:log_path=lsan.log"
|
export LSAN_OPTIONS="include=sanitizers/suppressions/runtime-lsan-options.txt:suppressions=sanitizers/suppressions/lsan.supp"
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
./xrpld --unittest --unittest-jobs=5
|
./xrpld --unittest --unittest-jobs=5
|
||||||
@@ -108,7 +108,7 @@ export LSAN_OPTIONS="suppressions=path/to/lsan.supp:halt_on_error=0:log_path=lsa
|
|||||||
### ThreadSanitizer (TSan)
|
### ThreadSanitizer (TSan)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export TSAN_OPTIONS="suppressions=path/to/tsan.supp halt_on_error=0 log_path=tsan.log"
|
export TSAN_OPTIONS="include=sanitizers/suppressions/runtime-tsan-options.txt:suppressions=sanitizers/suppressions/tsan.supp"
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
./xrpld --unittest --unittest-jobs=5
|
./xrpld --unittest --unittest-jobs=5
|
||||||
@@ -129,7 +129,7 @@ More details [here](https://github.com/google/sanitizers/wiki/AddressSanitizerLe
|
|||||||
### UndefinedBehaviorSanitizer (UBSan)
|
### UndefinedBehaviorSanitizer (UBSan)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export UBSAN_OPTIONS="suppressions=path/to/ubsan.supp:print_stacktrace=1:halt_on_error=0:log_path=ubsan.log"
|
export UBSAN_OPTIONS="include=sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=sanitizers/suppressions/ubsan.supp"
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
./xrpld --unittest --unittest-jobs=5
|
./xrpld --unittest --unittest-jobs=5
|
||||||
|
|||||||
155
include/xrpl/basics/Mutex.hpp
Normal file
155
include/xrpl/basics/Mutex.hpp
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace xrpl {
|
||||||
|
|
||||||
|
template <typename ProtectedDataType, typename MutexType>
|
||||||
|
class Mutex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A lock on a mutex that provides access to the protected data.
|
||||||
|
*
|
||||||
|
* @tparam ProtectedDataType data type to hold
|
||||||
|
* @tparam LockType type of lock
|
||||||
|
* @tparam MutexType type of mutex
|
||||||
|
*/
|
||||||
|
template <typename ProtectedDataType, template <typename...> typename LockType, typename MutexType>
|
||||||
|
class Lock
|
||||||
|
{
|
||||||
|
LockType<MutexType> lock_;
|
||||||
|
ProtectedDataType& data_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** @cond */
|
||||||
|
ProtectedDataType const&
|
||||||
|
operator*() const
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectedDataType&
|
||||||
|
operator*()
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectedDataType const&
|
||||||
|
get() const
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectedDataType&
|
||||||
|
get()
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectedDataType const*
|
||||||
|
operator->() const
|
||||||
|
{
|
||||||
|
return &data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectedDataType*
|
||||||
|
operator->()
|
||||||
|
{
|
||||||
|
return &data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator LockType<MutexType>&() &
|
||||||
|
{
|
||||||
|
return lock_;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator LockType<MutexType> const&() const&
|
||||||
|
{
|
||||||
|
return lock_;
|
||||||
|
}
|
||||||
|
/** @endcond */
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class Mutex<std::remove_const_t<ProtectedDataType>, MutexType>;
|
||||||
|
|
||||||
|
Lock(MutexType& mutex, ProtectedDataType& data) : lock_(mutex), data_(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A container for data that is protected by a mutex. Inspired by Mutex in Rust.
|
||||||
|
*
|
||||||
|
* @tparam ProtectedDataType data type to hold
|
||||||
|
* @tparam MutexType type of mutex
|
||||||
|
*/
|
||||||
|
template <typename ProtectedDataType, typename MutexType = std::mutex>
|
||||||
|
class Mutex
|
||||||
|
{
|
||||||
|
mutable MutexType mutex_;
|
||||||
|
ProtectedDataType data_{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Mutex() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct a new Mutex object with the given data
|
||||||
|
*
|
||||||
|
* @param data The data to protect
|
||||||
|
*/
|
||||||
|
explicit Mutex(ProtectedDataType data) : data_(std::move(data))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Make a new Mutex object with the given data
|
||||||
|
*
|
||||||
|
* @tparam Args The types of the arguments to forward to the constructor of the protected data
|
||||||
|
* @param args The arguments to forward to the constructor of the protected data
|
||||||
|
* @return The Mutex object that protects the given data
|
||||||
|
*/
|
||||||
|
template <typename... Args>
|
||||||
|
static Mutex
|
||||||
|
make(Args&&... args)
|
||||||
|
{
|
||||||
|
return Mutex{ProtectedDataType{std::forward<Args>(args)...}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lock the mutex and get a lock object allowing access to the protected data
|
||||||
|
*
|
||||||
|
* @tparam LockType The type of lock to use
|
||||||
|
* @return A lock on the mutex and a reference to the protected data
|
||||||
|
*/
|
||||||
|
template <template <typename...> typename LockType = std::lock_guard>
|
||||||
|
Lock<ProtectedDataType const, LockType, MutexType>
|
||||||
|
lock() const
|
||||||
|
{
|
||||||
|
return {mutex_, data_};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lock the mutex and get a lock object allowing access to the protected data
|
||||||
|
*
|
||||||
|
* @tparam LockType The type of lock to use
|
||||||
|
* @return A lock on the mutex and a reference to the protected data
|
||||||
|
*/
|
||||||
|
template <template <typename...> typename LockType = std::lock_guard>
|
||||||
|
Lock<ProtectedDataType, LockType, MutexType>
|
||||||
|
lock()
|
||||||
|
{
|
||||||
|
return {mutex_, data_};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xrpl
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/basics/sanitizers.h>
|
||||||
#include <xrpl/beast/type_name.h>
|
#include <xrpl/beast/type_name.h>
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@@ -23,16 +24,28 @@ LogThrow(std::string const& title);
|
|||||||
When called from within a catch block, it will pass
|
When called from within a catch block, it will pass
|
||||||
control to the next matching exception handler, if any.
|
control to the next matching exception handler, if any.
|
||||||
Otherwise, std::terminate will be called.
|
Otherwise, std::terminate will be called.
|
||||||
|
|
||||||
|
ASAN can't handle sudden jumps in control flow very well. This
|
||||||
|
function is marked as XRPL_NO_SANITIZE_ADDRESS to prevent it from
|
||||||
|
triggering false positives, since it throws.
|
||||||
*/
|
*/
|
||||||
[[noreturn]] inline void
|
[[noreturn]] XRPL_NO_SANITIZE_ADDRESS inline void
|
||||||
Rethrow()
|
Rethrow()
|
||||||
{
|
{
|
||||||
LogThrow("Re-throwing exception");
|
LogThrow("Re-throwing exception");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Logs and throws an exception of type E.
|
||||||
|
|
||||||
|
ASAN can't handle sudden jumps in control flow very well. This
|
||||||
|
function is marked as XRPL_NO_SANITIZE_ADDRESS to prevent it from
|
||||||
|
triggering false positives, since it throws.
|
||||||
|
*/
|
||||||
|
|
||||||
template <class E, class... Args>
|
template <class E, class... Args>
|
||||||
[[noreturn]] inline void
|
[[noreturn]] XRPL_NO_SANITIZE_ADDRESS inline void
|
||||||
Throw(Args&&... args)
|
Throw(Args&&... args)
|
||||||
{
|
{
|
||||||
static_assert(
|
static_assert(
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace xrpl {
|
namespace xrpl {
|
||||||
@@ -70,4 +72,31 @@ unsafe_cast(Src s) noexcept
|
|||||||
return unsafe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
|
return unsafe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Dest, class Src>
|
||||||
|
requires std::is_pointer_v<Dest>
|
||||||
|
inline Dest
|
||||||
|
safe_downcast(Src* s) noexcept
|
||||||
|
{
|
||||||
|
#ifdef NDEBUG
|
||||||
|
return static_cast<Dest>(s); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
|
||||||
|
#else
|
||||||
|
auto* result = dynamic_cast<Dest>(s);
|
||||||
|
XRPL_ASSERT(result != nullptr, "xrpl::safe_downcast : pointer downcast is valid");
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Dest, class Src>
|
||||||
|
requires std::is_lvalue_reference_v<Dest>
|
||||||
|
inline Dest
|
||||||
|
safe_downcast(Src& s) noexcept
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
XRPL_ASSERT(
|
||||||
|
dynamic_cast<std::add_pointer_t<std::remove_reference_t<Dest>>>(&s) != nullptr,
|
||||||
|
"xrpl::safe_downcast : reference downcast is valid");
|
||||||
|
#endif
|
||||||
|
return static_cast<Dest>(s); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xrpl
|
} // namespace xrpl
|
||||||
|
|||||||
13
include/xrpl/basics/sanitizers.h
Normal file
13
include/xrpl/basics/sanitizers.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Helper to disable ASan/HwASan for specific functions
|
||||||
|
/*
|
||||||
|
ASAN flags some false positives with sudden jumps in control flow, like
|
||||||
|
exceptions, or when encountering coroutine stack switches. This macro can be used to disable ASAN
|
||||||
|
intrumentation for specific functions.
|
||||||
|
*/
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define XRPL_NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address", "hwaddress")))
|
||||||
|
#else
|
||||||
|
#define XRPL_NO_SANITIZE_ADDRESS
|
||||||
|
#endif
|
||||||
@@ -43,8 +43,8 @@ private:
|
|||||||
template <typename>
|
template <typename>
|
||||||
friend class ListIterator;
|
friend class ListIterator;
|
||||||
|
|
||||||
ListNode* m_next;
|
ListNode* m_next = nullptr;
|
||||||
ListNode* m_prev;
|
ListNode* m_prev = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -567,7 +567,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_type m_size;
|
size_type m_size = 0u;
|
||||||
Node m_head;
|
Node m_head;
|
||||||
Node m_tail;
|
Node m_tail;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@@ -26,14 +27,14 @@ public:
|
|||||||
|
|
||||||
SemanticVersion();
|
SemanticVersion();
|
||||||
|
|
||||||
SemanticVersion(std::string const& version);
|
SemanticVersion(std::string_view version);
|
||||||
|
|
||||||
/** Parse a semantic version string.
|
/** Parse a semantic version string.
|
||||||
The parsing is as strict as possible.
|
The parsing is as strict as possible.
|
||||||
@return `true` if the string was parsed.
|
@return `true` if the string was parsed.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
parse(std::string const& input);
|
parse(std::string_view input);
|
||||||
|
|
||||||
/** Produce a string from semantic version components. */
|
/** Produce a string from semantic version components. */
|
||||||
std::string
|
std::string
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#define ALWAYS_OR_UNREACHABLE(cond, message) assert((message) && (cond))
|
#define ALWAYS_OR_UNREACHABLE(cond, message) assert((message) && (cond))
|
||||||
#define SOMETIMES(cond, message, ...)
|
#define SOMETIMES(cond, message, ...)
|
||||||
#define REACHABLE(message, ...)
|
#define REACHABLE(message, ...)
|
||||||
#define UNREACHABLE(message, ...) assert((message) && false)
|
#define UNREACHABLE(message, ...) assert((message) && false) // NOLINT(misc-static-assert)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define XRPL_ASSERT ALWAYS_OR_UNREACHABLE
|
#define XRPL_ASSERT ALWAYS_OR_UNREACHABLE
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <xrpl/basics/ByteUtilities.h>
|
|
||||||
|
|
||||||
namespace xrpl {
|
namespace xrpl {
|
||||||
|
|
||||||
template <class F>
|
template <class F>
|
||||||
@@ -11,16 +9,18 @@ JobQueue::Coro::Coro(Coro_create_t, JobQueue& jq, JobType type, std::string cons
|
|||||||
, name_(name)
|
, name_(name)
|
||||||
, running_(false)
|
, running_(false)
|
||||||
, coro_(
|
, coro_(
|
||||||
|
// Stack size of 1MB wasn't sufficient for deep calls. ASAN tests flagged the issue. Hence
|
||||||
|
// increasing the size to 1.5MB.
|
||||||
|
boost::context::protected_fixedsize_stack(1536 * 1024),
|
||||||
[this, fn = std::forward<F>(f)](
|
[this, fn = std::forward<F>(f)](
|
||||||
boost::coroutines::asymmetric_coroutine<void>::push_type& do_yield) {
|
boost::coroutines2::asymmetric_coroutine<void>::push_type& do_yield) {
|
||||||
yield_ = &do_yield;
|
yield_ = &do_yield;
|
||||||
yield();
|
yield();
|
||||||
fn(shared_from_this());
|
fn(shared_from_this());
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
#endif
|
#endif
|
||||||
},
|
})
|
||||||
boost::coroutines::attributes(megabytes(1)))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,14 +70,24 @@ JobQueue::Coro::resume()
|
|||||||
running_ = true;
|
running_ = true;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard lock(jq_.m_mutex);
|
std::lock_guard lk(jq_.m_mutex);
|
||||||
--jq_.nSuspend_;
|
--jq_.nSuspend_;
|
||||||
}
|
}
|
||||||
auto saved = detail::getLocalValues().release();
|
auto saved = detail::getLocalValues().release();
|
||||||
detail::getLocalValues().reset(&lvs_);
|
detail::getLocalValues().reset(&lvs_);
|
||||||
std::lock_guard lock(mutex_);
|
std::lock_guard lock(mutex_);
|
||||||
XRPL_ASSERT(static_cast<bool>(coro_), "xrpl::JobQueue::Coro::resume : is runnable");
|
// A late resume() can arrive after the coroutine has already completed.
|
||||||
coro_();
|
// This is an expected (if rare) outcome of the race condition documented
|
||||||
|
// in JobQueue.h:354-377 where post() schedules a resume job before the
|
||||||
|
// coroutine yields — the mutex serializes access, but by the time this
|
||||||
|
// resume() acquires the lock the coroutine may have already run to
|
||||||
|
// completion. Calling operator() on a completed boost::coroutine2 is
|
||||||
|
// undefined behavior, so we must check and skip invoking the coroutine
|
||||||
|
// body if it has already completed.
|
||||||
|
if (coro_)
|
||||||
|
{
|
||||||
|
coro_();
|
||||||
|
}
|
||||||
detail::getLocalValues().release();
|
detail::getLocalValues().release();
|
||||||
detail::getLocalValues().reset(saved);
|
detail::getLocalValues().reset(saved);
|
||||||
std::lock_guard lk(mutex_run_);
|
std::lock_guard lk(mutex_run_);
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
#include <xrpl/core/detail/Workers.h>
|
#include <xrpl/core/detail/Workers.h>
|
||||||
#include <xrpl/json/json_value.h>
|
#include <xrpl/json/json_value.h>
|
||||||
|
|
||||||
#include <boost/coroutine/all.hpp>
|
#include <boost/context/protected_fixedsize_stack.hpp>
|
||||||
|
#include <boost/coroutine2/all.hpp>
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@@ -48,8 +49,8 @@ public:
|
|||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
std::mutex mutex_run_;
|
std::mutex mutex_run_;
|
||||||
std::condition_variable cv_;
|
std::condition_variable cv_;
|
||||||
boost::coroutines::asymmetric_coroutine<void>::pull_type coro_;
|
boost::coroutines2::coroutine<void>::pull_type coro_;
|
||||||
boost::coroutines::asymmetric_coroutine<void>::push_type* yield_;
|
boost::coroutines2::coroutine<void>::push_type* yield_;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
bool finished_ = false;
|
bool finished_ = false;
|
||||||
#endif
|
#endif
|
||||||
@@ -98,8 +99,8 @@ public:
|
|||||||
Effects:
|
Effects:
|
||||||
The coroutine continues execution from where it last left off
|
The coroutine continues execution from where it last left off
|
||||||
using this same thread.
|
using this same thread.
|
||||||
Undefined behavior if called after the coroutine has completed
|
If the coroutine has already completed, returns immediately
|
||||||
with a return (as opposed to a yield()).
|
(handles the documented post-before-yield race condition).
|
||||||
Undefined behavior if resume() or post() called consecutively
|
Undefined behavior if resume() or post() called consecutively
|
||||||
without a corresponding yield.
|
without a corresponding yield.
|
||||||
*/
|
*/
|
||||||
@@ -315,7 +316,7 @@ private:
|
|||||||
// Returns the limit of running jobs for the given job type.
|
// Returns the limit of running jobs for the given job type.
|
||||||
// For jobs with no limit, we return the largest int. Hopefully that
|
// For jobs with no limit, we return the largest int. Hopefully that
|
||||||
// will be enough.
|
// will be enough.
|
||||||
int
|
static int
|
||||||
getJobLimit(JobType type);
|
getJobLimit(JobType type);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -356,8 +357,10 @@ private:
|
|||||||
If the post() job were to be executed before yield(), undefined behavior
|
If the post() job were to be executed before yield(), undefined behavior
|
||||||
would occur. The lock ensures that coro_ is not called again until we exit
|
would occur. The lock ensures that coro_ is not called again until we exit
|
||||||
the coroutine. At which point a scheduled resume() job waiting on the lock
|
the coroutine. At which point a scheduled resume() job waiting on the lock
|
||||||
would gain entry, harmlessly call coro_ and immediately return as we have
|
would gain entry. resume() checks if the coroutine has already completed
|
||||||
already completed the coroutine.
|
(coro_ converts to false) and, if so, skips invoking operator() since
|
||||||
|
calling operator() on a completed boost::coroutine2 pull_type is undefined
|
||||||
|
behavior.
|
||||||
|
|
||||||
The race condition occurs as follows:
|
The race condition occurs as follows:
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <xrpl/basics/Blob.h>
|
#include <xrpl/basics/Blob.h>
|
||||||
#include <xrpl/basics/SHAMapHash.h>
|
#include <xrpl/basics/SHAMapHash.h>
|
||||||
#include <xrpl/basics/TaggedCache.h>
|
#include <xrpl/basics/TaggedCache.h>
|
||||||
#include <xrpl/ledger/CachedSLEs.h>
|
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
@@ -23,6 +22,20 @@ class PerfLog;
|
|||||||
// This is temporary until we migrate all code to use ServiceRegistry.
|
// This is temporary until we migrate all code to use ServiceRegistry.
|
||||||
class Application;
|
class Application;
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Key,
|
||||||
|
class T,
|
||||||
|
bool IsKeyCache,
|
||||||
|
class SharedWeakUnionPointer,
|
||||||
|
class SharedPointerType,
|
||||||
|
class Hash,
|
||||||
|
class KeyEqual,
|
||||||
|
class Mutex>
|
||||||
|
class TaggedCache;
|
||||||
|
class STLedgerEntry;
|
||||||
|
using SLE = STLedgerEntry;
|
||||||
|
using CachedSLEs = TaggedCache<uint256, SLE const>;
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
class AcceptedLedger;
|
class AcceptedLedger;
|
||||||
class AmendmentTable;
|
class AmendmentTable;
|
||||||
@@ -45,7 +58,7 @@ class NetworkIDService;
|
|||||||
class OpenLedger;
|
class OpenLedger;
|
||||||
class OrderBookDB;
|
class OrderBookDB;
|
||||||
class Overlay;
|
class Overlay;
|
||||||
class PathRequests;
|
class PathRequestManager;
|
||||||
class PeerReservationTable;
|
class PeerReservationTable;
|
||||||
class PendingSaves;
|
class PendingSaves;
|
||||||
class RelationalDatabase;
|
class RelationalDatabase;
|
||||||
@@ -89,7 +102,7 @@ public:
|
|||||||
getNodeFamily() = 0;
|
getNodeFamily() = 0;
|
||||||
|
|
||||||
virtual TimeKeeper&
|
virtual TimeKeeper&
|
||||||
timeKeeper() = 0;
|
getTimeKeeper() = 0;
|
||||||
|
|
||||||
virtual JobQueue&
|
virtual JobQueue&
|
||||||
getJobQueue() = 0;
|
getJobQueue() = 0;
|
||||||
@@ -98,7 +111,7 @@ public:
|
|||||||
getTempNodeCache() = 0;
|
getTempNodeCache() = 0;
|
||||||
|
|
||||||
virtual CachedSLEs&
|
virtual CachedSLEs&
|
||||||
cachedSLEs() = 0;
|
getCachedSLEs() = 0;
|
||||||
|
|
||||||
virtual NetworkIDService&
|
virtual NetworkIDService&
|
||||||
getNetworkIDService() = 0;
|
getNetworkIDService() = 0;
|
||||||
@@ -120,26 +133,26 @@ public:
|
|||||||
getValidations() = 0;
|
getValidations() = 0;
|
||||||
|
|
||||||
virtual ValidatorList&
|
virtual ValidatorList&
|
||||||
validators() = 0;
|
getValidators() = 0;
|
||||||
|
|
||||||
virtual ValidatorSite&
|
virtual ValidatorSite&
|
||||||
validatorSites() = 0;
|
getValidatorSites() = 0;
|
||||||
|
|
||||||
virtual ManifestCache&
|
virtual ManifestCache&
|
||||||
validatorManifests() = 0;
|
getValidatorManifests() = 0;
|
||||||
|
|
||||||
virtual ManifestCache&
|
virtual ManifestCache&
|
||||||
publisherManifests() = 0;
|
getPublisherManifests() = 0;
|
||||||
|
|
||||||
// Network services
|
// Network services
|
||||||
virtual Overlay&
|
virtual Overlay&
|
||||||
overlay() = 0;
|
getOverlay() = 0;
|
||||||
|
|
||||||
virtual Cluster&
|
virtual Cluster&
|
||||||
cluster() = 0;
|
getCluster() = 0;
|
||||||
|
|
||||||
virtual PeerReservationTable&
|
virtual PeerReservationTable&
|
||||||
peerReservations() = 0;
|
getPeerReservations() = 0;
|
||||||
|
|
||||||
virtual Resource::Manager&
|
virtual Resource::Manager&
|
||||||
getResourceManager() = 0;
|
getResourceManager() = 0;
|
||||||
@@ -174,13 +187,13 @@ public:
|
|||||||
getLedgerReplayer() = 0;
|
getLedgerReplayer() = 0;
|
||||||
|
|
||||||
virtual PendingSaves&
|
virtual PendingSaves&
|
||||||
pendingSaves() = 0;
|
getPendingSaves() = 0;
|
||||||
|
|
||||||
virtual OpenLedger&
|
virtual OpenLedger&
|
||||||
openLedger() = 0;
|
getOpenLedger() = 0;
|
||||||
|
|
||||||
virtual OpenLedger const&
|
virtual OpenLedger const&
|
||||||
openLedger() const = 0;
|
getOpenLedger() const = 0;
|
||||||
|
|
||||||
// Transaction and operation services
|
// Transaction and operation services
|
||||||
virtual NetworkOPs&
|
virtual NetworkOPs&
|
||||||
@@ -195,8 +208,8 @@ public:
|
|||||||
virtual TxQ&
|
virtual TxQ&
|
||||||
getTxQ() = 0;
|
getTxQ() = 0;
|
||||||
|
|
||||||
virtual PathRequests&
|
virtual PathRequestManager&
|
||||||
getPathRequests() = 0;
|
getPathRequestManager() = 0;
|
||||||
|
|
||||||
// Server services
|
// Server services
|
||||||
virtual ServerHandler&
|
virtual ServerHandler&
|
||||||
@@ -210,16 +223,16 @@ public:
|
|||||||
isStopping() const = 0;
|
isStopping() const = 0;
|
||||||
|
|
||||||
virtual beast::Journal
|
virtual beast::Journal
|
||||||
journal(std::string const& name) = 0;
|
getJournal(std::string const& name) = 0;
|
||||||
|
|
||||||
virtual boost::asio::io_context&
|
virtual boost::asio::io_context&
|
||||||
getIOContext() = 0;
|
getIOContext() = 0;
|
||||||
|
|
||||||
virtual Logs&
|
virtual Logs&
|
||||||
logs() = 0;
|
getLogs() = 0;
|
||||||
|
|
||||||
virtual std::optional<uint256> const&
|
virtual std::optional<uint256> const&
|
||||||
trapTxID() const = 0;
|
getTrapTxID() const = 0;
|
||||||
|
|
||||||
/** Retrieve the "wallet database" */
|
/** Retrieve the "wallet database" */
|
||||||
virtual DatabaseCon&
|
virtual DatabaseCon&
|
||||||
@@ -228,7 +241,7 @@ public:
|
|||||||
// Temporary: Get the underlying Application for functions that haven't
|
// Temporary: Get the underlying Application for functions that haven't
|
||||||
// been migrated yet. This should be removed once all code is migrated.
|
// been migrated yet. This should be removed once all code is migrated.
|
||||||
virtual Application&
|
virtual Application&
|
||||||
app() = 0;
|
getApp() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xrpl
|
} // namespace xrpl
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace xrpl {
|
namespace xrpl {
|
||||||
|
|
||||||
enum class StartUpType { FRESH, NORMAL, LOAD, LOAD_FILE, REPLAY, NETWORK };
|
enum class StartUpType { Fresh, Normal, Load, LoadFile, Replay, Network };
|
||||||
|
|
||||||
inline std::ostream&
|
inline std::ostream&
|
||||||
operator<<(std::ostream& os, StartUpType const& type)
|
operator<<(std::ostream& os, StartUpType const& type)
|
||||||
|
|||||||
13
include/xrpl/git/Git.h
Normal file
13
include/xrpl/git/Git.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace xrpl::git {
|
||||||
|
|
||||||
|
std::string const&
|
||||||
|
getCommitHash();
|
||||||
|
|
||||||
|
std::string const&
|
||||||
|
getBuildBranch();
|
||||||
|
|
||||||
|
} // namespace xrpl::git
|
||||||
@@ -421,7 +421,7 @@ private:
|
|||||||
ObjectValues* map_{nullptr};
|
ObjectValues* map_{nullptr};
|
||||||
} value_;
|
} value_;
|
||||||
ValueType type_ : 8;
|
ValueType type_ : 8;
|
||||||
int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
|
int allocated_ : 1 {}; // Notes: if declared as bool, bitfield is useless.
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Value
|
inline Value
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ private:
|
|||||||
std::string indentString_;
|
std::string indentString_;
|
||||||
int rightMargin_;
|
int rightMargin_;
|
||||||
int indentSize_;
|
int indentSize_;
|
||||||
bool addChildValues_;
|
bool addChildValues_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
||||||
@@ -175,7 +175,7 @@ private:
|
|||||||
std::string indentString_;
|
std::string indentString_;
|
||||||
int rightMargin_;
|
int rightMargin_;
|
||||||
std::string indentation_;
|
std::string indentation_;
|
||||||
bool addChildValues_;
|
bool addChildValues_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <xrpl/ledger/View.h>
|
|
||||||
#include <xrpl/protocol/IOUAmount.h>
|
|
||||||
#include <xrpl/protocol/STAmount.h>
|
|
||||||
|
|
||||||
namespace xrpl {
|
|
||||||
|
|
||||||
/** Calculate the maximum amount of IOUs that an account can hold
|
|
||||||
@param ledger the ledger to check against.
|
|
||||||
@param account the account of interest.
|
|
||||||
@param issuer the issuer of the IOU.
|
|
||||||
@param currency the IOU to check.
|
|
||||||
@return The maximum amount that can be held.
|
|
||||||
*/
|
|
||||||
/** @{ */
|
|
||||||
STAmount
|
|
||||||
creditLimit(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
AccountID const& issuer,
|
|
||||||
Currency const& currency);
|
|
||||||
|
|
||||||
IOUAmount
|
|
||||||
creditLimit2(ReadView const& v, AccountID const& acc, AccountID const& iss, Currency const& cur);
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** Returns the amount of IOUs issued by issuer that are held by an account
|
|
||||||
@param ledger the ledger to check against.
|
|
||||||
@param account the account of interest.
|
|
||||||
@param issuer the issuer of the IOU.
|
|
||||||
@param currency the IOU to check.
|
|
||||||
*/
|
|
||||||
/** @{ */
|
|
||||||
STAmount
|
|
||||||
creditBalance(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
AccountID const& issuer,
|
|
||||||
Currency const& currency);
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
} // namespace xrpl
|
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <xrpld/core/Config.h>
|
|
||||||
#include <xrpld/core/TimeKeeper.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/CountedObject.h>
|
#include <xrpl/basics/CountedObject.h>
|
||||||
#include <xrpl/beast/utility/Journal.h>
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
#include <xrpl/ledger/CachedView.h>
|
#include <xrpl/ledger/CachedView.h>
|
||||||
#include <xrpl/ledger/View.h>
|
#include <xrpl/ledger/View.h>
|
||||||
|
#include <xrpl/protocol/Fees.h>
|
||||||
#include <xrpl/protocol/Indexes.h>
|
#include <xrpl/protocol/Indexes.h>
|
||||||
|
#include <xrpl/protocol/Rules.h>
|
||||||
#include <xrpl/protocol/STLedgerEntry.h>
|
#include <xrpl/protocol/STLedgerEntry.h>
|
||||||
#include <xrpl/protocol/Serializer.h>
|
#include <xrpl/protocol/Serializer.h>
|
||||||
#include <xrpl/protocol/TxMeta.h>
|
#include <xrpl/protocol/TxMeta.h>
|
||||||
@@ -15,7 +14,7 @@
|
|||||||
|
|
||||||
namespace xrpl {
|
namespace xrpl {
|
||||||
|
|
||||||
class Application;
|
class ServiceRegistry;
|
||||||
class Job;
|
class Job;
|
||||||
class TransactionMaster;
|
class TransactionMaster;
|
||||||
|
|
||||||
@@ -83,21 +82,26 @@ public:
|
|||||||
*/
|
*/
|
||||||
Ledger(
|
Ledger(
|
||||||
create_genesis_t,
|
create_genesis_t,
|
||||||
Config const& config,
|
Rules const& rules,
|
||||||
|
Fees const& fees,
|
||||||
std::vector<uint256> const& amendments,
|
std::vector<uint256> const& amendments,
|
||||||
Family& family);
|
Family& family);
|
||||||
|
|
||||||
Ledger(LedgerHeader const& info, Config const& config, Family& family);
|
Ledger(LedgerHeader const& info, Rules const& rules, Family& family);
|
||||||
|
|
||||||
/** Used for ledgers loaded from JSON files
|
/** Used for ledgers loaded from JSON files
|
||||||
|
|
||||||
@param acquire If true, acquires the ledger if not found locally
|
@param acquire If true, acquires the ledger if not found locally
|
||||||
|
|
||||||
|
@note The fees parameter provides default values, but setup() may
|
||||||
|
override them from the ledger state if fee-related SLEs exist.
|
||||||
*/
|
*/
|
||||||
Ledger(
|
Ledger(
|
||||||
LedgerHeader const& info,
|
LedgerHeader const& info,
|
||||||
bool& loaded,
|
bool& loaded,
|
||||||
bool acquire,
|
bool acquire,
|
||||||
Config const& config,
|
Rules const& rules,
|
||||||
|
Fees const& fees,
|
||||||
Family& family,
|
Family& family,
|
||||||
beast::Journal j);
|
beast::Journal j);
|
||||||
|
|
||||||
@@ -113,7 +117,8 @@ public:
|
|||||||
Ledger(
|
Ledger(
|
||||||
std::uint32_t ledgerSeq,
|
std::uint32_t ledgerSeq,
|
||||||
NetClock::time_point closeTime,
|
NetClock::time_point closeTime,
|
||||||
Config const& config,
|
Rules const& rules,
|
||||||
|
Fees const& fees,
|
||||||
Family& family);
|
Family& family);
|
||||||
|
|
||||||
~Ledger() = default;
|
~Ledger() = default;
|
||||||
@@ -322,7 +327,7 @@ public:
|
|||||||
walkLedger(beast::Journal j, bool parallel = false) const;
|
walkLedger(beast::Journal j, bool parallel = false) const;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
assertSensible(beast::Journal ledgerJ) const;
|
isSensible() const;
|
||||||
|
|
||||||
void
|
void
|
||||||
invariants() const;
|
invariants() const;
|
||||||
@@ -379,8 +384,26 @@ private:
|
|||||||
bool
|
bool
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
void
|
/** @brief Deserialize a SHAMapItem containing a single STTx.
|
||||||
defaultFees(Config const& config);
|
*
|
||||||
|
* @param item The SHAMapItem to deserialize.
|
||||||
|
* @return A shared pointer to the deserialized transaction.
|
||||||
|
* @throw May throw on deserialization error.
|
||||||
|
*/
|
||||||
|
static std::shared_ptr<STTx const>
|
||||||
|
deserializeTx(SHAMapItem const& item);
|
||||||
|
|
||||||
|
/** @brief Deserialize a SHAMapItem containing STTx + STObject metadata.
|
||||||
|
*
|
||||||
|
* The SHAMapItem must contain two variable length serialization objects.
|
||||||
|
*
|
||||||
|
* @param item The SHAMapItem to deserialize.
|
||||||
|
* @return A pair containing shared pointers to the deserialized transaction
|
||||||
|
* and metadata.
|
||||||
|
* @throw May throw on deserialization error.
|
||||||
|
*/
|
||||||
|
static std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>>
|
||||||
|
deserializeTxPlusMeta(SHAMapItem const& item);
|
||||||
|
|
||||||
bool mImmutable;
|
bool mImmutable;
|
||||||
|
|
||||||
@@ -402,54 +425,4 @@ private:
|
|||||||
/** A ledger wrapped in a CachedView. */
|
/** A ledger wrapped in a CachedView. */
|
||||||
using CachedLedger = CachedView<Ledger>;
|
using CachedLedger = CachedView<Ledger>;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// API
|
|
||||||
//
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
extern bool
|
|
||||||
pendSaveValidated(
|
|
||||||
Application& app,
|
|
||||||
std::shared_ptr<Ledger const> const& ledger,
|
|
||||||
bool isSynchronous,
|
|
||||||
bool isCurrent);
|
|
||||||
|
|
||||||
std::shared_ptr<Ledger>
|
|
||||||
loadLedgerHelper(LedgerHeader const& sinfo, Application& app, bool acquire);
|
|
||||||
|
|
||||||
std::shared_ptr<Ledger>
|
|
||||||
loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire = true);
|
|
||||||
|
|
||||||
std::shared_ptr<Ledger>
|
|
||||||
loadByHash(uint256 const& ledgerHash, Application& app, bool acquire = true);
|
|
||||||
|
|
||||||
// Fetch the ledger with the highest sequence contained in the database
|
|
||||||
extern std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
|
|
||||||
getLatestLedger(Application& app);
|
|
||||||
|
|
||||||
/** Deserialize a SHAMapItem containing a single STTx
|
|
||||||
|
|
||||||
Throw:
|
|
||||||
|
|
||||||
May throw on deserializaton error
|
|
||||||
*/
|
|
||||||
std::shared_ptr<STTx const>
|
|
||||||
deserializeTx(SHAMapItem const& item);
|
|
||||||
|
|
||||||
/** Deserialize a SHAMapItem containing STTx + STObject metadata
|
|
||||||
|
|
||||||
The SHAMap must contain two variable length
|
|
||||||
serialization objects.
|
|
||||||
|
|
||||||
Throw:
|
|
||||||
|
|
||||||
May throw on deserializaton error
|
|
||||||
*/
|
|
||||||
std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>>
|
|
||||||
deserializeTxPlusMeta(SHAMapItem const& item);
|
|
||||||
|
|
||||||
uint256
|
|
||||||
calculateLedgerHash(LedgerHeader const& info);
|
|
||||||
|
|
||||||
} // namespace xrpl
|
} // namespace xrpl
|
||||||
@@ -76,16 +76,33 @@ public:
|
|||||||
@return true if a book from this issue to XRP exists
|
@return true if a book from this issue to XRP exists
|
||||||
*/
|
*/
|
||||||
virtual bool
|
virtual bool
|
||||||
isBookToXRP(Issue const& issue, std::optional<Domain> domain = std::nullopt) = 0;
|
isBookToXRP(Issue const& issue, std::optional<Domain> const& domain = std::nullopt) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a transaction for order book tracking.
|
||||||
|
* @param ledger The ledger the transaction was applied to
|
||||||
|
* @param alTx The transaction to process
|
||||||
|
* @param jvObj The JSON object of the transaction
|
||||||
|
*/
|
||||||
virtual void
|
virtual void
|
||||||
processTxn(
|
processTxn(
|
||||||
std::shared_ptr<ReadView const> const& ledger,
|
std::shared_ptr<ReadView const> const& ledger,
|
||||||
AcceptedLedgerTx const& alTx,
|
AcceptedLedgerTx const& alTx,
|
||||||
MultiApiJson const& jvObj) = 0;
|
MultiApiJson const& jvObj) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the book listeners for a book.
|
||||||
|
* @param book The book to get the listeners for
|
||||||
|
* @return The book listeners for the book
|
||||||
|
*/
|
||||||
virtual BookListeners::pointer
|
virtual BookListeners::pointer
|
||||||
getBookListeners(Book const&) = 0;
|
getBookListeners(Book const&) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new book listeners for a book.
|
||||||
|
* @param book The book to create the listeners for
|
||||||
|
* @return The new book listeners for the book
|
||||||
|
*/
|
||||||
virtual BookListeners::pointer
|
virtual BookListeners::pointer
|
||||||
makeBookListeners(Book const&) = 0;
|
makeBookListeners(Book const&) = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,26 +2,23 @@
|
|||||||
|
|
||||||
#include <xrpl/beast/utility/Journal.h>
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
#include <xrpl/ledger/ApplyView.h>
|
#include <xrpl/ledger/ApplyView.h>
|
||||||
#include <xrpl/ledger/OpenView.h>
|
|
||||||
#include <xrpl/ledger/ReadView.h>
|
#include <xrpl/ledger/ReadView.h>
|
||||||
#include <xrpl/protocol/Asset.h>
|
|
||||||
#include <xrpl/protocol/Indexes.h>
|
|
||||||
#include <xrpl/protocol/MPTIssue.h>
|
#include <xrpl/protocol/MPTIssue.h>
|
||||||
#include <xrpl/protocol/Protocol.h>
|
#include <xrpl/protocol/Protocol.h>
|
||||||
#include <xrpl/protocol/Rate.h>
|
|
||||||
#include <xrpl/protocol/STLedgerEntry.h>
|
#include <xrpl/protocol/STLedgerEntry.h>
|
||||||
#include <xrpl/protocol/STObject.h>
|
#include <xrpl/protocol/STTx.h>
|
||||||
#include <xrpl/protocol/Serializer.h>
|
|
||||||
#include <xrpl/protocol/TER.h>
|
#include <xrpl/protocol/TER.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <initializer_list>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace xrpl {
|
namespace xrpl {
|
||||||
|
|
||||||
enum class WaiveTransferFee : bool { No = false, Yes };
|
|
||||||
enum class SkipEntry : bool { No = false, Yes };
|
enum class SkipEntry : bool { No = false, Yes };
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -54,24 +51,6 @@ enum class SkipEntry : bool { No = false, Yes };
|
|||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
hasExpired(ReadView const& view, std::optional<std::uint32_t> const& exp);
|
hasExpired(ReadView const& view, std::optional<std::uint32_t> const& exp);
|
||||||
|
|
||||||
/** Controls the treatment of frozen account balances */
|
|
||||||
enum FreezeHandling { fhIGNORE_FREEZE, fhZERO_IF_FROZEN };
|
|
||||||
|
|
||||||
/** Controls the treatment of unauthorized MPT balances */
|
|
||||||
enum AuthHandling { ahIGNORE_AUTH, ahZERO_IF_UNAUTHORIZED };
|
|
||||||
|
|
||||||
/** Controls whether to include the account's full spendable balance */
|
|
||||||
enum SpendableHandling { shSIMPLE_BALANCE, shFULL_BALANCE };
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isGlobalFrozen(ReadView const& view, AccountID const& issuer);
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue);
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isGlobalFrozen(ReadView const& view, Asset const& asset);
|
|
||||||
|
|
||||||
// Note, depth parameter is used to limit the recursion depth
|
// Note, depth parameter is used to limit the recursion depth
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
isVaultPseudoAccountFrozen(
|
isVaultPseudoAccountFrozen(
|
||||||
@@ -80,175 +59,6 @@ isVaultPseudoAccountFrozen(
|
|||||||
MPTIssue const& mptShare,
|
MPTIssue const& mptShare,
|
||||||
int depth);
|
int depth);
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isIndividualFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
AccountID const& issuer);
|
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isIndividualFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
|
|
||||||
{
|
|
||||||
return isIndividualFrozen(view, account, issue.currency, issue.account);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
|
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&](auto const& issue) { return isIndividualFrozen(view, account, issue); }, asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
AccountID const& issuer);
|
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isFrozen(ReadView const& view, AccountID const& account, Issue const& issue, int = 0 /*ignored*/)
|
|
||||||
{
|
|
||||||
return isFrozen(view, account, issue.currency, issue.account);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* isFrozen check is recursive for MPT shares in a vault, descending to
|
|
||||||
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
|
||||||
* purely defensive, as we currently do not allow such vaults to be created.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&](auto const& issue) { return isFrozen(view, account, issue, depth); }, asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
checkFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
|
|
||||||
{
|
|
||||||
return isFrozen(view, account, issue) ? (TER)tecFROZEN : (TER)tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
checkFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue)
|
|
||||||
{
|
|
||||||
return isFrozen(view, account, mptIssue) ? (TER)tecLOCKED : (TER)tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
checkFrozen(ReadView const& view, AccountID const& account, Asset const& asset)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&](auto const& issue) { return checkFrozen(view, account, issue); }, asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isAnyFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
std::initializer_list<AccountID> const& accounts,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
int depth = 0);
|
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isAnyFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
std::initializer_list<AccountID> const& accounts,
|
|
||||||
Issue const& issue)
|
|
||||||
{
|
|
||||||
for (auto const& account : accounts)
|
|
||||||
{
|
|
||||||
if (isFrozen(view, account, issue.currency, issue.account))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isAnyFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
std::initializer_list<AccountID> const& accounts,
|
|
||||||
Asset const& asset,
|
|
||||||
int depth = 0)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&]<ValidIssueType TIss>(TIss const& issue) {
|
|
||||||
if constexpr (std::is_same_v<TIss, Issue>)
|
|
||||||
return isAnyFrozen(view, accounts, issue);
|
|
||||||
else
|
|
||||||
return isAnyFrozen(view, accounts, issue, depth);
|
|
||||||
},
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isDeepFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
AccountID const& issuer);
|
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isDeepFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Issue const& issue,
|
|
||||||
int = 0 /*ignored*/)
|
|
||||||
{
|
|
||||||
return isDeepFrozen(view, account, issue.currency, issue.account);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isDeepFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
int depth = 0)
|
|
||||||
{
|
|
||||||
// Unlike IOUs, frozen / locked MPTs are not allowed to send or receive
|
|
||||||
// funds, so checking "deep frozen" is the same as checking "frozen".
|
|
||||||
return isFrozen(view, account, mptIssue, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* isFrozen check is recursive for MPT shares in a vault, descending to
|
|
||||||
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
|
||||||
* purely defensive, as we currently do not allow such vaults to be created.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&](auto const& issue) { return isDeepFrozen(view, account, issue, depth); },
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
checkDeepFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
|
|
||||||
{
|
|
||||||
return isDeepFrozen(view, account, issue) ? (TER)tecFROZEN : (TER)tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
checkDeepFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue)
|
|
||||||
{
|
|
||||||
return isDeepFrozen(view, account, mptIssue) ? (TER)tecLOCKED : (TER)tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
checkDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&](auto const& issue) { return checkDeepFrozen(view, account, issue); }, asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
isLPTokenFrozen(
|
isLPTokenFrozen(
|
||||||
ReadView const& view,
|
ReadView const& view,
|
||||||
@@ -256,159 +66,6 @@ isLPTokenFrozen(
|
|||||||
Issue const& asset,
|
Issue const& asset,
|
||||||
Issue const& asset2);
|
Issue const& asset2);
|
||||||
|
|
||||||
// Returns the amount an account can spend.
|
|
||||||
//
|
|
||||||
// If shSIMPLE_BALANCE is specified, this is the amount the account can spend
|
|
||||||
// without going into debt.
|
|
||||||
//
|
|
||||||
// If shFULL_BALANCE is specified, this is the amount the account can spend
|
|
||||||
// total. Specifically:
|
|
||||||
// * The account can go into debt if using a trust line, and the other side has
|
|
||||||
// a non-zero limit.
|
|
||||||
// * If the account is the asset issuer the limit is defined by the asset /
|
|
||||||
// issuance.
|
|
||||||
//
|
|
||||||
// <-- saAmount: amount of currency held by account. May be negative.
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountHolds(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
AccountID const& issuer,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
beast::Journal j,
|
|
||||||
SpendableHandling includeFullBalance = shSIMPLE_BALANCE);
|
|
||||||
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountHolds(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Issue const& issue,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
beast::Journal j,
|
|
||||||
SpendableHandling includeFullBalance = shSIMPLE_BALANCE);
|
|
||||||
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountHolds(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
AuthHandling zeroIfUnauthorized,
|
|
||||||
beast::Journal j,
|
|
||||||
SpendableHandling includeFullBalance = shSIMPLE_BALANCE);
|
|
||||||
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountHolds(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Asset const& asset,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
AuthHandling zeroIfUnauthorized,
|
|
||||||
beast::Journal j,
|
|
||||||
SpendableHandling includeFullBalance = shSIMPLE_BALANCE);
|
|
||||||
|
|
||||||
// Returns the amount an account can spend of the currency type saDefault, or
|
|
||||||
// returns saDefault if this account is the issuer of the currency in
|
|
||||||
// question. Should be used in favor of accountHolds when questioning how much
|
|
||||||
// an account can spend while also allowing currency issuers to spend
|
|
||||||
// unlimited amounts of their own currency (since they can always issue more).
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountFunds(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& id,
|
|
||||||
STAmount const& saDefault,
|
|
||||||
FreezeHandling freezeHandling,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
// Return the account's liquid (not reserved) XRP. Generally prefer
|
|
||||||
// calling accountHolds() over this interface. However, this interface
|
|
||||||
// allows the caller to temporarily adjust the owner count should that be
|
|
||||||
// necessary.
|
|
||||||
//
|
|
||||||
// @param ownerCountAdj positive to add to count, negative to reduce count.
|
|
||||||
[[nodiscard]] XRPAmount
|
|
||||||
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j);
|
|
||||||
|
|
||||||
/** Iterate all items in the given directory. */
|
|
||||||
void
|
|
||||||
forEachItem(
|
|
||||||
ReadView const& view,
|
|
||||||
Keylet const& root,
|
|
||||||
std::function<void(std::shared_ptr<SLE const> const&)> const& f);
|
|
||||||
|
|
||||||
/** Iterate all items after an item in the given directory.
|
|
||||||
@param after The key of the item to start after
|
|
||||||
@param hint The directory page containing `after`
|
|
||||||
@param limit The maximum number of items to return
|
|
||||||
@return `false` if the iteration failed
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
forEachItemAfter(
|
|
||||||
ReadView const& view,
|
|
||||||
Keylet const& root,
|
|
||||||
uint256 const& after,
|
|
||||||
std::uint64_t const hint,
|
|
||||||
unsigned int limit,
|
|
||||||
std::function<bool(std::shared_ptr<SLE const> const&)> const& f);
|
|
||||||
|
|
||||||
/** Iterate all items in an account's owner directory. */
|
|
||||||
inline void
|
|
||||||
forEachItem(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& id,
|
|
||||||
std::function<void(std::shared_ptr<SLE const> const&)> const& f)
|
|
||||||
{
|
|
||||||
return forEachItem(view, keylet::ownerDir(id), f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Iterate all items after an item in an owner directory.
|
|
||||||
@param after The key of the item to start after
|
|
||||||
@param hint The directory page containing `after`
|
|
||||||
@param limit The maximum number of items to return
|
|
||||||
@return `false` if the iteration failed
|
|
||||||
*/
|
|
||||||
inline bool
|
|
||||||
forEachItemAfter(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& id,
|
|
||||||
uint256 const& after,
|
|
||||||
std::uint64_t const hint,
|
|
||||||
unsigned int limit,
|
|
||||||
std::function<bool(std::shared_ptr<SLE const> const&)> const& f)
|
|
||||||
{
|
|
||||||
return forEachItemAfter(view, keylet::ownerDir(id), after, hint, limit, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns IOU issuer transfer fee as Rate. Rate specifies
|
|
||||||
* the fee as fractions of 1 billion. For example, 1% transfer rate
|
|
||||||
* is represented as 1,010,000,000.
|
|
||||||
* @param issuer The IOU issuer
|
|
||||||
*/
|
|
||||||
[[nodiscard]] Rate
|
|
||||||
transferRate(ReadView const& view, AccountID const& issuer);
|
|
||||||
|
|
||||||
/** Returns MPT transfer fee as Rate. Rate specifies
|
|
||||||
* the fee as fractions of 1 billion. For example, 1% transfer rate
|
|
||||||
* is represented as 1,010,000,000.
|
|
||||||
* @param issuanceID MPTokenIssuanceID of MPTTokenIssuance object
|
|
||||||
*/
|
|
||||||
[[nodiscard]] Rate
|
|
||||||
transferRate(ReadView const& view, MPTID const& issuanceID);
|
|
||||||
|
|
||||||
/** Returns the transfer fee as Rate based on the type of token
|
|
||||||
* @param view The ledger view
|
|
||||||
* @param amount The amount to transfer
|
|
||||||
*/
|
|
||||||
[[nodiscard]] Rate
|
|
||||||
transferRate(ReadView const& view, STAmount const& amount);
|
|
||||||
|
|
||||||
/** Returns `true` if the directory is empty
|
|
||||||
@param key The key of the directory
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool
|
|
||||||
dirIsEmpty(ReadView const& view, Keylet const& k);
|
|
||||||
|
|
||||||
// Return the list of enabled amendments
|
// Return the list of enabled amendments
|
||||||
[[nodiscard]] std::set<uint256>
|
[[nodiscard]] std::set<uint256>
|
||||||
getEnabledAmendments(ReadView const& view);
|
getEnabledAmendments(ReadView const& view);
|
||||||
@@ -474,81 +131,6 @@ areCompatible(
|
|||||||
//
|
//
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Adjust the owner count up or down. */
|
|
||||||
void
|
|
||||||
adjustOwnerCount(
|
|
||||||
ApplyView& view,
|
|
||||||
std::shared_ptr<SLE> const& sle,
|
|
||||||
std::int32_t amount,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
/** @{ */
|
|
||||||
/** Returns the first entry in the directory, advancing the index
|
|
||||||
|
|
||||||
@deprecated These are legacy function that are considered deprecated
|
|
||||||
and will soon be replaced with an iterator-based model
|
|
||||||
that is easier to use. You should not use them in new code.
|
|
||||||
|
|
||||||
@param view The view against which to operate
|
|
||||||
@param root The root (i.e. first page) of the directory to iterate
|
|
||||||
@param page The current page
|
|
||||||
@param index The index inside the current page
|
|
||||||
@param entry The entry at the current index
|
|
||||||
|
|
||||||
@return true if the directory isn't empty; false otherwise
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
cdirFirst(
|
|
||||||
ReadView const& view,
|
|
||||||
uint256 const& root,
|
|
||||||
std::shared_ptr<SLE const>& page,
|
|
||||||
unsigned int& index,
|
|
||||||
uint256& entry);
|
|
||||||
|
|
||||||
bool
|
|
||||||
dirFirst(
|
|
||||||
ApplyView& view,
|
|
||||||
uint256 const& root,
|
|
||||||
std::shared_ptr<SLE>& page,
|
|
||||||
unsigned int& index,
|
|
||||||
uint256& entry);
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** @{ */
|
|
||||||
/** Returns the next entry in the directory, advancing the index
|
|
||||||
|
|
||||||
@deprecated These are legacy function that are considered deprecated
|
|
||||||
and will soon be replaced with an iterator-based model
|
|
||||||
that is easier to use. You should not use them in new code.
|
|
||||||
|
|
||||||
@param view The view against which to operate
|
|
||||||
@param root The root (i.e. first page) of the directory to iterate
|
|
||||||
@param page The current page
|
|
||||||
@param index The index inside the current page
|
|
||||||
@param entry The entry at the current index
|
|
||||||
|
|
||||||
@return true if the directory isn't empty; false otherwise
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
cdirNext(
|
|
||||||
ReadView const& view,
|
|
||||||
uint256 const& root,
|
|
||||||
std::shared_ptr<SLE const>& page,
|
|
||||||
unsigned int& index,
|
|
||||||
uint256& entry);
|
|
||||||
|
|
||||||
bool
|
|
||||||
dirNext(
|
|
||||||
ApplyView& view,
|
|
||||||
uint256 const& root,
|
|
||||||
std::shared_ptr<SLE>& page,
|
|
||||||
unsigned int& index,
|
|
||||||
uint256& entry);
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
[[nodiscard]] std::function<void(SLE::ref)>
|
|
||||||
describeOwnerDir(AccountID const& account);
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
[[nodiscard]] TER
|
||||||
dirLink(
|
dirLink(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
@@ -556,63 +138,6 @@ dirLink(
|
|||||||
std::shared_ptr<SLE>& object,
|
std::shared_ptr<SLE>& object,
|
||||||
SF_UINT64 const& node = sfOwnerNode);
|
SF_UINT64 const& node = sfOwnerNode);
|
||||||
|
|
||||||
AccountID
|
|
||||||
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Create pseudo-account, storing pseudoOwnerKey into ownerField.
|
|
||||||
*
|
|
||||||
* The list of valid ownerField is maintained in View.cpp and the caller to
|
|
||||||
* this function must perform necessary amendment check(s) before using a
|
|
||||||
* field. The amendment check is **not** performed in createPseudoAccount.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] Expected<std::shared_ptr<SLE>, TER>
|
|
||||||
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField);
|
|
||||||
|
|
||||||
// Returns true if and only if sleAcct is a pseudo-account or specific
|
|
||||||
// pseudo-accounts in pseudoFieldFilter.
|
|
||||||
//
|
|
||||||
// Returns false if sleAcct is
|
|
||||||
// * NOT a pseudo-account OR
|
|
||||||
// * NOT a ltACCOUNT_ROOT OR
|
|
||||||
// * null pointer
|
|
||||||
[[nodiscard]] bool
|
|
||||||
isPseudoAccount(
|
|
||||||
std::shared_ptr<SLE const> sleAcct,
|
|
||||||
std::set<SField const*> const& pseudoFieldFilter = {});
|
|
||||||
|
|
||||||
// Returns the list of fields that define an ACCOUNT_ROOT as a pseudo-account if
|
|
||||||
// set
|
|
||||||
// Pseudo-account designator fields MUST be maintained by including the
|
|
||||||
// SField::sMD_PseudoAccount flag in the SField definition. (Don't forget to
|
|
||||||
// "| SField::sMD_Default"!) The fields do NOT need to be amendment-gated,
|
|
||||||
// since a non-active amendment will not set any field, by definition.
|
|
||||||
// Specific properties of a pseudo-account are NOT checked here, that's what
|
|
||||||
// InvariantCheck is for.
|
|
||||||
[[nodiscard]] std::vector<SField const*> const&
|
|
||||||
getPseudoAccountFields();
|
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isPseudoAccount(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& accountId,
|
|
||||||
std::set<SField const*> const& pseudoFieldFilter = {})
|
|
||||||
{
|
|
||||||
return isPseudoAccount(view.read(keylet::account(accountId)), pseudoFieldFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
canAddHolding(ReadView const& view, Asset const& asset);
|
|
||||||
|
|
||||||
/** Validates that the destination SLE and tag are valid
|
|
||||||
|
|
||||||
- Checks that the SLE is not null.
|
|
||||||
- If the SLE requires a destination tag, checks that there is a tag.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag);
|
|
||||||
|
|
||||||
/** Checks that can withdraw funds from an object to itself or a destination.
|
/** Checks that can withdraw funds from an object to itself or a destination.
|
||||||
*
|
*
|
||||||
* The receiver may be either the submitting account (sfAccount) or a different
|
* The receiver may be either the submitting account (sfAccount) or a different
|
||||||
@@ -686,351 +211,6 @@ doWithdraw(
|
|||||||
STAmount const& amount,
|
STAmount const& amount,
|
||||||
beast::Journal j);
|
beast::Journal j);
|
||||||
|
|
||||||
/// Any transactors that call addEmptyHolding() in doApply must call
|
|
||||||
/// canAddHolding() in preflight with the same View and Asset
|
|
||||||
[[nodiscard]] TER
|
|
||||||
addEmptyHolding(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& accountID,
|
|
||||||
XRPAmount priorBalance,
|
|
||||||
Issue const& issue,
|
|
||||||
beast::Journal journal);
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
addEmptyHolding(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& accountID,
|
|
||||||
XRPAmount priorBalance,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
beast::Journal journal);
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
addEmptyHolding(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& accountID,
|
|
||||||
XRPAmount priorBalance,
|
|
||||||
Asset const& asset,
|
|
||||||
beast::Journal journal)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
|
|
||||||
return addEmptyHolding(view, accountID, priorBalance, issue, journal);
|
|
||||||
},
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
authorizeMPToken(
|
|
||||||
ApplyView& view,
|
|
||||||
XRPAmount const& priorBalance,
|
|
||||||
MPTID const& mptIssuanceID,
|
|
||||||
AccountID const& account,
|
|
||||||
beast::Journal journal,
|
|
||||||
std::uint32_t flags = 0,
|
|
||||||
std::optional<AccountID> holderID = std::nullopt);
|
|
||||||
|
|
||||||
// VFALCO NOTE Both STAmount parameters should just
|
|
||||||
// be "Amount", a unit-less number.
|
|
||||||
//
|
|
||||||
/** Create a trust line
|
|
||||||
|
|
||||||
This can set an initial balance.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
trustCreate(
|
|
||||||
ApplyView& view,
|
|
||||||
bool const bSrcHigh,
|
|
||||||
AccountID const& uSrcAccountID,
|
|
||||||
AccountID const& uDstAccountID,
|
|
||||||
uint256 const& uIndex, // --> ripple state entry
|
|
||||||
SLE::ref sleAccount, // --> the account being set.
|
|
||||||
bool const bAuth, // --> authorize account.
|
|
||||||
bool const bNoRipple, // --> others cannot ripple through
|
|
||||||
bool const bFreeze, // --> funds cannot leave
|
|
||||||
bool bDeepFreeze, // --> can neither receive nor send funds
|
|
||||||
STAmount const& saBalance, // --> balance of account being set.
|
|
||||||
// Issuer should be noAccount()
|
|
||||||
STAmount const& saLimit, // --> limit for account being set.
|
|
||||||
// Issuer should be the account being set.
|
|
||||||
std::uint32_t uSrcQualityIn,
|
|
||||||
std::uint32_t uSrcQualityOut,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
removeEmptyHolding(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& accountID,
|
|
||||||
Issue const& issue,
|
|
||||||
beast::Journal journal);
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
removeEmptyHolding(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& accountID,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
beast::Journal journal);
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
removeEmptyHolding(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& accountID,
|
|
||||||
Asset const& asset,
|
|
||||||
beast::Journal journal)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
|
|
||||||
return removeEmptyHolding(view, accountID, issue, journal);
|
|
||||||
},
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
trustDelete(
|
|
||||||
ApplyView& view,
|
|
||||||
std::shared_ptr<SLE> const& sleRippleState,
|
|
||||||
AccountID const& uLowAccountID,
|
|
||||||
AccountID const& uHighAccountID,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
/** Delete an offer.
|
|
||||||
|
|
||||||
Requirements:
|
|
||||||
The passed `sle` be obtained from a prior
|
|
||||||
call to view.peek()
|
|
||||||
*/
|
|
||||||
// [[nodiscard]] // nodiscard commented out so Flow, BookTip and others compile.
|
|
||||||
TER
|
|
||||||
offerDelete(ApplyView& view, std::shared_ptr<SLE> const& sle, beast::Journal j);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
//
|
|
||||||
// Money Transfers
|
|
||||||
//
|
|
||||||
|
|
||||||
// Direct send w/o fees:
|
|
||||||
// - Redeeming IOUs and/or sending sender's own IOUs.
|
|
||||||
// - Create trust line of needed.
|
|
||||||
// --> bCheckIssuer : normally require issuer to be involved.
|
|
||||||
// [[nodiscard]] // nodiscard commented out so DirectStep.cpp compiles.
|
|
||||||
|
|
||||||
/** Calls static rippleCreditIOU if saAmount represents Issue.
|
|
||||||
* Calls static rippleCreditMPT if saAmount represents MPTIssue.
|
|
||||||
*/
|
|
||||||
TER
|
|
||||||
rippleCredit(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& uSenderID,
|
|
||||||
AccountID const& uReceiverID,
|
|
||||||
STAmount const& saAmount,
|
|
||||||
bool bCheckIssuer,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
TER
|
|
||||||
rippleLockEscrowMPT(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& uGrantorID,
|
|
||||||
STAmount const& saAmount,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
TER
|
|
||||||
rippleUnlockEscrowMPT(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& uGrantorID,
|
|
||||||
AccountID const& uGranteeID,
|
|
||||||
STAmount const& netAmount,
|
|
||||||
STAmount const& grossAmount,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
/** Calls static accountSendIOU if saAmount represents Issue.
|
|
||||||
* Calls static accountSendMPT if saAmount represents MPTIssue.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
accountSend(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& from,
|
|
||||||
AccountID const& to,
|
|
||||||
STAmount const& saAmount,
|
|
||||||
beast::Journal j,
|
|
||||||
WaiveTransferFee waiveFee = WaiveTransferFee::No);
|
|
||||||
|
|
||||||
using MultiplePaymentDestinations = std::vector<std::pair<AccountID, Number>>;
|
|
||||||
/** Like accountSend, except one account is sending multiple payments (with the
|
|
||||||
* same asset!) simultaneously
|
|
||||||
*
|
|
||||||
* Calls static accountSendMultiIOU if saAmount represents Issue.
|
|
||||||
* Calls static accountSendMultiMPT if saAmount represents MPTIssue.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
accountSendMulti(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& senderID,
|
|
||||||
Asset const& asset,
|
|
||||||
MultiplePaymentDestinations const& receivers,
|
|
||||||
beast::Journal j,
|
|
||||||
WaiveTransferFee waiveFee = WaiveTransferFee::No);
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
issueIOU(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& account,
|
|
||||||
STAmount const& amount,
|
|
||||||
Issue const& issue,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
redeemIOU(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& account,
|
|
||||||
STAmount const& amount,
|
|
||||||
Issue const& issue,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
transferXRP(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& from,
|
|
||||||
AccountID const& to,
|
|
||||||
STAmount const& amount,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
/* Check if MPToken (for MPT) or trust line (for IOU) exists:
|
|
||||||
* - StrongAuth - before checking if authorization is required
|
|
||||||
* - WeakAuth
|
|
||||||
* for MPT - after checking lsfMPTRequireAuth flag
|
|
||||||
* for IOU - do not check if trust line exists
|
|
||||||
* - Legacy
|
|
||||||
* for MPT - before checking lsfMPTRequireAuth flag i.e. same as StrongAuth
|
|
||||||
* for IOU - do not check if trust line exists i.e. same as WeakAuth
|
|
||||||
*/
|
|
||||||
enum class AuthType { StrongAuth, WeakAuth, Legacy };
|
|
||||||
|
|
||||||
/** Check if the account lacks required authorization.
|
|
||||||
*
|
|
||||||
* Return tecNO_AUTH or tecNO_LINE if it does
|
|
||||||
* and tesSUCCESS otherwise.
|
|
||||||
*
|
|
||||||
* If StrongAuth then return tecNO_LINE if the RippleState doesn't exist. Return
|
|
||||||
* tecNO_AUTH if lsfRequireAuth is set on the issuer's AccountRoot, and the
|
|
||||||
* RippleState does exist, and the RippleState is not authorized.
|
|
||||||
*
|
|
||||||
* If WeakAuth then return tecNO_AUTH if lsfRequireAuth is set, and the
|
|
||||||
* RippleState exists, and is not authorized. Return tecNO_LINE if
|
|
||||||
* lsfRequireAuth is set and the RippleState doesn't exist. Consequently, if
|
|
||||||
* WeakAuth and lsfRequireAuth is *not* set, this function will return
|
|
||||||
* tesSUCCESS even if RippleState does *not* exist.
|
|
||||||
*
|
|
||||||
* The default "Legacy" auth type is equivalent to WeakAuth.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
requireAuth(
|
|
||||||
ReadView const& view,
|
|
||||||
Issue const& issue,
|
|
||||||
AccountID const& account,
|
|
||||||
AuthType authType = AuthType::Legacy);
|
|
||||||
|
|
||||||
/** Check if the account lacks required authorization.
|
|
||||||
*
|
|
||||||
* This will also check for expired credentials. If it is called directly
|
|
||||||
* from preclaim, the user should convert result tecEXPIRED to tesSUCCESS and
|
|
||||||
* proceed to also check permissions with enforceMPTokenAuthorization inside
|
|
||||||
* doApply. This will ensure that any expired credentials are deleted.
|
|
||||||
*
|
|
||||||
* requireAuth check is recursive for MPT shares in a vault, descending to
|
|
||||||
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
|
||||||
* purely defensive, as we currently do not allow such vaults to be created.
|
|
||||||
*
|
|
||||||
* If StrongAuth then return tecNO_AUTH if MPToken doesn't exist or
|
|
||||||
* lsfMPTRequireAuth is set and MPToken is not authorized. Vault and LoanBroker
|
|
||||||
* pseudo-accounts are implicitly authorized.
|
|
||||||
*
|
|
||||||
* If WeakAuth then return tecNO_AUTH if lsfMPTRequireAuth is set and MPToken
|
|
||||||
* doesn't exist or is not authorized (explicitly or via credentials, if
|
|
||||||
* DomainID is set in MPTokenIssuance). Consequently, if WeakAuth and
|
|
||||||
* lsfMPTRequireAuth is *not* set, this function will return true even if
|
|
||||||
* MPToken does *not* exist.
|
|
||||||
*
|
|
||||||
* The default "Legacy" auth type is equivalent to StrongAuth.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
requireAuth(
|
|
||||||
ReadView const& view,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
AccountID const& account,
|
|
||||||
AuthType authType = AuthType::Legacy,
|
|
||||||
int depth = 0);
|
|
||||||
|
|
||||||
[[nodiscard]] TER inline requireAuth(
|
|
||||||
ReadView const& view,
|
|
||||||
Asset const& asset,
|
|
||||||
AccountID const& account,
|
|
||||||
AuthType authType = AuthType::Legacy)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&]<ValidIssueType TIss>(TIss const& issue_) {
|
|
||||||
return requireAuth(view, issue_, account, authType);
|
|
||||||
},
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Enforce account has MPToken to match its authorization.
|
|
||||||
*
|
|
||||||
* Called from doApply - it will check for expired (and delete if found any)
|
|
||||||
* credentials matching DomainID set in MPTokenIssuance. Must be called if
|
|
||||||
* requireAuth(...MPTIssue...) returned tesSUCCESS or tecEXPIRED in preclaim,
|
|
||||||
* which implies that preclaim should replace `tecEXPIRED` with `tesSUCCESS`
|
|
||||||
* in order for the transactor to proceed to doApply.
|
|
||||||
*
|
|
||||||
* This function will create MPToken (if needed) on the basis of any
|
|
||||||
* non-expired credentials and will delete any expired credentials, indirectly
|
|
||||||
* via verifyValidDomain, as per DomainID (if set in MPTokenIssuance).
|
|
||||||
*
|
|
||||||
* The caller does NOT need to ensure that DomainID is actually set - this
|
|
||||||
* function handles gracefully both cases when DomainID is set and when not.
|
|
||||||
*
|
|
||||||
* The caller does NOT need to look for existing MPToken to match
|
|
||||||
* mptIssue/account - this function checks lsfMPTAuthorized of an existing
|
|
||||||
* MPToken iff DomainID is not set.
|
|
||||||
*
|
|
||||||
* Do not use for accounts which hold implied permission e.g. object owners or
|
|
||||||
* if MPTokenIssuance does not require authorization. In both cases use
|
|
||||||
* MPTokenAuthorize::authorize if MPToken does not yet exist.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
enforceMPTokenAuthorization(
|
|
||||||
ApplyView& view,
|
|
||||||
MPTID const& mptIssuanceID,
|
|
||||||
AccountID const& account,
|
|
||||||
XRPAmount const& priorBalance,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
/** Check if the destination account is allowed
|
|
||||||
* to receive MPT. Return tecNO_AUTH if it doesn't
|
|
||||||
* and tesSUCCESS otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
canTransfer(
|
|
||||||
ReadView const& view,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
AccountID const& from,
|
|
||||||
AccountID const& to);
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, AccountID const& to);
|
|
||||||
|
|
||||||
[[nodiscard]] TER inline canTransfer(
|
|
||||||
ReadView const& view,
|
|
||||||
Asset const& asset,
|
|
||||||
AccountID const& from,
|
|
||||||
AccountID const& to)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
|
|
||||||
return canTransfer(view, issue, from, to);
|
|
||||||
},
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Deleter function prototype. Returns the status of the entry deletion
|
/** Deleter function prototype. Returns the status of the entry deletion
|
||||||
* (if should not be skipped) and if the entry should be skipped. The status
|
* (if should not be skipped) and if the entry should be skipped. The status
|
||||||
* is always tesSUCCESS if the entry should be skipped.
|
* is always tesSUCCESS if the entry should be skipped.
|
||||||
@@ -1052,57 +232,6 @@ cleanupOnAccountDelete(
|
|||||||
beast::Journal j,
|
beast::Journal j,
|
||||||
std::optional<std::uint16_t> maxNodesToDelete = std::nullopt);
|
std::optional<std::uint16_t> maxNodesToDelete = std::nullopt);
|
||||||
|
|
||||||
/** Delete trustline to AMM. The passed `sle` must be obtained from a prior
|
|
||||||
* call to view.peek(). Fail if neither side of the trustline is AMM or
|
|
||||||
* if ammAccountID is seated and is not one of the trustline's side.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
deleteAMMTrustLine(
|
|
||||||
ApplyView& view,
|
|
||||||
std::shared_ptr<SLE> sleState,
|
|
||||||
std::optional<AccountID> const& ammAccountID,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
// From the perspective of a vault, return the number of shares to give the
|
|
||||||
// depositor when they deposit a fixed amount of assets. Since shares are MPT
|
|
||||||
// this number is integral and always truncated in this calculation.
|
|
||||||
[[nodiscard]] std::optional<STAmount>
|
|
||||||
assetsToSharesDeposit(
|
|
||||||
std::shared_ptr<SLE const> const& vault,
|
|
||||||
std::shared_ptr<SLE const> const& issuance,
|
|
||||||
STAmount const& assets);
|
|
||||||
|
|
||||||
// From the perspective of a vault, return the number of assets to take from
|
|
||||||
// depositor when they receive a fixed amount of shares. Note, since shares are
|
|
||||||
// MPT, they are always an integral number.
|
|
||||||
[[nodiscard]] std::optional<STAmount>
|
|
||||||
sharesToAssetsDeposit(
|
|
||||||
std::shared_ptr<SLE const> const& vault,
|
|
||||||
std::shared_ptr<SLE const> const& issuance,
|
|
||||||
STAmount const& shares);
|
|
||||||
|
|
||||||
enum class TruncateShares : bool { no = false, yes = true };
|
|
||||||
|
|
||||||
// From the perspective of a vault, return the number of shares to demand from
|
|
||||||
// the depositor when they ask to withdraw a fixed amount of assets. Since
|
|
||||||
// shares are MPT this number is integral, and it will be rounded to nearest
|
|
||||||
// unless explicitly requested to be truncated instead.
|
|
||||||
[[nodiscard]] std::optional<STAmount>
|
|
||||||
assetsToSharesWithdraw(
|
|
||||||
std::shared_ptr<SLE const> const& vault,
|
|
||||||
std::shared_ptr<SLE const> const& issuance,
|
|
||||||
STAmount const& assets,
|
|
||||||
TruncateShares truncate = TruncateShares::no);
|
|
||||||
|
|
||||||
// From the perspective of a vault, return the number of assets to give the
|
|
||||||
// depositor when they redeem a fixed amount of shares. Note, since shares are
|
|
||||||
// MPT, they are always an integral number.
|
|
||||||
[[nodiscard]] std::optional<STAmount>
|
|
||||||
sharesToAssetsWithdraw(
|
|
||||||
std::shared_ptr<SLE const> const& vault,
|
|
||||||
std::shared_ptr<SLE const> const& issuance,
|
|
||||||
STAmount const& shares);
|
|
||||||
|
|
||||||
/** Has the specified time passed?
|
/** Has the specified time passed?
|
||||||
|
|
||||||
@param now the current time
|
@param now the current time
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ public:
|
|||||||
static constexpr size_t initialBufferSize = kilobytes(256);
|
static constexpr size_t initialBufferSize = kilobytes(256);
|
||||||
|
|
||||||
RawStateTable()
|
RawStateTable()
|
||||||
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
: monotonic_resource_{
|
||||||
initialBufferSize)}
|
std::make_unique<boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)}
|
||||||
, items_{monotonic_resource_.get()} {};
|
, items_{monotonic_resource_.get()} {};
|
||||||
|
|
||||||
RawStateTable(RawStateTable const& rhs)
|
RawStateTable(RawStateTable const& rhs)
|
||||||
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
: monotonic_resource_{
|
||||||
initialBufferSize)}
|
std::make_unique<boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)}
|
||||||
, items_{rhs.items_, monotonic_resource_.get()}
|
, items_{rhs.items_, monotonic_resource_.get()}
|
||||||
, dropsDestroyed_{rhs.dropsDestroyed_} {};
|
, dropsDestroyed_{rhs.dropsDestroyed_} {};
|
||||||
|
|
||||||
|
|||||||
112
include/xrpl/ledger/helpers/AccountRootHelpers.h
Normal file
112
include/xrpl/ledger/helpers/AccountRootHelpers.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/basics/Expected.h>
|
||||||
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
#include <xrpl/ledger/ApplyView.h>
|
||||||
|
#include <xrpl/ledger/ReadView.h>
|
||||||
|
#include <xrpl/protocol/Indexes.h>
|
||||||
|
#include <xrpl/protocol/Rate.h>
|
||||||
|
#include <xrpl/protocol/STLedgerEntry.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace xrpl {
|
||||||
|
|
||||||
|
/** Check if the issuer has the global freeze flag set.
|
||||||
|
@param issuer The account to check
|
||||||
|
@return true if the account has global freeze set
|
||||||
|
*/
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isGlobalFrozen(ReadView const& view, AccountID const& issuer);
|
||||||
|
|
||||||
|
// Calculate liquid XRP balance for an account.
|
||||||
|
// This function may be used to calculate the amount of XRP that
|
||||||
|
// the holder is able to freely spend. It subtracts reserve requirements.
|
||||||
|
//
|
||||||
|
// ownerCountAdj adjusts the owner count in case the caller calculates
|
||||||
|
// before ledger entries are added or removed. Positive to add, negative
|
||||||
|
// to subtract.
|
||||||
|
//
|
||||||
|
// @param ownerCountAdj positive to add to count, negative to reduce count.
|
||||||
|
[[nodiscard]] XRPAmount
|
||||||
|
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j);
|
||||||
|
|
||||||
|
/** Adjust the owner count up or down. */
|
||||||
|
void
|
||||||
|
adjustOwnerCount(
|
||||||
|
ApplyView& view,
|
||||||
|
std::shared_ptr<SLE> const& sle,
|
||||||
|
std::int32_t amount,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
/** Returns IOU issuer transfer fee as Rate. Rate specifies
|
||||||
|
* the fee as fractions of 1 billion. For example, 1% transfer rate
|
||||||
|
* is represented as 1,010,000,000.
|
||||||
|
* @param issuer The IOU issuer
|
||||||
|
*/
|
||||||
|
[[nodiscard]] Rate
|
||||||
|
transferRate(ReadView const& view, AccountID const& issuer);
|
||||||
|
|
||||||
|
/** Generate a pseudo-account address from a pseudo owner key.
|
||||||
|
@param pseudoOwnerKey The key to generate the address from
|
||||||
|
@return The generated account ID
|
||||||
|
*/
|
||||||
|
AccountID
|
||||||
|
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey);
|
||||||
|
|
||||||
|
/** Returns the list of fields that define an ACCOUNT_ROOT as a pseudo-account
|
||||||
|
if set.
|
||||||
|
|
||||||
|
The list is constructed during initialization and is const after that.
|
||||||
|
Pseudo-account designator fields MUST be maintained by including the
|
||||||
|
SField::sMD_PseudoAccount flag in the SField definition.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::vector<SField const*> const&
|
||||||
|
getPseudoAccountFields();
|
||||||
|
|
||||||
|
/** Returns true if and only if sleAcct is a pseudo-account or specific
|
||||||
|
pseudo-accounts in pseudoFieldFilter.
|
||||||
|
|
||||||
|
Returns false if sleAcct is:
|
||||||
|
- NOT a pseudo-account OR
|
||||||
|
- NOT a ltACCOUNT_ROOT OR
|
||||||
|
- null pointer
|
||||||
|
*/
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isPseudoAccount(
|
||||||
|
std::shared_ptr<SLE const> sleAcct,
|
||||||
|
std::set<SField const*> const& pseudoFieldFilter = {});
|
||||||
|
|
||||||
|
/** Convenience overload that reads the account from the view. */
|
||||||
|
[[nodiscard]] inline bool
|
||||||
|
isPseudoAccount(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& accountId,
|
||||||
|
std::set<SField const*> const& pseudoFieldFilter = {})
|
||||||
|
{
|
||||||
|
return isPseudoAccount(view.read(keylet::account(accountId)), pseudoFieldFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create pseudo-account, storing pseudoOwnerKey into ownerField.
|
||||||
|
*
|
||||||
|
* The list of valid ownerField is maintained in AccountRootHelpers.cpp and
|
||||||
|
* the caller to this function must perform necessary amendment check(s)
|
||||||
|
* before using a field. The amendment check is **not** performed in
|
||||||
|
* createPseudoAccount.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] Expected<std::shared_ptr<SLE>, TER>
|
||||||
|
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField);
|
||||||
|
|
||||||
|
/** Checks the destination and tag.
|
||||||
|
|
||||||
|
- Checks that the SLE is not null.
|
||||||
|
- If the SLE requires a destination tag, checks that there is a tag.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag);
|
||||||
|
|
||||||
|
} // namespace xrpl
|
||||||
@@ -49,7 +49,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject);
|
|||||||
// This function is only called when we about to return tecNO_PERMISSION
|
// This function is only called when we about to return tecNO_PERMISSION
|
||||||
// because all the checks for the DepositPreauth authorization failed.
|
// because all the checks for the DepositPreauth authorization failed.
|
||||||
TER
|
TER
|
||||||
authorizedDepositPreauth(ApplyView const& view, STVector256 const& ctx, AccountID const& dst);
|
authorizedDepositPreauth(ReadView const& view, STVector256 const& ctx, AccountID const& dst);
|
||||||
|
|
||||||
// Sort credentials array, return empty set if there are duplicates
|
// Sort credentials array, return empty set if there are duplicates
|
||||||
std::set<std::pair<AccountID, Slice>>
|
std::set<std::pair<AccountID, Slice>>
|
||||||
@@ -74,7 +74,7 @@ verifyDepositPreauth(
|
|||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
AccountID const& src,
|
AccountID const& src,
|
||||||
AccountID const& dst,
|
AccountID const& dst,
|
||||||
std::shared_ptr<SLE> const& sleDst,
|
std::shared_ptr<SLE const> const& sleDst,
|
||||||
beast::Journal j);
|
beast::Journal j);
|
||||||
|
|
||||||
} // namespace xrpl
|
} // namespace xrpl
|
||||||
223
include/xrpl/ledger/helpers/DirectoryHelpers.h
Normal file
223
include/xrpl/ledger/helpers/DirectoryHelpers.h
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
#include <xrpl/ledger/ApplyView.h>
|
||||||
|
#include <xrpl/ledger/ReadView.h>
|
||||||
|
#include <xrpl/protocol/Indexes.h>
|
||||||
|
#include <xrpl/protocol/STLedgerEntry.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace xrpl {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <
|
||||||
|
class V,
|
||||||
|
class N,
|
||||||
|
class = std::enable_if_t<
|
||||||
|
std::is_same_v<std::remove_cv_t<N>, SLE> && std::is_base_of_v<ReadView, V>>>
|
||||||
|
bool
|
||||||
|
internalDirNext(
|
||||||
|
V& view,
|
||||||
|
uint256 const& root,
|
||||||
|
std::shared_ptr<N>& page,
|
||||||
|
unsigned int& index,
|
||||||
|
uint256& entry)
|
||||||
|
{
|
||||||
|
auto const& svIndexes = page->getFieldV256(sfIndexes);
|
||||||
|
XRPL_ASSERT(index <= svIndexes.size(), "xrpl::detail::internalDirNext : index inside range");
|
||||||
|
|
||||||
|
if (index >= svIndexes.size())
|
||||||
|
{
|
||||||
|
auto const next = page->getFieldU64(sfIndexNext);
|
||||||
|
|
||||||
|
if (!next)
|
||||||
|
{
|
||||||
|
entry.zero();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::is_const_v<N>)
|
||||||
|
{
|
||||||
|
page = view.read(keylet::page(root, next));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
page = view.peek(keylet::page(root, next));
|
||||||
|
}
|
||||||
|
|
||||||
|
XRPL_ASSERT(page, "xrpl::detail::internalDirNext : non-null root");
|
||||||
|
|
||||||
|
if (!page)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
return internalDirNext(view, root, page, index, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = svIndexes[index++];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
class V,
|
||||||
|
class N,
|
||||||
|
class = std::enable_if_t<
|
||||||
|
std::is_same_v<std::remove_cv_t<N>, SLE> && std::is_base_of_v<ReadView, V>>>
|
||||||
|
bool
|
||||||
|
internalDirFirst(
|
||||||
|
V& view,
|
||||||
|
uint256 const& root,
|
||||||
|
std::shared_ptr<N>& page,
|
||||||
|
unsigned int& index,
|
||||||
|
uint256& entry)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_const_v<N>)
|
||||||
|
{
|
||||||
|
page = view.read(keylet::page(root));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
page = view.peek(keylet::page(root));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!page)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
return internalDirNext(view, root, page, index, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/** @{ */
|
||||||
|
/** Returns the first entry in the directory, advancing the index
|
||||||
|
|
||||||
|
@deprecated These are legacy function that are considered deprecated
|
||||||
|
and will soon be replaced with an iterator-based model
|
||||||
|
that is easier to use. You should not use them in new code.
|
||||||
|
|
||||||
|
@param view The view against which to operate
|
||||||
|
@param root The root (i.e. first page) of the directory to iterate
|
||||||
|
@param page The current page
|
||||||
|
@param index The index inside the current page
|
||||||
|
@param entry The entry at the current index
|
||||||
|
|
||||||
|
@return true if the directory isn't empty; false otherwise
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
cdirFirst(
|
||||||
|
ReadView const& view,
|
||||||
|
uint256 const& root,
|
||||||
|
std::shared_ptr<SLE const>& page,
|
||||||
|
unsigned int& index,
|
||||||
|
uint256& entry);
|
||||||
|
|
||||||
|
bool
|
||||||
|
dirFirst(
|
||||||
|
ApplyView& view,
|
||||||
|
uint256 const& root,
|
||||||
|
std::shared_ptr<SLE>& page,
|
||||||
|
unsigned int& index,
|
||||||
|
uint256& entry);
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** @{ */
|
||||||
|
/** Returns the next entry in the directory, advancing the index
|
||||||
|
|
||||||
|
@deprecated These are legacy function that are considered deprecated
|
||||||
|
and will soon be replaced with an iterator-based model
|
||||||
|
that is easier to use. You should not use them in new code.
|
||||||
|
|
||||||
|
@param view The view against which to operate
|
||||||
|
@param root The root (i.e. first page) of the directory to iterate
|
||||||
|
@param page The current page
|
||||||
|
@param index The index inside the current page
|
||||||
|
@param entry The entry at the current index
|
||||||
|
|
||||||
|
@return true if the directory isn't empty; false otherwise
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
cdirNext(
|
||||||
|
ReadView const& view,
|
||||||
|
uint256 const& root,
|
||||||
|
std::shared_ptr<SLE const>& page,
|
||||||
|
unsigned int& index,
|
||||||
|
uint256& entry);
|
||||||
|
|
||||||
|
bool
|
||||||
|
dirNext(
|
||||||
|
ApplyView& view,
|
||||||
|
uint256 const& root,
|
||||||
|
std::shared_ptr<SLE>& page,
|
||||||
|
unsigned int& index,
|
||||||
|
uint256& entry);
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** Iterate all items in the given directory. */
|
||||||
|
void
|
||||||
|
forEachItem(
|
||||||
|
ReadView const& view,
|
||||||
|
Keylet const& root,
|
||||||
|
std::function<void(std::shared_ptr<SLE const> const&)> const& f);
|
||||||
|
|
||||||
|
/** Iterate all items after an item in the given directory.
|
||||||
|
@param after The key of the item to start after
|
||||||
|
@param hint The directory page containing `after`
|
||||||
|
@param limit The maximum number of items to return
|
||||||
|
@return `false` if the iteration failed
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
forEachItemAfter(
|
||||||
|
ReadView const& view,
|
||||||
|
Keylet const& root,
|
||||||
|
uint256 const& after,
|
||||||
|
std::uint64_t const hint,
|
||||||
|
unsigned int limit,
|
||||||
|
std::function<bool(std::shared_ptr<SLE const> const&)> const& f);
|
||||||
|
|
||||||
|
/** Iterate all items in an account's owner directory. */
|
||||||
|
inline void
|
||||||
|
forEachItem(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& id,
|
||||||
|
std::function<void(std::shared_ptr<SLE const> const&)> const& f)
|
||||||
|
{
|
||||||
|
return forEachItem(view, keylet::ownerDir(id), f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Iterate all items after an item in an owner directory.
|
||||||
|
@param after The key of the item to start after
|
||||||
|
@param hint The directory page containing `after`
|
||||||
|
@param limit The maximum number of items to return
|
||||||
|
@return `false` if the iteration failed
|
||||||
|
*/
|
||||||
|
inline bool
|
||||||
|
forEachItemAfter(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& id,
|
||||||
|
uint256 const& after,
|
||||||
|
std::uint64_t const hint,
|
||||||
|
unsigned int limit,
|
||||||
|
std::function<bool(std::shared_ptr<SLE const> const&)> const& f)
|
||||||
|
{
|
||||||
|
return forEachItemAfter(view, keylet::ownerDir(id), after, hint, limit, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns `true` if the directory is empty
|
||||||
|
@param key The key of the directory
|
||||||
|
*/
|
||||||
|
[[nodiscard]] bool
|
||||||
|
dirIsEmpty(ReadView const& view, Keylet const& k);
|
||||||
|
|
||||||
|
/** Returns a function that sets the owner on a directory SLE */
|
||||||
|
[[nodiscard]] std::function<void(SLE::ref)>
|
||||||
|
describeOwnerDir(AccountID const& account);
|
||||||
|
|
||||||
|
} // namespace xrpl
|
||||||
160
include/xrpl/ledger/helpers/MPTokenHelpers.h
Normal file
160
include/xrpl/ledger/helpers/MPTokenHelpers.h
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
#include <xrpl/ledger/ApplyView.h>
|
||||||
|
#include <xrpl/ledger/ReadView.h>
|
||||||
|
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||||
|
#include <xrpl/protocol/MPTIssue.h>
|
||||||
|
#include <xrpl/protocol/Rate.h>
|
||||||
|
#include <xrpl/protocol/STAmount.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace xrpl {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Freeze checking (MPT-specific)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue);
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth = 0);
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isAnyFrozen(
|
||||||
|
ReadView const& view,
|
||||||
|
std::initializer_list<AccountID> const& accounts,
|
||||||
|
MPTIssue const& mptIssue,
|
||||||
|
int depth = 0);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Transfer rate (MPT-specific)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Returns MPT transfer fee as Rate. Rate specifies
|
||||||
|
* the fee as fractions of 1 billion. For example, 1% transfer rate
|
||||||
|
* is represented as 1,010,000,000.
|
||||||
|
* @param issuanceID MPTokenIssuanceID of MPTTokenIssuance object
|
||||||
|
*/
|
||||||
|
[[nodiscard]] Rate
|
||||||
|
transferRate(ReadView const& view, MPTID const& issuanceID);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Holding checks (MPT-specific)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
canAddHolding(ReadView const& view, MPTIssue const& mptIssue);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Authorization (MPT-specific)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
authorizeMPToken(
|
||||||
|
ApplyView& view,
|
||||||
|
XRPAmount const& priorBalance,
|
||||||
|
MPTID const& mptIssuanceID,
|
||||||
|
AccountID const& account,
|
||||||
|
beast::Journal journal,
|
||||||
|
std::uint32_t flags = 0,
|
||||||
|
std::optional<AccountID> holderID = std::nullopt);
|
||||||
|
|
||||||
|
/** Check if the account lacks required authorization for MPT.
|
||||||
|
*
|
||||||
|
* requireAuth check is recursive for MPT shares in a vault, descending to
|
||||||
|
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
||||||
|
* purely defensive, as we currently do not allow such vaults to be created.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
requireAuth(
|
||||||
|
ReadView const& view,
|
||||||
|
MPTIssue const& mptIssue,
|
||||||
|
AccountID const& account,
|
||||||
|
AuthType authType = AuthType::Legacy,
|
||||||
|
int depth = 0);
|
||||||
|
|
||||||
|
/** Enforce account has MPToken to match its authorization.
|
||||||
|
*
|
||||||
|
* Called from doApply - it will check for expired (and delete if found any)
|
||||||
|
* credentials matching DomainID set in MPTokenIssuance. Must be called if
|
||||||
|
* requireAuth(...MPTIssue...) returned tesSUCCESS or tecEXPIRED in preclaim.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
enforceMPTokenAuthorization(
|
||||||
|
ApplyView& view,
|
||||||
|
MPTID const& mptIssuanceID,
|
||||||
|
AccountID const& account,
|
||||||
|
XRPAmount const& priorBalance,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
/** Check if the destination account is allowed
|
||||||
|
* to receive MPT. Return tecNO_AUTH if it doesn't
|
||||||
|
* and tesSUCCESS otherwise.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
canTransfer(
|
||||||
|
ReadView const& view,
|
||||||
|
MPTIssue const& mptIssue,
|
||||||
|
AccountID const& from,
|
||||||
|
AccountID const& to);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Empty holding operations (MPT-specific)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
addEmptyHolding(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& accountID,
|
||||||
|
XRPAmount priorBalance,
|
||||||
|
MPTIssue const& mptIssue,
|
||||||
|
beast::Journal journal);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
removeEmptyHolding(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& accountID,
|
||||||
|
MPTIssue const& mptIssue,
|
||||||
|
beast::Journal journal);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Escrow operations (MPT-specific)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TER
|
||||||
|
rippleLockEscrowMPT(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& uGrantorID,
|
||||||
|
STAmount const& saAmount,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
TER
|
||||||
|
rippleUnlockEscrowMPT(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& uGrantorID,
|
||||||
|
AccountID const& uGranteeID,
|
||||||
|
STAmount const& netAmount,
|
||||||
|
STAmount const& grossAmount,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
} // namespace xrpl
|
||||||
28
include/xrpl/ledger/helpers/OfferHelpers.h
Normal file
28
include/xrpl/ledger/helpers/OfferHelpers.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
#include <xrpl/ledger/ApplyView.h>
|
||||||
|
#include <xrpl/protocol/STLedgerEntry.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace xrpl {
|
||||||
|
|
||||||
|
/** Delete an offer.
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
The offer must exist.
|
||||||
|
The caller must have already checked permissions.
|
||||||
|
|
||||||
|
@param view The ApplyView to modify.
|
||||||
|
@param sle The offer to delete.
|
||||||
|
@param j Journal for logging.
|
||||||
|
|
||||||
|
@return tesSUCCESS on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
// [[nodiscard]] // nodiscard commented out so Flow, BookTip and others compile.
|
||||||
|
TER
|
||||||
|
offerDelete(ApplyView& view, std::shared_ptr<SLE> const& sle, beast::Journal j);
|
||||||
|
|
||||||
|
} // namespace xrpl
|
||||||
255
include/xrpl/ledger/helpers/RippleStateHelpers.h
Normal file
255
include/xrpl/ledger/helpers/RippleStateHelpers.h
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
#include <xrpl/ledger/ApplyView.h>
|
||||||
|
#include <xrpl/ledger/ReadView.h>
|
||||||
|
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||||
|
#include <xrpl/protocol/IOUAmount.h>
|
||||||
|
#include <xrpl/protocol/Issue.h>
|
||||||
|
#include <xrpl/protocol/STAmount.h>
|
||||||
|
#include <xrpl/protocol/STLedgerEntry.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// RippleState (Trustline) helpers
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace xrpl {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Credit functions (from Credit.h)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Calculate the maximum amount of IOUs that an account can hold
|
||||||
|
@param view the ledger to check against.
|
||||||
|
@param account the account of interest.
|
||||||
|
@param issuer the issuer of the IOU.
|
||||||
|
@param currency the IOU to check.
|
||||||
|
@return The maximum amount that can be held.
|
||||||
|
*/
|
||||||
|
/** @{ */
|
||||||
|
STAmount
|
||||||
|
creditLimit(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
AccountID const& issuer,
|
||||||
|
Currency const& currency);
|
||||||
|
|
||||||
|
IOUAmount
|
||||||
|
creditLimit2(ReadView const& v, AccountID const& acc, AccountID const& iss, Currency const& cur);
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** Returns the amount of IOUs issued by issuer that are held by an account
|
||||||
|
@param view the ledger to check against.
|
||||||
|
@param account the account of interest.
|
||||||
|
@param issuer the issuer of the IOU.
|
||||||
|
@param currency the IOU to check.
|
||||||
|
*/
|
||||||
|
/** @{ */
|
||||||
|
STAmount
|
||||||
|
creditBalance(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
AccountID const& issuer,
|
||||||
|
Currency const& currency);
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Freeze checking (IOU-specific)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isIndividualFrozen(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
Currency const& currency,
|
||||||
|
AccountID const& issuer);
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool
|
||||||
|
isIndividualFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
|
||||||
|
{
|
||||||
|
return isIndividualFrozen(view, account, issue.currency, issue.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isFrozen(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
Currency const& currency,
|
||||||
|
AccountID const& issuer);
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool
|
||||||
|
isFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
|
||||||
|
{
|
||||||
|
return isFrozen(view, account, issue.currency, issue.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overload with depth parameter for uniformity with MPTIssue version.
|
||||||
|
// The depth parameter is ignored for IOUs since they don't have vault recursion.
|
||||||
|
[[nodiscard]] inline bool
|
||||||
|
isFrozen(ReadView const& view, AccountID const& account, Issue const& issue, int /*depth*/)
|
||||||
|
{
|
||||||
|
return isFrozen(view, account, issue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isDeepFrozen(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
Currency const& currency,
|
||||||
|
AccountID const& issuer);
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool
|
||||||
|
isDeepFrozen(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
Issue const& issue,
|
||||||
|
int = 0 /*ignored*/)
|
||||||
|
{
|
||||||
|
return isDeepFrozen(view, account, issue.currency, issue.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline TER
|
||||||
|
checkDeepFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
|
||||||
|
{
|
||||||
|
return isDeepFrozen(view, account, issue) ? (TER)tecFROZEN : (TER)tesSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Trust line operations
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Create a trust line
|
||||||
|
|
||||||
|
This can set an initial balance.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
trustCreate(
|
||||||
|
ApplyView& view,
|
||||||
|
bool const bSrcHigh,
|
||||||
|
AccountID const& uSrcAccountID,
|
||||||
|
AccountID const& uDstAccountID,
|
||||||
|
uint256 const& uIndex, // --> ripple state entry
|
||||||
|
SLE::ref sleAccount, // --> the account being set.
|
||||||
|
bool const bAuth, // --> authorize account.
|
||||||
|
bool const bNoRipple, // --> others cannot ripple through
|
||||||
|
bool const bFreeze, // --> funds cannot leave
|
||||||
|
bool bDeepFreeze, // --> can neither receive nor send funds
|
||||||
|
STAmount const& saBalance, // --> balance of account being set.
|
||||||
|
// Issuer should be noAccount()
|
||||||
|
STAmount const& saLimit, // --> limit for account being set.
|
||||||
|
// Issuer should be the account being set.
|
||||||
|
std::uint32_t uQualityIn,
|
||||||
|
std::uint32_t uQualityOut,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
trustDelete(
|
||||||
|
ApplyView& view,
|
||||||
|
std::shared_ptr<SLE> const& sleRippleState,
|
||||||
|
AccountID const& uLowAccountID,
|
||||||
|
AccountID const& uHighAccountID,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// IOU issuance/redemption
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
issueIOU(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& account,
|
||||||
|
STAmount const& amount,
|
||||||
|
Issue const& issue,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
redeemIOU(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& account,
|
||||||
|
STAmount const& amount,
|
||||||
|
Issue const& issue,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Authorization and transfer checks (IOU-specific)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Check if the account lacks required authorization.
|
||||||
|
*
|
||||||
|
* Return tecNO_AUTH or tecNO_LINE if it does
|
||||||
|
* and tesSUCCESS otherwise.
|
||||||
|
*
|
||||||
|
* If StrongAuth then return tecNO_LINE if the RippleState doesn't exist. Return
|
||||||
|
* tecNO_AUTH if lsfRequireAuth is set on the issuer's AccountRoot, and the
|
||||||
|
* RippleState does exist, and the RippleState is not authorized.
|
||||||
|
*
|
||||||
|
* If WeakAuth then return tecNO_AUTH if lsfRequireAuth is set, and the
|
||||||
|
* RippleState exists, and is not authorized. Return tecNO_LINE if
|
||||||
|
* lsfRequireAuth is set and the RippleState doesn't exist. Consequently, if
|
||||||
|
* WeakAuth and lsfRequireAuth is *not* set, this function will return
|
||||||
|
* tesSUCCESS even if RippleState does *not* exist.
|
||||||
|
*
|
||||||
|
* The default "Legacy" auth type is equivalent to WeakAuth.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
requireAuth(
|
||||||
|
ReadView const& view,
|
||||||
|
Issue const& issue,
|
||||||
|
AccountID const& account,
|
||||||
|
AuthType authType = AuthType::Legacy);
|
||||||
|
|
||||||
|
/** Check if the destination account is allowed
|
||||||
|
* to receive IOU. Return terNO_RIPPLE if rippling is
|
||||||
|
* disabled on both sides and tesSUCCESS otherwise.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, AccountID const& to);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Empty holding operations (IOU-specific)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Any transactors that call addEmptyHolding() in doApply must call
|
||||||
|
/// canAddHolding() in preflight with the same View and Asset
|
||||||
|
[[nodiscard]] TER
|
||||||
|
addEmptyHolding(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& accountID,
|
||||||
|
XRPAmount priorBalance,
|
||||||
|
Issue const& issue,
|
||||||
|
beast::Journal journal);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
removeEmptyHolding(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& accountID,
|
||||||
|
Issue const& issue,
|
||||||
|
beast::Journal journal);
|
||||||
|
|
||||||
|
/** Delete trustline to AMM. The passed `sle` must be obtained from a prior
|
||||||
|
* call to view.peek(). Fail if neither side of the trustline is AMM or
|
||||||
|
* if ammAccountID is seated and is not one of the trustline's side.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
deleteAMMTrustLine(
|
||||||
|
ApplyView& view,
|
||||||
|
std::shared_ptr<SLE> sleState,
|
||||||
|
std::optional<AccountID> const& ammAccountID,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
} // namespace xrpl
|
||||||
286
include/xrpl/ledger/helpers/TokenHelpers.h
Normal file
286
include/xrpl/ledger/helpers/TokenHelpers.h
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
#include <xrpl/ledger/ApplyView.h>
|
||||||
|
#include <xrpl/ledger/ReadView.h>
|
||||||
|
#include <xrpl/protocol/Asset.h>
|
||||||
|
#include <xrpl/protocol/MPTIssue.h>
|
||||||
|
#include <xrpl/protocol/Rate.h>
|
||||||
|
#include <xrpl/protocol/STAmount.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace xrpl {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Enums for token handling
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Controls the treatment of frozen account balances */
|
||||||
|
enum FreezeHandling { fhIGNORE_FREEZE, fhZERO_IF_FROZEN };
|
||||||
|
|
||||||
|
/** Controls the treatment of unauthorized MPT balances */
|
||||||
|
enum AuthHandling { ahIGNORE_AUTH, ahZERO_IF_UNAUTHORIZED };
|
||||||
|
|
||||||
|
/** Controls whether to include the account's full spendable balance */
|
||||||
|
enum SpendableHandling { shSIMPLE_BALANCE, shFULL_BALANCE };
|
||||||
|
|
||||||
|
enum class WaiveTransferFee : bool { No = false, Yes };
|
||||||
|
|
||||||
|
/* Check if MPToken (for MPT) or trust line (for IOU) exists:
|
||||||
|
* - StrongAuth - before checking if authorization is required
|
||||||
|
* - WeakAuth
|
||||||
|
* for MPT - after checking lsfMPTRequireAuth flag
|
||||||
|
* for IOU - do not check if trust line exists
|
||||||
|
* - Legacy
|
||||||
|
* for MPT - before checking lsfMPTRequireAuth flag i.e. same as StrongAuth
|
||||||
|
* for IOU - do not check if trust line exists i.e. same as WeakAuth
|
||||||
|
*/
|
||||||
|
enum class AuthType { StrongAuth, WeakAuth, Legacy };
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Freeze checking (Asset-based dispatchers)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isGlobalFrozen(ReadView const& view, Asset const& asset);
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isFrozen check is recursive for MPT shares in a vault, descending to
|
||||||
|
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
||||||
|
* purely defensive, as we currently do not allow such vaults to be created.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
checkFrozen(ReadView const& view, AccountID const& account, Issue const& issue);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
checkFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
checkFrozen(ReadView const& view, AccountID const& account, Asset const& asset);
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isAnyFrozen(
|
||||||
|
ReadView const& view,
|
||||||
|
std::initializer_list<AccountID> const& accounts,
|
||||||
|
Issue const& issue);
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isAnyFrozen(
|
||||||
|
ReadView const& view,
|
||||||
|
std::initializer_list<AccountID> const& accounts,
|
||||||
|
Asset const& asset,
|
||||||
|
int depth = 0);
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isDeepFrozen(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
MPTIssue const& mptIssue,
|
||||||
|
int depth = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isFrozen check is recursive for MPT shares in a vault, descending to
|
||||||
|
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
||||||
|
* purely defensive, as we currently do not allow such vaults to be created.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] bool
|
||||||
|
isDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
checkDeepFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
checkDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Account balance functions (Asset-based dispatchers)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Returns the amount an account can spend.
|
||||||
|
//
|
||||||
|
// If shSIMPLE_BALANCE is specified, this is the amount the account can spend
|
||||||
|
// without going into debt.
|
||||||
|
//
|
||||||
|
// If shFULL_BALANCE is specified, this is the amount the account can spend
|
||||||
|
// total. Specifically:
|
||||||
|
// * The account can go into debt if using a trust line, and the other side has
|
||||||
|
// a non-zero limit.
|
||||||
|
// * If the account is the asset issuer the limit is defined by the asset /
|
||||||
|
// issuance.
|
||||||
|
//
|
||||||
|
// <-- saAmount: amount of currency held by account. May be negative.
|
||||||
|
[[nodiscard]] STAmount
|
||||||
|
accountHolds(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
Currency const& currency,
|
||||||
|
AccountID const& issuer,
|
||||||
|
FreezeHandling zeroIfFrozen,
|
||||||
|
beast::Journal j,
|
||||||
|
SpendableHandling includeFullBalance = shSIMPLE_BALANCE);
|
||||||
|
|
||||||
|
[[nodiscard]] STAmount
|
||||||
|
accountHolds(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
Issue const& issue,
|
||||||
|
FreezeHandling zeroIfFrozen,
|
||||||
|
beast::Journal j,
|
||||||
|
SpendableHandling includeFullBalance = shSIMPLE_BALANCE);
|
||||||
|
|
||||||
|
[[nodiscard]] STAmount
|
||||||
|
accountHolds(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
MPTIssue const& mptIssue,
|
||||||
|
FreezeHandling zeroIfFrozen,
|
||||||
|
AuthHandling zeroIfUnauthorized,
|
||||||
|
beast::Journal j,
|
||||||
|
SpendableHandling includeFullBalance = shSIMPLE_BALANCE);
|
||||||
|
|
||||||
|
[[nodiscard]] STAmount
|
||||||
|
accountHolds(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& account,
|
||||||
|
Asset const& asset,
|
||||||
|
FreezeHandling zeroIfFrozen,
|
||||||
|
AuthHandling zeroIfUnauthorized,
|
||||||
|
beast::Journal j,
|
||||||
|
SpendableHandling includeFullBalance = shSIMPLE_BALANCE);
|
||||||
|
|
||||||
|
// Returns the amount an account can spend of the currency type saDefault, or
|
||||||
|
// returns saDefault if this account is the issuer of the currency in
|
||||||
|
// question. Should be used in favor of accountHolds when questioning how much
|
||||||
|
// an account can spend while also allowing currency issuers to spend
|
||||||
|
// unlimited amounts of their own currency (since they can always issue more).
|
||||||
|
[[nodiscard]] STAmount
|
||||||
|
accountFunds(
|
||||||
|
ReadView const& view,
|
||||||
|
AccountID const& id,
|
||||||
|
STAmount const& saDefault,
|
||||||
|
FreezeHandling freezeHandling,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
/** Returns the transfer fee as Rate based on the type of token
|
||||||
|
* @param view The ledger view
|
||||||
|
* @param amount The amount to transfer
|
||||||
|
*/
|
||||||
|
[[nodiscard]] Rate
|
||||||
|
transferRate(ReadView const& view, STAmount const& amount);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Holding operations (Asset-based dispatchers)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
canAddHolding(ReadView const& view, Asset const& asset);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
addEmptyHolding(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& accountID,
|
||||||
|
XRPAmount priorBalance,
|
||||||
|
Asset const& asset,
|
||||||
|
beast::Journal journal);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
removeEmptyHolding(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& accountID,
|
||||||
|
Asset const& asset,
|
||||||
|
beast::Journal journal);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Authorization and transfer checks (Asset-based dispatchers)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
requireAuth(
|
||||||
|
ReadView const& view,
|
||||||
|
Asset const& asset,
|
||||||
|
AccountID const& account,
|
||||||
|
AuthType authType = AuthType::Legacy);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
canTransfer(ReadView const& view, Asset const& asset, AccountID const& from, AccountID const& to);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Money Transfers (Asset-based dispatchers)
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Direct send w/o fees:
|
||||||
|
// - Redeeming IOUs and/or sending sender's own IOUs.
|
||||||
|
// - Create trust line of needed.
|
||||||
|
// --> bCheckIssuer : normally require issuer to be involved.
|
||||||
|
// [[nodiscard]] // nodiscard commented out so DirectStep.cpp compiles.
|
||||||
|
|
||||||
|
/** Calls static rippleCreditIOU if saAmount represents Issue.
|
||||||
|
* Calls static rippleCreditMPT if saAmount represents MPTIssue.
|
||||||
|
*/
|
||||||
|
TER
|
||||||
|
rippleCredit(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& uSenderID,
|
||||||
|
AccountID const& uReceiverID,
|
||||||
|
STAmount const& saAmount,
|
||||||
|
bool bCheckIssuer,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
/** Calls static accountSendIOU if saAmount represents Issue.
|
||||||
|
* Calls static accountSendMPT if saAmount represents MPTIssue.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
accountSend(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& from,
|
||||||
|
AccountID const& to,
|
||||||
|
STAmount const& saAmount,
|
||||||
|
beast::Journal j,
|
||||||
|
WaiveTransferFee waiveFee = WaiveTransferFee::No);
|
||||||
|
|
||||||
|
using MultiplePaymentDestinations = std::vector<std::pair<AccountID, Number>>;
|
||||||
|
/** Like accountSend, except one account is sending multiple payments (with the
|
||||||
|
* same asset!) simultaneously
|
||||||
|
*
|
||||||
|
* Calls static accountSendMultiIOU if saAmount represents Issue.
|
||||||
|
* Calls static accountSendMultiMPT if saAmount represents MPTIssue.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TER
|
||||||
|
accountSendMulti(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& senderID,
|
||||||
|
Asset const& asset,
|
||||||
|
MultiplePaymentDestinations const& receivers,
|
||||||
|
beast::Journal j,
|
||||||
|
WaiveTransferFee waiveFee = WaiveTransferFee::No);
|
||||||
|
|
||||||
|
[[nodiscard]] TER
|
||||||
|
transferXRP(
|
||||||
|
ApplyView& view,
|
||||||
|
AccountID const& from,
|
||||||
|
AccountID const& to,
|
||||||
|
STAmount const& amount,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
|
} // namespace xrpl
|
||||||
81
include/xrpl/ledger/helpers/VaultHelpers.h
Normal file
81
include/xrpl/ledger/helpers/VaultHelpers.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xrpl/protocol/STAmount.h>
|
||||||
|
#include <xrpl/protocol/STLedgerEntry.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace xrpl {
|
||||||
|
|
||||||
|
/** From the perspective of a vault, return the number of shares to give
|
||||||
|
depositor when they offer a fixed amount of assets. Note, since shares are
|
||||||
|
MPT, this number is integral and always truncated in this calculation.
|
||||||
|
|
||||||
|
@param vault The vault SLE.
|
||||||
|
@param issuance The MPTokenIssuance SLE for the vault's shares.
|
||||||
|
@param assets The amount of assets to convert.
|
||||||
|
|
||||||
|
@return The number of shares, or nullopt on error.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::optional<STAmount>
|
||||||
|
assetsToSharesDeposit(
|
||||||
|
std::shared_ptr<SLE const> const& vault,
|
||||||
|
std::shared_ptr<SLE const> const& issuance,
|
||||||
|
STAmount const& assets);
|
||||||
|
|
||||||
|
/** From the perspective of a vault, return the number of assets to take from
|
||||||
|
depositor when they receive a fixed amount of shares. Note, since shares are
|
||||||
|
MPT, they are always an integral number.
|
||||||
|
|
||||||
|
@param vault The vault SLE.
|
||||||
|
@param issuance The MPTokenIssuance SLE for the vault's shares.
|
||||||
|
@param shares The amount of shares to convert.
|
||||||
|
|
||||||
|
@return The number of assets, or nullopt on error.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::optional<STAmount>
|
||||||
|
sharesToAssetsDeposit(
|
||||||
|
std::shared_ptr<SLE const> const& vault,
|
||||||
|
std::shared_ptr<SLE const> const& issuance,
|
||||||
|
STAmount const& shares);
|
||||||
|
|
||||||
|
/** Controls whether to truncate shares instead of rounding. */
|
||||||
|
enum class TruncateShares : bool { no = false, yes = true };
|
||||||
|
|
||||||
|
/** From the perspective of a vault, return the number of shares to demand from
|
||||||
|
the depositor when they ask to withdraw a fixed amount of assets. Since
|
||||||
|
shares are MPT this number is integral, and it will be rounded to nearest
|
||||||
|
unless explicitly requested to be truncated instead.
|
||||||
|
|
||||||
|
@param vault The vault SLE.
|
||||||
|
@param issuance The MPTokenIssuance SLE for the vault's shares.
|
||||||
|
@param assets The amount of assets to convert.
|
||||||
|
@param truncate Whether to truncate instead of rounding.
|
||||||
|
|
||||||
|
@return The number of shares, or nullopt on error.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::optional<STAmount>
|
||||||
|
assetsToSharesWithdraw(
|
||||||
|
std::shared_ptr<SLE const> const& vault,
|
||||||
|
std::shared_ptr<SLE const> const& issuance,
|
||||||
|
STAmount const& assets,
|
||||||
|
TruncateShares truncate = TruncateShares::no);
|
||||||
|
|
||||||
|
/** From the perspective of a vault, return the number of assets to give the
|
||||||
|
depositor when they redeem a fixed amount of shares. Note, since shares are
|
||||||
|
MPT, they are always an integral number.
|
||||||
|
|
||||||
|
@param vault The vault SLE.
|
||||||
|
@param issuance The MPTokenIssuance SLE for the vault's shares.
|
||||||
|
@param shares The amount of shares to convert.
|
||||||
|
|
||||||
|
@return The number of assets, or nullopt on error.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::optional<STAmount>
|
||||||
|
sharesToAssetsWithdraw(
|
||||||
|
std::shared_ptr<SLE const> const& vault,
|
||||||
|
std::shared_ptr<SLE const> const& issuance,
|
||||||
|
STAmount const& shares);
|
||||||
|
|
||||||
|
} // namespace xrpl
|
||||||
@@ -29,6 +29,18 @@ public:
|
|||||||
bool sslVerify,
|
bool sslVerify,
|
||||||
beast::Journal j);
|
beast::Journal j);
|
||||||
|
|
||||||
|
/** Destroys the global SSL context created by initializeSSLContext().
|
||||||
|
*
|
||||||
|
* This releases the underlying boost::asio::ssl::context and any
|
||||||
|
* associated OpenSSL resources. Must not be called while any
|
||||||
|
* HTTPClient requests are in flight.
|
||||||
|
*
|
||||||
|
* @note Currently only called from tests during teardown. In production,
|
||||||
|
* the SSL context lives for the lifetime of the process.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cleanupSSLContext();
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get(bool bSSL,
|
get(bool bSSL,
|
||||||
boost::asio::io_context& io_context,
|
boost::asio::io_context& io_context,
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ getFullVersionString();
|
|||||||
@return the encoded version in a 64-bit integer
|
@return the encoded version in a 64-bit integer
|
||||||
*/
|
*/
|
||||||
std::uint64_t
|
std::uint64_t
|
||||||
encodeSoftwareVersion(char const* const versionStr);
|
encodeSoftwareVersion(std::string_view versionStr);
|
||||||
|
|
||||||
/** Returns this server's version packed in a 64-bit integer. */
|
/** Returns this server's version packed in a 64-bit integer. */
|
||||||
std::uint64_t
|
std::uint64_t
|
||||||
|
|||||||
@@ -64,6 +64,49 @@
|
|||||||
|
|
||||||
namespace xrpl {
|
namespace xrpl {
|
||||||
|
|
||||||
|
// Feature names must not exceed this length (in characters, excluding the null terminator).
|
||||||
|
static constexpr std::size_t maxFeatureNameSize = 63;
|
||||||
|
// Reserve this exact feature-name length (in characters/bytes, excluding the null terminator)
|
||||||
|
// so that a 32-byte uint256 (for example, in WASM or other interop contexts) can be used
|
||||||
|
// as a compact, fixed-size feature selector without conflicting with human-readable names.
|
||||||
|
static constexpr std::size_t reservedFeatureNameSize = 32;
|
||||||
|
|
||||||
|
// Both validFeatureNameSize and validFeatureName are consteval functions that can be used in
|
||||||
|
// static_asserts to validate feature names at compile time. They are only used inside
|
||||||
|
// enforceValidFeatureName in Feature.cpp, but are exposed here for testing. The expected
|
||||||
|
// parameter `auto fn` is a constexpr lambda which returns a const char*, making it available
|
||||||
|
// for compile-time evaluation. Read more in https://accu.org/journals/overload/30/172/wu/
|
||||||
|
consteval auto
|
||||||
|
validFeatureNameSize(auto fn) -> bool
|
||||||
|
{
|
||||||
|
constexpr char const* n = fn();
|
||||||
|
// Note, std::strlen is not constexpr, we need to implement our own here.
|
||||||
|
constexpr std::size_t N = [](auto n) {
|
||||||
|
std::size_t ret = 0;
|
||||||
|
for (auto ptr = n; *ptr != '\0'; ret++, ++ptr)
|
||||||
|
;
|
||||||
|
return ret;
|
||||||
|
}(n);
|
||||||
|
return N != reservedFeatureNameSize && //
|
||||||
|
N <= maxFeatureNameSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
consteval auto
|
||||||
|
validFeatureName(auto fn) -> bool
|
||||||
|
{
|
||||||
|
constexpr char const* n = fn();
|
||||||
|
// Prevent the use of visually confusable characters and enforce that feature names
|
||||||
|
// are always valid ASCII. This is needed because C++ allows Unicode identifiers.
|
||||||
|
// Characters below 0x20 are nonprintable control characters, and characters with the 0x80 bit
|
||||||
|
// set are non-ASCII (e.g. UTF-8 encoding of Unicode), so both are disallowed.
|
||||||
|
for (auto ptr = n; *ptr != '\0'; ++ptr)
|
||||||
|
{
|
||||||
|
if (*ptr & 0x80 || *ptr < 0x20)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes };
|
enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes };
|
||||||
enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported };
|
enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported };
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
namespace xrpl {
|
namespace xrpl {
|
||||||
|
|
||||||
|
// Deprecated constant for backwards compatibility with pre-XRPFees amendment.
|
||||||
|
// This was the reference fee units used in the old fee calculation.
|
||||||
|
inline constexpr std::uint32_t FEE_UNITS_DEPRECATED = 10;
|
||||||
|
|
||||||
/** Reflects the fee settings for a particular ledger.
|
/** Reflects the fee settings for a particular ledger.
|
||||||
|
|
||||||
The fees are always the same for any transactions applied
|
The fees are always the same for any transactions applied
|
||||||
@@ -11,15 +15,25 @@ namespace xrpl {
|
|||||||
*/
|
*/
|
||||||
struct Fees
|
struct Fees
|
||||||
{
|
{
|
||||||
XRPAmount base{0}; // Reference tx cost (drops)
|
/** @brief Cost of a reference transaction in drops. */
|
||||||
XRPAmount reserve{0}; // Reserve base (drops)
|
XRPAmount base{0};
|
||||||
XRPAmount increment{0}; // Reserve increment (drops)
|
|
||||||
|
/** @brief Minimum XRP an account must hold to exist on the ledger. */
|
||||||
|
XRPAmount reserve{0};
|
||||||
|
|
||||||
|
/** @brief Additional XRP reserve required per owned ledger object. */
|
||||||
|
XRPAmount increment{0};
|
||||||
|
|
||||||
explicit Fees() = default;
|
explicit Fees() = default;
|
||||||
Fees(Fees const&) = default;
|
Fees(Fees const&) = default;
|
||||||
Fees&
|
Fees&
|
||||||
operator=(Fees const&) = default;
|
operator=(Fees const&) = default;
|
||||||
|
|
||||||
|
Fees(XRPAmount base_, XRPAmount reserve_, XRPAmount increment_)
|
||||||
|
: base(base_), reserve(reserve_), increment(increment_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the account reserve given the owner count, in drops.
|
/** Returns the account reserve given the owner count, in drops.
|
||||||
|
|
||||||
The reserve is calculated as the reserve base plus
|
The reserve is calculated as the reserve base plus
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user