diff options
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/compilers/c.py | 75 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 18 | ||||
-rw-r--r-- | mesonbuild/compilers/cpp.py | 14 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 64 |
4 files changed, 95 insertions, 76 deletions
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 0e474e7..1230e3f 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -323,25 +323,21 @@ class CCompiler(Compiler): args += extra_args return args - def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile', want_output=False): - 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: + def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile'): + with self._build_wrapper(code, env, extra_args, dependencies, mode) as p: return p.returncode == 0 - def _links_wrapper(self, code, env, extra_args, dependencies, want_output=False): - "Shares common code between self.links and self.run" - args = self._get_compiler_check_args(env, extra_args, dependencies, mode='link') - return self.compile(code, args, want_output=want_output) + def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False): + args = self._get_compiler_check_args(env, extra_args, dependencies, mode) + return self.compile(code, args.to_native(), mode, want_output=want_output) def links(self, code, env, extra_args=None, dependencies=None): - with self._links_wrapper(code, env, extra_args, dependencies) as p: - return p.returncode == 0 + return self.compiles(code, env, extra_args, dependencies, mode='link') def run(self, code, env, extra_args=None, dependencies=None): if self.is_cross and self.exe_wrapper is None: raise CrossNoRunException('Can not run test applications in this cross environment.') - with self._links_wrapper(code, env, extra_args, dependencies, True) as p: + with self._build_wrapper(code, env, extra_args, dependencies, mode='link', want_output=True) as p: if p.returncode != 0: mlog.debug('Could not compile test file %s: %d\n' % ( p.input_name, @@ -841,6 +837,12 @@ class CCompiler(Compiler): return [] return ['-pthread'] + def linker_to_compiler_args(self, args): + return args + + def has_arguments(self, args, env, code, mode): + return self.compiles(code, env, extra_args=args, mode=mode) + def has_multi_arguments(self, args, env): for arg in args[:]: # some compilers, e.g. GCC, don't warn for unsupported warning-disable @@ -849,13 +851,21 @@ class CCompiler(Compiler): if arg.startswith('-Wno-'): args.append('-W' + arg[5:]) if arg.startswith('-Wl,'): - mlog.warning('''{} looks like a linker argument, but has_argument -and other similar methods only support checking compiler arguments. -Using them to check linker arguments are never supported, and results -are likely to be wrong regardless of the compiler you are using. -'''.format(arg)) - return self.compiles('int i;\n', env, extra_args=args) + mlog.warning('{} looks like a linker argument, ' + 'but has_argument and other similar methods only ' + 'support checking compiler arguments. Using them ' + 'to check linker arguments are never supported, ' + 'and results are likely to be wrong regardless of ' + 'the compiler you are using. has_link_argument or ' + 'other similar method can be used instead.' + .format(arg)) + code = 'int i;\n' + return self.has_arguments(args, env, code, mode='compile') + def has_multi_link_arguments(self, args, env): + args = self.linker_to_compiler_args(args) + code = 'int main(int argc, char **argv) { return 0; }' + return self.has_arguments(args, env, code, mode='link') class ClangCCompiler(ClangCompiler, CCompiler): def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None, **kwargs): @@ -981,8 +991,8 @@ class IntelCCompiler(IntelCompiler, CCompiler): def get_std_shared_lib_link_args(self): return ['-shared'] - def has_multi_arguments(self, args, env): - return super().has_multi_arguments(args + ['-diag-error', '10006'], env) + def has_arguments(self, args, env, code, mode): + return super().has_arguments(args + ['-diag-error', '10006'], env, code, mode) class VisualStudioCCompiler(CCompiler): @@ -1066,6 +1076,9 @@ class VisualStudioCCompiler(CCompiler): def get_linker_search_args(self, dirname): return ['/LIBPATH:' + dirname] + def linker_to_compiler_args(self, args): + return ['/link'] + args + def get_gui_app_args(self): return ['/SUBSYSTEM:WINDOWS'] @@ -1149,24 +1162,12 @@ class VisualStudioCCompiler(CCompiler): # Visual Studio is special. It ignores some arguments it does not # understand and you can't tell it to error out on those. # http://stackoverflow.com/questions/15259720/how-can-i-make-the-microsoft-c-compiler-treat-unknown-flags-as-errors-rather-t - def has_multi_arguments(self, args, env): - warning_text = '9002' - code = 'int i;\n' - (fd, srcname) = tempfile.mkstemp(suffix='.' + self.default_suffix) - os.close(fd) - with open(srcname, 'w') as ofile: - ofile.write(code) - # Read c_args/cpp_args/etc from the cross-info file (if needed) - extra_args = self.get_cross_extra_flags(env, link=False) - extra_args += self.get_compile_only_args() - commands = self.exelist + args + extra_args + [srcname] - mlog.debug('Running VS compile:') - mlog.debug('Command line: ', ' '.join(commands)) - mlog.debug('Code:\n', code) - p, stdo, stde = Popen_safe(commands, cwd=os.path.dirname(srcname)) - if p.returncode != 0: - return False - return not(warning_text in stde or warning_text in stdo) + def has_arguments(self, args, env, code, mode): + warning_text = '4044' if mode == 'link' else '9002' + with self._build_wrapper(code, env, extra_args=args, mode=mode) as p: + if p.returncode != 0: + return False + return not(warning_text in p.stde or warning_text in p.stdo) def get_compile_debugfile_args(self, rel_obj, pch=False): pdbarr = rel_obj.split('.')[:-1] diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 37326d8..a2c6668 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -745,20 +745,15 @@ class Compiler: def get_library_dirs(self): return [] - def has_argument(self, arg, env): - return self.has_multi_arguments([arg], env) - def has_multi_arguments(self, args, env): raise EnvironmentException( 'Language {} does not support has_multi_arguments.'.format( self.get_display_language())) - def get_supported_arguments(self, args, env): - supported_args = [] - for arg in args: - if self.has_argument(arg, env): - supported_args.append(arg) - return supported_args + 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 = [] @@ -815,7 +810,6 @@ class Compiler: # Construct the compiler command-line commands = CompilerArgs(self) commands.append(srcname) - commands += extra_args commands += self.get_always_args() if mode == 'compile': commands += self.get_compile_only_args() @@ -825,6 +819,10 @@ class Compiler: else: output = self._get_compile_output(tmpdirname, mode) commands += self.get_output_args(output) + # extra_args must be last because it could contain '/link' to + # pass args to VisualStudio's linker. In that case everything + # in the command line after '/link' is given to the linker. + commands += extra_args # Generate full command-line with the exelist commands = self.get_exelist() + commands.to_native() mlog.debug('Running compile:') diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 8dd2306..4c48052 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -199,20 +199,10 @@ class IntelCPPCompiler(IntelCompiler, CPPCompiler): def get_option_link_args(self, options): return [] - def has_multi_arguments(self, args, env): - for arg in args: - if arg.startswith('-Wl,'): - mlog.warning('''{} looks like a linker argument, but has_argument -and other similar methods only support checking compiler arguments. -Using them to check linker arguments are never supported, and results -are likely to be wrong regardless of the compiler you are using. -'''.format(arg)) - return super().has_multi_arguments(args + ['-diag-error', '10006'], env) - class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrap, is_64): - self.language = 'cpp' + CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap, is_64) self.base_options = ['b_pch'] # FIXME add lto, pgo and the like @@ -239,7 +229,7 @@ class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): def get_compiler_check_args(self): # Visual Studio C++ compiler doesn't support -fpermissive, # so just use the plain C args. - return super(VisualStudioCCompiler, self).get_compiler_check_args() + return VisualStudioCCompiler.get_compiler_check_args(self) class ArmCPPCompiler(ArmCompiler, CPPCompiler): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 2c92895..4fe879a 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -741,6 +741,10 @@ class CompilerHolder(InterpreterObject): '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, }) @@ -1183,14 +1187,8 @@ class CompilerHolder(InterpreterObject): def has_argument_method(self, args, kwargs): args = mesonlib.stringlistify(args) if len(args) != 1: - raise InterpreterException('Has_arg takes exactly one argument.') - result = self.compiler.has_argument(args[0], self.environment) - if result: - h = mlog.green('YES') - else: - h = mlog.red('NO') - mlog.log('Compiler for {} supports argument {}:'.format(self.compiler.get_display_language(), args[0]), h) - return result + raise InterpreterException('has_argument takes exactly one argument.') + return self.has_multi_arguments_method(args, kwargs) @permittedMethodKwargs({}) def has_multi_arguments_method(self, args, kwargs): @@ -1209,26 +1207,58 @@ class CompilerHolder(InterpreterObject): @permittedMethodKwargs({}) def get_supported_arguments_method(self, args, kwargs): args = mesonlib.stringlistify(args) - result = self.compiler.get_supported_arguments(args, self.environment) - if len(result) == len(args): + supported_args = [] + for arg in args: + if self.has_argument_method(arg, kwargs): + supported_args.append(arg) + return supported_args + + @permittedMethodKwargs({}) + def first_supported_argument_method(self, args, kwargs): + for i in mesonlib.stringlistify(args): + if self.has_argument_method(i, kwargs): + mlog.log('First supported argument:', mlog.bold(i)) + return [i] + 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') - elif len(result) > 0: - h = mlog.yellow('SOME') else: h = mlog.red('NO') mlog.log( - 'Compiler for {} supports arguments {}:'.format( + 'Compiler for {} supports link arguments {}:'.format( self.compiler.get_display_language(), ' '.join(args)), h) return result @permittedMethodKwargs({}) - def first_supported_argument_method(self, args, kwargs): + 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.compiler.has_argument(i, self.environment): - mlog.log('First supported argument:', mlog.bold(i)) + if self.has_link_argument_method(i, kwargs): + mlog.log('First supported link argument:', mlog.bold(i)) return [i] - mlog.log('First supported argument:', mlog.red('None')) + mlog.log('First supported link argument:', mlog.red('None')) return [] ModuleState = namedtuple('ModuleState', [ |