Merge pull request #1545 from centricular/dont-link-recursively

Don't add dependencies recursively while linking
pull/1730/merge
Jussi Pakkanen 8 years ago committed by GitHub
commit 62051626a5
  1. 12
      mesonbuild/backend/backends.py
  2. 58
      mesonbuild/backend/ninjabackend.py
  3. 50
      mesonbuild/compilers.py
  4. 31
      run_unittests.py
  5. 8
      test cases/common/153 recursive linking/3rdorderdeps/lib.c.in
  6. 16
      test cases/common/153 recursive linking/3rdorderdeps/main.c.in
  7. 49
      test cases/common/153 recursive linking/3rdorderdeps/meson.build
  8. 6
      test cases/common/153 recursive linking/circular/lib1.c
  9. 6
      test cases/common/153 recursive linking/circular/lib2.c
  10. 6
      test cases/common/153 recursive linking/circular/lib3.c
  11. 28
      test cases/common/153 recursive linking/circular/main.c
  12. 5
      test cases/common/153 recursive linking/circular/meson.build
  13. 3
      test cases/common/153 recursive linking/circular/prop1.c
  14. 3
      test cases/common/153 recursive linking/circular/prop2.c
  15. 3
      test cases/common/153 recursive linking/circular/prop3.c
  16. 17
      test cases/common/153 recursive linking/lib.h
  17. 46
      test cases/common/153 recursive linking/main.c
  18. 26
      test cases/common/153 recursive linking/meson.build
  19. 6
      test cases/common/153 recursive linking/shnodep/lib.c
  20. 1
      test cases/common/153 recursive linking/shnodep/meson.build
  21. 8
      test cases/common/153 recursive linking/shshdep/lib.c
  22. 1
      test cases/common/153 recursive linking/shshdep/meson.build
  23. 8
      test cases/common/153 recursive linking/shstdep/lib.c
  24. 1
      test cases/common/153 recursive linking/shstdep/meson.build
  25. 6
      test cases/common/153 recursive linking/stnodep/lib.c
  26. 2
      test cases/common/153 recursive linking/stnodep/meson.build
  27. 8
      test cases/common/153 recursive linking/stshdep/lib.c
  28. 2
      test cases/common/153 recursive linking/stshdep/meson.build
  29. 8
      test cases/common/153 recursive linking/ststdep/lib.c
  30. 2
      test cases/common/153 recursive linking/ststdep/meson.build
  31. 2
      test cases/frameworks/7 gnome/gir/meson.build
  32. 2
      test cases/vala/11 generated vapi/meson.build

@ -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):

