interpreter: add <lang>_(static|shared)_args

Which allow passing arguments specifically to the static or shared
libraries.

For design, this is all handled in the interpreter, by the build layer
the arguments are combined into the existing fields. This limits changes
required in the mid and backend layers
pull/12331/head
Dylan Baker 2 years ago committed by Eli Schwartz
parent e24f430512
commit 013536fcb4
  1. 9
      docs/markdown/snippets/shared_static_only_args.md
  2. 34
      docs/yaml/functions/library.yaml
  3. 17
      mesonbuild/interpreter/interpreter.py
  4. 29
      mesonbuild/interpreter/kwargs.py
  5. 11
      mesonbuild/interpreter/type_checking.py
  6. 10
      test cases/common/178 bothlibraries/meson.build
  7. 11
      test cases/common/3 static/lib3.c
  8. 7
      test cases/common/3 static/meson.build
  9. 22
      test cases/common/4 shared/libfile2.c
  10. 7
      test cases/common/4 shared/meson.build
  11. 2
      unittests/allplatformstests.py

@ -0,0 +1,9 @@
## `<lang>_(shared|static)_args` for both_library, library, and build_target
We now allow passing arguments like `c_static_args` and `c_shared_args`. This
allows a [[both_libraries]] to have arguments specific to either the shared or
static library, as well as common arguments to both.
There is a drawback to this, since Meson now cannot re-use object files between
the static and shared targets. This could lead to much higher compilation time
when using a [[both_libraries]] if there are many sources.

@ -16,6 +16,12 @@ description: |
The keyword arguments for this are the same as for
[[build_target]]
warnings:
- using <lang>_shared_args and/or <lang>_static_args may lead to much higher
compilation times with both_library, as object files cannot be shared between
the static and shared targets. It is guaranteed to not duplicate the build if
these arguments are empty arrays
posargs_inherit: _build_target_base
varargs_inherit: _build_target_base
kwargs_inherit:
@ -32,3 +38,31 @@ kwargs:
type being build.
- 'c': Create a "cdylib" or "staticlib" crate depending on the library
type being build.
<lang>_static_args:
type: list[str]
since: 1.3.0
description:
Arguments that are only passed to a static library
vala_static_args:
type: list[str | file]
since: 1.3.0
description:
Arguments that are only passed to a static library
Like `vala_args`, [[files]] is allowed in addition to string
<lang>_shared_args:
type: list[str]
since: 1.3.0
description:
Arguments that are only passed to a shared library
vala_shared_args:
type: list[str | file]
since: 1.3.0
description:
Arguments that are only passed to a shared library
Like `vala_args`, [[files]] is allowed in addition to string

