-
Notifications
You must be signed in to change notification settings - Fork 6
nix build system part 1 #1142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
nix build system part 1 #1142
Conversation
6c50e20 to
1f9c2db
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR introduces the foundation of a Nix-based build system for building DPDK and its dependencies with custom compilation profiles. The system uses npins for dependency pinning and provides two build profiles (debug and release) with carefully configured compiler and linker flags for performance optimization and security hardening.
Key changes:
- Introduces compilation profiles (debug/release) with LTO, security hardening, and performance optimization flags
- Adds npins-based dependency management for DPDK, rdma-core, and nixpkgs
- Creates Nix overlays for building dataplane dependencies (DPDK, rdma-core, libnl, numactl, libbsd, libmd) with custom stdenv and static linking
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| shell.nix | Adds npins to the development environment |
| profiles.nix | Defines compilation flag profiles for debug and release builds with LTO and security features |
| npins/sources.json | Pins specific versions of DPDK (25.11), rdma-core, and nixpkgs-unstable |
| npins/default.nix | Generated npins helper code for loading pinned dependencies |
| nix/pkgs/dpdk/default.nix | DPDK package definition with extensive library/driver customization and meson configuration |
| nix/overlays/default.nix | Entry point for overlay definitions |
| nix/overlays/dataplane.nix | Main overlay that applies custom stdenv and builds dataplane dependencies with static linking |
| default.nix | Top-level entry point that combines profiles and overlays to create debug and release package sets |
1f9c2db to
8510569
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
| "raw/ioat" | ||
| "raw/ntb" | ||
| "raw/skeleton" | ||
| "regex/*" | ||
| "regex/mlx5" | ||
| "vdpa/*" | ||
| "vdpa/ifc" |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The disabledDrivers list contains redundant entries. Line 109 specifies the wildcard pattern "compress/*" which already covers the specific drivers listed on lines 110-111 ("compress/mlx5" and "compress/zlib").
Similarly, line 112 specifies "crypto/*" which already covers all the specific crypto drivers listed on lines 113-125.
And line 208 specifies "raw/*" which covers lines 209-211, and line 212 specifies "regex/*" which covers line 213, and line 214 specifies "vdpa/*" which covers line 215.
These specific entries after wildcards are unnecessary and should be removed for clarity and maintainability, unless there's a specific reason to list them explicitly (which should be documented if so).
| "raw/ioat" | |
| "raw/ntb" | |
| "raw/skeleton" | |
| "regex/*" | |
| "regex/mlx5" | |
| "vdpa/*" | |
| "vdpa/ifc" | |
| "regex/*" | |
| "vdpa/*" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix
| "net/ixgbe" | ||
| "net/kasumi" | ||
| "net/kni" | ||
| "net/liquidio" | ||
| "net/memif" | ||
| "net/mlx4" | ||
| "net/netvsc" | ||
| "net/nfp" | ||
| "net/ngbe" | ||
| "net/nitrox" | ||
| "net/ntb" | ||
| "net/null" | ||
| "net/octeontx" | ||
| "net/octeontx2" | ||
| "net/octeontx2_dma" | ||
| "net/octeontx2_ep" | ||
| "net/octeontx_ep" | ||
| "net/opdl" | ||
| "net/pcap" | ||
| "net/pfe" | ||
| "net/qede" | ||
| "net/sfc" | ||
| "net/sfc_efx" | ||
| "net/skeleton" | ||
| "net/snow3g" | ||
| "net/softnic" | ||
| "net/tap" | ||
| "net/thunderx" | ||
| "net/turbo_sw" | ||
| "net/txgbe" | ||
| "net/vdev" | ||
| "net/vdev_netvsc" | ||
| "net/vmbus" | ||
| "net/vmxnet3" | ||
| "net/zuc" | ||
| "raw/*" | ||
| "raw/ioat" | ||
| "raw/ntb" | ||
| "raw/skeleton" | ||
| "regex/*" | ||
| "regex/mlx5" | ||
| "vdpa/*" | ||
| "vdpa/ifc" | ||
| ]; | ||
| enabledDrivers = [ | ||
| "bus/auxiliary" | ||
| "bus/pci" | ||
| "common/mlx5" | ||
| "mempool/bucket" | ||
| "mempool/ring" | ||
| "mempool/stack" | ||
| "net/auxiliary" | ||
| "net/dmadev" | ||
| "net/intel/e1000" | ||
| "net/intel/i40e" | ||
| "net/intel/iavf" | ||
| "net/intel/ixgbe" |
Copilot
AI
Dec 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a conflict between the disabled and enabled drivers lists. Line 173 disables "net/ixgbe" in the disabledDrivers list, but line 229 enables "net/intel/ixgbe" in the enabledDrivers list.
If these refer to different drivers (one being net/ixgbe and the other net/intel/ixgbe), this is fine. However, if they refer to the same driver, this creates a conflict that should be resolved by removing one of the entries. Please verify which path is correct for the ixgbe driver in DPDK 25.11.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix
mvachhar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would love someone that knows nix better than I do to approve. I just have the comment about ethtool and iproute2.
Also, I presume most of the work this does gets cached so we don't have to repeated build?
Finally, it might be good to update the README.md with new build instructions when the time comes. I appears that this set of changes doesn't have any effect on the current build so I am not asking for it here. If I've misunderstood, then we need an updated README.md
| # If you want to include ethtool, I recommend just cutting another small overlay and static linking the thing. | ||
| # Then you can drop a single (tiny) binary in whatever container you need. | ||
| # Alternatively, you could skip that and just ship the default build of ethtool (tho that may also ship glibc again). | ||
| ethtool = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would ship these tools, the odds of needing them to debug something once dpdk rolls out is high.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can and will ship them. That said, I would attach them to the FRR container (which runs in the same netns)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the very minimum, they don't need to be in the build toolchain of DPDK
| "branch": "fix-lto-60.0", | ||
| "submodules": false, | ||
| "revision": "9ae1b26593e2cb53239e1124f88ce1698d53857e", | ||
| "url": "https://github.com/githedgehog/rdma-core/archive/9ae1b26593e2cb53239e1124f88ce1698d53857e.tar.gz", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have we submitted this patch upstream?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, nor should we.
The problem isn't in the rdma-core source code. It is just in the way they use nm to find symbols in .o files. When you enable lto you don't put object code in the .o file (usually), you just put in the LLVM IR. That isn't compatible with nm and so the build fails to generate .so files (because it can't find symbols) and fails.
The patch is just a hack to tell it to ignore this and move on with its life. That is harmless for us because we never use any of those .so files anyway. They go directly to the trash regardless of how they are produced. Symbol versioning isn't a thing for .a files, so this is just us side stepping the whole problem
8510569 to
43b02a8
Compare
The goal of this series of commits is to migrate functionality from dpdk-sys (and give it a much needed refactor in the process). More specifically, this series of commits is intended to get the project to the point where you can do a sterile build of DPDK with the correct set of CFLAGS/LDFLAGS in both the debug and release profiles. Forming that build into a sysroot which can actually replace dpdk-sys will be left as future work. Signed-off-by: Daniel Noland <[email protected]>
We begin the construction of our sysroot with a helper function designed to inject environment variables into a nixpkgs provided stdenv. This will (eventually) allow us to customize the flags used to compile each package needed for our sysroot. Signed-off-by: Daniel Noland <[email protected]>
This commit introduces a nixpkgs provided stdenv based on the LLVM toolchain. We explicitly forswear GCC for this sysroot on the grounds that rustc is based on LLVM. Given that we want LTO to work properly, we need to ensure that all of our (modest list of) dataplane dependencies are built with LLVM. In a future commit we will add infrastructure to ensure that we are also always using the same version of LLVM used by our selected version of rustc. Signed-off-by: Daniel Noland <[email protected]>
For reasons which make no sense to me, llvmPackages.stdenv does not seem to add LLVM's bintools or linker to the nativeBuildInputs by default. If you attempt to pass `-fuse-ld=lld` to the compiler without explicitly adding them to the build time dependency list then you fail to link. The fix is easy: inject those packages as dependencies. Note that I deliberately don't use `pkgs.lld` as that version of lld is not wrapped by nix and will not ensure correct settings for the rpath in generated elf files. llvmPackages.lld is the version we need here, as that version of lld is wrapped. Signed-off-by: Daniel Noland <[email protected]>
It is neat that nixpkgs attempts to run unit tests for compiled packages, but in my experience those tests spuriously fail on the regular. The cause of these failures is almost uniformly due to insufficient permissions in the build environment. I will leave the testing of packages to the developers and package maintainers and simply disable those tests in our overlay. This is especially important in that we will (in the future) cross compile for aarch64 and our build machine would be unable to run the tests anyway. Signed-off-by: Daniel Noland <[email protected]>
Invoke or previously built helper function to pass user supplied flags into our new llvm stdenv. Signed-off-by: Daniel Noland <[email protected]>
Cook a quick helper function to override the stdenv of select packages with our static + llvm + user supplied flags stdenv. Signed-off-by: Daniel Noland <[email protected]>
See comment for my reasoning. Signed-off-by: Daniel Noland <[email protected]>
See comment for my reasoning. Signed-off-by: Daniel Noland <[email protected]>
See comment for my reasoning. Signed-off-by: Daniel Noland <[email protected]>
This is an indirect dependency of DPDK, so we want to customize its build. Signed-off-by: Daniel Noland <[email protected]>
This is an dependency of DPDK, so we want to customize its build. Signed-off-by: Daniel Noland <[email protected]>
This is an dependency of DPDK, so we want to customize its build. Signed-off-by: Daniel Noland <[email protected]>
This is an dependency of DPDK, so we want to customize its build. Signed-off-by: Daniel Noland <[email protected]>
This is a handy tool for "pinning" our external dependencies to known versions with fixed cryptographic hashes. I tried to make this work with nix flakes, but I had an extremely difficult time making cross compile work, and I frankly don't understand what flakes does that npins doesn't do objectively better. Signed-off-by: Daniel Noland <[email protected]>
We want to have exact control over our version of rdma-core. We pin the version to use our fork of rdma-core which contains a minor patch sequence to help LTO compiles. This pin was added via ``` npins add github githedgehog rdma-core -b fix-lto-60.0 ``` Signed-off-by: Daniel Noland <[email protected]>
Now that we have our pinned version of nixpkgs and rdma-core set up we can pipe those sources into our build system for consumption by the rest of our overlay. Signed-off-by: Daniel Noland <[email protected]>
Use the pinned version of nixpkgs. Signed-off-by: Daniel Noland <[email protected]>
We currently only have one overlay in play, but I expect that to change when I add additional logic for FRR. Regardless, there is little cost in making the set of selected overlays flexible. Signed-off-by: Daniel Noland <[email protected]>
These pinned sources need to be consumed by the dataplane overlay in order to pin our external dependencies, rdma-core and (soon) dpdk. Signed-off-by: Daniel Noland <[email protected]>
Use the newly piped in value of sources to fix rdma-core to our chosen version. Signed-off-by: Daniel Noland <[email protected]>
DPDK recently released a new LTS version (25.11). Given that we are reworking our build system anyway, there is little reason to stay on the (now) outdated 25.07 version. This process will (in a future commit series) require regenerating our rust bindings anyway. While that is a relatively easy task, I can't see any real reason to do it twice. This pin was generated with the command ``` npins add github DPDK dpdk -b 25.11 ``` Signed-off-by: Daniel Noland <[email protected]>
This commit introduces a build recipe for DPDK optimized for our use case. This is largely just transferred over from dpdk-sys. The primary reason to focus on minimizing DPDK is to make it as easy as possible to bind DPDK to rust. In particular, enabling all of the drivers significantly complicates the binding process and significantly increases build times. Signed-off-by: Daniel Noland <[email protected]>
Call dpdk package from this repo rather than using the upstream build instructions (which are somewhat unfriendly to bindgen). Signed-off-by: Daniel Noland <[email protected]>
Now that our overlay is mostly ready, we can re-export our overlay plus nixpkgs from default.nix. Signed-off-by: Daniel Noland <[email protected]>
Now that our overlay is mostly cooked, we can inject it into our pinned version of nixpkgs. Signed-off-by: Daniel Noland <[email protected]>
We don't yet have the machinery to generate our compile flags, but we can pre-emptively wire up the system which will feed in those flags into our overlay. Signed-off-by: Daniel Noland <[email protected]>
Now that we have our overlay in a place where it can accept flags we can start constructing machinery to generate those flags. We start with the "common" profile. This profile consists of flags we expect to pass to each and every build environment on all target platforms. Flags should be added to this profile conservatively, as they apply globally. Do not add performance compromising flags here. Signed-off-by: Daniel Noland <[email protected]>
This commit constructs the "debug" profile. This profile should only be activated in environments where performance is of much less concern than debugging. Signed-off-by: Daniel Noland <[email protected]>
The optimize profile contains flags which optimize the performance of the generated artifacts. This build profile makes no attempt to preserve debugability and will greatly increase build times when activated. Signed-off-by: Daniel Noland <[email protected]>
The secure profile is a set of flags intended to degrade security vulnerabilities into denial of service attacks. This should mostly be used in release builds, but can be applied to debug or (especially) to (future) fuzz environments as a means of instructing the fuzzer to hunt bugs with plausible security impacts. In particular, enabling safe-stack and or cfi (both future goals) should be done in future fuzz builds if possible. Signed-off-by: Daniel Noland <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
This commit introduces a (regrettably opaque) helper function for composing build environments from an arbitrary combination of profiles. Signed-off-by: Daniel Noland <[email protected]>
Combine the common and debug profiles to define the debug environment. Signed-off-by: Daniel Noland <[email protected]>
Combine the common, optimize, and secure profiles to define the release environment. Signed-off-by: Daniel Noland <[email protected]>
This commit (somewhat awkwardly) injects our build environments as top level children of the pkgs key. I am aware that I can do nix + fp tricks to make this more succinct and flexible, but I really am trying to keep this nix code basic where practical, and I don't expect us to have a very large number of environments. Signed-off-by: Daniel Noland <[email protected]>
This flag allows builds which make use of tools like nm to build when lto is enabled. We enable it here (for the moment) to allow rdma-core to build on aarch64 / aarch64-musl. That said, I don't like this flag as it makes the object files and thus the archive files much bigger. It opens the window for LTO linking mistakes which are much easier avoided if this is off. Once I have cooked a patch for rdma-core to skip the nm step we can revert this commit. Signed-off-by: Daniel Noland <[email protected]>
43b02a8 to
d40759f
Compare
| # We don't care about performance here, so this may be a good candidate for size reduction compiler flags like -Os. | ||
| # | ||
| # That said, we don't currently have infrastructure to pass flags at a per package level and building that is more | ||
| # trouble than a minor reduction in binary size / instruction cache pressure is likely worth. Also, lto does't |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does't -> doesn't
|
(gpt:120b ai review) Review of PR #1142 – "nix build system part 1"Overall impression
Specific observations1.
|
This is the first part of our shiny new build system.
In the name of making things easy to review I am cutting this PR into small chapters.
I added detailed notes on every commit and many comments in the name of keeping my design decisions documented and clear.
(nix code has the habit of becoming an opaque magic soup, and I really want to avoid that here)
Quick check list
Right out of the gate you need to
Remove fake-nix if you have installed it
If you have fake-nix setup you need to remove that
Install nix (if you don't already have it)
Caution
Follow this next step if and only if you don't already have nix installed
If you don't have nix installed, go ahead and install single user nix now.
Formal instructions are available here but the tl;dr is
sh <(curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install) --no-daemonThis command should also print a note about a file you need to source.
Do that or the next steps won't work.
Debug build
This is the table-stakes test: build the debug version of dpdk.
time nix build -f default.nix pkgs.debug.dpdk.static --out-link debug.dpdk --extra-experimental-features nix-commandIf that worked, you should have a symlink file named
debug.dpdk-static.If you run this
You should see the dpdk archive files.
Release build
This is the next table-stakes test: build the release version of dpdk.
time nix build -f default.nix pkgs.release.dpdk.static --out-link release.dpdk --extra-experimental-features nix-commandSmoke test build (musl)
This is one step removed from table stakes: build against musl64 so we can confirm our sysroot works.
These two commands are expected to work on basically any machine with nix.
time nix build -f default.nix pkgs.debug.pkgsCross.musl64.dpdk.static --out-link debug.musl64.dpdk --extra-experimental-features nix-commandtime nix build -f default.nix pkgs.release.pkgsCross.musl64.dpdk.static --out-link release.musl64.dpdk --extra-experimental-features nix-commandSmoke test build (aarch64 debug / release)
This is all expected to work.
This only matters (at this time) in that it provides an excelent smoke test for the next PR (which builds a full sysroot).