diff --git a/.envrc b/.envrc index cecf4b4767..ec38b75f5c 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1,7 @@ watch_file nix/*.nix +# The dev shell derivation includes all of conan/ (see nix/devshell.nix), so any +# change in there has to invalidate direnv's cached environment. +watch_dir conan + use flake diff --git a/BUILD.md b/BUILD.md index ad4666b141..ae2e69bb97 100644 --- a/BUILD.md +++ b/BUILD.md @@ -53,33 +53,25 @@ releases](https://github.com/XRPLF/rippled/releases). ### Set Up Conan -Once your [development environment](./docs/build/environment.md) is ready, you -may need to set up your Conan profile. - -#### Profiles - -We recommend that you install our Conan profiles: +Once your [development environment](./docs/build/environment.md) is ready, set +Conan up for this repository: ```bash -conan config install conan/profiles/ -tf $(conan config home)/profiles/ +./conan/init.sh ``` -You can check your Conan profile by running: +That installs our [`global.conf`](./conan/global.conf), our Conan +[profiles](./conan/profiles), and the `xrplf` remote that hosts some of our +dependencies. It honours `CONAN_HOME` and never deletes an existing Conan home, +so it is safe to re-run — it only overwrites the files it manages. -```bash -conan profile show -``` +> [!TIP] +> In the [Nix development shell](./docs/build/nix.md#conan-configuration) this is +> already done for you: the script runs on entry. -If the default profile is not suitable for your environment, you can create a custom profile and pass it to Conan. -More information on customizing Conan can be found in the [Advanced Conan configuration](./docs/build/advanced_conan.md). - -#### Add xrplf remote - -Run the following command to add the `xrplf` remote, which hosts some of our dependencies: - -```bash -conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/ -``` +You can inspect the resulting profile with `conan profile show`. If it is not +suitable for your environment, create a custom profile and pass it to Conan — see +[Advanced Conan configuration](./docs/build/advanced_conan.md). ### Set Up Ccache @@ -368,14 +360,14 @@ After any updates or changes to dependencies, you may need to do the following: 4. [Regenerate lockfile](./docs/build/advanced_conan.md#conan-lockfile). 5. Re-run [conan install](#build-and-test). -If you are using the Nix development shell, prebuilt Conan binaries may be -incompatible with it — see -[Building xrpld in the Nix shell](./docs/build/nix.md#building-xrpld-in-the-nix-shell). +If you are using the Nix development shell, whether prebuilt Conan binaries apply +depends on your platform — see +[Prebuilt packages](./docs/build/nix.md#prebuilt-packages). #### ERROR: Package not resolved If you're seeing an error like `ERROR: Package 'snappy/1.1.10' not resolved: Unable to find 'snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246' in remotes.`, -please [add `xrplf` remote](#add-xrplf-remote) or re-run `conan export` for [patched recipes](./docs/build/advanced_conan.md#patched-recipes). +please [set Conan up](#set-up-conan) so the `xrplf` remote is configured, or re-run `conan export` for [patched recipes](./docs/build/advanced_conan.md#patched-recipes). ### `protobuf/port_def.inc` file not found diff --git a/conan/init.sh b/conan/init.sh new file mode 100755 index 0000000000..287ee83001 --- /dev/null +++ b/conan/init.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Install our Conan configuration, profiles and the xrplf remote into CONAN_HOME. +# Safe to re-run; never deletes the Conan home. + +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +CONAN_DIR="$(conan config home)" + +echo "Installing Conan configuration into ${CONAN_DIR}" +conan config install "${SCRIPT_DIR}/global.conf" +conan config install "${SCRIPT_DIR}/profiles" -tf "${CONAN_DIR}/profiles" +# This script manages these files, so make them read-only - Conan does not +# preserve the source mode. Only the files: the directories must stay writable +# for `conan config install` to replace them. +chmod a-w "${CONAN_DIR}/global.conf" +find "${CONAN_DIR}/profiles" -type f -exec chmod a-w {} + + +echo "Adding the xrplf Conan remote" +# --index 0: our patched recipes must win over Conan Center. +conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/ diff --git a/conan/profiles/default b/conan/profiles/default index f2d93213ac..1b7eaff980 100644 --- a/conan/profiles/default +++ b/conan/profiles/default @@ -1,10 +1,7 @@ {% set os = detect_api.detect_os() %} {% set arch = detect_api.detect_arch() %} {% set compiler, version, compiler_exe = detect_api.detect_default_compiler() %} -{% set compiler_version = version %} -{% if os == "Linux" %} {% set compiler_version = detect_api.default_compiler_version(compiler, version) %} -{% endif %} {% if os == "Macos" %} {# Minimum macOS the dependencies target. #} {# Without this, Conan builds each dependency against the (possibly newer) host SDK, so the #} diff --git a/docs/build/nix.md b/docs/build/nix.md index fad8bc701d..d1e40fcc89 100644 --- a/docs/build/nix.md +++ b/docs/build/nix.md @@ -124,14 +124,32 @@ nix develop -c "$SHELL" Once inside the Nix development shell, follow the standard [build instructions](../../BUILD.md#steps). The Nix shell provides all necessary tools (CMake, Ninja, Conan, etc.). -Two things differ from a system environment: - -**Prebuilt Conan packages.** There is no guarantee that binaries from the Conan cache will work when using Nix. If you encounter any errors, add `--build '*'` to the `conan install` command in [Build and Test](../../BUILD.md#build-and-test) to force Conan to compile everything from source. Keep the rest of the command as it is there, so it rebuilds the `build_type` you are actually configuring. - -**Coverage builds.** `-Dcoverage=ON` works in the `gcc` shell (and `gcc-plain` on Linux): +Coverage builds (`-Dcoverage=ON`) work in the `gcc` shell (and `gcc-plain` on Linux): each ships a `gcov` matching its compiler, since Nix's cc-wrapper does not expose one. The `clang` shells do not include `llvm-cov`, so use a `gcc` shell for coverage. +## Conan configuration + +The shell runs [`conan/init.sh`](../../conan/init.sh) on entry, so +[Set Up Conan](../../BUILD.md#set-up-conan) is already done for you. It installs +into the shell's own Conan home: `CONAN_HOME=~/.conan2-nix`. + +### Prebuilt packages + +On **Linux**, the binaries on the `xrplf` remote are built in this same Nix +environment — CI runs in Docker images that bundle the dev shell's toolchain (see +[`nix/docker`](../../nix/docker)) — so `.#gcc` and `.#clang` can reuse them. The +`-plain` shells do not match that toolchain's glibc, so binaries from the remote +are not a reliable match there. + +On **macOS**, CI builds with Apple Clang, so the remote holds nothing for the Nix +`clang` toolchain and dependencies are compiled locally. We do not publish +Nix-built macOS binaries because a Conan package ID records the compiler version +but not the nixpkgs revision. + +To compile everything from source, add `--build '*'` to the `conan install` +command. + ## Automatic Activation with direnv [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. diff --git a/nix/devshell.nix b/nix/devshell.nix index cb4a99c76a..ac0b84e169 100644 --- a/nix/devshell.nix +++ b/nix/devshell.nix @@ -30,10 +30,29 @@ let }; customGccGcov = if pkgs.stdenv.isLinux then customCompilers.customGcov else plainGcov; + # Whole directory: init.sh locates the profiles relative to itself. + conanDir = ../conan; + + # Own Conan home, so Nix-built packages never share a cache with a system + # Conan. The stamp holds a content-addressed store path, so init.sh re-runs + # only when something in conan/ changes. + conanHook = '' + export CONAN_HOME=~/.conan2-nix + _xrpl_conan_stamp="$CONAN_HOME/.xrpld-devshell" + if [ "$(cat "$_xrpl_conan_stamp" 2>/dev/null)" != "${conanDir}" ]; then + if ${conanDir}/init.sh; then + printf '%s' "${conanDir}" >"$_xrpl_conan_stamp" + else + echo "⚠️ Conan setup failed - run ./conan/init.sh from the repository root to retry." + fi + fi + unset _xrpl_conan_stamp + ''; + # Shown when entering a *-plain shell. These exist only on Linux (see below), # where the stock toolchain diverges from CI. plainWarningHook = '' - echo "⚠️ WARNING: this is the stock nixpkgs toolchain and does not match CI's glibc. Prefer 'nix develop .#gcc' / '.#clang' unless you need to skip the custom-glibc build." + echo "⚠️ WARNING: this is the stock nixpkgs toolchain and does not match CI's glibc. Prefer 'nix develop .#gcc' / '.#clang' unless you need to skip the custom-glibc build." ''; # Tools to expose under version-suffixed names (see mkVersionedToolLinks). @@ -87,6 +106,7 @@ let shellHook = '' echo "Welcome to xrpld development shell"; ${compilerVersionHook} + ${conanHook} ${warningHook} ''; }