Merge pull request #5161 from TheQwertiest/feature/custom_target_link
Can link against custom_target[i]
This commit is contained in:
commit
7059c47aad
|
@ -1,6 +1,6 @@
|
||||||
## Can link against custom targets
|
## Can link against custom targets
|
||||||
|
|
||||||
The output of `custom_target` can be used in `link_with` and
|
The output of `custom_target` and `custom_target[i]` can be used in `link_with` and
|
||||||
`link_whole` keyword arguments. This is useful for integrating custom
|
`link_whole` keyword arguments. This is useful for integrating custom
|
||||||
code generator steps, but note that there are many limitations:
|
code generator steps, but note that there are many limitations:
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@ code generator steps, but note that there are many limitations:
|
||||||
- The user is responsible for ensuring that the code produced by
|
- The user is responsible for ensuring that the code produced by
|
||||||
different toolchains are compatible.
|
different toolchains are compatible.
|
||||||
|
|
||||||
- The custom target can only have one output file.
|
- `custom_target` may only be used when it has a single output file.
|
||||||
|
Use `custom_target[i]` when dealing with multiple output files.
|
||||||
|
|
||||||
- The output file must have the correct file name extension.
|
- The output file must have the correct file name extension.
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,8 @@ class Backend:
|
||||||
mlog.warning('custom_target {!r} has more than one output! '
|
mlog.warning('custom_target {!r} has more than one output! '
|
||||||
'Using the first one.'.format(t.name))
|
'Using the first one.'.format(t.name))
|
||||||
filename = t.get_outputs()[0]
|
filename = t.get_outputs()[0]
|
||||||
|
elif isinstance(t, build.CustomTargetIndex):
|
||||||
|
filename = t.get_outputs()[0]
|
||||||
else:
|
else:
|
||||||
assert(isinstance(t, build.BuildTarget))
|
assert(isinstance(t, build.BuildTarget))
|
||||||
filename = t.get_filename()
|
filename = t.get_filename()
|
||||||
|
@ -214,7 +216,7 @@ class Backend:
|
||||||
return os.path.join(self.get_target_dir(target), link_lib)
|
return os.path.join(self.get_target_dir(target), link_lib)
|
||||||
elif isinstance(target, build.StaticLibrary):
|
elif isinstance(target, build.StaticLibrary):
|
||||||
return os.path.join(self.get_target_dir(target), target.get_filename())
|
return os.path.join(self.get_target_dir(target), target.get_filename())
|
||||||
elif isinstance(target, build.CustomTarget):
|
elif isinstance(target, (build.CustomTarget, build.CustomTargetIndex)):
|
||||||
if not target.is_linkable_target():
|
if not target.is_linkable_target():
|
||||||
raise MesonException('Tried to link against custom target "%s", which is not linkable.' % target.name)
|
raise MesonException('Tried to link against custom target "%s", which is not linkable.' % target.name)
|
||||||
return os.path.join(self.get_target_dir(target), target.get_filename())
|
return os.path.join(self.get_target_dir(target), target.get_filename())
|
||||||
|
|
|
@ -249,9 +249,15 @@ class Vs2010Backend(backends.Backend):
|
||||||
all_deps[d.get_id()] = d
|
all_deps[d.get_id()] = d
|
||||||
elif isinstance(target, build.BuildTarget):
|
elif isinstance(target, build.BuildTarget):
|
||||||
for ldep in target.link_targets:
|
for ldep in target.link_targets:
|
||||||
all_deps[ldep.get_id()] = ldep
|
if isinstance(ldep, build.CustomTargetIndex):
|
||||||
|
all_deps[ldep.get_id()] = ldep.target
|
||||||
|
else:
|
||||||
|
all_deps[ldep.get_id()] = ldep
|
||||||
for ldep in target.link_whole_targets:
|
for ldep in target.link_whole_targets:
|
||||||
all_deps[ldep.get_id()] = ldep
|
if isinstance(ldep, build.CustomTargetIndex):
|
||||||
|
all_deps[ldep.get_id()] = ldep.target
|
||||||
|
else:
|
||||||
|
all_deps[ldep.get_id()] = ldep
|
||||||
for obj_id, objdep in self.get_obj_target_deps(target.objects):
|
for obj_id, objdep in self.get_obj_target_deps(target.objects):
|
||||||
all_deps[obj_id] = objdep
|
all_deps[obj_id] = objdep
|
||||||
for gendep in target.get_generated_sources():
|
for gendep in target.get_generated_sources():
|
||||||
|
@ -1111,7 +1117,11 @@ class Vs2010Backend(backends.Backend):
|
||||||
|
|
||||||
# Add more libraries to be linked if needed
|
# Add more libraries to be linked if needed
|
||||||
for t in target.get_dependencies():
|
for t in target.get_dependencies():
|
||||||
lobj = self.build.targets[t.get_id()]
|
if isinstance(t, build.CustomTargetIndex):
|
||||||
|
# We don't need the actual project here, just the library name
|
||||||
|
lobj = t
|
||||||
|
else:
|
||||||
|
lobj = self.build.targets[t.get_id()]
|
||||||
linkname = os.path.join(down, self.get_target_filename_for_linking(lobj))
|
linkname = os.path.join(down, self.get_target_filename_for_linking(lobj))
|
||||||
if t in target.link_whole_targets:
|
if t in target.link_whole_targets:
|
||||||
# /WHOLEARCHIVE:foo must go into AdditionalOptions
|
# /WHOLEARCHIVE:foo must go into AdditionalOptions
|
||||||
|
|
|
@ -576,7 +576,7 @@ class BuildTarget(Target):
|
||||||
if self.link_targets or self.link_whole_targets:
|
if self.link_targets or self.link_whole_targets:
|
||||||
extra = set()
|
extra = set()
|
||||||
for t in itertools.chain(self.link_targets, self.link_whole_targets):
|
for t in itertools.chain(self.link_targets, self.link_whole_targets):
|
||||||
if isinstance(t, CustomTarget):
|
if isinstance(t, CustomTarget) or isinstance(t, CustomTargetIndex):
|
||||||
continue # We can't know anything about these.
|
continue # We can't know anything about these.
|
||||||
for name, compiler in t.compilers.items():
|
for name, compiler in t.compilers.items():
|
||||||
if name in clink_langs:
|
if name in clink_langs:
|
||||||
|
@ -1066,7 +1066,7 @@ You probably should put it in link_with instead.''')
|
||||||
|
|
||||||
def link(self, target):
|
def link(self, target):
|
||||||
for t in listify(target, unholder=True):
|
for t in listify(target, unholder=True):
|
||||||
if not isinstance(t, Target):
|
if not isinstance(t, (Target, CustomTargetIndex)):
|
||||||
raise InvalidArguments('{!r} is not a target.'.format(t))
|
raise InvalidArguments('{!r} is not a target.'.format(t))
|
||||||
if not t.is_linkable_target():
|
if not t.is_linkable_target():
|
||||||
raise InvalidArguments('Link target {!r} is not linkable.'.format(t))
|
raise InvalidArguments('Link target {!r} is not linkable.'.format(t))
|
||||||
|
@ -1074,13 +1074,13 @@ You probably should put it in link_with instead.''')
|
||||||
msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name)
|
msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name)
|
||||||
msg += "Use the 'pic' option to static_library to build with PIC."
|
msg += "Use the 'pic' option to static_library to build with PIC."
|
||||||
raise InvalidArguments(msg)
|
raise InvalidArguments(msg)
|
||||||
if not isinstance(t, CustomTarget) and self.is_cross != t.is_cross:
|
if not isinstance(t, (CustomTarget, CustomTargetIndex)) and self.is_cross != t.is_cross:
|
||||||
raise InvalidArguments('Tried to mix cross built and native libraries in target {!r}'.format(self.name))
|
raise InvalidArguments('Tried to mix cross built and native libraries in target {!r}'.format(self.name))
|
||||||
self.link_targets.append(t)
|
self.link_targets.append(t)
|
||||||
|
|
||||||
def link_whole(self, target):
|
def link_whole(self, target):
|
||||||
for t in listify(target, unholder=True):
|
for t in listify(target, unholder=True):
|
||||||
if isinstance(t, CustomTarget):
|
if isinstance(t, (CustomTarget, CustomTargetIndex)):
|
||||||
if not t.is_linkable_target():
|
if not t.is_linkable_target():
|
||||||
raise InvalidArguments('Custom target {!r} is not linkable.'.format(t))
|
raise InvalidArguments('Custom target {!r} is not linkable.'.format(t))
|
||||||
if not t.get_filename().endswith('.a'):
|
if not t.get_filename().endswith('.a'):
|
||||||
|
@ -1091,7 +1091,7 @@ You probably should put it in link_with instead.''')
|
||||||
msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name)
|
msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name)
|
||||||
msg += "Use the 'pic' option to static_library to build with PIC."
|
msg += "Use the 'pic' option to static_library to build with PIC."
|
||||||
raise InvalidArguments(msg)
|
raise InvalidArguments(msg)
|
||||||
if not isinstance(t, CustomTarget) and self.is_cross != t.is_cross:
|
if not isinstance(t, (CustomTarget, CustomTargetIndex)) and self.is_cross != t.is_cross:
|
||||||
raise InvalidArguments('Tried to mix cross built and native libraries in target {!r}'.format(self.name))
|
raise InvalidArguments('Tried to mix cross built and native libraries in target {!r}'.format(self.name))
|
||||||
self.link_whole_targets.append(t)
|
self.link_whole_targets.append(t)
|
||||||
|
|
||||||
|
@ -1168,7 +1168,7 @@ You probably should put it in link_with instead.''')
|
||||||
# Check if any of the internal libraries this target links to were
|
# Check if any of the internal libraries this target links to were
|
||||||
# written in this language
|
# written in this language
|
||||||
for link_target in itertools.chain(self.link_targets, self.link_whole_targets):
|
for link_target in itertools.chain(self.link_targets, self.link_whole_targets):
|
||||||
if isinstance(link_target, CustomTarget):
|
if isinstance(link_target, (CustomTarget, CustomTargetIndex)):
|
||||||
continue
|
continue
|
||||||
for language in link_target.compilers:
|
for language in link_target.compilers:
|
||||||
if language not in langs:
|
if language not in langs:
|
||||||
|
@ -2259,6 +2259,26 @@ class CustomTargetIndex:
|
||||||
def get_subdir(self):
|
def get_subdir(self):
|
||||||
return self.target.get_subdir()
|
return self.target.get_subdir()
|
||||||
|
|
||||||
|
def get_filename(self):
|
||||||
|
return self.output
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return self.target.get_id()
|
||||||
|
|
||||||
|
def get_all_link_deps(self):
|
||||||
|
return self.target.get_all_link_deps()
|
||||||
|
|
||||||
|
def get_link_deps_mapping(self, prefix, environment):
|
||||||
|
return self.target.get_link_deps_mapping(prefix, environment)
|
||||||
|
|
||||||
|
def get_link_dep_subdirs(self):
|
||||||
|
return self.target.get_link_dep_subdirs()
|
||||||
|
|
||||||
|
def is_linkable_target(self):
|
||||||
|
suf = os.path.splitext(self.output)[-1]
|
||||||
|
if suf == '.a' or suf == '.dll' or suf == '.lib' or suf == '.so':
|
||||||
|
return True
|
||||||
|
|
||||||
class ConfigureFile:
|
class ConfigureFile:
|
||||||
|
|
||||||
def __init__(self, subdir, sourcename, targetname, configuration_data):
|
def __init__(self, subdir, sourcename, targetname, configuration_data):
|
||||||
|
|
|
@ -16,6 +16,8 @@ clib = custom_target('linkcustom',
|
||||||
'-o', '@OUTPUT@',
|
'-o', '@OUTPUT@',
|
||||||
'--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array())
|
'--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array())
|
||||||
|
|
||||||
|
# custom_target tests
|
||||||
|
|
||||||
exe = executable('prog', 'prog.c', link_with: clib)
|
exe = executable('prog', 'prog.c', link_with: clib)
|
||||||
test('linkcustom', exe)
|
test('linkcustom', exe)
|
||||||
|
|
||||||
|
@ -33,3 +35,23 @@ d2 = declare_dependency(link_whole: clib)
|
||||||
|
|
||||||
exe4 = executable('prog4', 'prog.c', dependencies: d2)
|
exe4 = executable('prog4', 'prog.c', dependencies: d2)
|
||||||
test('linkwhole2', exe2)
|
test('linkwhole2', exe2)
|
||||||
|
|
||||||
|
# custom_target[i] tests
|
||||||
|
|
||||||
|
exe_i = executable('prog_i', 'prog.c', link_with: clib[0])
|
||||||
|
test('linkcustom', exe_i)
|
||||||
|
|
||||||
|
d_i = declare_dependency(link_with: clib[0])
|
||||||
|
|
||||||
|
exe2_i = executable('prog2_i', 'prog.c', dependencies: d_i)
|
||||||
|
test('linkcustom2_i', exe2_i)
|
||||||
|
|
||||||
|
# Link whole tests
|
||||||
|
|
||||||
|
exe3_i = executable('prog3_i', 'prog.c', link_whole: clib[0])
|
||||||
|
test('linkwhole', exe)
|
||||||
|
|
||||||
|
d2_i = declare_dependency(link_whole: clib[0])
|
||||||
|
|
||||||
|
exe4_i = executable('prog4_i', 'prog.c', dependencies: d2_i)
|
||||||
|
test('linkwhole2_i', exe2_i)
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import shutil, sys, subprocess, argparse, pathlib
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
parser.add_argument('--private-dir', required=True)
|
||||||
|
parser.add_argument('-o', nargs='+', required=True)
|
||||||
|
parser.add_argument('cmparr', nargs='+')
|
||||||
|
|
||||||
|
contents = ['''
|
||||||
|
int flob() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
''', '''
|
||||||
|
int flob() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
''']
|
||||||
|
|
||||||
|
def generate_lib_gnulike(outfile, c_file, private_dir, compiler_array):
|
||||||
|
if shutil.which('ar'):
|
||||||
|
static_linker = 'ar'
|
||||||
|
elif shutil.which('llvm-ar'):
|
||||||
|
static_linker = 'llvm-ar'
|
||||||
|
elif shutil.which('gcc-ar'):
|
||||||
|
static_linker = 'gcc-ar'
|
||||||
|
else:
|
||||||
|
sys.exit('Could not detect a static linker.')
|
||||||
|
o_file = c_file.with_suffix('.o')
|
||||||
|
compile_cmd = compiler_array + ['-c', '-g', '-O2', '-o', str(o_file), str(c_file)]
|
||||||
|
subprocess.check_call(compile_cmd)
|
||||||
|
out_file = pathlib.Path(outfile)
|
||||||
|
if out_file.exists():
|
||||||
|
out_file.unlink()
|
||||||
|
link_cmd = [static_linker, 'csr', outfile, str(o_file)]
|
||||||
|
subprocess.check_call(link_cmd)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def generate_lib_msvc(outfile, c_file, private_dir, compiler_array):
|
||||||
|
static_linker = 'lib'
|
||||||
|
o_file = c_file.with_suffix('.obj')
|
||||||
|
compile_cmd = compiler_array + ['/MDd',
|
||||||
|
'/nologo',
|
||||||
|
'/ZI',
|
||||||
|
'/Ob0',
|
||||||
|
'/Od',
|
||||||
|
'/c',
|
||||||
|
'/Fo' + str(o_file),
|
||||||
|
str(c_file)]
|
||||||
|
subprocess.check_call(compile_cmd)
|
||||||
|
out_file = pathlib.Path(outfile)
|
||||||
|
if out_file.exists():
|
||||||
|
out_file.unlink()
|
||||||
|
link_cmd = [static_linker,
|
||||||
|
'/nologo',
|
||||||
|
'/OUT:' + str(outfile),
|
||||||
|
str(o_file)]
|
||||||
|
subprocess.check_call(link_cmd)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def generate_lib(outfiles, private_dir, compiler_array):
|
||||||
|
private_dir = pathlib.Path(private_dir)
|
||||||
|
if not private_dir.exists():
|
||||||
|
private_dir.mkdir()
|
||||||
|
|
||||||
|
for i, content in enumerate(contents):
|
||||||
|
c_file = private_dir / ('flob_' + str(i + 1) + '.c')
|
||||||
|
c_file.write_text(content)
|
||||||
|
outfile = outfiles[i]
|
||||||
|
|
||||||
|
cl_found = False
|
||||||
|
for cl_arg in compiler_array:
|
||||||
|
if (cl_arg.endswith('cl') or cl_arg.endswith('cl.exe')) and 'clang-cl' not in cl_arg:
|
||||||
|
ret = generate_lib_msvc(outfile, c_file, private_dir, compiler_array)
|
||||||
|
if ret > 0:
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
cl_found = True
|
||||||
|
break
|
||||||
|
if not cl_found:
|
||||||
|
ret = generate_lib_gnulike(outfile, c_file, private_dir, compiler_array)
|
||||||
|
if ret > 0:
|
||||||
|
return ret
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
options = parser.parse_args()
|
||||||
|
sys.exit(generate_lib(options.o, options.private_dir, options.cmparr))
|
|
@ -0,0 +1,37 @@
|
||||||
|
project('linkcustom', 'c')
|
||||||
|
|
||||||
|
# This would require passing the static linker to the build script or having
|
||||||
|
# it detect it by itself. I'm too lazy to implement it now and it is not
|
||||||
|
# really needed for testing that custom targets work. It is the responsibility
|
||||||
|
# of the custom target to produce things in the correct format.
|
||||||
|
assert(not meson.is_cross_build(),
|
||||||
|
'MESON_SKIP_TEST cross checking not implemented.')
|
||||||
|
|
||||||
|
cc = meson.get_compiler('c')
|
||||||
|
genprog = find_program('generate_conflicting_stlibs.py')
|
||||||
|
|
||||||
|
clib = custom_target('linkcustom',
|
||||||
|
output: ['libflob_1.a', 'libflob_2.a'],
|
||||||
|
command: [genprog,
|
||||||
|
'-o', '@OUTPUT@',
|
||||||
|
'--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array())
|
||||||
|
|
||||||
|
clib_2 = clib[1]
|
||||||
|
|
||||||
|
exe = executable('prog', 'prog.c', link_with: clib_2)
|
||||||
|
test('linkcustom', exe)
|
||||||
|
|
||||||
|
d = declare_dependency(link_with: clib_2)
|
||||||
|
|
||||||
|
exe2 = executable('prog2', 'prog.c', dependencies: d)
|
||||||
|
test('linkcustom2', exe2)
|
||||||
|
|
||||||
|
# Link whole tests
|
||||||
|
|
||||||
|
exe3 = executable('prog3', 'prog.c', link_whole: clib_2)
|
||||||
|
test('linkwhole', exe)
|
||||||
|
|
||||||
|
d2 = declare_dependency(link_whole: clib_2)
|
||||||
|
|
||||||
|
exe4 = executable('prog4', 'prog.c', dependencies: d2)
|
||||||
|
test('linkwhole2', exe2)
|
|
@ -0,0 +1,5 @@
|
||||||
|
int flob();
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
return (flob() == 1 ? 0 : 1);
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import shutil, sys, subprocess, argparse, pathlib
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
parser.add_argument('--private-dir', required=True)
|
||||||
|
parser.add_argument('-o', nargs='+', required=True)
|
||||||
|
parser.add_argument('cmparr', nargs='+')
|
||||||
|
|
||||||
|
contents = ['''#include<stdio.h>
|
||||||
|
|
||||||
|
void flob_1() {
|
||||||
|
printf("Now flobbing #1.\\n");
|
||||||
|
}
|
||||||
|
''', '''#include<stdio.h>
|
||||||
|
|
||||||
|
void flob_2() {
|
||||||
|
printf("Now flobbing #2.\\n");
|
||||||
|
}
|
||||||
|
''']
|
||||||
|
|
||||||
|
def generate_lib_gnulike(outfile, c_file, private_dir, compiler_array):
|
||||||
|
if shutil.which('ar'):
|
||||||
|
static_linker = 'ar'
|
||||||
|
elif shutil.which('llvm-ar'):
|
||||||
|
static_linker = 'llvm-ar'
|
||||||
|
elif shutil.which('gcc-ar'):
|
||||||
|
static_linker = 'gcc-ar'
|
||||||
|
else:
|
||||||
|
sys.exit('Could not detect a static linker.')
|
||||||
|
o_file = c_file.with_suffix('.o')
|
||||||
|
compile_cmd = compiler_array + ['-c', '-g', '-O2', '-o', str(o_file), str(c_file)]
|
||||||
|
subprocess.check_call(compile_cmd)
|
||||||
|
out_file = pathlib.Path(outfile)
|
||||||
|
if out_file.exists():
|
||||||
|
out_file.unlink()
|
||||||
|
link_cmd = [static_linker, 'csr', outfile, str(o_file)]
|
||||||
|
subprocess.check_call(link_cmd)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def generate_lib_msvc(outfile, c_file, private_dir, compiler_array):
|
||||||
|
static_linker = 'lib'
|
||||||
|
o_file = c_file.with_suffix('.obj')
|
||||||
|
compile_cmd = compiler_array + ['/MDd',
|
||||||
|
'/nologo',
|
||||||
|
'/ZI',
|
||||||
|
'/Ob0',
|
||||||
|
'/Od',
|
||||||
|
'/c',
|
||||||
|
'/Fo' + str(o_file),
|
||||||
|
str(c_file)]
|
||||||
|
subprocess.check_call(compile_cmd)
|
||||||
|
out_file = pathlib.Path(outfile)
|
||||||
|
if out_file.exists():
|
||||||
|
out_file.unlink()
|
||||||
|
link_cmd = [static_linker,
|
||||||
|
'/nologo',
|
||||||
|
'/OUT:' + str(outfile),
|
||||||
|
str(o_file)]
|
||||||
|
subprocess.check_call(link_cmd)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def generate_lib(outfiles, private_dir, compiler_array):
|
||||||
|
private_dir = pathlib.Path(private_dir)
|
||||||
|
if not private_dir.exists():
|
||||||
|
private_dir.mkdir()
|
||||||
|
|
||||||
|
for i, content in enumerate(contents):
|
||||||
|
c_file = private_dir / ('flob_' + str(i + 1) + '.c')
|
||||||
|
c_file.write_text(content)
|
||||||
|
outfile = outfiles[i]
|
||||||
|
|
||||||
|
cl_found = False
|
||||||
|
for cl_arg in compiler_array:
|
||||||
|
if (cl_arg.endswith('cl') or cl_arg.endswith('cl.exe')) and 'clang-cl' not in cl_arg:
|
||||||
|
ret = generate_lib_msvc(outfile, c_file, private_dir, compiler_array)
|
||||||
|
if ret > 0:
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
cl_found = True
|
||||||
|
break
|
||||||
|
if not cl_found:
|
||||||
|
ret = generate_lib_gnulike(outfile, c_file, private_dir, compiler_array)
|
||||||
|
if ret > 0:
|
||||||
|
return ret
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
options = parser.parse_args()
|
||||||
|
sys.exit(generate_lib(options.o, options.private_dir, options.cmparr))
|
|
@ -0,0 +1,37 @@
|
||||||
|
project('linkcustom', 'c')
|
||||||
|
|
||||||
|
# This would require passing the static linker to the build script or having
|
||||||
|
# it detect it by itself. I'm too lazy to implement it now and it is not
|
||||||
|
# really needed for testing that custom targets work. It is the responsibility
|
||||||
|
# of the custom target to produce things in the correct format.
|
||||||
|
assert(not meson.is_cross_build(),
|
||||||
|
'MESON_SKIP_TEST cross checking not implemented.')
|
||||||
|
|
||||||
|
cc = meson.get_compiler('c')
|
||||||
|
genprog = find_program('generate_stlibs.py')
|
||||||
|
|
||||||
|
clib = custom_target('linkcustom',
|
||||||
|
output: ['libflob_1.a', 'libflob_2.a'],
|
||||||
|
command: [genprog,
|
||||||
|
'-o', '@OUTPUT@',
|
||||||
|
'--private-dir', '@PRIVATE_DIR@'] + cc.cmd_array())
|
||||||
|
|
||||||
|
clibs = [clib[0], clib[1]]
|
||||||
|
|
||||||
|
exe = executable('prog', 'prog.c', link_with: clibs)
|
||||||
|
test('linkcustom', exe)
|
||||||
|
|
||||||
|
d = declare_dependency(link_with: clibs)
|
||||||
|
|
||||||
|
exe2 = executable('prog2', 'prog.c', dependencies: d)
|
||||||
|
test('linkcustom2', exe2)
|
||||||
|
|
||||||
|
# Link whole tests
|
||||||
|
|
||||||
|
exe3 = executable('prog3', 'prog.c', link_whole: clibs)
|
||||||
|
test('linkwhole', exe)
|
||||||
|
|
||||||
|
d2 = declare_dependency(link_whole: clibs)
|
||||||
|
|
||||||
|
exe4 = executable('prog4', 'prog.c', dependencies: d2)
|
||||||
|
test('linkwhole2', exe2)
|
|
@ -0,0 +1,8 @@
|
||||||
|
void flob_1();
|
||||||
|
void flob_2();
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
flob_1();
|
||||||
|
flob_2();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue