Repository: mesonbuild/meson

Issue:
Boost not detected on Fedora 27
I installed `boost-devel` as well as `boost-static` using `dnf` on Fedora 27. I am including boost in a Meson project with

```
dep_boost = dependency('boost', modules : ['filesystem', 'system', 'asio'])
```

Which results in the following error messages:

```
WARNING: Invalid Boost modules: asio
Dependency Boost (filesystem, system, asio) found: NO

Meson encountered an error in file meson.build, line 69, column 0:
Dependency "boost" not found
```

I also installed `boost-*`, which didn't help. Meson version is `0.44.0`. Works fine with `0.42.1`.

To me this does not seem to be related to #2547 and #2564, my locale is English.


Discussion:
asio seem to be missing.. lets see how b2 builds that library then........
> By default, Boost.Asio is a header-only library.

Do you have `libboost_asio.so` on fedora?
Btw, if you are using `asio` as a header-only library you should remove it from the list of modules in your boost dependency.
Thanks, requiring `asio` as a dependency is the root issue here. There is no `libboost_asio.so` or `libboost_asio.a` installed on my system. Removing `asio` from the module list fixed the problem with meson `0.44.0`.

However, I must say that I find this a little counter-intuitive ‒ I'd like to be able to explicitly state the boost dependencies and ultimately not think about whether they are header-only or not.
@astoeckel I tried that approach, but some boost modules are super complex when it comes to if they should be linked or not, and to what. For example `asio` seem to have dependencies on `system`, `coroutine`, `regex` and `openssl` but some of them are optional. They even have three different types of metafiles to describe the modules, which libraries they contain and which you should/could link to. The libraries can have different names depending on build-time configuration.

The proper way would be that boost switches to a sane build system or at least supports pkgconfig. Until then I think it is impossible to improve the boost support in meson.

Anyway, most modules are header-only and I acknowledge that `modules` is not a very descriptive name. `link_with` or `libraries` would be better. 
Thank you for the explanation! I see that boost brings its own bag of intricacies. I wonder whether it wouldn't be sufficient for at least 90% of the use cases to just not issue an error message if a static/dynamic boost library is not found, yet the corresponding `boost/<module_name>` include directory exists.

I also agree that `link_with` is a better name for the `modules` parameter in the current implementation.
> just not issue an error message if a static/dynamic boost library is not found

We could of course go back to the old behavior but that would increase code complexity. We had two or three bugs that where all solved by my "simplification" to the new behavior.

I don't like it for several reasons:
- `boost/<dirname>` isn't a 1 to 1 mapping to boost modules. A descriptive name for the `modules` parameter would be `include-dir-or-link-with` in this case.
- The implicitness of "allow input that isn't required"
- more code = more bugs
- some modules, like `test`, has libraries that are named differently like `boost_unit_test_framework` and `boost_prg_exec_monitor`. Previously meson allowed you to write `test` and then it linked to some of the libraries in the module without any possibility to change. If boost had a sane build system we could automatically create the dependency with all these weird cases, but it doesn't. So now it would be a huge effort to add all this logic to the meson dependency. Especially since they have so many ways to define a library in the various boost build system and documentation metafiles.

If you are up for it, fine, but I don't have the possibility to implement/maintain a more intelligent boost dependency.
Regardless of what the right thing to do is, it is a bad user experience to error out instead of telling the user what to do. I suggest that we add a hand-maintained list of header-only modules, warn when the user adds them to the list, ignore them, and continue.

Resolving patch:
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -71,11 +71,6 @@ def __init__(self, environment, kwargs):
         self.is_multithreading = threading == "multi"
 
         self.requested_modules = self.get_requested(kwargs)
-        invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS]
-        if invalid_modules:
-            mlog.warning('Invalid Boost modules: ' + ', '.join(invalid_modules))
-            self.log_fail()
-            return
 
         self.boost_root = None
         self.boost_roots = []
@@ -112,6 +107,24 @@ def __init__(self, environment, kwargs):
             self.log_fail()
             return
 
+        invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS]
+
+        # previous versions of meson allowed include dirs as modules
+        remove = []
+        for m in invalid_modules:
+            if m in os.listdir(os.path.join(self.incdir, 'boost')):
+                mlog.warning('Requested boost library', mlog.bold(m), 'that doesn\'t exist. '
+                             'This will be an error in the future')
+                remove.append(m)
+
+        self.requested_modules = [x for x in self.requested_modules if x not in remove]
+        invalid_modules = [x for x in invalid_modules if x not in remove]
+
+        if invalid_modules:
+            mlog.warning('Invalid Boost modules: ' + ', '.join(invalid_modules))
+            self.log_fail()
+            return
+
         mlog.debug('Boost library root dir is', mlog.bold(self.boost_root))
         mlog.debug('Boost include directory is', mlog.bold(self.incdir))
 


Test patch:
diff --git a/test cases/failing/69 wrong boost module/meson.build b/test cases/failing/69 wrong boost module/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/failing/69 wrong boost module/meson.build	
@@ -0,0 +1,5 @@
+project('boosttest', 'cpp',
+  default_options : ['cpp_std=c++11'])
+
+# abc doesn't exist
+linkdep = dependency('boost', modules : ['thread', 'system', 'test', 'abc'])
diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build
--- a/test cases/frameworks/1 boost/meson.build	
+++ b/test cases/frameworks/1 boost/meson.build	
@@ -9,7 +9,7 @@ add_project_arguments(['-DBOOST_LOG_DYN_LINK'],
 # within one project. The need to be independent of each other.
 # Use one without a library dependency and one with it.
 
-linkdep = dependency('boost', modules : ['thread', 'system'])
+linkdep = dependency('boost', modules : ['thread', 'system', 'test'])
 staticdep = dependency('boost', modules : ['thread', 'system'], static : true)
 testdep = dependency('boost', modules : ['unit_test_framework'])
 nomoddep = dependency('boost')