@ -216,7 +216,9 @@ class Summary:
known_library_kwargs = (
build.known_shlib_kwargs |
build.known_stlib_kwargs
build.known_stlib_kwargs |
{f'{l}_shared_args' for l in compilers.all_languages - {'java'}} |
{f'{l}_static_args' for l in compilers.all_languages - {'java'}}
)
known_build_target_kwargs = (
@ -3202,6 +3204,9 @@ class Interpreter(InterpreterBase, HoldableObject):
# FIXME: rustc supports generating both libraries in a single invocation,
# but for now compile twice.
reuse_object_files = False
elif any(k.endswith(('static_args', 'shared_args')) and v for k, v in kwargs.items()):
# Ensure not just the keyword arguments exist, but that they are non-empty.
reuse_object_files = False
else:
reuse_object_files = static_lib.pic
@ -3336,6 +3341,16 @@ class Interpreter(InterpreterBase, HoldableObject):
raise RuntimeError('Unreachable code')
self.kwarg_strings_to_includedirs(kwargs)
self.__process_language_args(kwargs)
if targetclass is build.StaticLibrary:
for lang in compilers.all_languages - {'java'}:
deps, args = self.__convert_file_args(kwargs.get(f'{lang}_static_args', []))
kwargs['language_args'][lang].extend(args)
kwargs['depend_files'].extend(deps)
elif targetclass is build.SharedLibrary:
for lang in compilers.all_languages - {'java'}:
deps, args = self.__convert_file_args(kwargs.get(f'{lang}_shared_args', []))
kwargs['language_args'][lang].extend(args)
kwargs['depend_files'].extend(deps)
# Filter out kwargs from other target types. For example 'soversion'
# passed to library() when default_library == 'static'.

@ -397,6 +397,35 @@ class Library(_BuildTarget, _SharedLibMixin, _StaticLibMixin, _LibraryMixin):
"""For library, both_library, and as a base for build_target"""
c_static_args: NotRequired[T.List[str]]
c_shared_args: NotRequired[T.List[str]]
cpp_static_args: NotRequired[T.List[str]]
cpp_shared_args: NotRequired[T.List[str]]
cuda_static_args: NotRequired[T.List[str]]
cuda_shared_args: NotRequired[T.List[str]]
fortran_static_args: NotRequired[T.List[str]]
fortran_shared_args: NotRequired[T.List[str]]
d_static_args: NotRequired[T.List[str]]
d_shared_args: NotRequired[T.List[str]]
objc_static_args: NotRequired[T.List[str]]
objc_shared_args: NotRequired[T.List[str]]
objcpp_static_args: NotRequired[T.List[str]]
objcpp_shared_args: NotRequired[T.List[str]]
rust_static_args: NotRequired[T.List[str]]
rust_shared_args: NotRequired[T.List[str]]
vala_static_args: NotRequired[T.List[T.Union[str, File]]] # Yes, Vala is really special
vala_shared_args: NotRequired[T.List[T.Union[str, File]]] # Yes, Vala is really special
cs_static_args: NotRequired[T.List[str]]
cs_shared_args: NotRequired[T.List[str]]
swift_static_args: NotRequired[T.List[str]]
swift_shared_args: NotRequired[T.List[str]]
cython_static_args: NotRequired[T.List[str]]
cython_shared_args: NotRequired[T.List[str]]
nasm_static_args: NotRequired[T.List[str]]
nasm_shared_args: NotRequired[T.List[str]]
masm_static_args: NotRequired[T.List[str]]
masm_shared_args: NotRequired[T.List[str]]
class BuildTarget(Library):

@ -665,7 +665,7 @@ STATIC_LIB_KWS = [
_EXCLUSIVE_SHARED_LIB_KWS: T.List[KwargInfo] = [
_DARWIN_VERSIONS_KW,
KwargInfo('soversion', (str, int, NoneType), convertor=lambda x: str(x) if x is not None else None),
KwargInfo('version', (str, NoneType), validator=_validate_shlib_version)
KwargInfo('version', (str, NoneType), validator=_validate_shlib_version),
]
# The total list of arguments used by SharedLibrary
@ -712,6 +712,13 @@ JAR_KWS = [
for a in _LANGUAGE_KWS],
]
_SHARED_STATIC_ARGS: T.List[KwargInfo[T.List[str]]] = [
*[l.evolve(name=l.name.replace('_', '_static_'), since='1.3.0')
for l in _LANGUAGE_KWS],
*[l.evolve(name=l.name.replace('_', '_shared_'), since='1.3.0')
for l in _LANGUAGE_KWS],
]
# Arguments used by both_library and library
LIBRARY_KWS = [
*_BUILD_TARGET_KWS,
@ -719,6 +726,7 @@ LIBRARY_KWS = [
*_EXCLUSIVE_SHARED_LIB_KWS,
*_EXCLUSIVE_SHARED_MOD_KWS,
*_EXCLUSIVE_STATIC_LIB_KWS,
*_SHARED_STATIC_ARGS,
_VS_MODULE_DEFS_KW,
_JAVA_LANG_KW,
]
@ -730,6 +738,7 @@ BUILD_TARGET_KWS = [
*_EXCLUSIVE_SHARED_MOD_KWS,
*_EXCLUSIVE_STATIC_LIB_KWS,
*_EXCLUSIVE_EXECUTABLE_KWS,
*_SHARED_STATIC_ARGS,
*[a.evolve(deprecated='1.3.0', deprecated_message='The use of "jar" in "build_target()" is deprecated, and this argument is only used by jar()')
for a in _EXCLUSIVE_JAR_KWS],
KwargInfo(

@ -55,9 +55,17 @@ test('runtest-both-2', exe_both2)
# the executable linking using the C compiler.
# https://github.com/Netflix/vmaf/issues/1107
libccpp = both_libraries('ccpp', 'foo.cpp', 'libfile.c',
cpp_args : ['-std=c++11'])
cpp_args : ['-std=c++11'],
c_static_args : ['-DSTATIC_COMPILATION'],
cpp_static_args : ['-DSTATIC_COMPILATION'],
)
exe = executable('prog-ccpp', 'main2.c',
link_with: libccpp.get_static_lib(),
c_args : ['-DSTATIC_COMPILATION'],
)
test('runtest-ccpp', exe)
exe = executable('prog-ccpp-shared', 'main2.c',
link_with: libccpp.get_shared_lib(),
)
test('runtest-ccpp-shared', exe)

@ -0,0 +1,11 @@
int func3(const int x) {
return x + 1;
}
#ifndef WORK
# error "did not get static only C args"
#endif
#ifdef BREAK
# error "got shared only C args, but shouldn't have"
#endif

@ -1,4 +1,4 @@
project('static library test', 'c')
project('static library test', 'c', default_options : ['default_library=static'])
lib = static_library('mylib', get_option('source'),
link_args : '-THISMUSTNOBEUSED') # Static linker needs to ignore all link args.
@ -12,3 +12,8 @@ endif
assert(has_not_changed, 'Static library has changed.')
assert(not is_disabler(lib), 'Static library is a disabler.')
if get_option('default_library') == 'static'
library('lib2', 'lib3.c', c_static_args : ['-DWORK'], c_shared_args : ['-DBREAK'])
endif
build_target('lib4', 'lib3.c', c_static_args : ['-DWORK'], target_type : 'static_library')

@ -0,0 +1,22 @@
#if defined _WIN32 || defined __CYGWIN__
#define DLL_PUBLIC __declspec(dllexport)
#else
#if defined __GNUC__
#define DLL_PUBLIC __attribute__ ((visibility("default")))
#else
#pragma message ("Compiler does not support symbol visibility.")
#define DLL_PUBLIC
#endif
#endif
#ifndef WORK
# error "Did not get shared only arguments"
#endif
#ifdef BREAK
# error "got static only C args, but shouldn't have"
#endif
int DLL_PUBLIC libfunc(void) {
return 3;
}

@ -1,4 +1,4 @@
project('shared library test', 'c')
project('shared library test', 'c', default_options : ['default_library=shared'])
lib = shared_library('mylib', 'libfile.c')
build_target('mylib2', 'libfile.c', target_type: 'shared_library')
@ -11,3 +11,8 @@ endif
assert(has_not_changed, 'Shared library has changed.')
assert(not is_disabler(lib), 'Shared library is a disabler.')
if get_option('default_library') == 'shared'
library('mylib5', 'libfile2.c', c_shared_args : ['-DWORK'])
endif
build_target('mylib4', 'libfile2.c', target_type: 'shared_library', c_shared_args : ['-DWORK'], c_static_args : ['-DBREAK'])

@ -394,7 +394,7 @@ class AllPlatformTests(BasePlatformTests):
self.init(testdir)
# Get name of static library
targets = self.introspect('--targets')
self.assertEqual(len(targets), 1)
self.assertGreaterEqual(len(targets), 1)
libname = targets[0]['filename'][0]
# Build and get contents of static library
self.build()

Loading…
Cancel
Save