Should I use buildPythonApplication or mkDerivation here?

I’m going to attempt to package the finite element package Fenics for nix. The installation instructions (found here GitHub - FEniCS/dolfinx: Next generation FEniCS problem solving environment) say to:

  1. First build the C++ core using cmake
  2. Then enter the python/ directory of the project and use pip install - r build-requirements.txt to build the python interface.

In a case like this, should I be using buildPythonApplication or mkDerivation to package the project for nix?

My gut tells me to use buildPythonApplication and something like preConfigure to compile the C++ core. But perhaps it would be better to use mkDerivation to compile the C++ core, then have a separate nix expression to create the python interface which uses buildPythonApplication and the C++ core as a build input.

Above all, what I would really appreciate is for some more experienced nixpkgs contributors to give me some insight on how they would think about approaching this problem. I want to understand what methods people have for planning and troubleshooting package development.

Thank you!

(P.S. I know fenics is technically in nixpkgs, but this is a very old version, the new version (fenicsx) has been almost completely rewritten).

1 Like

It seems like you should use mkDerivation to build the C++ , and then use that as a buildInput for buildPythonApplication

And I guess it could be like

{ ...}:

let

cppdrv = mkDerivation { "do stuff" };

fenics = buildPythonApplication { ..

...
buildInputs = [ cppdrv ];

};

in fenics

and that should allow you to nest the cpp and the python into one nix expression package

(I don’t know anything about fenics so i was just rolling the with the assumption that buildPythonApplication is the correct choice there)

2 Likes

With regards to differences between buildPythonPackage and buildPythonApplication, the main distinction is that the package variant will include Python modules and any associated executables, whereas the application variant will only include executables. I’m not familiar with this project so you’ll have to make the call here - does this derivation include any libraries/modules that you’d want to use in Python code? If so, you want buildPythonPackage - otherwise, either will work.

A quick glance at that repo shows that you’ll probably want to add pyproject = true to the buildPython* call, as the project has a pyproject.toml file. By default, the builder assumes the code is built with a setuptools setup.py script, but this doesn’t appear to be the case for this project.

See: Python section of the Nixpkgs manual

2 Likes

Absolutely the nested approach, yes.

The package is primarily a python package, so it should be declared as such. Aside from current features provided by that, the declaration ensures this package will be included in future changes and deliberations related to python packaging in nixpkgs.

Similarly, by nesting a derivation for the core build, the nature of that build is mirrored in your nix package.

2 Likes

Thank you for the advice. This is exactly what I was looking for.

1 Like

Thank you. Mirroring the nature of the build in the nix package wasn’t something I had considered but it makes a lot of sense. I appreciate the advice.

2 Likes

Thanks for making that distinction. I’ll spend some more time with the nixpkgs manual. The derivation does include libraries that I want to use in python code e.g. import dolphin so I’m thinking buildPythonPackage is the right call here.

2 Likes