@ -12,6 +12,11 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import shlex
import os, sys, pickle, re
import subprocess, shutil
from collections import OrderedDict
from . import backends from . import backends
from .. import modules from .. import modules
from .. import environment, mesonlib from .. import environment, mesonlib
@ -24,16 +29,13 @@ from ..mesonlib import File, MesonException, OrderedSet
from ..mesonlib import get_meson_script, get_compiler_for_source from ..mesonlib import get_meson_script, get_compiler_for_source
from .backends import CleanTrees, InstallData from .backends import CleanTrees, InstallData
from ..build import InvalidArguments from ..build import InvalidArguments
import os, sys, pickle, re
import subprocess, shutil
from collections import OrderedDict
if mesonlib.is_windows(): if mesonlib.is_windows():
quote_char = '"' quote_func = lambda s: '"{}"'.format(s)
execute_wrapper = 'cmd /c' execute_wrapper = 'cmd /c'
rmfile_prefix = 'del /f /s /q {} &&' rmfile_prefix = 'del /f /s /q {} &&'
else: else:
quote_char = "'" quote_func = shlex.quote
execute_wrapper = '' execute_wrapper = ''
rmfile_prefix = 'rm -f {} &&' rmfile_prefix = 'rm -f {} &&'
@ -58,22 +60,22 @@ class NinjaBuildElement:
self.infilenames = [infilenames] self.infilenames = [infilenames]
else: else:
self.infilenames = infilenames self.infilenames = infilenames
self.deps = [] self.deps = set()
self.orderdeps = [] self.orderdeps = set()
self.elems = [] self.elems = []
self.all_outputs = all_outputs self.all_outputs = all_outputs
def add_dep(self, dep): def add_dep(self, dep):
if isinstance(dep, list): if isinstance(dep, list):
self.deps += dep self.deps.update(dep)
else: else:
self.deps.append(dep) self.deps.add(dep)
def add_orderdep(self, dep): def add_orderdep(self, dep):
if isinstance(dep, list): if isinstance(dep, list):
self.orderdeps += dep self.orderdeps.update(dep)
else: else:
self.orderdeps.append(dep) self.orderdeps.add(dep)
def add_item(self, name, elems): def add_item(self, name, elems):
if isinstance(elems, str): if isinstance(elems, str):
@ -105,18 +107,17 @@ class NinjaBuildElement:
(name, elems) = e (name, elems) = e
should_quote = name not in raw_names should_quote = name not in raw_names
line = ' %s = ' % name line = ' %s = ' % name
q_templ = quote_char + "%s" + quote_char
noq_templ = "%s" noq_templ = "%s"
newelems = [] newelems = []
for i in elems: for i in elems:
if not should_quote or i == '&&': # Hackety hack hack if not should_quote or i == '&&': # Hackety hack hack
templ = noq_templ quoter = ninja_quote
else: else:
templ = q_templ quoter = lambda x: ninja_quote(quote_func(x))
i = i.replace('\\', '\\\\') i = i.replace('\\', '\\\\')
if quote_char == '"': if quote_func('') == '""':
i = i.replace('"', '\\"') i = i.replace('"', '\\"')
newelems.append(templ % ninja_quote(i)) newelems.append(quoter(i))
line += ' '.join(newelems) line += ' '.join(newelems)
line += '\n' line += '\n'
outfile.write(line) outfile.write(line)
@ -854,12 +855,12 @@ int dummy;
outfile.write(' depfile = $DEPFILE\n') outfile.write(' depfile = $DEPFILE\n')
outfile.write(' restat = 1\n\n') outfile.write(' restat = 1\n\n')
outfile.write('rule REGENERATE_BUILD\n') outfile.write('rule REGENERATE_BUILD\n')
c = (quote_char + ninja_quote(sys.executable) + quote_char, c = (ninja_quote(quote_func(sys.executable)),
quote_char + ninja_quote(self.environment.get_build_command()) + quote_char, ninja_quote(quote_func(self.environment.get_build_command())),
'--internal', '--internal',
'regenerate', 'regenerate',
quote_char + ninja_quote(self.environment.get_source_dir()) + quote_char, ninja_quote(quote_func(self.environment.get_source_dir())),
quote_char + ninja_quote(self.environment.get_build_dir()) + quote_char) ninja_quote(quote_func(self.environment.get_build_dir())))
outfile.write(" command = %s %s %s %s %s %s --backend ninja\n" % c) outfile.write(" command = %s %s %s %s %s %s --backend ninja\n" % c)
outfile.write(' description = Regenerating build files.\n') outfile.write(' description = Regenerating build files.\n')
outfile.write(' generator = 1\n\n') outfile.write(' generator = 1\n\n')
@ -1515,7 +1516,7 @@ rule FORTRAN_DEP_HACK
pass pass
return [] return []
def generate_compile_rule_for(self, langname, compiler, qstr, is_cross, outfile): def generate_compile_rule_for(self, langname, compiler, is_cross, outfile):
if langname == 'java': if langname == 'java':
if not is_cross: if not is_cross:
self.generate_java_compile_rule(compiler, outfile) self.generate_java_compile_rule(compiler, outfile)
@ -1547,7 +1548,7 @@ rule FORTRAN_DEP_HACK
quoted_depargs = [] quoted_depargs = []
for d in depargs: for d in depargs:
if d != '$out' and d != '$in': if d != '$out' and d != '$in':
d = qstr % d d = quote_func(d)
quoted_depargs.append(d) quoted_depargs.append(d)
cross_args = self.get_cross_info_lang_args(langname, is_cross) cross_args = self.get_cross_info_lang_args(langname, is_cross)
if mesonlib.is_windows(): if mesonlib.is_windows():
@ -1576,7 +1577,7 @@ rule FORTRAN_DEP_HACK
outfile.write(description) outfile.write(description)
outfile.write('\n') outfile.write('\n')
def generate_pch_rule_for(self, langname, compiler, qstr, is_cross, outfile): def generate_pch_rule_for(self, langname, compiler, is_cross, outfile):
if langname != 'c' and langname != 'cpp': if langname != 'c' and langname != 'cpp':
return return
if is_cross: if is_cross:
@ -1595,7 +1596,7 @@ rule FORTRAN_DEP_HACK
quoted_depargs = [] quoted_depargs = []
for d in depargs: for d in depargs:
if d != '$out' and d != '$in': if d != '$out' and d != '$in':
d = qstr % d d = quote_func(d)
quoted_depargs.append(d) quoted_depargs.append(d)
if compiler.get_id() == 'msvc': if compiler.get_id() == 'msvc':
output = '' output = ''
@ -1621,12 +1622,11 @@ rule FORTRAN_DEP_HACK
outfile.write('\n') outfile.write('\n')
def generate_compile_rules(self, outfile): def generate_compile_rules(self, outfile):
qstr = quote_char + "%s" + quote_char
for langname, compiler in self.build.compilers.items(): for langname, compiler in self.build.compilers.items():
if compiler.get_id() == 'clang': if compiler.get_id() == 'clang':
self.generate_llvm_ir_compile_rule(compiler, False, outfile) self.generate_llvm_ir_compile_rule(compiler, False, outfile)
self.generate_compile_rule_for(langname, compiler, qstr, False, outfile) self.generate_compile_rule_for(langname, compiler, False, outfile)
self.generate_pch_rule_for(langname, compiler, qstr, False, outfile) self.generate_pch_rule_for(langname, compiler, False, outfile)
if self.environment.is_cross_build(): if self.environment.is_cross_build():
# In case we are going a target-only build, make the native compilers # In case we are going a target-only build, make the native compilers
# masquerade as cross compilers. # masquerade as cross compilers.
@ -1637,8 +1637,8 @@ rule FORTRAN_DEP_HACK
for langname, compiler in cclist.items(): for langname, compiler in cclist.items():
if compiler.get_id() == 'clang': if compiler.get_id() == 'clang':
self.generate_llvm_ir_compile_rule(compiler, True, outfile) self.generate_llvm_ir_compile_rule(compiler, True, outfile)
self.generate_compile_rule_for(langname, compiler, qstr, True, outfile) self.generate_compile_rule_for(langname, compiler, True, outfile)
self.generate_pch_rule_for(langname, compiler, qstr, True, outfile) self.generate_pch_rule_for(langname, compiler, True, outfile)
outfile.write('\n') outfile.write('\n')
def generate_generator_list_rules(self, target, outfile): def generate_generator_list_rules(self, target, outfile):

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import re
import shutil import shutil
import contextlib import contextlib
import subprocess, os.path import subprocess, os.path
@ -385,10 +386,15 @@ class CompilerArgs(list):
# Arg prefixes that override by prepending instead of appending # Arg prefixes that override by prepending instead of appending
prepend_prefixes = ('-I', '-L') prepend_prefixes = ('-I', '-L')
# Arg prefixes and args that must be de-duped by returning 2 # Arg prefixes and args that must be de-duped by returning 2
dedup2_prefixes = ('-I', '-L', '-D') dedup2_prefixes = ('-I', '-L', '-D', '-U')
dedup2_suffixes = ()
dedup2_args = () dedup2_args = ()
# Arg prefixes and args that must be de-duped by returning 1 # Arg prefixes and args that must be de-duped by returning 1
dedup1_prefixes = () dedup1_prefixes = ('-l',)
dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a')
# Match a .so of the form path/to/libfoo.so.0.1.0
# Only UNIX shared libraries require this. Others have a fixed extension.
dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread') dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread')
compiler = None compiler = None
@ -426,7 +432,7 @@ class CompilerArgs(list):
def _can_dedup(cls, arg): def _can_dedup(cls, arg):
''' '''
Returns whether the argument can be safely de-duped. This is dependent Returns whether the argument can be safely de-duped. This is dependent
on two things: on three things:
a) Whether an argument can be 'overriden' by a later argument. For a) Whether an argument can be 'overriden' by a later argument. For
example, -DFOO defines FOO and -UFOO undefines FOO. In this case, we example, -DFOO defines FOO and -UFOO undefines FOO. In this case, we
@ -440,10 +446,20 @@ class CompilerArgs(list):
a particular argument is present. This can matter for symbol a particular argument is present. This can matter for symbol
resolution in static or shared libraries, so we cannot de-dup or resolution in static or shared libraries, so we cannot de-dup or
reorder them. For these we return `0`. This is the default. reorder them. For these we return `0`. This is the default.
In addition to these, we handle library arguments specially.
With GNU ld, we surround library arguments with -Wl,--start/end-group
to recursively search for symbols in the libraries. This is not needed
with other linkers.
''' '''
if arg.startswith(cls.dedup2_prefixes) or arg in cls.dedup2_args: if arg in cls.dedup2_args or \
arg.startswith(cls.dedup2_prefixes) or \
arg.endswith(cls.dedup2_suffixes):
return 2 return 2
if arg.startswith(cls.dedup1_prefixes) or arg in cls.dedup1_args: if arg in cls.dedup1_args or \
arg.startswith(cls.dedup1_prefixes) or \
arg.endswith(cls.dedup1_suffixes) or \
re.search(cls.dedup1_regex, arg):
return 1 return 1
return 0 return 0
@ -454,6 +470,21 @@ class CompilerArgs(list):
return False return False
def to_native(self): def to_native(self):
# Check if we need to add --start/end-group for circular dependencies
# between static libraries.
if get_compiler_uses_gnuld(self.compiler):
group_started = False
for each in self:
if not each.startswith('-l') and not each.endswith('.a'):
continue
i = self.index(each)
if not group_started:
# First occurance of a library
self.insert(i, '-Wl,--start-group')
group_started = True
# Last occurance of a library
if group_started:
self.insert(i + 1, '-Wl,--end-group')
return self.compiler.unix_args_to_native(self) return self.compiler.unix_args_to_native(self)
def __add__(self, args): def __add__(self, args):
@ -2412,6 +2443,15 @@ def get_compiler_is_linuxlike(compiler):
return True return True
return False return False
def get_compiler_uses_gnuld(c):
# FIXME: Perhaps we should detect the linker in the environment?
# FIXME: Assumes that *BSD use GNU ld, but they might start using lld soon
if (getattr(c, 'gcc_type', None) in (GCC_STANDARD, GCC_MINGW, GCC_CYGWIN)) or \
(getattr(c, 'clang_type', None) in (CLANG_STANDARD, CLANG_WIN)) or \
(getattr(c, 'icc_type', None) in (ICC_STANDARD, ICC_WIN)):
return True
return False
def get_largefile_args(compiler): def get_largefile_args(compiler):
''' '''
Enable transparent large-file-support for 32-bit UNIX systems Enable transparent large-file-support for 32-bit UNIX systems

