aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2022-09-23 09:19:05 -0400
committerJussi Pakkanen <jpakkane@gmail.com>2022-10-23 13:18:34 +0300
commit064165485ce00aac64afd98120fd725032e559fd (patch)
tree2d173ee74fb5d582c60dc8c9faf57ed9f05464b0
parentfa2585d0b364143fb588b8bb611eaa4d1c277811 (diff)
downloadmeson-064165485ce00aac64afd98120fd725032e559fd.zip
meson-064165485ce00aac64afd98120fd725032e559fd.tar.gz
meson-064165485ce00aac64afd98120fd725032e559fd.tar.bz2
Fix excluding sources for static lib in both_libraries()
When using both_libraries(), or library() with default_library=both, we remove all sources from args and kwargs when building the static library, and replace them by the objects from the shared library. But sources could also come from any InternalDependency, in which case we currently build them twice (not efficient) and link both objects into the static library. It also means that when we needlessly build those source for the static library, it miss order dependency on generated headers that we removed from args/kwargs, which can cause build errors in the case the source from static lib is compiled before the header in shared lib gets generated. This happened in GLib: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2917.
-rw-r--r--mesonbuild/interpreter/interpreter.py22
-rw-r--r--test cases/common/254 generated header dep/foo.c1
-rw-r--r--test cases/common/254 generated header dep/meson.build22
3 files changed, 35 insertions, 10 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 1f9a99a..d4f185f 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -101,6 +101,7 @@ import typing as T
import textwrap
import importlib
import copy
+import itertools
if T.TYPE_CHECKING:
import argparse
@@ -3050,6 +3051,7 @@ Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey
@FeatureNew('both_libraries', '0.46.0')
def build_both_libraries(self, node, args, kwargs):
shared_lib = self.build_target(node, args, kwargs, build.SharedLibrary)
+ static_lib = self.build_target(node, args, kwargs, build.StaticLibrary)
# Check if user forces non-PIC static library.
pic = True
@@ -3071,16 +3073,16 @@ Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey
reuse_object_files = pic
if reuse_object_files:
- # Exclude sources from args and kwargs to avoid building them twice
- static_args = [args[0]]
- static_kwargs = kwargs.copy()
- static_kwargs['sources'] = []
- static_kwargs['objects'] = shared_lib.extract_all_objects()
- else:
- static_args = args
- static_kwargs = kwargs
-
- static_lib = self.build_target(node, static_args, static_kwargs, build.StaticLibrary)
+ # Replace sources with objects from the shared library to avoid
+ # building them twice. We post-process the static library instead of
+ # removing sources from args because sources could also come from
+ # any InternalDependency, see BuildTarget.add_deps().
+ static_lib.objects.append(build.ExtractedObjects(shared_lib, shared_lib.sources, shared_lib.generated, []))
+ static_lib.sources = []
+ static_lib.generated = []
+ # Compilers with no corresponding sources confuses the backend.
+ # Keep only the first compiler because it is the linker.
+ static_lib.compilers = dict(itertools.islice(static_lib.compilers.items(), 1))
return build.BothLibraries(shared_lib, static_lib)
diff --git a/test cases/common/254 generated header dep/foo.c b/test cases/common/254 generated header dep/foo.c
new file mode 100644
index 0000000..f4de601
--- /dev/null
+++ b/test cases/common/254 generated header dep/foo.c
@@ -0,0 +1 @@
+#include "foo.h"
diff --git a/test cases/common/254 generated header dep/meson.build b/test cases/common/254 generated header dep/meson.build
new file mode 100644
index 0000000..195d082
--- /dev/null
+++ b/test cases/common/254 generated header dep/meson.build
@@ -0,0 +1,22 @@
+project('generated header dep', 'c')
+
+# Regression test case for a very specific case:
+# - Uses both_libraries(), or library() with default_library=both.
+# - A header file is generated by a custom_target() and passed as source.
+# - A C file that uses that header is passed as a declare_dependency() source.
+# Under those specific conditions, the static library used to miss an order
+# dependency on the header file. This happened in GLib:
+# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2917.
+
+python = import('python').find_installation()
+header = custom_target(
+ output: 'foo.h',
+ capture: true,
+ command: [python, '-c', 'print("#define FOO")'],
+)
+
+sources_dep = declare_dependency(sources: files('foo.c'))
+
+both_libraries('foo', header,
+ dependencies: sources_dep,
+)