From 63f4f9481ebc865b11a06aeecf0c624104d46afd Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 16 Oct 2018 10:03:13 -0700 Subject: [PATCH] Add new compiler.get_argument_syntax method Some compilers try very had to pretend they're another compiler (ICC pretends to be GCC and Linux and MacOS, and MSVC on windows), Clang behaves much like GCC, but now also has clang-cl, which behaves like MSVC. This method provides an easy way to determine whether testing for MSVC like arguments `/w1234` or gcc like arguments `-Wfoo` are likely to succeed, without having to check for dozens of compilers and the host operating system, (as you would otherwise have to do with ICC). --- docs/markdown/Compiler-properties.md | 14 ++++-- docs/markdown/Reference-manual.md | 7 +++ docs/markdown/Reference-tables.md | 45 ++++++++++--------- .../snippets/compiler_argument_syntax.md | 22 +++++++++ mesonbuild/compilers/c.py | 3 ++ mesonbuild/compilers/compilers.py | 14 ++++++ mesonbuild/interpreter.py | 7 +++ .../common/206 argument syntax/meson.build | 25 +++++++++++ 8 files changed, 112 insertions(+), 25 deletions(-) create mode 100644 docs/markdown/snippets/compiler_argument_syntax.md create mode 100644 test cases/common/206 argument syntax/meson.build diff --git a/docs/markdown/Compiler-properties.md b/docs/markdown/Compiler-properties.md index 1228f42dd..4f5ebdb89 100644 --- a/docs/markdown/Compiler-properties.md +++ b/docs/markdown/Compiler-properties.md @@ -29,9 +29,17 @@ Compiler id == The compiler object has a method called `get_id`, which returns a -lower case string describing the "family" of the compiler. See -[reference tables](Reference-tables.md) for a list of supported -compiler ids. +lower case string describing the "family" of the compiler. + +The compiler object also has a method `get_argument_syntax` which +returns a lower case string of `gcc`, `msvc`, or another undefined string +value; identifying whether the compiler arguments use the same syntax as +either `gcc` or `msvc`, or that its arguments are not like either. This should +only be used to select the syntax of the arguments, such as those to test +with `has_argument`. + +See [reference tables](Reference-tables.md#compiler-ids) for a list of supported compiler +ids and their argument type. Does code compile? == diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index f43f1f62e..72e960994 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1702,6 +1702,13 @@ the following methods: - `get_id()` returns a string identifying the compiler. For example, `gcc`, `msvc`, [and more](Reference-tables.md#compiler-ids). +- `get_argument_syntax()` *(new in 0.49.0)* returns a string identifying the type + of arguments the compiler takes. Can be one of `gcc`, `msvc`, or an undefined + string value. This method is useful for identifying compilers that are not + gcc or msvc, but use the same argument syntax as one of those two compilers + such as clang or icc, especially when they use different syntax on different + operating systems. + - `get_supported_arguments(list_of_string)` *(added 0.43.0)* returns an array containing only the arguments supported by the compiler, as if `has_argument` were called on them individually. diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index ef5d24bb9..72dce4b4d 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -2,28 +2,29 @@ ## Compiler ids -These are return values of the `get_id` method in a compiler object. - -| Value | Compiler family | -| ----- | ---------------- | -| gcc | The GNU Compiler Collection | -| clang | The Clang compiler | -| msvc | Microsoft Visual Studio | -| intel | Intel compiler | -| llvm | LLVM-based compiler (Swift, D) | -| mono | Xamarin C# compiler | -| dmd | D lang reference compiler | -| rustc | Rust compiler | -| valac | Vala compiler | -| pathscale | The Pathscale Fortran compiler | -| pgi | The Portland Fortran compiler | -| sun | Sun Fortran compiler | -| g95 | The G95 Fortran compiler | -| open64 | The Open64 Fortran Compiler | -| nagfor | The NAG Fortran compiler | -| lcc | Elbrus C/C++/Fortran Compiler | -| arm | ARM compiler | -| armclang | ARMCLANG compiler | +These are return values of the `get_id` (Compiler family) and +`get_argument_syntax` (Argument syntax) method in a compiler object. + +| Value | Compiler family | Argument syntax | +| ----- | ---------------- | -------------------------------| +| gcc | The GNU Compiler Collection | gcc | +| clang | The Clang compiler | gcc | +| msvc | Microsoft Visual Studio | msvc | +| intel | Intel compiler | msvc on windows, otherwise gcc | +| llvm | LLVM-based compiler (Swift, D) | | +| mono | Xamarin C# compiler | | +| dmd | D lang reference compiler | | +| rustc | Rust compiler | | +| valac | Vala compiler | | +| pathscale | The Pathscale Fortran compiler | | +| pgi | The Portland Fortran compiler | | +| sun | Sun Fortran compiler | | +| g95 | The G95 Fortran compiler | | +| open64 | The Open64 Fortran Compiler | | +| nagfor | The NAG Fortran compiler | | +| lcc | Elbrus C/C++/Fortran Compiler | | +| arm | ARM compiler | | +| armclang | ARMCLANG compiler | | ## Script environment variables diff --git a/docs/markdown/snippets/compiler_argument_syntax.md b/docs/markdown/snippets/compiler_argument_syntax.md new file mode 100644 index 000000000..6ae32d48c --- /dev/null +++ b/docs/markdown/snippets/compiler_argument_syntax.md @@ -0,0 +1,22 @@ +## new compiler method `get_argument_syntax` + +The compiler object now has `get_argument_syntax` method, which returns a +string value of `gcc`, `msvc`, or an undefined value string value. This can be +used to determine if a compiler uses gcc syntax (`-Wfoo`), msvc syntax +(`/w1234`), or some other kind of arguments. + +```meson +cc = meson.get_compiler('c') + +if cc.get_argument_syntax() == 'msvc' + if cc.has_argument('/w1235') + add_project_arguments('/w1235', language : ['c']) + endif +elif cc.get_argument_syntax() == 'gcc' + if cc.has_argument('-Wfoo') + add_project_arguments('-Wfoo', language : ['c']) + endif +elif cc.get_id() == 'some other compiler' + add_project_arguments('--error-on-foo', language : ['c']) +endif +``` diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index a6ae4af94..9b24e850c 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -1543,6 +1543,9 @@ class VisualStudioCCompiler(CCompiler): # false without compiling anything return name in ['dllimport', 'dllexport'] + def get_argument_syntax(self): + return 'msvc' + class ArmCCompiler(ArmCompiler, CCompiler): def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 8adacefec..a038abf91 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1214,6 +1214,17 @@ class Compiler: m = 'Language {} does not support position-independent executable' raise EnvironmentException(m.format(self.get_display_language())) + def get_argument_syntax(self): + """Returns the argument family type. + + Compilers fall into families if they try to emulate the command line + interface of another compiler. For example, clang is in the GCC family + since it accepts most of the same arguments as GCC. ICL (ICC on + windows) is in the MSVC family since it accepts most of the same + arguments as MSVC. + """ + return 'other' + @enum.unique class CompilerType(enum.Enum): @@ -1449,6 +1460,9 @@ class GnuLikeCompiler(abc.ABC): # For other targets, discard the .def file. return [] + def get_argument_syntax(self): + return 'gcc' + class GnuCompiler(GnuLikeCompiler): """ diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index e724e6a57..c2cfe5c90 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -935,6 +935,7 @@ class CompilerHolder(InterpreterObject): '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, + 'get_argument_syntax': self.get_argument_syntax_method, }) def _dep_msg(self, deps, endl): @@ -1532,6 +1533,12 @@ class CompilerHolder(InterpreterObject): args = mesonlib.stringlistify(args) return [a for a in args if self.has_func_attribute_method(a, kwargs)] + @FeatureNew('compiler.get_argument_syntax_method', '0.49.0') + @noPosargs + @noKwargs + def get_argument_syntax_method(self, args, kwargs): + return self.compiler.get_argument_syntax() + ModuleState = namedtuple('ModuleState', [ 'build_to_src', 'subproject', 'subdir', 'current_lineno', 'environment', diff --git a/test cases/common/206 argument syntax/meson.build b/test cases/common/206 argument syntax/meson.build new file mode 100644 index 000000000..c884f9086 --- /dev/null +++ b/test cases/common/206 argument syntax/meson.build @@ -0,0 +1,25 @@ +project( + 'argument syntax', + ['c'], +) + +cc = meson.get_compiler('c') + +if ['gcc', 'lcc', 'clang'].contains(cc.get_id()) + expected = 'gcc' +elif cc.get_id() == 'msvc' + expected = 'msvc' +elif cc.get_id() == 'intel' + if host_machine.system() == 'windows' + expected = 'msvc' + else + expected = 'gcc' + endif +else + # It's possible that other compilers end up here that shouldn't + expected = 'other' +endif + +assert(cc.get_argument_syntax() == expected, + 'Wrong output for compiler @0@. expected @1@ but got @2@'.format( + cc.get_id(), expected, cc.get_argument_syntax()))