@ -139,7 +139,7 @@ class InternalTests(unittest.TestCase):
self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall'])
## Test that reflected addition works ## Test that reflected addition works
# Test that adding to a list with just one old arg works and DOES NOT yield the same array # Test that adding to a list with just one old arg works and yields the same array
a = ['-Ifoo'] + a a = ['-Ifoo'] + a
self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall'])
# Test that adding to a list with just one new arg that is not pre-pended works # Test that adding to a list with just one new arg that is not pre-pended works
@ -148,6 +148,19 @@ class InternalTests(unittest.TestCase):
# Test that adding to a list with two new args preserves the order # Test that adding to a list with two new args preserves the order
a = ['-Ldir', '-Lbah'] + a a = ['-Ldir', '-Lbah'] + a
self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall']) self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall'])
# Test that adding to a list with old args does nothing
a = ['-Ibar', '-Ibaz', '-Ifoo'] + a
self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall'])
## Test that adding libraries works
l = cargsfunc(c, ['-Lfoodir', '-lfoo'])
self.assertEqual(l, ['-Lfoodir', '-lfoo'])
# Adding a library and a libpath appends both correctly
l += ['-Lbardir', '-lbar']
self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar'])
# Adding the same library again does nothing
l += ['-lbar']
self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar'])
def test_commonpath(self): def test_commonpath(self):
from os.path import sep from os.path import sep
@ -1253,15 +1266,15 @@ class LinuxlikeTests(BasePlatformTests):
self.assertIsNotNone(vala_command) self.assertIsNotNone(vala_command)
self.assertIsNotNone(c_command) self.assertIsNotNone(c_command)
# -w suppresses all warnings, should be there in Vala but not in C # -w suppresses all warnings, should be there in Vala but not in C
self.assertIn("'-w'", vala_command) self.assertIn(" -w ", vala_command)
self.assertNotIn("'-w'", c_command) self.assertNotIn(" -w ", c_command)
# -Wall enables all warnings, should be there in C but not in Vala # -Wall enables all warnings, should be there in C but not in Vala
self.assertNotIn("'-Wall'", vala_command) self.assertNotIn(" -Wall ", vala_command)
self.assertIn("'-Wall'", c_command) self.assertIn(" -Wall ", c_command)
# -Werror converts warnings to errors, should always be there since it's # -Werror converts warnings to errors, should always be there since it's
# injected by an unrelated piece of code and the project has werror=true # injected by an unrelated piece of code and the project has werror=true
self.assertIn("'-Werror'", vala_command) self.assertIn(" -Werror ", vala_command)
self.assertIn("'-Werror'", c_command) self.assertIn(" -Werror ", c_command)
def test_qt5dependency_pkgconfig_detection(self): def test_qt5dependency_pkgconfig_detection(self):
''' '''
@ -1392,7 +1405,7 @@ class LinuxlikeTests(BasePlatformTests):
self.init(testdir, ['-D' + std_opt]) self.init(testdir, ['-D' + std_opt])
cmd = self.get_compdb()[0]['command'] cmd = self.get_compdb()[0]['command']
if v != 'none': if v != 'none':
cmd_std = "'-std={}'".format(v) cmd_std = " -std={} ".format(v)
self.assertIn(cmd_std, cmd) self.assertIn(cmd_std, cmd)
try: try:
self.build() self.build()
@ -1407,7 +1420,7 @@ class LinuxlikeTests(BasePlatformTests):
os.environ[env_flags] = cmd_std os.environ[env_flags] = cmd_std
self.init(testdir) self.init(testdir)
cmd = self.get_compdb()[0]['command'] cmd = self.get_compdb()[0]['command']
qcmd_std = "'{}'".format(cmd_std) qcmd_std = " {} ".format(cmd_std)
self.assertIn(qcmd_std, cmd) self.assertIn(qcmd_std, cmd)
with self.assertRaises(subprocess.CalledProcessError, with self.assertRaises(subprocess.CalledProcessError,
msg='{} should have failed'.format(qcmd_std)): msg='{} should have failed'.format(qcmd_std)):

