Repository: mesonbuild/meson

Issue:
Can't build projects dynamically linked to boost.log
Since this change:

https://github.com/mesonbuild/meson/blob/7c68fe80083fd72a100998578417b223e3704af5/mesonbuild/dependencies/boost.py#L791

I can't compile anymore some applications dynamically linked to boost.log:

```
/usr/include/boost169/boost/log/detail/config.hpp:225: error: "BOOST_LOG_DLL" redefined [-Werror]
 #       define BOOST_LOG_DLL

<command-line>: note: this is the location of the previous definition
```

I think that `-DBOOST_LOG_DLL` should not specified (see https://www.boost.org/doc/libs/1_72_0/libs/log/doc/html/log/rationale/namespace_mangling.html) but only `-DBOOST_LOG_DYN_LINK=1`

Tested with boost from 1.69 to 1.72 on CentOS and MacOS.

If you confirm that `-DBOOST_LOG_DLL` can be removed I can provide a PR, just let me know .


Discussion:
Since this is only a warning, you should still be able to build the projects if you disable `werror` in meson (which is admittedly not ideal) until the next release.

But I can confirm that this is a meson issue, since this define is not specified in the `usage-requirements`: https://github.com/boostorg/log/blob/develop/build/Jamfile.v2#L493
Hi @mensinda,

I know, but you guessed that it is not ideal indeed (my development policy is to have zero warning/errors, and I cannot silent selectively only this kind of error on some compiler).

So I'm not going to wait for the next release (even because there are other issues with the 0.54.0 solved on the master). I'm going to fix the thing for me and use the fork. If you agree with my change (since we agree on the solution), I'll be very happy to open the PR, it's just a little removal, isn't? 

Thank you for your answer!
Yes and no. The code in question was automatically generated by [boost_names.py](https://github.com/mesonbuild/meson/blob/master/tools/boost_names.py), so I would rather fix this properly by fixing the code generator. If removing it in your fork works better for you than disabling `werror` go for it.

So, in short, I won't accept a PR that just removes `-DBOOST_LOG_DLL`. That being said, I am looking into the underlying issue right now.
Sorry, I didn't realize there was a code generator here! No hurry, in the meanwhile I'll manage in some way!

Resolving patch:
diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py
--- a/mesonbuild/dependencies/boost.py
+++ b/mesonbuild/dependencies/boost.py
@@ -665,9 +665,9 @@ def _extra_compile_args(self) -> T.List[str]:
 ####      ---- BEGIN GENERATED ----      ####
 #                                           #
 # Generated with tools/boost_names.py:
-#  - boost version:   1.72.0
-#  - modules found:   158
-#  - libraries found: 42
+#  - boost version:   1.73.0
+#  - modules found:   159
+#  - libraries found: 43
 #
 
 class BoostLibrary():
@@ -690,16 +690,16 @@ def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
 boost_libraries = {
     'boost_atomic': BoostLibrary(
         name='boost_atomic',
-        shared=[],
-        static=[],
+        shared=['-DBOOST_ATOMIC_DYN_LINK=1'],
+        static=['-DBOOST_ATOMIC_STATIC_LINK=1'],
         single=[],
         multi=[],
     ),
     'boost_chrono': BoostLibrary(
         name='boost_chrono',
-        shared=['-DBOOST_ALL_DYN_LINK=1'],
-        static=['-DBOOST_All_STATIC_LINK=1'],
-        single=[],
+        shared=['-DBOOST_CHRONO_DYN_LINK=1'],
+        static=['-DBOOST_CHRONO_STATIC_LINK=1'],
+        single=['-DBOOST_CHRONO_THREAD_DISABLED'],
         multi=[],
     ),
     'boost_container': BoostLibrary(
@@ -711,28 +711,28 @@ def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
     ),
     'boost_context': BoostLibrary(
         name='boost_context',
-        shared=[],
+        shared=['-DBOOST_CONTEXT_DYN_LINK=1'],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_contract': BoostLibrary(
         name='boost_contract',
-        shared=[],
-        static=[],
-        single=[],
+        shared=['-DBOOST_CONTRACT_DYN_LINK'],
+        static=['-DBOOST_CONTRACT_STATIC_LINK'],
+        single=['-DBOOST_CONTRACT_DISABLE_THREADS'],
         multi=[],
     ),
     'boost_coroutine': BoostLibrary(
         name='boost_coroutine',
-        shared=[],
+        shared=['-DBOOST_COROUTINES_DYN_LINK=1'],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_date_time': BoostLibrary(
         name='boost_date_time',
-        shared=[],
+        shared=['-DBOOST_DATE_TIME_DYN_LINK=1'],
         static=[],
         single=[],
         multi=[],
@@ -746,14 +746,14 @@ def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
     ),
     'boost_fiber': BoostLibrary(
         name='boost_fiber',
-        shared=[],
+        shared=['-DBOOST_FIBERS_DYN_LINK=1'],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_fiber_numa': BoostLibrary(
         name='boost_fiber_numa',
-        shared=[],
+        shared=['-DBOOST_FIBERS_DYN_LINK=1'],
         static=[],
         single=[],
         multi=[],
@@ -767,84 +767,91 @@ def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
     ),
     'boost_graph': BoostLibrary(
         name='boost_graph',
-        shared=['-DBOOST_GRAPH_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_iostreams': BoostLibrary(
         name='boost_iostreams',
-        shared=['-DBOOST_IOSTREAMS_DYN_LINK=1', '-DBOOST_IOSTREAMS_DYN_LINK=1'],
+        shared=['-DBOOST_IOSTREAMS_DYN_LINK=1'],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_locale': BoostLibrary(
         name='boost_locale',
-        shared=['-DBOOST_LOCALE_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_log': BoostLibrary(
         name='boost_log',
-        shared=['-DBOOST_LOG_DLL', '-DBOOST_LOG_DYN_LINK=1'],
+        shared=['-DBOOST_LOG_DYN_LINK=1'],
         static=[],
-        single=['BOOST_LOG_NO_THREADS'],
+        single=['-DBOOST_LOG_NO_THREADS'],
         multi=[],
     ),
     'boost_log_setup': BoostLibrary(
         name='boost_log_setup',
-        shared=['-DBOOST_LOG_DYN_LINK=1', '-DBOOST_LOG_SETUP_DLL', '-DBOOST_LOG_SETUP_DYN_LINK=1'],
+        shared=['-DBOOST_LOG_SETUP_DYN_LINK=1'],
         static=[],
-        single=['BOOST_LOG_NO_THREADS'],
+        single=['-DBOOST_LOG_NO_THREADS'],
         multi=[],
     ),
     'boost_math_c99': BoostLibrary(
         name='boost_math_c99',
-        shared=['-DBOOST_MATH_TR1_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_math_c99f': BoostLibrary(
         name='boost_math_c99f',
-        shared=['-DBOOST_MATH_TR1_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_math_c99l': BoostLibrary(
         name='boost_math_c99l',
-        shared=['-DBOOST_MATH_TR1_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_math_tr1': BoostLibrary(
         name='boost_math_tr1',
-        shared=['-DBOOST_MATH_TR1_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_math_tr1f': BoostLibrary(
         name='boost_math_tr1f',
-        shared=['-DBOOST_MATH_TR1_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_math_tr1l': BoostLibrary(
         name='boost_math_tr1l',
-        shared=['-DBOOST_MATH_TR1_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_mpi': BoostLibrary(
         name='boost_mpi',
-        shared=['-DBOOST_MPI_DYN_LINK=1'],
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_nowide': BoostLibrary(
+        name='boost_nowide',
+        shared=['-DBOOST_NOWIDE_DYN_LINK=1'],
         static=[],
         single=[],
         multi=[],
@@ -865,63 +872,63 @@ def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
     ),
     'boost_random': BoostLibrary(
         name='boost_random',
-        shared=[],
+        shared=['-DBOOST_RANDOM_DYN_LINK'],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_regex': BoostLibrary(
         name='boost_regex',
-        shared=['-DBOOST_REGEX_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_serialization': BoostLibrary(
         name='boost_serialization',
-        shared=['-DBOOST_SERIALIZATION_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_stacktrace_addr2line': BoostLibrary(
         name='boost_stacktrace_addr2line',
-        shared=['-DBOOST_STACKTRACE_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_stacktrace_backtrace': BoostLibrary(
         name='boost_stacktrace_backtrace',
-        shared=['-DBOOST_STACKTRACE_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_stacktrace_basic': BoostLibrary(
         name='boost_stacktrace_basic',
-        shared=['-DBOOST_STACKTRACE_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_stacktrace_noop': BoostLibrary(
         name='boost_stacktrace_noop',
-        shared=['-DBOOST_STACKTRACE_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_stacktrace_windbg': BoostLibrary(
         name='boost_stacktrace_windbg',
-        shared=['-DBOOST_STACKTRACE_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
     ),
     'boost_stacktrace_windbg_cached': BoostLibrary(
         name='boost_stacktrace_windbg_cached',
-        shared=['-DBOOST_STACKTRACE_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
@@ -942,8 +949,8 @@ def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
     ),
     'boost_thread': BoostLibrary(
         name='boost_thread',
-        shared=['-DBOOST_THREAD_USE_DLL=1'],
-        static=['-DBOOST_THREAD_USE_LIB=1'],
+        shared=['-DBOOST_THREAD_BUILD_DLL=1', '-DBOOST_THREAD_USE_DLL=1'],
+        static=['-DBOOST_THREAD_BUILD_LIB=1', '-DBOOST_THREAD_USE_LIB=1'],
         single=[],
         multi=[],
     ),
@@ -956,7 +963,7 @@ def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
     ),
     'boost_type_erasure': BoostLibrary(
         name='boost_type_erasure',
-        shared=[],
+        shared=['-DBOOST_TYPE_ERASURE_DYN_LINK'],
         static=[],
         single=[],
         multi=[],
@@ -977,7 +984,7 @@ def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
     ),
     'boost_wserialization': BoostLibrary(
         name='boost_wserialization',
-        shared=['-DBOOST_SERIALIZATION_DYN_LINK=1'],
+        shared=[],
         static=[],
         single=[],
         multi=[],
diff --git a/tools/boost_names.py b/tools/boost_names.py
--- a/tools/boost_names.py
+++ b/tools/boost_names.py
@@ -43,10 +43,10 @@
 class BoostLibrary():
     def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]):
         self.name = name
-        self.shared = shared
-        self.static = static
-        self.single = single
-        self.multi = multi
+        self.shared = sorted(set(shared))
+        self.static = sorted(set(static))
+        self.single = sorted(set(single))
+        self.multi = sorted(set(multi))
 
     def __lt__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
         if isinstance(other, BoostLibrary):
@@ -99,15 +99,35 @@ def get_libraries(jamfile: Path) -> T.List[BoostLibrary]:
     cmds = raw.split(';')              # Commands always terminate with a ; (I hope)
     cmds = [x.strip() for x in cmds]   # Some cleanup
 
+    project_usage_requirements: T.List[str] = []
+
     # "Parse" the relevant sections
     for i in cmds:
         parts = i.split(' ')
-        parts = [x for x in parts if x not in ['', ':']]
+        parts = [x for x in parts if x not in ['']]
         if not parts:
             continue
 
-        # Parese libraries
-        if parts[0] in ['lib', 'boost-lib']:
+        # Parse project
+        if parts[0] in ['project']:
+            attributes: T.Dict[str, T.List[str]] = {}
+            curr: T.Optional[str] = None
+
+            for j in parts:
+                if j == ':':
+                    curr = None
+                elif curr is None:
+                    curr = j
+                else:
+                    if curr not in attributes:
+                        attributes[curr] = []
+                    attributes[curr] += [j]
+
+            if 'usage-requirements' in attributes:
+                project_usage_requirements = attributes['usage-requirements']
+
+        # Parse libraries
+        elif parts[0] in ['lib', 'boost-lib']:
             assert len(parts) >= 2
 
             # Get and check the library name
@@ -117,28 +137,36 @@ def get_libraries(jamfile: Path) -> T.List[BoostLibrary]:
             if not lname.startswith('boost_'):
                 continue
 
+            # Count `:` to only select the 'usage-requirements'
+            # See https://boostorg.github.io/build/manual/master/index.html#bbv2.main-target-rule-syntax
+            colon_counter = 0
+            usage_requirements: T.List[str] = []
+            for j in parts:
+                if j == ':':
+                    colon_counter += 1
+                elif colon_counter >= 4:
+                    usage_requirements += [j]
+
             # Get shared / static defines
             shared: T.List[str] = []
             static: T.List[str] = []
             single: T.List[str] = []
             multi: T.List[str] = []
-            for j in parts:
+            for j in usage_requirements + project_usage_requirements:
                 m1 = re.match(r'<link>shared:<define>(.*)', j)
                 m2 = re.match(r'<link>static:<define>(.*)', j)
                 m3 = re.match(r'<threading>single:<define>(.*)', j)
                 m4 = re.match(r'<threading>multi:<define>(.*)', j)
 
                 if m1:
-                    shared += [m1.group(1)]
+                    shared += [f'-D{m1.group(1)}']
                 if m2:
-                    static += [m2.group(1)]
+                    static += [f'-D{m2.group(1)}']
                 if m3:
-                    single += [m3.group(1)]
+                    single +=[f'-D{m3.group(1)}']
                 if m4:
-                    multi += [m4.group(1)]
+                    multi += [f'-D{m4.group(1)}']
 
-            shared = [f'-D{x}' for x in shared]
-            static = [f'-D{x}' for x in static]
             libs += [BoostLibrary(lname, shared, static, single, multi)]
 
     return libs


Test patch:
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	
@@ -13,7 +13,7 @@ endif
 # within one project. The need to be independent of each other.
 # Use one without a library dependency and one with it.
 
-linkdep     = dependency('boost', static: s, modules : ['thread', 'system'])
+linkdep     = dependency('boost', static: s, modules : ['thread', 'system', 'date_time'])
 testdep     = dependency('boost', static: s, modules : ['unit_test_framework'])
 nomoddep    = dependency('boost', static: s)
 extralibdep = dependency('boost', static: s, modules : ['thread', 'system', 'date_time', 'log_setup', 'log', 'filesystem', 'regex'])