diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 58444bb28..1c6c1da7d 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -902,16 +902,21 @@ int main(int argc, char **argv) { # directly try to link via main(). return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), env, args) - def has_member(self, typename, membername, prefix, env, extra_args=None): + def has_members(self, typename, membernames, prefix, env, extra_args=None): if extra_args is None: extra_args = [] - templ = '''%s -void bar() { - %s foo; - foo.%s; -}; + templ = '''{0} +void bar() {{ + {1} {2}; + {3} +}}; ''' - return self.compiles(templ % (prefix, typename, membername), env, extra_args) + # Create code that accesses all members + members = '' + for m in membernames: + members += 'foo.{};\n'.format(m) + code = templ.format(prefix, typename, 'foo', members) + return self.compiles(code, env, extra_args) def has_type(self, typename, prefix, env, extra_args): templ = '''%s diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 94119f9ed..c9a81fb87 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -590,6 +590,7 @@ class CompilerHolder(InterpreterObject): 'run' : self.run_method, 'has_function' : self.has_function_method, 'has_member' : self.has_member_method, + 'has_members' : self.has_members_method, 'has_type' : self.has_type_method, 'alignment' : self.alignment_method, 'version' : self.version_method, @@ -665,9 +666,10 @@ class CompilerHolder(InterpreterObject): membername = args[1] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): - raise InterpreterException('Prefix argument of has_function must be a string.') + raise InterpreterException('Prefix argument of has_member must be a string.') extra_args = self.determine_args(kwargs) - had = self.compiler.has_member(typename, membername, prefix, self.environment, extra_args) + had = self.compiler.has_members(typename, [membername], prefix, + self.environment, extra_args) if had: hadtxt = mlog.green('YES') else: @@ -676,6 +678,25 @@ class CompilerHolder(InterpreterObject): '" has member "', mlog.bold(membername), '": ', hadtxt, sep='') return had + def has_members_method(self, args, kwargs): + check_stringlist(args) + typename = args[0] + membernames = args[1:] + prefix = kwargs.get('prefix', '') + if not isinstance(prefix, str): + raise InterpreterException('Prefix argument of has_members must be a string.') + extra_args = self.determine_args(kwargs) + had = self.compiler.has_members(typename, membernames, prefix, + self.environment, extra_args) + if had: + hadtxt = mlog.green('YES') + else: + hadtxt = mlog.red('NO') + members = mlog.bold(', '.join(['"{}"'.format(m) for m in membernames])) + mlog.log('Checking whether type "', mlog.bold(typename), + '" has members ', members, ': ', hadtxt, sep='') + return had + def has_function_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Has_function takes exactly one argument.') diff --git a/test cases/common/44 has member/meson.build b/test cases/common/44 has member/meson.build index fa0187730..e60aeb365 100644 --- a/test cases/common/44 has member/meson.build +++ b/test cases/common/44 has member/meson.build @@ -3,9 +3,17 @@ project('has member', 'c') cc = meson.get_compiler('c') if not cc.has_member('struct tm', 'tm_sec', prefix : '#include') - error('Did not detect member that exists.') + error('Did not detect member of "struct tm" that exists: "tm_sec"') endif if cc.has_member('struct tm', 'tm_nonexistent', prefix : '#include') - error('Not existing member found.') + error('Not existing member "tm_nonexistent" found.') +endif + +if not cc.has_members('struct tm', 'tm_sec', 'tm_min', prefix : '#include') + error('Did not detect members of "struct tm" that exist: "tm_sec" "tm_min"') +endif + +if cc.has_members('struct tm', 'tm_sec', 'tm_nonexistent2', prefix : '#include') + error('Not existing member "tm_nonexistent2" found.') endif