@ -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,49 @@
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'
build_args = []
elif libtype == 'st'
target = 'static_library'
build_args = ['-DMESON_STATIC_BUILD']
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,
c_args : build_args)
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,
c_args : build_args)
test(name + 'test', dep3_bin)
endforeach
endforeach
endforeach

@ -0,0 +1,6 @@
int get_st2_prop (void);
int get_st3_prop (void);
int get_st1_value (void) {
return get_st2_prop () + get_st3_prop ();
}

@ -0,0 +1,6 @@
int get_st1_prop (void);
int get_st3_prop (void);
int get_st2_value (void) {
return get_st1_prop () + get_st3_prop ();
}

@ -0,0 +1,6 @@
int get_st1_prop (void);
int get_st2_prop (void);
int get_st3_value (void) {
return get_st1_prop () + get_st2_prop ();
}

@ -0,0 +1,28 @@
#include <stdio.h>
#include "../lib.h"
int get_st1_value (void);
int get_st2_value (void);
int get_st3_value (void);
int main(int argc, char *argv[]) {
int val;
val = get_st1_value ();
if (val != 5) {
printf("st1 value was %i instead of 5\n", val);
return -1;
}
val = get_st2_value ();
if (val != 4) {
printf("st2 value was %i instead of 4\n", val);
return -2;
}
val = get_st3_value ();
if (val != 3) {
printf("st3 value was %i instead of 3\n", val);
return -3;
}
return 0;
}

