diff options
-rw-r--r-- | mesonbuild/build.py | 34 | ||||
-rw-r--r-- | mesonbuild/compilers.py | 16 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 5 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 6 | ||||
-rw-r--r-- | mesonbuild/wrap/wrap.py | 2 | ||||
-rwxr-xr-x | run_tests.py | 11 | ||||
-rwxr-xr-x | run_unittests.py | 67 | ||||
-rw-r--r-- | test cases/common/141 c cpp and asm/main.c | 8 | ||||
-rw-r--r-- | test cases/common/141 c cpp and asm/main.cpp | 11 | ||||
-rw-r--r-- | test cases/common/141 c cpp and asm/meson.build | 18 | ||||
-rw-r--r-- | test cases/common/141 c cpp and asm/retval-arm.S | 8 | ||||
-rw-r--r-- | test cases/common/141 c cpp and asm/retval-x86.S | 8 | ||||
-rw-r--r-- | test cases/common/141 c cpp and asm/retval-x86_64.S | 8 | ||||
-rw-r--r-- | test cases/common/141 c cpp and asm/somelib.c | 3 | ||||
-rw-r--r-- | test cases/common/141 c cpp and asm/symbol-underscore.h | 5 | ||||
-rw-r--r-- | test cases/common/9 header install/meson.build | 2 | ||||
-rw-r--r-- | test cases/unit/5 compiler detection/meson.build | 2 |
17 files changed, 188 insertions, 26 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 41e21e3..ce5638d 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 = [] @@ -391,13 +393,6 @@ class BuildTarget(Target): raise InvalidArguments(msg) @staticmethod - def can_compile_sources(compiler, sources): - for s in sources: - if compiler.can_compile(s): - return True - return False - - @staticmethod def can_compile_remove_sources(compiler, sources): removed = False for s in sources[:]: @@ -442,13 +437,18 @@ class BuildTarget(Target): if not s.endswith(lang_suffixes['vala']): sources.append(s) if sources: - # Add compilers based on the above sources - for lang, compiler in compilers.items(): - # We try to be conservative because sometimes people add files - # in the list of sources that we can't determine the type based - # just on the suffix. - if self.can_compile_sources(compiler, sources): - self.compilers[lang] = compiler + # For each source, try to add one compiler that can compile it. + # It's ok if no compilers can do so, because users are expected to + # be able to add arbitrary non-source files to the sources list. + for s in sources: + for lang, compiler in compilers.items(): + if compiler.can_compile(s): + 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 f16a05f..5e7db24 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 @@ -514,6 +525,11 @@ class Compiler: self.version = version self.base_options = [] + def __repr__(self): + repr_str = "<{0}: v{1} `{2}`>" + return repr_str.format(self.__class__.__name__, self.version, + ' '.join(self.exelist)) + def can_compile(self, src): if hasattr(src, 'fname'): src = src.fname diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 9562211..51eeaff 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -14,6 +14,7 @@ import pickle, os, uuid from pathlib import PurePath +from collections import OrderedDict from .mesonlib import MesonException, commonpath from .mesonlib import default_libdir, default_libexecdir, default_prefix @@ -128,8 +129,8 @@ class CoreData: else: self.cross_file = None self.wrap_mode = options.wrap_mode - self.compilers = {} - self.cross_compilers = {} + self.compilers = OrderedDict() + self.cross_compilers = OrderedDict() self.deps = {} self.modules = {} # Only to print a warning if it changes between Meson invocations. diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 7ee4bb9..0c6d980 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1613,6 +1613,8 @@ class Interpreter(InterpreterBase): @stringArgs def func_project(self, node, args, kwargs): + if len(args) < 1: + raise InvalidArguments('Not enough arguments to project(). Needs at least the project name.') default_options = kwargs.get('default_options', []) if self.environment.first_invocation and (len(default_options) > 0 or len(self.default_project_options) > 0): @@ -1625,8 +1627,6 @@ class Interpreter(InterpreterBase): ) oi.process(self.option_file) self.build.environment.merge_options(oi.options) - if len(args) < 2: - raise InvalidArguments('Not enough arguments to project(). Needs at least the project name and one language') self.active_projectname = args[0] self.project_version = kwargs.get('version', 'undefined') if self.build.project_version is None: @@ -1755,7 +1755,7 @@ class Interpreter(InterpreterBase): 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 args: + 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/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index fcacc16..67e4700 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -39,7 +39,7 @@ def build_ssl_context(): return ctx def quiet_git(cmd): - pc = subprocess.Popen(['git'] + cmd, stdout=subprocess.PIPE) + pc = subprocess.Popen(['git'] + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = pc.communicate() if pc.returncode != 0: return False, err diff --git a/run_tests.py b/run_tests.py index 5025057..02aa701 100755 --- a/run_tests.py +++ b/run_tests.py @@ -21,6 +21,12 @@ import subprocess import platform from mesonbuild import mesonlib +def using_vs_backend(): + for arg in sys.argv[1:]: + if arg.startswith('--backend=vs'): + return True + return False + if __name__ == '__main__': returncode = 0 # Running on a developer machine? Be nice! @@ -32,7 +38,10 @@ if __name__ == '__main__': units += ['LinuxlikeTests'] elif mesonlib.is_windows(): units += ['WindowsTests'] - returncode += subprocess.call([sys.executable, 'run_unittests.py', '-v'] + units) + # Unit tests always use the Ninja backend, so just skip them if we're + # testing the VS backend + if not using_vs_backend(): + returncode += subprocess.call([sys.executable, 'run_unittests.py', '-v'] + units) # Ubuntu packages do not have a binary without -6 suffix. if shutil.which('arm-linux-gnueabihf-gcc-6') and not platform.machine().startswith('arm'): print('Running cross compilation tests.\n') diff --git a/run_unittests.py b/run_unittests.py index 66f8205..be73839 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -880,6 +880,73 @@ 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') + # Skip if building with MSVC + env = Environment(testdir, self.builddir, self.meson_command, + get_fake_options(self.prefix), []) + if env.detect_c_compiler(False).get_id() == 'msvc': + raise unittest.SkipTest('MSVC can\'t compile assembly') + self.init(testdir) + commands = {'c-asm': {}, '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 'Ic-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['c-asm']['asm'] = compiler + elif cmd['file'].endswith('.c'): + commands['c-asm']['c'] = compiler + else: + raise AssertionError('{!r} found in cpp-asm?'.format(cmd['command'])) + elif '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'])) + # Check that .S files are always built with the C compiler + self.assertEqual(commands['c-asm']['asm'], commands['c-asm']['c']) + self.assertEqual(commands['c-asm']['asm'], commands['cpp-asm']['asm']) + 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']) + # Check that the c-asm target is always linked with the C linker + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, 'r', encoding='utf-8') as f: + contents = f.read() + m = re.search('build c-asm.*: c_LINKER', contents) + self.assertIsNotNone(m, msg=contents) + class WindowsTests(BasePlatformTests): ''' diff --git a/test cases/common/141 c cpp and asm/main.c b/test cases/common/141 c cpp and asm/main.c new file mode 100644 index 0000000..8976723 --- /dev/null +++ b/test cases/common/141 c cpp and asm/main.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +int get_retval(void); + +int main(int argc, char **argv) { + printf("C seems to be working.\n"); + return get_retval(); +} 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 0000000..c089870 --- /dev/null +++ b/test cases/common/141 c cpp and asm/main.cpp @@ -0,0 +1,11 @@ +#include <iostream> + +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 0000000..9c90434 --- /dev/null +++ b/test cases/common/141 c cpp and asm/meson.build @@ -0,0 +1,18 @@ +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-c-asm', executable('c-asm', ['main.c', 'retval-' + cpu + '.S'])) +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 0000000..8b37197 --- /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 0000000..06bd75c --- /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 0000000..638921e --- /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 0000000..e585b8e --- /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 0000000..508cf50 --- /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 diff --git a/test cases/common/9 header install/meson.build b/test cases/common/9 header install/meson.build index 7f3ce51..7dfbddb 100644 --- a/test cases/common/9 header install/meson.build +++ b/test cases/common/9 header install/meson.build @@ -1,4 +1,4 @@ -project('header install', 'c') +project('header install') as_array = ['subdir.h'] diff --git a/test cases/unit/5 compiler detection/meson.build b/test cases/unit/5 compiler detection/meson.build index 5491c64..8b47bd4 100644 --- a/test cases/unit/5 compiler detection/meson.build +++ b/test cases/unit/5 compiler detection/meson.build @@ -3,6 +3,6 @@ project('trivial test', meson_version : '>=0.27.0') executable('trivialc', 'trivial.c') -executable('trivialcpp', 'trivial.cpp') +executable('trivialcpp', 'trivial.cc') executable('trivialobjc', 'trivial.m') executable('trivialobjcpp', 'trivial.mm') |