3

I cannot make local include paths work in the Meson build system.

This C++ inclusion works correctly:

#include </cygdrive/c/Users/user/project/Third-Party/eigen/Eigen/Dense>

This one does not:

#include "Third-Party/eigen/Eigen/Dense"

fatal error: Eigen/Dense: No such file or directory

In the Meson build file, I tried to add Eigen's path, without success:

# '.' will refer to current build directory
include_dirs = include_directories('include', '.', '../project/Third-Party/eigen')

This is the project tree structure:

project
   meson.build
   src
      meson.build
      example.h
      example.cpp
   Third-Party
      eigen  (headers only lib)
         Eigen

Note: with CMake I do not have this issue.

Pietro
  • 12,086
  • 26
  • 100
  • 193
  • Does adding `/cygdrive/c/Users/user/project/Third-Party/eigen/` to `include_directories` work? (And writing `#include ` in the c++ file). Writing absolute paths in c++ files is not a good idea. – chtz Jun 12 '18 at 13:15
  • @chtz: now I get an error directly from Meson, and not the compiler: "meson.build:28:0: ERROR: Tried to form an absolute path to a source dir. You should not do that but use relative paths instead." – Pietro Jun 12 '18 at 14:02
  • And the `'../project/Third-Party/eigen'` together with `#include ` does not work, either? – chtz Jun 12 '18 at 14:09
  • No: that was my first attempt. – Pietro Jun 12 '18 at 14:22

1 Answers1

4

For dependency management, meson allows you to manually declare include_directories() in your build files. However, there is another way do handle dependencies: using dependency() command.

dependency() is a much better way to handle dependencies, because meson will build it if necessary (if dependency is a shared or a static library) and safely allows you to use includes. That means that you don't have to know where includes for dependency are located physically or care about their paths ever after. The only downside is that this kind of dependency needs it's own meson.build file.

Using dependency() command:

To actually use it, you have to write a wrap file for dependency. Or, if you are lucky enough, there is already a wrap file for you in the Wrap DB -- a community-driven database for meson wrap files. Wrap file is a config of some kind that declare where you can get a dependency and in what form. Wrap file can wrap around zip archives and git repositories.

For your given dependency, there is wrap file in Wrap DB: eigen. All you have to do is download it and place it in the subprojects directory near your meson.build. For example:

$ cd project
$ mkdir subprojects
$ wget "https://wrapdb.mesonbuild.com/v1/projects/eigen/3.3.4/1/get_wrap" \
  -O subprojects/eigen.wrap

Now, not every project builds with meson. For the ones that don't, wrap file also specify a patch. Patch is used to just copy appropriate meson.build file into dependency directory (as well as any other files that would be needed for building that particular dependency with meson). Eigen wrap file contains a patch.

To find out how any particular dependency declare itself as a dependency (using declare_dependency() command), you need to investigate meson.build file in dependency source directory (although it's often just name of the dependency plus _dep, e.g. "eigen_dep"). For me, eigen directory was subprojects/eigen-eigen-5a0156e40feb. So, you search for the declare_dependency() command:

$ grep declare_dependency subprojects/eigen-eigen-5a0156e40feb/meson.build
eigen_dep = declare_dependency(

As you can see, eigen declare dependency as eigen_dep. If you want to know what exactly is declared, just scroll down the dependency meson.build file.

Now, to use that eigen_dep in your project, create a dependency object with a dependency() command. Here is a sample project that I used to compile "A simple first program" from Eigen: Getting Started:

project('example', 'cpp')
eigen_dependency = dependency('eigen', fallback: ['eigen', 'eigen_dep'])
executable('example', 'example.cpp', dependencies: eigen_dependency) 

Notice arguments for the dependency() command. The first one is system-wide dependency that meson is searching for. If there is no eigen for development installed in your system, then meson uses fallback: first item in fallback is basename of the wrap file, second item is a name of declared dependency.

Then use eigen_dependency variable in whatever you build, passing it to the dependencies argument.

Using include_directories() command:

If you want to just include some files from external directory (such as your "Third-Party" directory) using include_directories() command, that directory has to be relative to the meson.build file where you use it.

To use manually declared includes, you need to call include_directories() command to get the include_directories object. Pass that object to include_directories argument in whatever you build.

Given your example, I assume that root meson.build file is a project build file. Then in that root meson.build, for example, you can write:

# File: project/meson.build
project('example', 'cpp')
eigen_includes = include_directories('Third-Parties/eigen')
executable('example', 'example.cpp', include_directories: eigen_includes)

But if you want to get eigen includes from src/meson.build, then you need to change include_directories to:

# File: project/src/meson.build
eigen_includes = include_directories('../Third-Parties/eigen')
...
barsoosayque
  • 329
  • 2
  • 11