diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..48380a6 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail + +nix fmt . 2>/dev/null + +changed=$(git diff --name-only) +if [ -n "$changed" ]; then + echo "nix fmt modified files:" + echo "$changed" + echo "" + echo "Stage the changes and retry your commit." + exit 1 +fi diff --git a/.github/workflows/depends.yml b/.github/workflows/depends.yml index c8e5760..5d9a862 100644 --- a/.github/workflows/depends.yml +++ b/.github/workflows/depends.yml @@ -80,19 +80,8 @@ jobs: run: nix flake check - name: Build bitcoin from depends - run: | - nix develop .#depends --command bash -c " - set -eux - - export CCACHE_DIR=${{ env.CCACHE_DIR }} - export SOURCES_PATH=${{ env.SOURCES_PATH }} - export BASE_CACHE=${{ env.BASE_CACHE }} - - cd bitcoin - HOST_TRIPLET=\$(./depends/config.guess) - export HOST_TRIPLET - make -C depends -j\$(nproc) NO_QT=1 build_CC="$CC" build_CXX="$CXX" - cmake -B build --toolchain \"depends/\$HOST_TRIPLET/toolchain.cmake\" - cmake --build build -j\$(nproc) - ccache --show-stats - " + env: + CCACHE_DIR: ${{ env.CCACHE_DIR }} + SOURCES_PATH: ${{ env.SOURCES_PATH }} + BASE_CACHE: ${{ env.BASE_CACHE }} + run: nix develop .#depends --command ./scripts/build-depends.sh diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 61120cb..79db485 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -28,8 +28,8 @@ jobs: cores: 4 cmake_flags: - system: x86_64-darwin - runner_label: macos-15-intel - cores: 4 + runner_label: macos-latest + cores: 3 cmake_flags: -DWITH_USDT=OFF - system: aarch64-darwin runner_label: macos-latest @@ -85,16 +85,4 @@ jobs: run: nix flake check - name: Build bitcoind - run: | - nix develop --command bash -c " - set -eux - export CCACHE_DIR=${{ env.CCACHE_DIR }} - cd bitcoin - cmake -B build \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ - --preset dev-mode \ - ${{ matrix.cmake_flags }} - cmake --build build -j${{ matrix.cores }} - ccache --show-stats - " + run: nix develop --command ./scripts/build-systemlibs.sh ${{ matrix.cores }} ${{ matrix.cmake_flags }} diff --git a/flake.lock b/flake.lock index 6714924..8b5984e 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1768886240, - "narHash": "sha256-C2TjvwYZ2VDxYWeqvvJ5XPPp6U7H66zeJlRaErJKoEM=", + "lastModified": 1773734432, + "narHash": "sha256-IF5ppUWh6gHGHYDbtVUyhwy/i7D261P7fWD1bPefOsw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "80e4adbcf8992d3fd27ad4964fbb84907f9478b0", + "rev": "cda48547b432e8d3b18b4180ba07473762ec8558", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index fcf531c..39301b9 100644 --- a/flake.nix +++ b/flake.nix @@ -17,20 +17,6 @@ let pkgs = import nixpkgs { inherit system; - overlays = [ - (final: prev: { - capnproto = prev.capnproto.overrideAttrs (oldAttrs: rec { - version = "1.3.0"; - src = prev.fetchFromGitHub { - owner = "capnproto"; - repo = "capnproto"; - rev = "v${version}"; - hash = "sha256-fvZzNDBZr73U+xbj1LhVj1qWZyNmblKluh7lhacV+6I="; - }; - patches = [ ]; - }); - }) - ]; }; inherit (pkgs) lib; inherit (pkgs.stdenv) isLinux isDarwin; @@ -57,6 +43,19 @@ } ''; + patchelf-releases = pkgs.writeShellApplication { + name = "patchelf-releases"; + runtimeInputs = with pkgs; [ + patchelf + file + findutils + gnugrep + ]; + text = builtins.replaceStrings [ "@interp@" ] [ "${pkgs.glibc}/lib/ld-linux-x86-64.so.2" ] ( + builtins.readFile ./scripts/patchelf-releases.sh + ); + }; + stdEnv = let llvmStdenv = @@ -69,10 +68,10 @@ else llvmPackages.stdenv; in - if isLinux then - pkgs.stdenvAdapters.useMoldLinker (pkgs.ccacheStdenv.override { stdenv = llvmStdenv; }) - else - pkgs.ccacheStdenv.override { stdenv = llvmStdenv; }; + let + moldStdenv = if isLinux then pkgs.stdenvAdapters.useMoldLinker llvmStdenv else llvmStdenv; + in + pkgs.ccacheStdenv.override { stdenv = moldStdenv; }; pythonEnv = python.withPackages ( ps: @@ -84,7 +83,6 @@ pyzmq pycapnp requests - vulture ] ++ lib.optionals isLinux [ bcc @@ -108,17 +106,11 @@ pkgs.linuxPackages.bpftrace ]; - qtBuildInputs = [ - pkgs.qt6.qtbase # https://nixos.org/manual/nixpkgs/stable/#sec-language-qt - pkgs.qt6.qttools - ]; - # Will exist in the runtime environment buildInputs = [ pkgs.boost pkgs.capnproto pkgs.libevent - pkgs.qrencode pkgs.sqlite.dev pkgs.zeromq ]; @@ -132,6 +124,7 @@ packages = [ clang-tidy-diff pkgs.codespell + pkgs.doxygen pkgs.hexdump pkgs.include-what-you-use pkgs.ruff @@ -139,6 +132,7 @@ pythonEnv ] ++ lib.optionals isLinux [ + patchelf-releases pkgs.gdb pkgs.valgrind ] @@ -148,18 +142,15 @@ CMAKE_EXPORT_COMPILE_COMMANDS = 1; LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.capnproto ]; LOCALE_ARCHIVE = lib.optionalString isLinux "${pkgs.glibcLocales}/lib/locale/locale-archive"; + # Force depends capnp to also use clang, otherwise it fails when + # looking for the default (gcc/g++) + build_CC = "clang"; + build_CXX = "clang++"; }; in { - devShells.default = mkDevShell nativeBuildInputs ( - buildInputs ++ qtBuildInputs ++ [ pkgs.qt6.wrapQtAppsHook ] - ); - devShells.depends = (mkDevShell nativeBuildInputs qtBuildInputs).overrideAttrs (oldAttrs: { - # Set these to force depends capnp to also use clang, otherwise it - # fails when looking for the default (gcc/g++) - build_CC = "clang"; - build_CXX = "clang++"; - }); + devShells.default = mkDevShell nativeBuildInputs buildInputs; + devShells.depends = mkDevShell nativeBuildInputs [ ]; formatter = pkgs.nixfmt-tree; } ); diff --git a/scripts/build-depends.sh b/scripts/build-depends.sh new file mode 100755 index 0000000..bfa8d09 --- /dev/null +++ b/scripts/build-depends.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd bitcoin + +# Nix sets CC/CXX to bare names (e.g. 'clang'), relying on PATH. The depends +# Makefile substitutes these into toolchain.cmake, but cmake's find_program +# searches system dirs before PATH, so a bare 'clang' resolves to the system +# compiler instead of the Nix one. This causes glibc version mismatches: +# objects compiled against Nix's newer glibc headers reference fortified +# symbols (e.g. __inet_pton_chk) absent from the runner's older glibc. +NIX_CC=$(command -v "$CC") +NIX_CXX=$(command -v "$CXX") + +HOST_TRIPLET=$(./depends/config.guess) + +make -C depends "-j$(nproc)" NO_QT=1 \ + CC="$NIX_CC" CXX="$NIX_CXX" \ + build_CC="$NIX_CC" build_CXX="$NIX_CXX" + +cmake -B build --toolchain "depends/$HOST_TRIPLET/toolchain.cmake" +cmake --build build "-j$(nproc)" +ccache --show-stats diff --git a/scripts/build-systemlibs.sh b/scripts/build-systemlibs.sh new file mode 100755 index 0000000..d3f51b2 --- /dev/null +++ b/scripts/build-systemlibs.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +CORES=${1:?usage: build-systemlibs.sh [cmake_flags...]} +shift +CMAKE_FLAGS=("$@") + +cd bitcoin +cmake -B build \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + --preset dev-mode \ + -DBUILD_GUI=OFF \ + "${CMAKE_FLAGS[@]}" +cmake --build build "-j$CORES" +ccache --show-stats diff --git a/scripts/patchelf-releases.sh b/scripts/patchelf-releases.sh new file mode 100644 index 0000000..8644216 --- /dev/null +++ b/scripts/patchelf-releases.sh @@ -0,0 +1,24 @@ +INTERP="@interp@" + +if [ -z "${PREVIOUS_RELEASES_DIR:-}" ]; then + echo "error: PREVIOUS_RELEASES_DIR is not set" >&2 + exit 1 +fi + +if [ ! -f "$INTERP" ]; then + echo "error: interpreter not found: $INTERP" >&2 + exit 1 +fi + +echo "Using interpreter: $INTERP" + +count=0 +while IFS= read -r -d '' bin; do + if file "$bin" | grep -q 'ELF.*dynamically linked'; then + patchelf --set-interpreter "$INTERP" "$bin" + echo " patched: ${bin#"$PREVIOUS_RELEASES_DIR"/}" + count=$((count + 1)) + fi +done < <(find "$PREVIOUS_RELEASES_DIR" -path '*/bin/*' -type f -print0) + +echo "Patched $count binaries."