diff options
22 files changed, 180 insertions, 94 deletions
diff --git a/authors.txt b/authors.txt index e32bd28..fe479bf 100644 --- a/authors.txt +++ b/authors.txt @@ -22,3 +22,4 @@ Rafaël Kooi Marko Raatikainen German Diago Gomez Kyle Manna +Haakon Sporsheim @@ -124,11 +124,15 @@ class Build: return self.global_args.get(compiler.get_language(), []) class IncludeDirs(): - def __init__(self, curdir, dirs): + def __init__(self, curdir, dirs, extra_build_dirs=None): self.curdir = curdir self.incdirs = dirs # Interpreter has validated that all given directories # actually exist. + if extra_build_dirs is None: + self.extra_build_dirs = [] + else: + self.extra_build_dirs = extra_build_dirs def get_curdir(self): return self.curdir @@ -136,6 +140,9 @@ class IncludeDirs(): def get_incdirs(self): return self.incdirs + def get_extra_build_dirs(self): + return self.extra_build_dirs + class ExtractedObjects(): def __init__(self, target, srclist): self.target = target @@ -545,7 +552,7 @@ class Generator(): if not isinstance(rule, str): raise InvalidArguments('"output" may only contain strings.') if not '@BASENAME@' in rule and not '@PLAINNAME@' in rule: - raise InvalidArguments('"outputs" must contain @BASENAME@ or @PLAINNAME@.') + raise InvalidArguments('Every element of "output" must contain @BASENAME@ or @PLAINNAME@.') if '/' in rule or '\\' in rule: raise InvalidArguments('"outputs" must not contain a directory separator.') if len(outputs) > 1: @@ -613,6 +620,8 @@ class StaticLibrary(BuildTarget): raise InvalidArguments('Static libraries not supported for C#.') self.prefix = environment.get_static_lib_prefix() self.suffix = environment.get_static_lib_suffix() + if len(self.sources) > 0 and self.sources[0].endswith('.rs'): + self.suffix = 'rlib' self.filename = self.prefix + self.name + '.' + self.suffix def get_import_filename(self): @@ -635,6 +644,8 @@ class SharedLibrary(BuildTarget): else: self.prefix = environment.get_shared_lib_prefix() self.suffix = environment.get_shared_lib_suffix() + if len(self.sources) > 0 and self.sources[0].endswith('.rs'): + self.suffix = 'rlib' self.importsuffix = environment.get_import_lib_suffix() self.filename = self.prefix + self.name + '.' + self.suffix diff --git a/interpreter.py b/interpreter.py index 6cfe103..7e67711 100644 --- a/interpreter.py +++ b/interpreter.py @@ -355,9 +355,9 @@ class CrossMachineInfo(InterpreterObject): return self.info['endian'] class IncludeDirsHolder(InterpreterObject): - def __init__(self, curdir, dirs): + def __init__(self, idobj): super().__init__() - self.held_object = build.IncludeDirs(curdir, dirs) + self.held_object = idobj class Headers(InterpreterObject): @@ -459,11 +459,16 @@ class BuildTargetHolder(InterpreterObject): 'extract_all_objects' : self.extract_all_objects_method, 'get_id': self.get_id_method, 'outdir' : self.outdir_method, + 'private_dir_include' : self.private_dir_include_method, }) def is_cross(self): return self.held_object.is_cross() + def private_dir_include_method(self, args, kwargs): + return IncludeDirsHolder(build.IncludeDirs('', [], + [self.interpreter.backend.get_target_private_dir(self.held_object)])) + def outdir_method(self, args, kwargs): return self.interpreter.backend.get_target_dir(self.held_object) @@ -905,6 +910,8 @@ class Interpreter(): 'pkgconfig_gen' : self.func_pkgconfig_gen, 'vcs_tag' : self.func_vcs_tag, 'set_variable' : self.func_set_variable, + 'is_variable' : self.func_is_variable, + 'get_variable' : self.func_get_variable, 'import' : self.func_import, 'files' : self.func_files, 'declare_dependency': self.func_declare_dependency, @@ -1003,6 +1010,29 @@ class Interpreter(): value = self.to_native(args[1]) self.set_variable(varname, value) + @noKwargs + def func_get_variable(self, node, args, kwargs): + if len(args)<1 or len(args)>2: + raise InvalidCode('Get_variable takes one or two arguments.') + varname = args[0] + if not isinstance(varname, str): + raise InterpreterException('First argument must be a string.') + try: + return self.variables[varname] + except KeyError: + pass + if len(args) == 2: + return args[1] + raise InterpreterException('Tried to get unknown variable "%s".' % varname) + + @stringArgs + @noKwargs + def func_is_variable(self, node, args, kwargs): + if len(args) != 1: + raise InvalidCode('Is_variable takes two arguments.') + varname = args[0] + return varname in self.variables + @stringArgs @noKwargs def func_import(self, node, args, kwargs): @@ -1244,6 +1274,11 @@ class Interpreter(): if not self.is_subproject() and 'subproject_dir' in kwargs: self.subproject_dir = kwargs['subproject_dir'] + if 'meson_version' in kwargs: + cv = coredata.version + pv = kwargs['meson_version'] + if not mesonlib.version_compare(cv, pv): + raise InterpreterException('Meson version is %s but project requires %s.' % (cv, pv)) self.build.projects[self.subproject] = args[0] mlog.log('Project name: ', mlog.bold(args[0]), sep='') self.add_languages(node, args[1:]) @@ -1656,7 +1691,7 @@ class Interpreter(): absdir = os.path.join(absbase, a) if not os.path.isdir(absdir): raise InvalidArguments('Include dir %s does not exist.' % a) - i = IncludeDirsHolder(self.subdir, args) + i = IncludeDirsHolder(build.IncludeDirs(self.subdir, args)) return i @stringArgs @@ -1814,12 +1849,12 @@ class Interpreter(): def string_method_call(self, obj, method_name, args): obj = self.to_native(obj) + (posargs, _) = self.reduce_arguments(args) if method_name == 'strip': return obj.strip() elif method_name == 'format': return self.format_string(obj, args) elif method_name == 'split': - (posargs, _) = self.reduce_arguments(args) if len(posargs) > 1: raise InterpreterException('Split() must have at most one argument.') elif len(posargs) == 1: @@ -1829,6 +1864,13 @@ class Interpreter(): return obj.split(s) else: return obj.split() + elif method_name == 'startswith' or method_name == 'endswith': + s = posargs[0] + if not isinstance(s, str): + raise InterpreterException('Argument must be a string.') + if method_name == 'startswith': + return obj.startswith(s) + return obj.endswith(s) raise InterpreterException('Unknown method "%s" for a string.' % method_name) def to_native(self, arg): diff --git a/manual tests/4 standalone binaries/meson.build b/manual tests/4 standalone binaries/meson.build index b524873..baae796 100644 --- a/manual tests/4 standalone binaries/meson.build +++ b/manual tests/4 standalone binaries/meson.build @@ -1,12 +1,12 @@ project('myapp', 'cpp') -sdl = dependency('sdl2', required : host.name() != 'windows') +sdl = dependency('sdl2', required : host_machine.system() != 'windows') if meson.get_compiler('cpp').get_id() != 'msvc' add_global_arguments('-std=c++11', language : 'cpp') endif -if host.name() == 'darwin' +if host_machine.system() == 'darwin' install_data('myapp.sh', install_dir : 'Contents/MacOS') @@ -19,14 +19,14 @@ if host.name() == 'darwin' meson.set_install_script('osx_bundler.sh') endif -if host.name() == 'linux' +if host_machine.system() == 'linux' install_data('myapp.sh', install_dir : '.') meson.set_install_script('linux_bundler.sh') endif extra_link_args = [] -if host.name() == 'windows' +if host_machine.system() == 'windows' str = '-I@0@/@1@'.format(meson.current_build_dir(), 'SDL2-2.0.3/include') add_global_arguments(str, language : 'cpp') extra_link_args = ['/SUBSYSTEM:CONSOLE', 'SDL2main.lib', 'SDL2.lib'] diff --git a/ninjabackend.py b/ninjabackend.py index e6cb6a5..bd074bf 100644 --- a/ninjabackend.py +++ b/ninjabackend.py @@ -169,7 +169,10 @@ class NinjaBackend(backends.Backend): continue for src in gensource.get_outfilelist(): if self.environment.is_header(src): - header_deps.append(src) + header_deps.append(os.path.join(self.get_target_private_dir(target), src)) + for dep in target.link_targets: + if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)): + header_deps += self.get_generated_headers(dep) return header_deps def generate_target(self, target, outfile): @@ -815,22 +818,22 @@ class NinjaBackend(backends.Backend): for i in target.get_sources(): if not rustc.can_compile(i): raise InvalidArguments('Rust target %s contains a non-rust source file.' % target.get_basename()) - relsrc.append(os.path.join(self.build_to_src, i)) + relsrc.append(i.rel_to_builddir(self.build_to_src)) target_name = os.path.join(target.subdir, target.get_filename()) args = ['--crate-type'] if isinstance(target, build.Executable): cratetype = 'bin' elif isinstance(target, build.SharedLibrary): - cratetype = 'dylib' + cratetype = 'rlib' elif isinstance(target, build.StaticLibrary): - cratetype = 'lib' + cratetype = 'rlib' else: raise InvalidArguments('Unknown target type for rustc.') args.append(cratetype) args += rustc.get_buildtype_args(self.environment.coredata.buildtype) - depfile = target_name + '.d' + depfile = target.name + '.d' args += ['--out-dir', target.subdir] - args += ['--dep-info', depfile] + args += ['--emit', 'dep-info', '--emit', 'link'] orderdeps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets] linkdirs = {} for d in target.link_targets: @@ -973,12 +976,9 @@ class NinjaBackend(backends.Backend): def generate_rust_compile_rules(self, compiler, outfile): rule = 'rule %s_COMPILER\n' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) - command = ' command = %s %s $out $cratetype %s $ARGS $in\n' % \ - (ninja_quote(sys.executable), - ninja_quote(os.path.join(os.path.split(__file__)[0], "rustrunner.py")), - invoc) + command = ' command = %s $ARGS $in\n' % invoc description = ' description = Compiling Rust source $in.\n' - depfile = ' depfile = $out.d\n' + depfile = ' depfile = $targetdep\n' depstyle = ' deps = gcc\n' outfile.write(rule) @@ -1308,6 +1308,8 @@ rule FORTRAN_DEP_HACK sargs = compiler.get_include_args(srctreedir) commands += bargs commands += sargs + for d in i.get_extra_build_dirs(): + commands += compiler.get_include_args(d) custom_target_include_dirs = [] for i in target.generated: if isinstance(i, build.CustomTarget): @@ -1370,7 +1372,7 @@ rule FORTRAN_DEP_HACK def get_fortran_orderdeps(self, target, compiler): if compiler.language != 'fortran': return [] - return [os.path.join(self.get_target_dir(lt), lt.filename) for lt in target.link_targets] + return [os.path.join(self.get_target_dir(lt), lt.get_filename()) for lt in target.link_targets] def generate_msvc_pch_command(self, target, compiler, pch): if len(pch) != 2: diff --git a/rustrunner.py b/rustrunner.py deleted file mode 100755 index 6c20bb3..0000000 --- a/rustrunner.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2014 The Meson development team - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This is a wrapper script to run the Rust compiler. It is needed -because: - -- output file name of Rust compilation is not knowable at command - execution time (no, --crate-name can't be used) -- need to delete old crates so nobody uses them by accident -""" - -import sys, os, subprocess, glob - -def delete_old_crates(target_name, target_type): - if target_type == 'dylib': - (base, suffix) = os.path.splitext(target_name) - crates = glob.glob(base + '-*' + suffix) - crates = [(os.stat(i).st_mtime, i) for i in crates] - [os.unlink(c[1]) for c in sorted(crates)[:-1]] - if target_type == 'lib': - (base, suffix) = os.path.splitext(target_name) - crates = glob.glob(base + '-*' + '.rlib') # Rust does not use .a - crates = [(os.stat(i).st_mtime, i) for i in crates] - [os.unlink(c[1]) for c in sorted(crates)[:-1]] - -def invoke_rust(rustc_command): - return subprocess.call(rustc_command, shell=False) - -def touch_file(fname): - try: - os.unlink(fname) - except FileNotFoundError: - pass - open(fname, 'w').close() - -if __name__ == '__main__': - if len(sys.argv) < 3: - print('This script is internal to Meson. Do not run it on its own.') - print("%s <target name> <target type> <rustc invokation cmd line>") - sys.exit(1) - target_name = sys.argv[1] - target_type = sys.argv[2] - rustc_command = sys.argv[3:] - retval = invoke_rust(rustc_command) - if retval != 0: - sys.exit(retval) - if target_type != "bin": - delete_old_crates(target_name, target_type) - touch_file(target_name) - - diff --git a/test cases/common/1 trivial/meson.build b/test cases/common/1 trivial/meson.build index 2e0426a..3f14539 100644 --- a/test cases/common/1 trivial/meson.build +++ b/test cases/common/1 trivial/meson.build @@ -1,5 +1,5 @@ # Comment on the first line -project('trivial test', 'c') +project('trivial test', 'c', meson_version : '>=0.27.0') #this is a comment sources = 'trivial.c' diff --git a/test cases/common/17 if/meson.build b/test cases/common/17 if/meson.build index b77f93a..2103d20 100644 --- a/test cases/common/17 if/meson.build +++ b/test cases/common/17 if/meson.build @@ -12,3 +12,19 @@ if var2 endif test('iftest', exe) + +if not is_variable('var1') + error('Is_variable fail.') +endif + +if is_variable('nonexisting') + error('Is_variable fail 2.') +endif + +if not get_variable('var1', false) + error('Get_variable fail.') +endif + +if get_variable('nonexisting', false) + error('Get_variable fail.') +endif diff --git a/test cases/common/42 string formatting/meson.build b/test cases/common/42 string formatting/meson.build index 4e7cc1a..81f5268 100644 --- a/test cases/common/42 string formatting/meson.build +++ b/test cases/common/42 string formatting/meson.build @@ -20,3 +20,23 @@ subs2 = '42' if templ2.format(subs2) != '42' error('String formatting with variables is broken.') endif + +long = 'abcde' +prefix = 'abc' +suffix = 'cde' + +if not long.startswith(prefix) + error('Prefix.') +endif + +if long.startswith(suffix) + error('Not prefix.') +endif + +if not long.endswith(suffix) + error('Suffix.') +endif + +if long.endswith(prefix) + error('Not suffix.') +endif diff --git a/test cases/common/93 private include/meson.build b/test cases/common/93 private include/meson.build new file mode 100644 index 0000000..2485fbf --- /dev/null +++ b/test cases/common/93 private include/meson.build @@ -0,0 +1,4 @@ +project('access private', 'c') + +subdir('stlib') +subdir('user') diff --git a/test cases/common/93 private include/stlib/compiler.py b/test cases/common/93 private include/stlib/compiler.py new file mode 100755 index 0000000..3e74c88 --- /dev/null +++ b/test cases/common/93 private include/stlib/compiler.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +import sys, os + +assert(len(sys.argv) == 3) + +h_templ = '''#pragma once +unsigned int %s(); +''' + +c_templ = '''#include"%s.h" + +unsigned int %s() { + return 0; +} +''' + +ifile = sys.argv[1] +outdir = sys.argv[2] + +base = os.path.splitext(os.path.split(ifile)[-1])[0] + +cfile = os.path.join(outdir, base + '.c') +hfile = os.path.join(outdir, base + '.h') + +c_code = c_templ % (base, base) +h_code = h_templ % base + +open(cfile, 'w').write(c_code) +open(hfile, 'w').write(h_code) diff --git a/test cases/common/93 private include/stlib/foo1.def b/test cases/common/93 private include/stlib/foo1.def new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/93 private include/stlib/foo1.def diff --git a/test cases/common/93 private include/stlib/foo2.def b/test cases/common/93 private include/stlib/foo2.def new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/93 private include/stlib/foo2.def diff --git a/test cases/common/93 private include/stlib/meson.build b/test cases/common/93 private include/stlib/meson.build new file mode 100644 index 0000000..8d70650 --- /dev/null +++ b/test cases/common/93 private include/stlib/meson.build @@ -0,0 +1,12 @@ +genbin = find_program('compiler.py') + +gen = generator(genbin, + output : ['@BASENAME@.h', '@BASENAME@.c'], + arguments : ['@INPUT@', '@BUILD_DIR@'] + ) + +defs = ['foo1.def', 'foo2.def'] +generated = gen.process(defs) + +stlib = static_library('st', generated) +st_priv_inc = stlib.private_dir_include() diff --git a/test cases/common/93 private include/user/libuser.c b/test cases/common/93 private include/user/libuser.c new file mode 100644 index 0000000..a74a973 --- /dev/null +++ b/test cases/common/93 private include/user/libuser.c @@ -0,0 +1,6 @@ +#include"foo1.h" +#include"foo2.h" + +int main(int argc, char **argv) { + return foo1() + foo2(); +} diff --git a/test cases/common/93 private include/user/meson.build b/test cases/common/93 private include/user/meson.build new file mode 100644 index 0000000..ab88b1d --- /dev/null +++ b/test cases/common/93 private include/user/meson.build @@ -0,0 +1,5 @@ +exe = executable('libuser', 'libuser.c', + link_with : stlib, + include_directories : st_priv_inc) + +test('libuser', exe) diff --git a/test cases/failing/20 version/meson.build b/test cases/failing/20 version/meson.build new file mode 100644 index 0000000..9a3a851 --- /dev/null +++ b/test cases/failing/20 version/meson.build @@ -0,0 +1 @@ +project('version mismatch', 'c', meson_version : '>100.0.0') diff --git a/test cases/rust/1 basic/installed_files.txt b/test cases/rust/1 basic/installed_files.txt index 429fde7..61eda27 100644 --- a/test cases/rust/1 basic/installed_files.txt +++ b/test cases/rust/1 basic/installed_files.txt @@ -1 +1 @@ -bin/prog +usr/bin/prog diff --git a/test cases/rust/2 sharedlib/installed_files.txt b/test cases/rust/2 sharedlib/installed_files.txt index 0606d1f..5a7c7d6 100644 --- a/test cases/rust/2 sharedlib/installed_files.txt +++ b/test cases/rust/2 sharedlib/installed_files.txt @@ -1,2 +1,2 @@ -bin/prog -lib/libstuff-e4d2ee75-1.0.so +usr/bin/prog +usr/lib/libstuff.rlib diff --git a/test cases/rust/2 sharedlib/stuff.rs b/test cases/rust/2 sharedlib/stuff.rs index 5e1dcc2..8cabc62 100644 --- a/test cases/rust/2 sharedlib/stuff.rs +++ b/test cases/rust/2 sharedlib/stuff.rs @@ -1,3 +1,3 @@ -#![crate_id = "stuff#1.0"] +#![crate_name = "stuff"] pub fn explore() -> &'static str { "librarystring" } diff --git a/test cases/rust/3 staticlib/installed_files.txt b/test cases/rust/3 staticlib/installed_files.txt index 4c3dfed..5a7c7d6 100644 --- a/test cases/rust/3 staticlib/installed_files.txt +++ b/test cases/rust/3 staticlib/installed_files.txt @@ -1,2 +1,2 @@ -bin/prog -lib/libstuff-e4d2ee75-1.0.rlib +usr/bin/prog +usr/lib/libstuff.rlib diff --git a/test cases/rust/3 staticlib/stuff.rs b/test cases/rust/3 staticlib/stuff.rs index 5e1dcc2..8cabc62 100644 --- a/test cases/rust/3 staticlib/stuff.rs +++ b/test cases/rust/3 staticlib/stuff.rs @@ -1,3 +1,3 @@ -#![crate_id = "stuff#1.0"] +#![crate_name = "stuff"] pub fn explore() -> &'static str { "librarystring" } |