Skip to content

Commit

Permalink
Add has_link_argument() and friends
Browse files Browse the repository at this point in the history
  • Loading branch information
xclaesse committed Apr 1, 2018
1 parent 5dfb1d3 commit fad7851
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 3 deletions.
20 changes: 17 additions & 3 deletions docs/markdown/Reference-manual.md
Expand Up @@ -1472,6 +1472,10 @@ the following methods:
strings, returns the first argument that passes the `has_argument`
test above or an empty array if none pass.

- `first_supported_link_argument(list_of_strings)` *(added 0.46.0)*, given a
list of strings, returns the first argument that passes the
`has_link_argument` test above or an empty array if none pass.

- `get_define(definename)` returns the given preprocessor symbol's
value as a string or empty string if it is not defined.

Expand All @@ -1482,11 +1486,17 @@ the following methods:
an array containing only the arguments supported by the compiler,
as if `has_argument` were called on them individually.

- `get_supported_link_arguments(list_of_string)` *(added 0.46.0)* returns
an array containing only the arguments supported by the linker,
as if `has_link_argument` were called on them individually.

- `has_argument(argument_name)` returns true if the compiler accepts
the specified command line argument, that is, can compile code
without erroring out or printing a warning about an unknown flag,
you can specify external dependencies to use with `dependencies`
keyword argument.
without erroring out or printing a warning about an unknown flag.

- `has_link_argument(argument_name)` *(added 0.46.0)* returns true if the linker
accepts the specified command line argument, that is, can compile and link
code without erroring out or printing a warning about an unknown flag.

- `has_function(funcname)` returns true if the given function is
provided by the standard library or a library passed in with the
Expand Down Expand Up @@ -1521,6 +1531,10 @@ the following methods:
`has_argument` but takes multiple arguments and uses them all in a
single compiler invocation, available since 0.37.0.

- `has_multi_link_arguments(arg1, arg2, arg3, ...)` *(added 0.46.0)* is the same
as `has_link_argument` but takes multiple arguments and uses them all in a
single compiler invocation.

- `has_type(typename)` returns true if the specified token is a type,
you can specify external dependencies to use with `dependencies`
keyword argument.
Expand Down
9 changes: 9 additions & 0 deletions docs/markdown/snippets/has-link-argument.md
@@ -0,0 +1,9 @@
## has_link_argument() and friends

A new set of methods has been added on compiler objects to test if the linker
supports given arguments.

