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:
parent
6662f36ed3
commit
6963da616b
|
@ -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):
|
||||||
|
|
|
@ -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 ();
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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')
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "../lib.h"
|
||||||
|
|
||||||
|
SYMBOL_EXPORT
|
||||||
|
int get_shnodep_value (void) {
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
shnodep = shared_library('shnodep', 'lib.c')
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "../lib.h"
|
||||||
|
|
||||||
|
int get_shnodep_value (void);
|
||||||
|
|
||||||
|
SYMBOL_EXPORT
|
||||||
|
int get_shshdep_value (void) {
|
||||||
|
return get_shnodep_value ();
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
shshdep = shared_library('shshdep', 'lib.c', link_with : shnodep)
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "../lib.h"
|
||||||
|
|
||||||
|
int get_stnodep_value (void);
|
||||||
|
|
||||||
|
SYMBOL_EXPORT
|
||||||
|
int get_shstdep_value (void) {
|
||||||
|
return get_stnodep_value ();
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
shstdep = shared_library('shstdep', 'lib.c', link_with : stnodep)
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "../lib.h"
|
||||||
|
|
||||||
|
SYMBOL_EXPORT
|
||||||
|
int get_stnodep_value (void) {
|
||||||
|
return 2;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
stnodep = static_library('stnodep', 'lib.c')
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "../lib.h"
|
||||||
|
|
||||||
|
int get_shnodep_value (void);
|
||||||
|
|
||||||
|
SYMBOL_EXPORT
|
||||||
|
int get_stshdep_value (void) {
|
||||||
|
return get_shnodep_value ();
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
stshdep = static_library('stshdep', 'lib.c', link_with : shnodep)
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "../lib.h"
|
||||||
|
|
||||||
|
int get_stnodep_value (void);
|
||||||
|
|
||||||
|
SYMBOL_EXPORT
|
||||||
|
int get_ststdep_value (void) {
|
||||||
|
return get_stnodep_value ();
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
ststdep = static_library('ststdep', 'lib.c', link_with : stnodep)
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue