Skip to content

Commit

Permalink
Fix excluding sources for static lib in both_libraries()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
xclaesse authored and jpakkane committed Oct 23, 2022
1 parent fa2585d commit 0641654
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 10 deletions.
22 changes: 12 additions & 10 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
import textwrap
import importlib
import copy
import itertools

if T.TYPE_CHECKING:
import argparse
Expand Down Expand Up @@ -3050,6 +3051,7 @@ def add_target(self, name: str, tobj: build.Target) -> None:
@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
Expand All @@ -3071,16 +3073,16 @@ def build_both_libraries(self, node, args, kwargs):
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)

Expand Down
1 change: 1 addition & 0 deletions test cases/common/254 generated header dep/foo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "foo.h"
22 changes: 22 additions & 0 deletions test cases/common/254 generated header dep/meson.build
Original file line number Diff line number Diff line change
@@ -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,
)

0 comments on commit 0641654

Please sign in to comment.