I am trying to set up a reproducible C++ development environment with nix-shell for an existing project, and I have run into build issues even though the clang versions in and outside of the nix environment should match. The first issue was compiler warnings, which I was able to resolve by adding the appropriate -Wno- compiler flag.
Now I am stuck on a linker error. The linker is complaining about multiple definitions of __cxa_throw, one in libstdc++.a(eh_throw.o) in the nix store, the other in one of my project files. It’s entirely possible that the project is doing something funny that it should not be doing, but why is this only an issue in the nix shell?
Unfortunately, the build system is so complex that I have been unable to come up with a minimal reproduction of the build errors only occurring under the nix shell, so I instead have to ask for general advice on what to look for, and why clang from the llvm.org Ubuntu packages behaves differently to the corresponding version from nixpkgs?
Finally, is this even the best approach for what I am trying to achieve? I have a shell.nix with just this:
let
pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/refs/tags/22.05.zip") {};
in pkgs.mkShell {
packages = [
clang_13
ninja
# etc.
];
Here’s an outline of something that has been working for me. Haven’t touched it since putting it into place a couple of years ago, so the details are hazy in my mind. I’m pretty sure I based this on a very complete setup explained by someone else, somewhere. But this simplified version might be easier to start with.
I have a shell.nix that looks like this (stripped down):
# Fundamental derivation of how to build the project: a function from
# dependencies to build-result. Picking the specific versions of the
# dependencies is Someone Else's Problem: `default.nix`, `release.nix` get to
# pick these.
# geant4 is just an example of a dependency, replace with your own
{ geant4, stdenv }:
stdenv.mkDerivation {
name = "my-package-name";
src = ../.;
# build-time dependencies
nativeBuildInputs = [
geant4
geant4.data.G4PhotonEvaporation
geant4.data.G4EMLOW
geant4.data.G4RadioactiveDecay
geant4.data.G4ENSDFSTATE
geant4.data.G4SAIDDATA
geant4.data.G4PARTICLEXS
geant4.data.G4NDL
];
# run-time dependencies
buildInputs = [
];
# buildPhase = ...
# installPhase = ...
}
I’ve commented out the build/installPhase as I don’t actually use them: it seems that I have a justfile in which I’ve encoded the cmake build directory song-and-dance, as I don’t actually use Nix to publish this project, only to allow me to work on it. Which sounds similar to what you want.