Building derivation, unable to find files

I am having a hard time building a derivation with make, not finding the necessary files. I have no issue compiling from a developer shell, so definitely not an issue with ill-formed paths in the Makefile. It must be something obvious that I cannot grasp. Here are the relevant parts of my flake.nix:

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs";
 
  outputs = { self, nixpkgs }:
    let
      system = "x86_64-linux";

      pkgs = import nixpkgs { inherit system; };
        
      riscv-toolchain = import nixpkgs {
        localSystem = system;
        crossSystem = {
          config = "riscv32-none-elf";
          libc = "newlib-nano";
          abi = "ilp32";
        };          
      };
      
      fe310-toolchain = riscv-toolchain.stdenv.mkDerivation {
        name = "riscv-fe310-firmware";
        src = ./.;
        buildInputs = with pkgs; [
          riscv-toolchain.buildPackages.gcc
        ];
        buildPhase = ''
          make -f fw/fe310/Makefile
        '';
        installPhase = ''
          mkdir -p $out
          cp -rv . $out
        '';
      };
    in
      {
        packages = {
          x86_64-linux = {
            fe310 = fe310-toolchain;
          };
        };
      };
}

Which gives me the following error:

> fw/fe310/Makefile:5: /crypto/crypto_obj.mk: No such file or directory
> make: *** No rule to make target '/crypto/crypto_obj.mk'.  Stop.       

Whereas the file crypto_obj.mk lives in the directory ./ext/crypto/, the Makefile is located in ./fw/fe310/. The location of crypto_obj.mk is set with crypto_dir = $(ext_dir)/crypto on the Makefile then $(ext_dir) with ext_dir := $(abspath $(fe310_dir)/../../ext) and $(fe310_dir) with fe310_dir := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) on common.mk. Again, this does not pose any problem when using a developer shell.

I get the exact same error when specifying the path to the Makefile with the makefile attribute and leaving the default values for each phase intact:

 fe310-toolchain = riscv-toolchain.stdenv.mkDerivation {
   name = "riscv-fe310-firmware";
   src = ./.;
   makefile = [ "fw/fe310/Makefile" ];
   buildInputs = with pkgs; [
     riscv-toolchain.buildPackages.gcc
   ];

I finally tried moving the source tree to $out, prefixing all necessary paths with $out, just for the sake of testing them, and that seems to do the trick:

dontInstall = true;
configurePhase = ''                                                             
  export fe310_dir=$out/fw/fe310                                              
  export ext_dir=$out/ext                                                     
  export ecp_dir=$out/ecp                                                     
  mkdir -p $out                                                               
  cp -rv . $out                                                               
'';                                                                           
buildPhase = ''
  make -f $out/fw/fe310/Makefile
'';

Then on the Makefile I apend $(fe310_dir) where relevant:

include $(fe310_dir)/common.mk
...
subdirs = $(fe310_dir)/bsp/drivers $(fe310_dir)/bsp/gloss $(fe310_dir)/bsp/metal $(fe310_dir)/eos  $(fe310_dir)/eos/i2c  $(fe310_dir)/eos/eve $(fe310_dir)/eos/eve/screen $(fe310_dir)/eos/eve/widget $(ext_dir)/fsfat

However, there must be a better way to do this, one that frees me from touching the Makefile.

The source tree and Makefile can be found here. Any hint much appreciated!

Try running a nix-shell --pure on the derivation from a temporary directory and run the phases one at time, and see what’s changing. There’s probably an automatic behavior of stdenv you’re not expecting or something like that. set -x may also be helpful to see what stdenv itself is doing.

Incidentally, I don’t think you need to put gcc in the build inputs, as it’s part of stdenv itself. It would be more correctly part of nativeBuildInputs anyway…

Another possibility is that you haven’t added the relevant files to git. Whatever git sees as “untracked” is effectively invisible when evaluating the flake. git add -N is the bare minimum necessary to get around this.

1 Like