Struggling to create derivation for C++ libraries with CMake

I have been attempting to build my own derivation as nixpkgs doesn’t always have the library I need. I’ve found some guides such as Hacking Your First Package — nix-tutorial documentation and Jacek's C++ Blog · Managing libraries with Nix but I’ve had no success - I get different CMake errors with each library.

For example, this is what my nix file and output looks like for the osqp-eigen library https://github.com/robotology/osqp-eigen

{
  pkgs ? import <nixpkgs> {},
  stdenv ? pkgs.stdenv,
}:

stdenv.mkDerivation rec {
  name = "osqp-eigen";
  version = "master";

  src = builtins.fetchGit {
    url = "https://github.com/robotology/osqp-eigen.git";
    ref = "master";
  };

  nativeBuildInputs = with pkgs; [ cmake gcc ];
  buildInputs = with pkgs; [
    osqp
    eigen
    catch2
  ];

  configurePhase = ''
  mkdir build && cd build
  cmake ../
  '';

  buildPhase = ''
  make
  '';

  installPhase = ''
  make install
  '';

  meta = {
    description = "osqp-cpp";
  };

}

The corresponding error output is:

these derivations will be built:
  /nix/store/c3m0nxidw2inl4rxdm35rxyncyrkd869-osqp-eigen.drv
building '/nix/store/c3m0nxidw2inl4rxdm35rxyncyrkd869-osqp-eigen.drv'...
unpacking sources
unpacking source archive /nix/store/vx8pxcfw6d5kxiid1gqrrvllfbi7ga58-source
source root is source
patching sources
configuring
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /nix/store/8pbwywcj6vbswz7xmy2dh716x8blgh8w-gcc-wrapper-9.3.0/bin/gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /nix/store/8pbwywcj6vbswz7xmy2dh716x8blgh8w-gcc-wrapper-9.3.0/bin/g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Setting build type to 'Release' as none was specified.
-- Configuring done
CMake Error in CMakeLists.txt:
  Imported target "osqp::osqp" includes non-existent path

    "/nix/store/myrvaladws1l5dggxa2akylw3miyvi9f-osqp-0.6.0//nix/store/myrvaladws1l5dggxa2akylw3miyvi9f-osqp-0.6.0/include/osqp"

  in its INTERFACE_INCLUDE_DIRECTORIES.  Possible reasons include:

  * The path was deleted, renamed, or moved to another location.

  * An install or uninstall procedure did not complete successfully.

  * The installation package was faulty and references files it does not
  provide.



CMake Error in CMakeLists.txt:
  Imported target "osqp::osqp" includes non-existent path

    "/nix/store/myrvaladws1l5dggxa2akylw3miyvi9f-osqp-0.6.0//nix/store/myrvaladws1l5dggxa2akylw3miyvi9f-osqp-0.6.0/include/osqp"

  in its INTERFACE_INCLUDE_DIRECTORIES.  Possible reasons include:

  * The path was deleted, renamed, or moved to another location.

  * An install or uninstall procedure did not complete successfully.

  * The installation package was faulty and references files it does not
  provide.



-- Generating done
CMake Generate step failed.  Build files cannot be regenerated correctly.
builder for '/nix/store/c3m0nxidw2inl4rxdm35rxyncyrkd869-osqp-eigen.drv' failed with exit code 1
error: build of '/nix/store/c3m0nxidw2inl4rxdm35rxyncyrkd869-osqp-eigen.drv' failed

I’m unsure of how to write an idiomatic derivation for C++ libraries. I’ve come across different examples of how to include build steps inside a derivation, but often, their reasoning for the selected choices aren’t included.

Most likely you are misunderstanding the path structure that nix-build is creating and navigating by default during the phases.

Your definitions of the phases look like they closely follow the default behavior when you declare cmake as a nativeBuildInput anyway. Do you still get that error when you comment out all of your phase specifications?

If you have any more errors you can add breakpointHook to you build inputs (also you will need to install cntr to your profile or shell) then you can attach whenever you build fails and checkout if the commands are being executed in your expected directory structures (by running ls, pwd, etc.)

1 Like

The CMake files of the osqp package look wrong:

❯ grep "/nix" $(nix-build -A osqp --no-out-link)/lib/cmake/osqp/osqp-targets.cmake
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}//nix/store/jlx300kdq72gfamkmrx9dsmpj2y029hp-osqp-0.6.0/include/osqp"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}//nix/store/jlx300kdq72gfamkmrx9dsmpj2y029hp-osqp-0.6.0/include/osqp"

The ${_IMPORT_PREFIX}/ (or the full Nix path) part should not be there. Could you file a bug against the osqp derivation? (In turn, this seems to be a bug in the upstream CMake files, but it’s easier to keep track through a nixpkgs issue.)

3 Likes

Specifically there is an error in these lines https://github.com/robotology/osqp-eigen/blob/bba25ca59be224546abbd6470944e19a41ab455c/CMakeLists.txt#L46-L47

The cmake install dirs are assumed to be relative to the install prefix, but that is not necessarily the case - the nix build passes absolute paths for these. More info here https://github.com/jtojnar/cmake-snips#assuming-cmake_install_dir-is-relative-path

2 Likes