Have anyone got matplotlib-cpp working on Nix/NixOS?
Or is it Debian specific?
It would be great to have MatPlotLib available directly in C++ code.
Have anyone got matplotlib-cpp working on Nix/NixOS?
Or is it Debian specific?
It would be great to have MatPlotLib available directly in C++ code.
If I understood correctly, matplotlib-cpp is a header-only library. You can copy the matplotlibcpp.h
file inside you project and compile.
Thank you!
The main problem now is that g++ doesn’t find the NumPy C++ headers.
Where can I get them?
$ make Plot.o
g++ -o Plot.o -std=c++11 -g -Wall -Iresult/include/python3.8 -lpython3.8 src/Plot.cpp matplotlib-cpp/matplotlibcpp.h NumericDifferentiation.so
In file included from src/Plot.cpp:7:
src/../matplotlib-cpp/matplotlibcpp.h:17:12: fatal error: numpy/arrayobject.h: No such file or directory
17 | # include <numpy/arrayobject.h>
| ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
matplotlib-cpp/matplotlibcpp.h:1:9: warning: #pragma once in main file
1 | #pragma once
| ^~~~
matplotlib-cpp/matplotlibcpp.h:17:12: fatal error: numpy/arrayobject.h: No such file or directory
17 | # include <numpy/arrayobject.h>
| ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:10: Plot.o] Error 1
Try to add this to this g++ command:
-I$(python -c "import numpy as np; print(np.get_include())")
The examples can now be built successfully, but the output executable complains ModuleNotFound at run time.
I run it in nix-shell with a derivation generated using python38.withPackages
.
shamrock@nixos-202104:~/Documents/Reports_1092/NumericSimulation/W04/matplotlib-cpp/examples]$ python3
Python 3.8.8 (default, Feb 19 2021, 11:04:50)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib.pyplot as plt
>>> exit()
[shamrock@nixos-202104:~/Documents/Reports_1092/NumericSimulation/W04/matplotlib-cpp/examples]$ echo g++ -o basic.o -std=c++11 -g -Wall -I$(python3.8 -c "from sysconfig import get_paths; print(get_paths()['include'])") -lpython3.8 -I$(python3.8 -c "import numpy as np; print(np.get_include())") ./basic.cpp
g++ -o basic.o -std=c++11 -g -Wall -I/nix/store/qy5z9gcld7dljm4i5hj3z8a9l6p37y81-python3-3.8.8/include/python3.8 -lpython3.8 -I/nix/store/fkhwf951i9bdcmxsb2jijihq599jlkfh-python3-3.8.8-env/lib/python3.8/site-packages/numpy/core/include ./basic.cpp
[shamrock@nixos-202104:~/Documents/Reports_1092/NumericSimulation/W04/matplotlib-cpp/examples]$ g++ -o basic.o -std=c++11 -g -Wall -I$(python3.8 -c "from sysconfig import get_paths; print(get_paths()['include'])") -lpython3.8 -I$(python3.8 -c "import numpy as np; print(np.get_include())") ./basic.cpp
[shamrock@nixos-202104:~/Documents/Reports_1092/NumericSimulation/W04/matplotlib-cpp/examples]$ ./basic.o
ModuleNotFoundError: No module named 'numpy'
ModuleNotFoundError: No module named 'matplotlib'
terminate called after throwing an instance of 'std::runtime_error'
what(): Error loading module matplotlib!
Aborted (core dumped)
I fixed this problem exporting $PYTHONPATH
. It’s easier to create a shell.nix
like this:
with (import <nixpkgs> { });
let
my_python = python3.withPackages (ps:
with ps; [
numpy
matplotlib
]);
in
mkShell {
nativeBuildInputs = [
cmake
my_python
];
PYTHONPATH = "${my_python}/${my_python.sitePackages}";
}
Also, it’s better to use cmake
to ease the compilation process. I create this one, just replace test
with the name the executable do you want to create:
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(test LANGUAGES CXX)
find_package(Python3 COMPONENTS Interpreter Development NumPy REQUIRED)
include_directories(${Python_INCLUDE_DIRS})
include_directories(${Python_NumPy_INCLUDE_DIRS})
message(STATUS "PYTHON_EXECUTABLE = ${Python3_EXECUTABLE}")
message(STATUS "PYTHON_INCLUDE_DIRS = ${Python3_INCLUDE_DIRS}")
message(STATUS "NumPy_INCLUDE_DIRS = ${Python3_NumPy_INCLUDE_DIRS}")
message(STATUS "Python_LIBRARIES = ${Python3_LIBRARIES}")
add_executable(test test.cpp)
target_link_libraries(test Python3::Python)
target_link_libraries(test Python3::Module)
target_link_libraries(test Python3::NumPy)
The error indicates that the python interpreter that gets invoked by the library doesn’t have numpy and matplotlib in its site-packages. Maybe you have another python
in your PATH?
As an alternative to @brogos solution you can also use NIX_CFLAGS_COMPILE
& co as a backchannel to cc-wrapper
like so:
{ pkgs ? import <nixpkgs> {} }:
let
py3 = pkgs.python3;
in pkgs.mkShell {
buildInputs = [
py3.pkgs.numpy
py3.pkgs.matplotlib
];
NIX_CFLAGS_COMPILE = [
"-isystem ${py3}/include/${py3.libPrefix}"
"-isystem ${py3.pkgs.numpy}/${py3.sitePackages}/numpy/core/include"
];
NIX_LDFLAGS = [
"-l${py3.libPrefix}"
];
}
g++ basic.cpp
should work in this shell, and it doesn’t require CMake to do its magic.