From 001cf52c3a10aa4d2b0db5ec008fb5d2160ce23e Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Mon, 27 Mar 2017 14:40:34 +0530 Subject: Try even harder to use the C compiler for assembly Now as long as you have a C compiler available in the project, it will be used to compile assembly even if the target contains a C++ compiler and even if the target contains only assembly and C++ sources. Earlier, the order in which sources appeared in a target would decide which compiler would be used. However, if the project only provides a C++ compiler, that will be used for compiling assembly sources. If this breaks your use-case, please tell us. Includes a test that ensures that all of the above is adhered to. --- mesonbuild/build.py | 11 ++++-- mesonbuild/compilers.py | 11 ++++++ mesonbuild/interpreter.py | 14 +------ run_unittests.py | 46 ++++++++++++++++++++++ test cases/common/141 c cpp and asm/main.cpp | 11 ++++++ test cases/common/141 c cpp and asm/meson.build | 17 ++++++++ test cases/common/141 c cpp and asm/retval-arm.S | 8 ++++ test cases/common/141 c cpp and asm/retval-x86.S | 8 ++++ .../common/141 c cpp and asm/retval-x86_64.S | 8 ++++ test cases/common/141 c cpp and asm/somelib.c | 3 ++ .../common/141 c cpp and asm/symbol-underscore.h | 5 +++ 11 files changed, 126 insertions(+), 16 deletions(-) create mode 100644 test cases/common/141 c cpp and asm/main.cpp create mode 100644 test cases/common/141 c cpp and asm/meson.build create mode 100644 test cases/common/141 c cpp and asm/retval-arm.S create mode 100644 test cases/common/141 c cpp and asm/retval-x86.S create mode 100644 test cases/common/141 c cpp and asm/retval-x86_64.S create mode 100644 test cases/common/141 c cpp and asm/somelib.c create mode 100644 test cases/common/141 c cpp and asm/symbol-underscore.h diff --git a/mesonbuild/build.py b/mesonbuild/build.py index c28a8a4a6..1f646dc50 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -12,15 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. +import copy, os, re +from collections import OrderedDict + from . import environment from . import dependencies from . import mlog -import copy, os, re from .mesonlib import File, MesonException from .mesonlib import flatten, stringlistify, classify_unity_sources from .mesonlib import get_filenames_templates_dict, substitute_values from .environment import for_windows, for_darwin -from .compilers import is_object, clike_langs, lang_suffixes +from .compilers import is_object, clike_langs, sort_clike, lang_suffixes known_basic_kwargs = {'install': True, 'c_pch': True, @@ -291,7 +293,7 @@ class BuildTarget(Target): self.is_unity = environment.coredata.get_builtin_option('unity') self.environment = environment self.sources = [] - self.compilers = {} + self.compilers = OrderedDict() self.objects = [] self.external_deps = [] self.include_dirs = [] @@ -444,6 +446,9 @@ class BuildTarget(Target): if lang not in self.compilers: self.compilers[lang] = compiler break + # Re-sort according to clike_langs + self.compilers = OrderedDict(sorted(self.compilers.items(), + key=lambda t: sort_clike(t[0]))) else: # No source files, target consists of only object files of unknown # origin. Just add the first clike compiler that we have and hope diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 22fb522d5..76a906786 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -57,6 +57,17 @@ clike_suffixes += ('h', 'll', 's') # All these are only for C-like languages; see `clike_langs` above. +def sort_clike(lang): + ''' + Sorting function to sort the list of languages according to + reversed(compilers.clike_langs) and append the unknown langs in the end. + The purpose is to prefer C over C++ for files that can be compiled by + both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc. + ''' + if lang not in clike_langs: + return 1 + return -clike_langs.index(lang) + def is_header(fname): if hasattr(fname, 'fname'): fname = fname.fname diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 550e2f999..198c7583e 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1752,22 +1752,10 @@ class Interpreter(InterpreterBase): self.coredata.compiler_options = new_options return comp, cross_comp - @staticmethod - def sort_clike(lang): - ''' - Sorting function to sort the list of languages according to - reversed(compilers.clike_langs) and append the unknown langs in the end. - The purpose is to prefer C over C++ for files that can be compiled by - both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc. - ''' - if lang not in compilers.clike_langs: - return 1 - return -compilers.clike_langs.index(lang) - def add_languages(self, args, required): success = True need_cross_compiler = self.environment.is_cross_build() and self.environment.cross_info.need_cross_compiler() - for lang in sorted(args, key=self.sort_clike): + for lang in sorted(args, key=compilers.sort_clike): lang = lang.lower() if lang in self.coredata.compilers: comp = self.coredata.compilers[lang] diff --git a/run_unittests.py b/run_unittests.py index a11e3a5b3..91ccf37cb 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -878,6 +878,52 @@ class AllPlatformTests(BasePlatformTests): self.assertEqual(wcc.get_exelist(), wrappercc) self.assertEqual(wlinker.get_exelist(), wrapperlinker) + def test_always_prefer_c_compiler_for_asm(self): + testdir = os.path.join(self.common_test_dir, '141 c cpp and asm') + self.init(testdir) + commands = {'cpp-asm': {}, 'cpp-c-asm': {}, 'c-cpp-asm': {}} + for cmd in self.get_compdb(): + # Get compiler + split = shlex.split(cmd['command']) + if split[0] == 'ccache': + compiler = split[1] + else: + compiler = split[0] + # Classify commands + if 'Icpp-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['cpp-asm']['asm'] = compiler + elif cmd['file'].endswith('.cpp'): + commands['cpp-asm']['cpp'] = compiler + else: + raise AssertionError('{!r} found in cpp-asm?'.format(cmd['command'])) + elif 'Ic-cpp-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['c-cpp-asm']['asm'] = compiler + elif cmd['file'].endswith('.c'): + commands['c-cpp-asm']['c'] = compiler + elif cmd['file'].endswith('.cpp'): + commands['c-cpp-asm']['cpp'] = compiler + else: + raise AssertionError('{!r} found in c-cpp-asm?'.format(cmd['command'])) + elif 'Icpp-c-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['cpp-c-asm']['asm'] = compiler + elif cmd['file'].endswith('.c'): + commands['cpp-c-asm']['c'] = compiler + elif cmd['file'].endswith('.cpp'): + commands['cpp-c-asm']['cpp'] = compiler + else: + raise AssertionError('{!r} found in cpp-c-asm?'.format(cmd['command'])) + else: + raise AssertionError('Unknown command {!r} found'.format(cmd['command'])) + self.assertEqual(commands['cpp-asm']['asm'], commands['c-cpp-asm']['c']) + self.assertEqual(commands['c-cpp-asm']['asm'], commands['c-cpp-asm']['c']) + self.assertEqual(commands['cpp-c-asm']['asm'], commands['cpp-c-asm']['c']) + self.assertNotEqual(commands['cpp-asm']['asm'], commands['cpp-asm']['cpp']) + self.assertNotEqual(commands['c-cpp-asm']['c'], commands['c-cpp-asm']['cpp']) + self.assertNotEqual(commands['cpp-c-asm']['c'], commands['cpp-c-asm']['cpp']) + class WindowsTests(BasePlatformTests): ''' diff --git a/test cases/common/141 c cpp and asm/main.cpp b/test cases/common/141 c cpp and asm/main.cpp new file mode 100644 index 000000000..c08987073 --- /dev/null +++ b/test cases/common/141 c cpp and asm/main.cpp @@ -0,0 +1,11 @@ +#include + +extern "C" { + int get_retval(void); + int get_cval(void); +} + +int main(int argc, char **argv) { + std::cout << "C++ seems to be working." << std::endl; + return get_retval(); +} diff --git a/test cases/common/141 c cpp and asm/meson.build b/test cases/common/141 c cpp and asm/meson.build new file mode 100644 index 000000000..5004ef8aa --- /dev/null +++ b/test cases/common/141 c cpp and asm/meson.build @@ -0,0 +1,17 @@ +project('c cpp and asm', 'c', 'cpp') + +cpu = host_machine.cpu_family() + +supported_cpus = ['arm', 'x86', 'x86_64'] + +if not supported_cpus.contains(cpu) + error('MESON_SKIP_TEST unsupported cpu:' + cpu) +endif + +if meson.get_compiler('c').get_id() == 'msvc' + error('MESON_SKIP_TEST MSVC can\'t compile assembly') +endif + +test('test-cpp-asm', executable('cpp-asm', ['main.cpp', 'retval-' + cpu + '.S'])) +test('test-c-cpp-asm', executable('c-cpp-asm', ['somelib.c', 'main.cpp', 'retval-' + cpu + '.S'])) +test('test-cpp-c-asm', executable('cpp-c-asm', ['main.cpp', 'somelib.c', 'retval-' + cpu + '.S'])) diff --git a/test cases/common/141 c cpp and asm/retval-arm.S b/test cases/common/141 c cpp and asm/retval-arm.S new file mode 100644 index 000000000..8b3719765 --- /dev/null +++ b/test cases/common/141 c cpp and asm/retval-arm.S @@ -0,0 +1,8 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(get_retval) + +SYMBOL_NAME(get_retval): + mov r0, #0 + mov pc, lr diff --git a/test cases/common/141 c cpp and asm/retval-x86.S b/test cases/common/141 c cpp and asm/retval-x86.S new file mode 100644 index 000000000..06bd75c28 --- /dev/null +++ b/test cases/common/141 c cpp and asm/retval-x86.S @@ -0,0 +1,8 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(get_retval) + +SYMBOL_NAME(get_retval): + xorl %eax, %eax + retl diff --git a/test cases/common/141 c cpp and asm/retval-x86_64.S b/test cases/common/141 c cpp and asm/retval-x86_64.S new file mode 100644 index 000000000..638921e3e --- /dev/null +++ b/test cases/common/141 c cpp and asm/retval-x86_64.S @@ -0,0 +1,8 @@ +#include "symbol-underscore.h" + +.text +.globl SYMBOL_NAME(get_retval) + +SYMBOL_NAME(get_retval): + xorl %eax, %eax + retq diff --git a/test cases/common/141 c cpp and asm/somelib.c b/test cases/common/141 c cpp and asm/somelib.c new file mode 100644 index 000000000..e585b8e9f --- /dev/null +++ b/test cases/common/141 c cpp and asm/somelib.c @@ -0,0 +1,3 @@ +int get_cval (void) { + return 0; +} diff --git a/test cases/common/141 c cpp and asm/symbol-underscore.h b/test cases/common/141 c cpp and asm/symbol-underscore.h new file mode 100644 index 000000000..508cf50c5 --- /dev/null +++ b/test cases/common/141 c cpp and asm/symbol-underscore.h @@ -0,0 +1,5 @@ +#if defined(__WIN32__) || defined(__APPLE__) +# define SYMBOL_NAME(name) _##name +#else +# define SYMBOL_NAME(name) name +#endif -- cgit v1.2.3