Compare commits

...

25 Commits

Author SHA1 Message Date
Ed Hennis
84ac13c638 Merge branch 'develop' into ximinez/after-is-never-null 2026-07-08 17:23:20 -04:00
Sergey Kuznetsov
c7adb215ed chore: Add .envrc for automatic devshell switch by direnv (#7756) 2026-07-08 17:28:48 +00:00
Ayaz Salikhov
71ee0f400b chore: Use same compiler in Nix devshell as in CI (#7751) 2026-07-08 14:51:39 +00:00
Ed Hennis
a976076ecf Merge branch 'develop' into ximinez/after-is-never-null 2026-07-07 19:32:29 -04:00
Ed Hennis
d28053d209 Merge branch 'develop' into ximinez/after-is-never-null 2026-07-07 15:50:24 -04:00
Ed Hennis
6b919923a6 Merge branch 'develop' into ximinez/after-is-never-null 2026-07-02 21:03:19 -04:00
Ed Hennis
7cb4aaa737 Merge branch 'develop' into ximinez/after-is-never-null 2026-07-02 11:18:23 -04:00
Ed Hennis
4c4e773e6b Merge branch 'develop' into ximinez/after-is-never-null 2026-07-01 16:02:52 -04:00
Ed Hennis
119401db56 Merge branch 'develop' into ximinez/after-is-never-null 2026-06-30 16:28:01 -04:00
Ed Hennis
747d038cde Merge branch 'develop' into ximinez/after-is-never-null 2026-06-25 11:43:26 -04:00
Ed Hennis
66ce22dd52 Merge branch 'develop' into ximinez/after-is-never-null 2026-06-23 11:09:55 -04:00
Ed Hennis
dd461c253c Merge branch 'develop' into ximinez/after-is-never-null 2026-06-22 16:41:53 -04:00
Ed Hennis
1f35959632 Merge branch 'develop' into ximinez/after-is-never-null 2026-06-17 15:01:30 -04:00
Ed Hennis
dd74221c3f Merge branch 'develop' into ximinez/after-is-never-null 2026-06-16 18:56:08 -04:00
Ed Hennis
390d4158f4 Merge branch 'develop' into ximinez/after-is-never-null 2026-06-15 20:31:38 -04:00
Ed Hennis
d98dc72ea3 Merge branch 'develop' into ximinez/after-is-never-null 2026-06-15 15:28:51 -04:00
Ed Hennis
8d2dc63bdb Merge branch 'develop' into ximinez/after-is-never-null 2026-06-15 12:12:03 -04:00
Ed Hennis
1d45ed1559 Merge branch 'develop' into ximinez/after-is-never-null 2026-06-11 21:57:28 -04:00
Ed Hennis
e27b19d4d6 Merge branch 'develop' into ximinez/after-is-never-null 2026-06-05 18:48:46 -04:00
Ed Hennis
b364d8cf5e Merge branch 'develop' into ximinez/after-is-never-null 2026-06-04 13:32:27 -04:00
Ed Hennis
3f957d56ed Merge branch 'develop' into ximinez/after-is-never-null 2026-06-04 10:09:23 -04:00
Ed Hennis
231dc888aa Merge branch 'develop' into ximinez/after-is-never-null 2026-06-02 11:58:38 -04:00
Ed Hennis
3f52b71c89 Merge branch 'develop' into ximinez/after-is-never-null 2026-06-01 14:24:34 -04:00
Ed Hennis
4659ec0a7b Merge branch 'develop' into ximinez/after-is-never-null 2026-05-28 23:37:51 -04:00
Ed Hennis
88b81ee66e fix: Improve Invariant documentation to emphasize that "after" is never null
- Expand the description in InvariantChecker_PROTOTYPE::visitEntry.
- Add an explicit assertion in "XRPLNotCreated::visitEntry".
2026-05-28 23:34:13 -04:00
8 changed files with 131 additions and 162 deletions

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

View File

@@ -33,9 +33,10 @@ with a single command and without installing anything system-wide:
nix --experimental-features 'nix-command flakes' develop
```
On **Linux**, Nix also provides the compiler (GCC). On **macOS**, the shell uses
your **system-wide Apple Clang** as the compiler, so you still need to manage
its version (see below).
On **Linux**, Nix also provides the compiler (GCC); on **macOS**, it provides
Clang. If you instead opt to use your system-wide Apple Clang (via
`nix develop .#apple-clang`), you need to manage its version yourself (see
below).
See [Using the Nix development shell](./nix.md) for installation and usage
details, including how to select a different compiler.
@@ -48,10 +49,10 @@ details, including how to select a different compiler.
### macOS: managing the Apple Clang version
Because the Nix shell uses the system-wide Apple Clang on macOS, the compiler
version is whatever your installed Xcode (or Command Line Tools) provides. The
following command should return a version greater than or equal to the
[minimum required](#tested-compiler-versions):
If you use your system-wide Apple Clang on macOS (via `nix develop .#apple-clang`),
the compiler version is whatever your installed Xcode (or Command Line Tools)
provides. The following command should return a version greater than or equal to
the [minimum required](#tested-compiler-versions):
```bash
clang --version

40
docs/build/nix.md vendored
View File

@@ -9,7 +9,7 @@ This guide explains how to use Nix to set up a reproducible development environm
- **Reproducible environment**: Everyone gets the same versions of tools and compilers
- **Matches CI**: The Linux CI runs in Docker images built from this exact Nix environment
- **No system pollution**: Dependencies are isolated and don't affect your system packages
- **Multiple compiler versions**: Easily switch between different GCC and Clang versions
- **Consistent compilers**: The GCC and Clang shells use the same versions as CI
- **Quick setup**: Get started with a single command
- **Works on Linux and macOS**: Consistent experience across platforms
@@ -31,8 +31,8 @@ This will:
- Download and set up all required development tools (CMake, Ninja, Conan, etc.)
- Configure the appropriate compiler for your platform:
- **Linux**: GCC 15.2 (provided by Nix)
- **macOS**: Apple Clang (your system compiler)
- **Linux**: GCC (provided by Nix)
- **macOS**: Clang (provided by Nix)
The first time you run this command, it will take a few minutes to download and build the environment. Subsequent runs will be much faster.
@@ -40,12 +40,12 @@ The first time you run this command, it will take a few minutes to download and
- **Linux**: `nix develop` gives you a shell with all the tooling necessary to
develop xrpld and with GCC 15.2 (also provided by Nix). There are no caveats.
- **macOS**: `nix develop` gives you a full environment too. The compiler is
your system-wide Apple Clang, while every other tool including Conan — is
provided by Nix. Conan has no binary in the Nix cache for macOS, so it is
built from source the first time you enter the shell, which makes the initial
setup slower (this is handled automatically; see
[`nix/devshell.nix`](../../nix/devshell.nix)).
- **macOS**: `nix develop` gives you a full environment too, with Clang (and
every other tool, including Conan) provided by Nix. To use your system-wide
Apple Clang instead, enter `nix develop .#apple-clang`. Conan has no binary in
the Nix cache for macOS, so it is built from source the first time you enter
the shell, which makes the initial setup slower (this is handled
automatically; see [`nix/devshell.nix`](../../nix/devshell.nix)).
> [!TIP]
> To avoid typing `--experimental-features 'nix-command flakes'` every time, you can permanently enable flakes by creating `~/.config/nix/nix.conf`:
@@ -62,7 +62,9 @@ The first time you run this command, it will take a few minutes to download and
### Choosing a different compiler
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#gcc15`.
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#clang`.
The `.#gcc` and `.#clang` shells provide the same GCC and Clang versions used in CI
(pinned in [`nix/packages.nix`](../../nix/packages.nix)).
Use `nix flake show` to see all the available development shells.
Use `nix develop .#no-compiler` to use the compiler from your system.
@@ -70,11 +72,11 @@ Use `nix develop .#no-compiler` to use the compiler from your system.
### Example Usage
```bash
# Use GCC 14
nix develop .#gcc14
# Use GCC (same version as CI)
nix develop .#gcc
# Use Clang 19
nix develop .#clang19
# Use Clang (same version as CI)
nix develop .#clang
# Use default for your platform
nix develop
@@ -112,7 +114,15 @@ Once inside the Nix development shell, follow the standard [build instructions](
[direnv](https://direnv.net/) or [nix-direnv](https://github.com/nix-community/nix-direnv) can automatically activate the Nix development shell when you enter the repository directory.
This is also the most robust way to use the environment from **any shell** (bash, zsh, fish, …): direnv stays in your current shell and loads the environment _after_ your shell's startup files have run, so the Nix-provided tools take precedence over anything your shell configuration adds to `$PATH`. To use it, install direnv for your shell, then add an `.envrc` containing `use flake` at the repository root and run `direnv allow`.
This is also the most robust way to use the environment from **any shell** (bash, zsh, fish, …): direnv stays in your current shell and loads the environment _after_ your shell's startup files have run, so the Nix-provided tools take precedence over anything your shell configuration adds to `$PATH`.
The repository already ships an `.envrc` at its root that activates the Nix flake development shell, so you don't need to create one. To use it:
1. [Install direnv](https://direnv.net/docs/installation.html) and [hook it into your shell](https://direnv.net/docs/hook.html) (bash, zsh, fish, …). Installing [nix-direnv](https://github.com/nix-community/nix-direnv) as well is recommended: it caches the shell so that activation is near-instant after the first run.
2. Run `direnv allow` once in the repository root. direnv will then load (and reload) the Nix development shell automatically whenever you enter the directory.
> [!NOTE]
> direnv only caches the `.direnv` directory (already listed in `.gitignore`); no other repository files are affected.
## Conan and Prebuilt Packages

View File

@@ -70,9 +70,13 @@ public:
/**
* @brief called for each ledger entry in the current transaction.
*
* @param isDelete true if the SLE is being deleted
* @param before ledger entry before modification by the transaction
* @param after ledger entry after modification by the transaction
* @param isDelete true if the SLE is being deleted.
* @param before ledger entry before modification by the
* transaction.
* @param after ledger entry after modification by the transaction.
* `after` IS NEVER NULL. `isDelete` is the only correct way to check for deletions.
* Check for null defensively, but do not make any logic decisions based on whether `after` is
* set, because it will always be set.
*/
void
visitEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after);

View File

@@ -4,14 +4,16 @@
...
}:
let
inherit (import ./packages.nix { inherit pkgs; }) commonPackages;
inherit (pkgs) lib;
inherit (import ./packages.nix { inherit pkgs; })
commonPackages
gccPackage
llvmPackages
llvmVersion
;
# Underlying compiler toolchains to wrap. Bump these in one place to
# roll the whole environment forward.
customGccPackage = pkgs.gcc15;
customLlvmPackages = pkgs.llvmPackages_22;
customClangMajor = lib.versions.major (lib.getVersion customLlvmPackages.clang-unwrapped);
# Underlying compiler toolchains to wrap (versions pinned in packages.nix).
customGccPackage = gccPackage;
customLlvmPackages = llvmPackages;
# binutils wrapped to emit binaries that reference the custom glibc
# (dynamic linker path, library search path, RPATH).
@@ -90,7 +92,7 @@ let
extraBuildCommands = ''
rsrc="$out/resource-root"
mkdir "$rsrc"
ln -s "${customLlvmPackages.clang-unwrapped.lib}/lib/clang/${customClangMajor}/include" "$rsrc/include"
ln -s "${customLlvmPackages.clang-unwrapped.lib}/lib/clang/${toString llvmVersion}/include" "$rsrc/include"
ln -s "${customCompilerRt.out}/lib" "$rsrc/lib"
ln -s "${customCompilerRt.out}/share" "$rsrc/share" || true
echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags

View File

@@ -1,127 +1,57 @@
{ pkgs, ... }:
let
inherit (import ./packages.nix { inherit pkgs; }) commonPackages;
inherit (import ./packages.nix { inherit pkgs; })
commonPackages
gccVersion
llvmPackages
;
# Supported compiler versions
gccVersion = pkgs.lib.range 13 15;
clangVersions = pkgs.lib.range 18 21;
# Plain nixpkgs stdenvs — no custom glibc, unlike ci-env.nix.
gccStdenv = pkgs."gcc${toString gccVersion}Stdenv";
clangStdenv = llvmPackages.stdenv;
defaultCompiler = if pkgs.stdenv.isDarwin then "apple-clang" else "gcc";
defaultGccVersion = pkgs.lib.last gccVersion;
defaultClangVersion = pkgs.lib.last clangVersions;
strToCompilerEnv =
compiler: version:
(
if compiler == "gcc" then
let
gccPkg = pkgs."gcc${toString version}Stdenv" or null;
in
if gccPkg != null && builtins.elem version gccVersion then
gccPkg
else
throw "Invalid GCC version: ${toString version}. Must be one of: ${toString gccVersion}"
else if compiler == "clang" then
let
clangPkg = pkgs."llvmPackages_${toString version}".stdenv or null;
in
if clangPkg != null && builtins.elem version clangVersions then
clangPkg
else
throw "Invalid Clang version: ${toString version}. Must be one of: ${toString clangVersions}"
else if compiler == "apple-clang" || compiler == "none" then
pkgs.stdenvNoCC
else
throw "Invalid compiler: ${compiler}. Must be one of: gcc, clang, apple-clang, none"
);
# Helper function to create a shell with a specific compiler
# compilerName is the command used to print the version, or null for none.
makeShell =
{
compiler ? defaultCompiler,
version ? (
if compiler == "gcc" then
defaultGccVersion
else if compiler == "clang" then
defaultClangVersion
else
null
),
stdenv,
compilerName,
}:
let
compilerStdEnv = strToCompilerEnv compiler version;
compilerName =
if compiler == "apple-clang" then
"clang"
else if compiler == "none" then
null
else
compiler;
gccOnMacWarning =
if pkgs.stdenv.isDarwin && compiler == "gcc" then
''
echo "WARNING: Using GCC on macOS with Conan may not work."
echo " Consider using 'nix develop .#clang' or the default shell instead."
echo ""
''
else
"";
compilerVersion =
if compilerName != null then
if compilerName == null then
''echo "No compiler specified - using system compiler"''
else
''
echo "Compiler: "
${compilerName} --version
''
else
''
echo "No compiler specified - using system compiler"
'';
shellAttrs = {
packages = commonPackages;
shellHook = ''
echo "Welcome to xrpld development shell";
${gccOnMacWarning}${compilerVersion}
'';
};
in
pkgs.mkShell.override { stdenv = compilerStdEnv; } shellAttrs;
# Generate shells for each compiler version
gccShells = builtins.listToAttrs (
map (version: {
name = "gcc${toString version}";
value = makeShell {
compiler = "gcc";
version = version;
};
}) gccVersion
);
clangShells = builtins.listToAttrs (
map (version: {
name = "clang${toString version}";
value = makeShell {
compiler = "clang";
version = version;
};
}) clangVersions
);
(pkgs.mkShell.override { inherit stdenv; }) {
packages = commonPackages;
shellHook = ''
echo "Welcome to xrpld development shell";
${compilerVersion}
'';
};
in
gccShells
// clangShells
// {
# Default shells
default = makeShell { };
gcc = makeShell { compiler = "gcc"; };
clang = makeShell { compiler = "clang"; };
rec {
# macOS: Nix Clang. Linux: Nix GCC.
default = if pkgs.stdenv.isDarwin then clang else gcc;
# No compiler
no-compiler = makeShell { compiler = "none"; };
apple-clang = makeShell { compiler = "apple-clang"; };
gcc = makeShell {
stdenv = gccStdenv;
compilerName = "gcc";
};
clang = makeShell {
stdenv = clangStdenv;
compilerName = "clang";
};
# Nix provides no compiler; use the one from your system (e.g. Apple Clang).
no-compiler = makeShell {
stdenv = pkgs.stdenvNoCC;
compilerName = null;
};
apple-clang = no-compiler;
}

View File

@@ -1,15 +1,33 @@
{ pkgs }:
let
# Compiler versions used across the dev shell and the CI environment.
gccVersion = 15;
llvmVersion = 22;
gccPackage = pkgs."gcc${toString gccVersion}";
llvmPackages = pkgs."llvmPackages_${toString llvmVersion}";
# Bound explicitly so it tracks llvmPackages above, not the `with pkgs` default.
clangTools = llvmPackages.clang-tools;
# In LLVM 22, run-clang-tidy.py moved from share/clang/ to bin/, so nixpkgs
# clang-tools no longer links it. Wrap it manually.
runClangTidy = pkgs.writeShellScriptBin "run-clang-tidy" ''
exec ${pkgs.python3}/bin/python3 ${pkgs.llvmPackages_22.clang-unwrapped}/bin/run-clang-tidy "$@"
exec ${pkgs.python3}/bin/python3 ${llvmPackages.clang-unwrapped}/bin/run-clang-tidy "$@"
'';
in
{
inherit
gccVersion
llvmVersion
gccPackage
llvmPackages
;
commonPackages = with pkgs; [
ccache
clangbuildanalyzer
clangTools
cmake
conan
curlMinimal # needed for codecov/codecov-action
@@ -23,7 +41,6 @@ in
gnumake
gnupg # needed for signing commits & codecov/codecov-action
graphviz
llvmPackages_22.clang-tools
less # needed for git diff
mold
nettools # provides netstat, used to debug failures in CI

View File

@@ -153,24 +153,28 @@ XRPNotCreated::visitEntry(bool isDelete, SLE::const_ref before, SLE::const_ref a
}
}
if (after)
if (!after)
{
switch (after->getType())
{
case ltACCOUNT_ROOT:
drops_ += (*after)[sfBalance].xrp().drops();
break;
case ltPAYCHAN:
if (!isDelete)
drops_ += ((*after)[sfAmount] - (*after)[sfBalance]).xrp().drops();
break;
case ltESCROW:
if (!isDelete && isXRP((*after)[sfAmount]))
drops_ += (*after)[sfAmount].xrp().drops();
break;
default:
break;
}
// LCOV_EXCL_START
UNREACHABLE("xrpl::XRPNotCreated::visitEntry : after can't be null");
return;
// LCOV_EXCL_STOP
}
switch (after->getType())
{
case ltACCOUNT_ROOT:
drops_ += (*after)[sfBalance].xrp().drops();
break;
case ltPAYCHAN:
if (!isDelete)
drops_ += ((*after)[sfAmount] - (*after)[sfBalance]).xrp().drops();
break;
case ltESCROW:
if (!isDelete && isXRP((*after)[sfAmount]))
drops_ += (*after)[sfAmount].xrp().drops();
break;
default:
break;
}
}