Library Overlay Isn't Populating PKG_CONFIG_PATH

Hello again,

Continuing the discussion from this topic. The goal is to wrap a proprietary library archive into a Nix derivation and use it in my application.

After moving the overlay part out from eachDefaultSystem, Nix no longer emits errors when I use this overlay from a different flake. However, the $PKG_CONFIG_PATH is not set in nix develop (and I doubt if the package is “installed” in the devShell.) To better illustrate the scenario, the source directory layout is something like this:

.
├── example_c
│   ├── flake.nix
│   └── src
│       ├── CMakeLists.txt
│       └── main.c
└── nixos
     ├── default.nix
     └── flake.nix

The simplified nixos/flake.nix now only contains the overlay part:

{
outputs = { self }: {
    overlay = final: prev: { 
      fpgamgr = import ./default.nix { pkgs = prev; };
    };
  };
}

Where nixos/default.nix is calling pkgs.stdenvNoCC.mkDerivation: (note: this is a C-wrapper over .NET libraries)

{ pkgs ? import <nixpkgs> {
  config = { allowUnfree = true; };
}}:
pkgs.stdenvNoCC.mkDerivation rec {
  pname = "FpgaManager";
  version = "2.7.0";

  archive_name = "xxx-${version}.zip";
  archive = pkgs.fetchzip {
      url = "http://localhost/archives/fpgamgr/${archive_name}";
      hash = "xxxxxx";
      name = "fpgamanager-original-archive";
  };

  packager = pkgs.fetchurl {
    url = "http://localhost/archives/fpgamgr/package.sh";
    hash = "xxxxxx";
    name = "fpgamanager-packager";
  };

  srcs = [
    archive
    packager
  ];

  dontUnpack = true;

  installPhase = ''
    bash ${packager} -a ${pkgs.system} -d $out ${archive}
  '';

  nativeBuildInputs = with pkgs; [
    pkg-config
  ];

  buildInputs = with pkgs; [
    dotnet-runtime
  ];
}

which will place 2 pkg-config files under $out/usr/lib/pkgconfig:

result
└── usr
    ├── include
    │   └──...
    └── lib
        ├── ...
        └── pkgconfig
            ├── FpgaManagerCXX.pc
            └── FpgaManager.pc

Then I try to include this overlay from example_c/flake.nix:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    internal.url = "./../nixos";
  };

  outputs = { self, nixpkgs, internal }:
  let
      pkgs = import nixpkgs {
        system = "x86_64-linux";
        config.allowUnfree = true;
        overlays = [ internal.overlay ];
      };
  in
  {
    packages.${pkgs.system}.default = pkgs.stdenv.mkDerivation {
      pname = "FpgaDemo";
      version = "0.0.1";
      src = ./src;
      buildPhase = ''
        echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH | tee $out
        echo FLAGS=$(pkg-config --libs --cflags FpgaManager) | tee -a $out
      '';
      nativeBuildInputs = with pkgs; [
        fpgamgr
        pkg-config
      ];
    };
}

The build log suggests the overlay package may not be applied here:

# nix log `realpath result`
...
Running phase: buildPhase
PKG_CONFIG_PATH=
Package FpgaManager was not found in the pkg-config search path.
Perhaps you should add the directory containing `FpgaManager.pc'
to the PKG_CONFIG_PATH environment variable
No package 'FpgaManager' found
FLAGS=

I must be missing the magic sauce here, as normal library packages from nixpkgs will have PKG_CONFIG_PATH set automagically.

Thanks.

$out is supposed to be the prefix so there should be no usr directory. The layout should be as follows:

result
├── include
│   └──...
└── lib
    ├── ...
    └── pkgconfig
        ├── FpgaManagerCXX.pc
        └── FpgaManager.pc

Greatly appreciated. That was a big oops on me.

I have one last question: I can build my demo application with CMake, but the built executable spits out the error:

/nix/store/...-demo-0.0.1/bin/demo: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

I could force LD_LIBRARY_PATH in mkShell and have it run under nix develop, but I wonder how to run the demo program properly with nix run.

The full example_c/flake.nix:

{
  description = "Demo Application";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    internal.url = "./../nixos";
  };

  outputs = { self, nixpkgs, internal }:
  let
      pkgs = import nixpkgs {
        system = "x86_64-linux";
        config.allowUnfree = true;
        overlays = [ internal.overlay ];
      };
    in
    {
      packages.${pkgs.system}.default = pkgs.stdenv.mkDerivation {
        pname = "demo";
        version = "0.0.1";

        src = ./src;

        buildInputs = with pkgs; [
          fpgamgr
        ];

        nativeBuildInputs = with pkgs; [
          cmake
          fpgamgr
          pkg-config
        ];

        installPhase = ''
          install -d $out/bin
          mv demo $out/bin
        '';
      };

      devShells.${pkgs.system}.default = pkgs.callPackage ({ mkShell, pkg-config, ... }:
        mkShell {
          buildInputs = with pkgs; [
            cmake
            fpgamgr
            pkg-config
          ];

          shellHook = ''
            export LD_LIBRARY_PATH=${pkgs.lib.makeLibraryPath [
              pkgs.stdenv.cc.cc
            ]}
          '';
        }
      ) {};
    };
}

BTW, I put additional runtime dependencies under nixos/default.nix:

  propagatedBuildInputs = with pkgs; [
    icu
    dotnet-runtime
  ];

After digging a bit further, I found that this is probably related to the fact that the shared library links against dotnet and has the hard-coded LD_LIBRARY_PATH internally. The demo program would work if I removed this dependency.