Don't add dependencies recursively while linking

We were doing this on the basis of an old comment, but there was no
test for it and I couldn't reproduce the issue with clang on Linux
at all.

Let's add a (somewhat comprehensive) test and see if it breaks
anywhere if we stop doing this.

Halves the size of gstreamer's build.ninja from 20M to 8.7M

Closes https://github.com/mesonbuild/meson/issues/1057
This commit is contained in:
Nirbheek Chauhan 2017-03-30 23:38:28 +05:30
parent 6662f36ed3
commit 6963da616b
21 changed files with 204 additions and 10 deletions

View File

@ -453,15 +453,11 @@ class Backend:
for d in deps: for d in deps:
if not isinstance(d, (build.StaticLibrary, build.SharedLibrary)): if not isinstance(d, (build.StaticLibrary, build.SharedLibrary)):
raise RuntimeError('Tried to link with a non-library target "%s".' % d.get_basename()) raise RuntimeError('Tried to link with a non-library target "%s".' % d.get_basename())
if isinstance(compiler, compilers.LLVMDCompiler) or isinstance(compiler, compilers.DmdDCompiler): if isinstance(compiler, (compilers.LLVMDCompiler, compilers.DmdDCompiler)):
args += ['-L' + self.get_target_filename_for_linking(d)] d_arg = '-L' + self.get_target_filename_for_linking(d)
else: else:
args.append(self.get_target_filename_for_linking(d)) d_arg = self.get_target_filename_for_linking(d)
# If you have executable e that links to shared lib s1 that links to shared library s2 args.append(d_arg)
# you have to specify s2 as well as s1 when linking e even if e does not directly use
# s2. Gcc handles this case fine but Clang does not for some reason. Thus we need to
# explictly specify all libraries every time.
args += self.build_target_link_arguments(compiler, d.get_dependencies())
return args return args
def determine_windows_extra_paths(self, target): def determine_windows_extra_paths(self, target):

View File

@ -0,0 +1,8 @@
#include "../lib.h"
int get_@DEPENDENCY@dep_value (void);
SYMBOL_EXPORT
int get_@LIBTYPE@@DEPENDENCY@dep_value (void) {
return get_@DEPENDENCY@dep_value ();
}

View File

@ -0,0 +1,16 @@
#include <stdio.h>
#include "../lib.h"
SYMBOL_IMPORT int get_@LIBTYPE@@DEPENDENCY@dep_value (void);
int main(int argc, char *argv[]) {
int val;
val = get_@LIBTYPE@@DEPENDENCY@dep_value ();
if (val != @VALUE@) {
printf("@LIBTYPE@@DEPENDENCY@ was %i instead of @VALUE@\n", val);
return -1;
}
return 0;
}

View File

@ -0,0 +1,44 @@
dep3_libs = []
# Permutate all combinations of shared and static libraries up to three levels
# executable -> shared -> static -> shared (etc)
foreach dep2 : ['sh', 'st']
foreach dep1 : ['sh', 'st']
foreach libtype : ['sh', 'st']
name = libtype + dep1 + dep2
if dep2 == 'sh'
libret = 1
elif dep2 == 'st'
libret = 2
else
error('Unknown dep2 "@0@"'.format(dep2))
endif
if libtype == 'sh'
target = 'shared_library'
elif libtype == 'st'
target = 'static_library'
else
error('Unknown libtype "@0@"'.format(libtype))
endif
cdata = configuration_data()
cdata.set('DEPENDENCY', dep1 + dep2)
cdata.set('LIBTYPE', libtype)
cdata.set('VALUE', libret)
lib_c = configure_file(input : 'lib.c.in',
output : name + '-lib.c',
configuration : cdata)
dep = get_variable(dep1 + dep2 + 'dep')
dep3_lib = build_target(name, lib_c, link_with : dep, target_type : target)
dep3_libs += [dep3_lib]
main_c = configure_file(input : 'main.c.in',
output : name + '-main.c',
configuration : cdata)
dep3_bin = executable(name, main_c, link_with : dep3_lib)
test(name + 'test', dep3_bin)
endforeach
endforeach
endforeach

View File

@ -0,0 +1,12 @@
#if defined _WIN32
#define SYMBOL_IMPORT __declspec(dllimport)
#define SYMBOL_EXPORT __declspec(dllexport)
#else
#define SYMBOL_IMPORT
#if defined __GNUC__
#define SYMBOL_EXPORT __attribute__ ((visibility("default")))
#else
#pragma message ("Compiler does not support symbol visibility.")
#define SYMBOL_EXPORT
#endif
#endif

