diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 7f3c82e88..ce3f09aea 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -906,8 +906,6 @@ class CCompiler(Compiler): return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) def has_header(self, hname, prefix, env, extra_args=None, dependencies=None): - if extra_args is None: - extra_args = [] fargs = {'prefix': prefix, 'header': hname} code = '''{prefix} #ifdef __has_include @@ -921,8 +919,6 @@ class CCompiler(Compiler): dependencies, 'preprocess') def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None): - if extra_args is None: - extra_args = [] fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} t = '''{prefix} #include <{header}> @@ -934,7 +930,7 @@ class CCompiler(Compiler): }}''' return self.compiles(t.format(**fargs), env, extra_args, dependencies) - def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile'): + def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): if extra_args is None: extra_args = [] elif isinstance(extra_args, str): @@ -943,49 +939,41 @@ class CCompiler(Compiler): dependencies = [] elif not isinstance(dependencies, list): dependencies = [dependencies] - # Add compile flags needed by dependencies + # Collect compiler arguments args = CompilerArgs(self) for d in dependencies: + # Add compile flags needed by dependencies args += d.get_compile_args() + if mode == 'link': + # Add link flags needed to find dependencies + args += d.get_link_args() + # Select a CRT if needed since we're linking + if mode == 'link': + args += self.get_linker_debug_crt_args() # Read c_args/cpp_args/etc from the cross-info file (if needed) - args += self.get_cross_extra_flags(env, compile=True, link=False) + args += self.get_cross_extra_flags(env, compile=(mode != 'preprocess'), + link=(mode == 'link')) # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS from the env # We assume that the user has ensured these are compiler-specific args += env.coredata.external_args[self.language] + # Add LDFLAGS from the env. We assume that the user has ensured these + # are compiler-specific + if mode == 'link': + args += env.coredata.external_link_args[self.language] args += self.get_compiler_check_args() # extra_args must override all other arguments, so we add them last args += extra_args + return args + + def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile'): + args = self._get_compiler_check_args(env, extra_args, dependencies, mode) # We only want to compile; not link with self.compile(code, args.to_native(), mode) as p: return p.returncode == 0 def _links_wrapper(self, code, env, extra_args, dependencies): "Shares common code between self.links and self.run" - if extra_args is None: - extra_args = [] - elif isinstance(extra_args, str): - extra_args = [extra_args] - if dependencies is None: - dependencies = [] - elif not isinstance(dependencies, list): - dependencies = [dependencies] - # Add compile and link flags needed by dependencies - args = CompilerArgs(self) - for d in dependencies: - args += d.get_compile_args() - args += d.get_link_args() - # Select a CRT if needed since we're linking - args += self.get_linker_debug_crt_args() - # Read c_args/c_link_args/cpp_args/cpp_link_args/etc from the - # cross-info file (if needed) - args += self.get_cross_extra_flags(env, compile=True, link=True) - # Add LDFLAGS from the env. We assume that the user has ensured these - # are compiler-specific - args += env.coredata.external_link_args[self.language] - # Add compiler check args such that they override - args += self.get_compiler_check_args() - # extra_args must override all other arguments, so we add them last - args += extra_args + args = self._get_compiler_check_args(env, extra_args, dependencies, mode='link') return self.compile(code, args.to_native()) def links(self, code, env, extra_args=None, dependencies=None): @@ -1141,6 +1129,24 @@ class CCompiler(Compiler): raise EnvironmentException('Could not determine alignment of %s. Sorry. You might want to file a bug.' % typename) return align + def get_define(self, dname, prefix, env, extra_args, dependencies): + delim = '"MESON_GET_DEFINE_DELIMITER"' + fargs = {'prefix': prefix, 'define': dname, 'delim': delim} + code = ''' + #ifndef {define} + # define {define} + #endif + {prefix} + {delim}\n{define}''' + args = self._get_compiler_check_args(env, extra_args, dependencies, + mode='preprocess').to_native() + with self.compile(code.format(**fargs), args, 'preprocess') as p: + if p.returncode != 0: + raise EnvironmentException('Could not get define {!r}'.format(dname)) + # Get the preprocessed value after the delimiter, + # minus the extra newline at the end + return p.stdo.split(delim + '\n')[-1][:-1] + @staticmethod def _no_prototype_templ(): """ diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 0c6d9809a..959ce6aee 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -634,6 +634,7 @@ class CompilerHolder(InterpreterObject): 'get_id': self.get_id_method, 'compute_int': self.compute_int_method, 'sizeof': self.sizeof_method, + 'get_define': self.get_define_method, 'has_header': self.has_header_method, 'has_header_symbol': self.has_header_symbol_method, 'run': self.run_method, @@ -865,6 +866,20 @@ class CompilerHolder(InterpreterObject): mlog.log('Checking for size of "%s": %d' % (element, esize)) return esize + def get_define_method(self, args, kwargs): + if len(args) != 1: + raise InterpreterException('get_define() takes exactly one argument.') + check_stringlist(args) + element = args[0] + prefix = kwargs.get('prefix', '') + if not isinstance(prefix, str): + raise InterpreterException('Prefix argument of get_define() must be a string.') + extra_args = self.determine_args(kwargs) + deps = self.determine_dependencies(kwargs) + value = self.compiler.get_define(element, prefix, self.environment, extra_args, deps) + mlog.log('Checking for value of define "%s": %s' % (element, value)) + return value + def compiles_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('compiles method takes exactly one argument.') diff --git a/test cases/common/140 get define/meson.build b/test cases/common/140 get define/meson.build new file mode 100644 index 000000000..0d83b8d6e --- /dev/null +++ b/test cases/common/140 get define/meson.build @@ -0,0 +1,19 @@ +project('get define', 'c', 'cpp') + +host_system = host_machine.system() + +foreach lang : ['c', 'cpp'] + cc = meson.get_compiler(lang) + if host_system == 'linux' + d = cc.get_define('__linux__') + assert(d == '1', '__linux__ value is @0@ instead of 1'.format(d)) + elif host_system == 'darwin' + d = cc.get_define('__APPLE__') + assert(d == '1', '__APPLE__ value is @0@ instead of 1'.format(d)) + elif host_system == 'windows' + d = cc.get_define('_WIN32') + assert(d == '1', '_WIN32 value is @0@ instead of 1'.format(d)) + else + error('Please report a bug and help us improve support for this platform') + endif +endforeach