- `has_link_argument()`
- `has_multi_link_arguments()`
- `get_supported_link_arguments()`
- `first_supported_link_argument()`
3 changes: 3 additions & 0 deletions mesonbuild/compilers/c.py
Expand Up @@ -816,6 +816,9 @@ def has_multi_arguments(self, args, env):
'''.format(arg))
return self.compiles('int i;\n', env, extra_args=args)

def has_multi_link_arguments(self, args, env):
code = 'int main(int argc, char **argv) { return 0; }'
return self.links(code, env, extra_args=args)

class ClangCCompiler(ClangCompiler, CCompiler):
def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None, **kwargs):
Expand Down
5 changes: 5 additions & 0 deletions mesonbuild/compilers/compilers.py
Expand Up @@ -718,6 +718,11 @@ def has_multi_arguments(self, args, env):
'Language {} does not support has_multi_arguments.'.format(
self.get_display_language()))

def has_multi_link_arguments(self, args, env):
raise EnvironmentException(
'Language {} does not support has_multi_link_arguments.'.format(
self.get_display_language()))

def get_cross_extra_flags(self, environment, link):
extra_flags = []
if self.is_cross and environment:
Expand Down
43 changes: 43 additions & 0 deletions mesonbuild/interpreter.py
Expand Up @@ -716,6 +716,10 @@ def __init__(self, compiler, env):
'has_multi_arguments': self.has_multi_arguments_method,
'get_supported_arguments': self.get_supported_arguments_method,
'first_supported_argument': self.first_supported_argument_method,
'has_link_argument': self.has_link_argument_method,
'has_multi_link_arguments': self.has_multi_link_arguments_method,
'get_supported_link_arguments': self.get_supported_link_arguments_method,
'first_supported_link_argument': self.first_supported_link_argument_method,
'unittest_args': self.unittest_args_method,
'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method,
})
Expand Down Expand Up @@ -1193,6 +1197,45 @@ def first_supported_argument_method(self, args, kwargs):
mlog.log('First supported argument:', mlog.red('None'))
return []

@permittedMethodKwargs({})
def has_link_argument_method(self, args, kwargs):
args = mesonlib.stringlistify(args)
if len(args) != 1:
raise InterpreterException('has_link_argument takes exactly one argument.')
return self.has_multi_link_arguments_method(args, kwargs)

@permittedMethodKwargs({})
def has_multi_link_arguments_method(self, args, kwargs):
args = mesonlib.stringlistify(args)
result = self.compiler.has_multi_link_arguments(args, self.environment)
if result:
h = mlog.green('YES')
else:
h = mlog.red('NO')
mlog.log(
'Compiler for {} supports link arguments {}:'.format(
self.compiler.get_display_language(), ' '.join(args)),
h)
return result

@permittedMethodKwargs({})
def get_supported_link_arguments_method(self, args, kwargs):
args = mesonlib.stringlistify(args)
supported_args = []
for arg in args:
if self.has_link_argument_method(arg, kwargs):
supported_args.append(arg)
return supported_args

@permittedMethodKwargs({})
def first_supported_link_argument_method(self, args, kwargs):
for i in mesonlib.stringlistify(args):
if self.has_link_argument_method(i, kwargs):
mlog.log('First supported link argument:', mlog.bold(i))
return [i]
mlog.log('First supported link argument:', mlog.red('None'))
return []

ModuleState = namedtuple('ModuleState', [
'build_to_src', 'subproject', 'subdir', 'current_lineno', 'environment',
'project_name', 'project_version', 'backend', 'compilers', 'targets',
Expand Down
42 changes: 42 additions & 0 deletions test cases/common/189 has link arg/meson.build
@@ -0,0 +1,42 @@
project('has link arg', 'c', 'cpp')

cc = meson.get_compiler('c')
cpp = meson.get_compiler('cpp')

# FIXME: I have no idea how linker args works on other compilers
if cc.get_id() != 'gcc' and cc.get_id() != 'clang'
subdir_done()
endif

is_arg = '-Wl,-Bsymbolic'
useless = '-Wl,-Lfoo'
isnt_arg = '-Wl,-iambroken'


assert(cc.has_link_argument(is_arg), 'Arg that should have worked does not work.')
assert(not cc.has_link_argument(isnt_arg), 'Arg that should be broken is not.')

assert(cpp.has_link_argument(is_arg), 'Arg that should have worked does not work.')
assert(not cpp.has_link_argument(isnt_arg), 'Arg that should be broken is not.')

assert(cc.get_supported_link_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.')
assert(cpp.get_supported_link_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.')

# Have useless at the end to ensure that the search goes from front to back.
l1 = cc.first_supported_link_argument([isnt_arg, is_arg, isnt_arg, useless])
l2 = cc.first_supported_link_argument(isnt_arg, isnt_arg, isnt_arg)

assert(l1.length() == 1, 'First supported returned wrong result.')
assert(l1.get(0) == is_arg, 'First supported returned wrong argument.')
assert(l2.length() == 0, 'First supported did not return empty array.')

l1 = cpp.first_supported_link_argument([isnt_arg, is_arg, isnt_arg, useless])
l2 = cpp.first_supported_link_argument(isnt_arg, isnt_arg, isnt_arg)

assert(l1.length() == 1, 'First supported returned wrong result.')
assert(l1.get(0) == is_arg, 'First supported returned wrong argument.')
assert(l2.length() == 0, 'First supported did not return empty array.')

assert(not cc.has_multi_link_arguments([isnt_arg, is_arg]), 'Arg that should be broken is not.')
assert(cc.has_multi_link_arguments(is_arg), 'Arg that should have worked does not work.')
assert(cc.has_multi_link_arguments([useless, is_arg]), 'Arg that should have worked does not work.')

0 comments on commit fad7851

Please sign in to comment.