View File

@ -0,0 +1,46 @@
#include <stdio.h>
#include "lib.h"
SYMBOL_IMPORT int get_stnodep_value (void);
SYMBOL_IMPORT int get_shnodep_value (void);
SYMBOL_IMPORT int get_shshdep_value (void);
SYMBOL_IMPORT int get_shstdep_value (void);
SYMBOL_IMPORT int get_stshdep_value (void);
SYMBOL_IMPORT int get_ststdep_value (void);
int main(int argc, char *argv[]) {
int val;
val = get_shnodep_value ();
if (val != 1) {
printf("shnodep was %i instead of 1\n", val);
return -1;
}
val = get_stnodep_value ();
if (val != 2) {
printf("stnodep was %i instead of 2\n", val);
return -2;
}
val = get_shshdep_value ();
if (val != 1) {
printf("shshdep was %i instead of 1\n", val);
return -3;
}
val = get_shstdep_value ();
if (val != 2) {
printf("shstdep was %i instead of 2\n", val);
return -4;
}
val = get_stshdep_value ();
if (val != 1) {
printf("shstdep was %i instead of 1\n", val);
return -5;
}
val = get_ststdep_value ();
if (val != 2) {
printf("ststdep was %i instead of 2\n", val);
return -6;
}
return 0;
}

View File

@ -0,0 +1,22 @@
project('recursive dependencies', 'c')
# Test that you can link a shared executable to:
# - A shared library with no other deps
subdir('shnodep')
# - A static library with no other deps
subdir('stnodep')
# - A shared library with a shared library dep
subdir('shshdep')
# - A shared library with a static library dep
subdir('shstdep')
# - A static library with a shared library dep
subdir('stshdep')
# - A static library with a static library dep
subdir('ststdep')
test('alldeps',
executable('alldeps', 'main.c',
link_with : [shshdep, shstdep, ststdep, stshdep]))
# More combinations of static and shared libraries
subdir('3rdorderdeps')

View File

@ -0,0 +1,6 @@
#include "../lib.h"
SYMBOL_EXPORT
int get_shnodep_value (void) {
return 1;
}

View File

@ -0,0 +1 @@
shnodep = shared_library('shnodep', 'lib.c')

View File

@ -0,0 +1,8 @@
#include "../lib.h"
int get_shnodep_value (void);
SYMBOL_EXPORT
int get_shshdep_value (void) {
return get_shnodep_value ();
}

View File

@ -0,0 +1 @@
shshdep = shared_library('shshdep', 'lib.c', link_with : shnodep)

View File

@ -0,0 +1,8 @@
#include "../lib.h"
int get_stnodep_value (void);
SYMBOL_EXPORT
int get_shstdep_value (void) {
return get_stnodep_value ();
}

View File

@ -0,0 +1 @@
shstdep = shared_library('shstdep', 'lib.c', link_with : stnodep)

View File

@ -0,0 +1,6 @@
#include "../lib.h"
SYMBOL_EXPORT
int get_stnodep_value (void) {
return 2;
}

View File

@ -0,0 +1 @@
stnodep = static_library('stnodep', 'lib.c')

View File

@ -0,0 +1,8 @@
#include "../lib.h"
int get_shnodep_value (void);
SYMBOL_EXPORT
int get_stshdep_value (void) {
return get_shnodep_value ();
}

View File

@ -0,0 +1 @@
stshdep = static_library('stshdep', 'lib.c', link_with : shnodep)

View File

@ -0,0 +1,8 @@
#include "../lib.h"
int get_stnodep_value (void);
SYMBOL_EXPORT
int get_ststdep_value (void) {
return get_stnodep_value ();
}

View File

@ -0,0 +1 @@
ststdep = static_library('ststdep', 'lib.c', link_with : stnodep)

View File

@ -12,7 +12,7 @@ girlib = shared_library(
girexe = executable( girexe = executable(
'girprog', 'girprog',
sources : 'prog.c', sources : 'prog.c',
dependencies : [glib, gobj, gir], dependencies : [glib, gobj, gir, dep1_dep],
link_with : girlib link_with : girlib
) )

View File

@ -6,7 +6,7 @@ subdir('libbar')
vapiexe = executable('vapigen-test', vapiexe = executable('vapigen-test',
'main.vala', 'main.vala',
dependencies: [dependency('gobject-2.0'), libbar_vapi], dependencies: [dependency('gobject-2.0'), libfoo_vapi, libbar_vapi],
install: true, install: true,
) )