@ -0,0 +1,5 @@
st1 = static_library('st1', 'lib1.c', 'prop1.c')
st2 = static_library('st2', 'lib2.c', 'prop2.c')
st3 = static_library('st3', 'lib3.c', 'prop3.c')
test('circular', executable('circular', 'main.c', link_with : [st1, st2, st3]))

@ -0,0 +1,3 @@
int get_st1_prop (void) {
return 1;
}

@ -0,0 +1,3 @@
int get_st2_prop (void) {
return 2;
}

@ -0,0 +1,3 @@
int get_st3_prop (void) {
return 3;
}

@ -0,0 +1,17 @@
#if defined _WIN32
#ifdef MESON_STATIC_BUILD
#define SYMBOL_EXPORT
#define SYMBOL_IMPORT
#else
#define SYMBOL_IMPORT __declspec(dllimport)
#define SYMBOL_EXPORT __declspec(dllexport)
#endif
#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"
int get_stnodep_value (void);
int get_stshdep_value (void);
int get_ststdep_value (void);
SYMBOL_IMPORT int get_shnodep_value (void);
SYMBOL_IMPORT int get_shshdep_value (void);
SYMBOL_IMPORT int get_shstdep_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,26 @@
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')
# Circular dependencies between static libraries
# This requires the use of --start/end-group with GNU ld
subdir('circular')

@ -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,2 @@
stnodep = static_library('stnodep', 'lib.c',
c_args : '-DMESON_STATIC_BUILD')

@ -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,2 @@
stshdep = static_library('stshdep', 'lib.c', link_with : shnodep,
c_args : '-DMESON_STATIC_BUILD')

@ -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,2 @@
ststdep = static_library('ststdep', 'lib.c', link_with : stnodep,
c_args : '-DMESON_STATIC_BUILD')

@ -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…
Cancel
Save