diff options
-rw-r--r-- | mesonbuild/backend/backends.py | 2 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 5 | ||||
-rw-r--r-- | mesonbuild/build.py | 2 | ||||
-rw-r--r-- | mesonbuild/compilers.py | 100 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 87 | ||||
-rw-r--r-- | mesonbuild/mesonlib.py | 8 | ||||
-rw-r--r-- | mesonbuild/modules/gnome.py | 3 | ||||
-rw-r--r-- | mesonbuild/scripts/gettext.py | 6 | ||||
-rwxr-xr-x | test cases/common/118 allgenerate/converter.py | 8 | ||||
-rw-r--r-- | test cases/common/118 allgenerate/foobar.cpp.in | 6 | ||||
-rw-r--r-- | test cases/common/118 allgenerate/meson.build | 20 | ||||
-rw-r--r-- | test cases/common/16 configure file/meson.build | 4 | ||||
-rw-r--r-- | test cases/common/94 default options/meson.build | 10 | ||||
-rw-r--r-- | test cases/linuxlike/9 compiler checks with dependencies/meson.build | 31 |
14 files changed, 227 insertions, 65 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index c726668..4139ace 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -481,7 +481,7 @@ class Backend(): if self.environment.is_cross_build() and \ self.environment.cross_info.need_exe_wrapper() and \ isinstance(exe, build.BuildTarget) and exe.is_cross: - if 'exe_wrapper' not in self.environment.cross_info.config: + if 'exe_wrapper' not in self.environment.cross_info.config['binaries']: s = 'Can not use target %s as a generator because it is cross-built\n' s += 'and no exe wrapper is defined. You might want to set it to native instead.' s = s % exe.name diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index db9e1b0..251f7ee 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -264,10 +264,12 @@ int dummy; unity_src = [] unity_deps = [] # Generated sources that must be built before compiling a Unity target. header_deps += self.get_generated_headers(target) + generator_output_sources = [] # Needed to determine the linker for gensource in target.get_generated_sources(): if isinstance(gensource, build.CustomTarget): for src in gensource.output: src = os.path.join(self.get_target_dir(gensource), src) + generator_output_sources.append(src) if self.environment.is_source(src) and not self.environment.is_header(src): if is_unity: unity_deps.append(os.path.join(self.environment.get_build_dir(), RawFilename(src))) @@ -285,6 +287,7 @@ int dummy; header_deps.append(RawFilename(src)) else: for src in gensource.get_outfilelist(): + generator_output_sources.append(src) if self.environment.is_object(src): obj_list.append(os.path.join(self.get_target_private_dir(target), src)) elif not self.environment.is_header(src): @@ -330,7 +333,7 @@ int dummy; if is_unity: for src in self.generate_unity_files(target, unity_src): obj_list.append(self.generate_single_compile(target, outfile, src, True, unity_deps + header_deps)) - linker = self.determine_linker(target, src_list) + linker = self.determine_linker(target, src_list + generator_output_sources) elem = self.generate_link(target, outfile, outname, obj_list, linker, pch_objects) self.generate_shlib_aliases(target, self.get_target_dir(target)) elem.write(outfile) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 7605b46..dce0236 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1271,7 +1271,7 @@ class ConfigurationData(): return repr(self.values) def get(self, name): - return self.values[name] + return self.values[name] # (val, desc) def keys(self): return self.values.keys() diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index fb2a81a..c5b932c 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -173,6 +173,9 @@ base_options = { 'b_colorout' : coredata.UserComboOption('b_colorout', 'Use colored output', ['auto', 'always', 'never'], 'always'), + 'b_ndebug' : coredata.UserBooleanOption('b_ndebug', + 'Disable asserts', + False) } def sanitizer_compile_args(value): @@ -218,6 +221,11 @@ def get_base_compile_args(options, compiler): args += compiler.get_coverage_args() except KeyError: pass + try: + if options['b_ndebug'].value: + args += ['-DNDEBUG'] + except KeyError: + pass return args def get_base_link_args(options, linker): @@ -580,15 +588,15 @@ class CCompiler(Compiler): code = 'int main(int argc, char **argv) { int class=0; return class; }\n' return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) - def has_header(self, hname, env, extra_args=None): + def has_header(self, hname, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] templ = '''#include<%s> int someSymbolHereJustForFun; ''' - return self.compiles(templ % hname, env, extra_args) + return self.compiles(templ % hname, env, extra_args, dependencies) - def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None): + def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] templ = '''{2} @@ -596,7 +604,7 @@ int someSymbolHereJustForFun; int main () {{ {1}; }}''' # Pass -O0 to ensure that the symbol isn't optimized away args = extra_args + self.get_no_optimization_args() - return self.compiles(templ.format(hname, symbol, prefix), env, args) + return self.compiles(templ.format(hname, symbol, prefix), env, args, dependencies) def compile(self, code, srcname, extra_args=None): if extra_args is None: @@ -616,18 +624,23 @@ int main () {{ {1}; }}''' os.remove(srcname) return p - def compiles(self, code, env, extra_args=None): + def compiles(self, code, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] if isinstance(extra_args, str): extra_args = [extra_args] + if dependencies is None: + dependencies = [] + elif not isinstance(dependencies, list): + dependencies = [dependencies] suflen = len(self.default_suffix) (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix) os.close(fd) with open(srcname, 'w') as ofile: ofile.write(code) + cargs = [a for d in dependencies for a in d.get_compile_args()] # Convert flags to the native type of the selected compiler - args = self.unix_link_flags_to_native(extra_args) + args = self.unix_link_flags_to_native(cargs + extra_args) # Read c_args/cpp_args/etc from the cross-info file (if needed) args += self.get_cross_extra_flags(env, compile=True, link=False) # We only want to compile; not link @@ -644,19 +657,25 @@ int main () {{ {1}; }}''' pass return p.returncode == 0 - def links(self, code, env, extra_args=None): + def links(self, code, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] elif isinstance(extra_args, str): extra_args = [extra_args] + if dependencies is None: + dependencies = [] + elif not isinstance(dependencies, list): + dependencies = [dependencies] (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix) os.close(fd) (fd, dstname) = tempfile.mkstemp() os.close(fd) with open(srcname, 'w') as ofile: ofile.write(code) + cargs = [a for d in dependencies for a in d.get_compile_args()] + link_args = [a for d in dependencies for a in d.get_link_args()] # Convert flags to the native type of the selected compiler - args = self.unix_link_flags_to_native(extra_args) + args = self.unix_link_flags_to_native(cargs + link_args + extra_args) # Select a CRT if needed since we're linking args += self.get_linker_debug_crt_args() # Read c_args/c_link_args/cpp_args/cpp_link_args/etc from the cross-info file (if needed) @@ -670,17 +689,23 @@ int main () {{ {1}; }}''' pass return p.returncode == 0 - def run(self, code, env, extra_args=None): + def run(self, code, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] + if dependencies is None: + dependencies = [] + elif not isinstance(dependencies, list): + dependencies = [dependencies] if self.is_cross and self.exe_wrapper is None: raise CrossNoRunException('Can not run test applications in this cross environment.') (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix) os.close(fd) with open(srcname, 'w') as ofile: ofile.write(code) + cargs = [a for d in dependencies for a in d.get_compile_args()] + link_args = [a for d in dependencies for a in d.get_link_args()] # Convert flags to the native type of the selected compiler - args = self.unix_link_flags_to_native(extra_args) + args = self.unix_link_flags_to_native(cargs + link_args + extra_args) # Select a CRT if needed since we're linking args += self.get_linker_debug_crt_args() # Read c_link_args/cpp_link_args/etc from the cross-info file @@ -729,7 +754,7 @@ int main () {{ {1}; }}''' pass return RunResult(True, pe.returncode, so, se) - def cross_sizeof(self, element, prefix, env, extra_args=None): + def cross_sizeof(self, element, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] element_exists_templ = '''#include <stdio.h> @@ -743,11 +768,11 @@ int main(int argc, char **argv) {{ int temparray[%d-sizeof(%s)]; ''' args = extra_args + self.get_no_optimization_args() - if not self.compiles(element_exists_templ.format(prefix, element), env, args): + if not self.compiles(element_exists_templ.format(prefix, element), env, args, dependencies): return -1 for i in range(1, 1024): code = templ % (prefix, i, element) - if self.compiles(code, env, args): + if self.compiles(code, env, args, dependencies): if self.id == 'msvc': # MSVC refuses to construct an array of zero size, so # the test only succeeds when i is sizeof(element) + 1 @@ -755,11 +780,11 @@ int temparray[%d-sizeof(%s)]; return i raise EnvironmentException('Cross checking sizeof overflowed.') - def sizeof(self, element, prefix, env, extra_args=None): + def sizeof(self, element, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] if self.is_cross: - return self.cross_sizeof(element, prefix, env, extra_args) + return self.cross_sizeof(element, prefix, env, extra_args, dependencies) templ = '''#include<stdio.h> %s @@ -768,14 +793,14 @@ int main(int argc, char **argv) { return 0; }; ''' - res = self.run(templ % (prefix, element), env, extra_args) + res = self.run(templ % (prefix, element), env, extra_args, dependencies) if not res.compiled: return -1 if res.returncode != 0: raise EnvironmentException('Could not run sizeof test binary.') return int(res.stdout) - def cross_alignment(self, typename, env, extra_args=None): + def cross_alignment(self, typename, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] type_exists_templ = '''#include <stdio.h> @@ -792,11 +817,11 @@ struct tmp { int testarray[%d-offsetof(struct tmp, target)]; ''' args = extra_args + self.get_no_optimization_args() - if not self.compiles(type_exists_templ.format(typename), env, args): + if not self.compiles(type_exists_templ.format(typename), env, args, dependencies): return -1 for i in range(1, 1024): code = templ % (typename, i) - if self.compiles(code, env, args): + if self.compiles(code, env, args, dependencies): if self.id == 'msvc': # MSVC refuses to construct an array of zero size, so # the test only succeeds when i is sizeof(element) + 1 @@ -804,11 +829,11 @@ int testarray[%d-offsetof(struct tmp, target)]; return i raise EnvironmentException('Cross checking offsetof overflowed.') - def alignment(self, typename, env, extra_args=None): + def alignment(self, typename, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] if self.is_cross: - return self.cross_alignment(typename, env, extra_args) + return self.cross_alignment(typename, env, extra_args, dependencies) templ = '''#include<stdio.h> #include<stddef.h> @@ -822,7 +847,7 @@ int main(int argc, char **argv) { return 0; } ''' - res = self.run(templ % typename, env, extra_args) + res = self.run(templ % typename, env, extra_args, dependencies) if not res.compiled: raise EnvironmentException('Could not compile alignment test.') if res.returncode != 0: @@ -832,7 +857,7 @@ int main(int argc, char **argv) { raise EnvironmentException('Could not determine alignment of %s. Sorry. You might want to file a bug.' % typename) return align - def has_function(self, funcname, prefix, env, extra_args=None): + def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None): """ First, this function looks for the symbol in the default libraries provided by the compiler (stdlib + a few others usually). If that @@ -889,7 +914,7 @@ int main(int argc, char **argv) { if isinstance(val, bool): return val raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname)) - if self.links(templ.format(prefix, funcname), env, extra_args): + if self.links(templ.format(prefix, funcname), env, extra_args, dependencies): return True # Add -O0 to ensure that the symbol isn't optimized away by the compiler args = extra_args + self.get_no_optimization_args() @@ -898,15 +923,15 @@ int main(int argc, char **argv) { # still detect the function. We still want to fail if __stub_foo or # _stub_foo are defined, of course. header_templ = '#include <limits.h>\n{0}\n' + stubs_fail + '\nint main() {{ {1}; }}' - if self.links(header_templ.format(prefix, funcname), env, args): + if self.links(header_templ.format(prefix, funcname), env, args, dependencies): return True # Some functions like alloca() are defined as compiler built-ins which # are inlined by the compiler, so test for that instead. Built-ins are # special functions that ignore all includes and defines, so we just # directly try to link via main(). - return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), env, args) + return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), env, args, dependencies) - def has_members(self, typename, membernames, prefix, env, extra_args=None): + def has_members(self, typename, membernames, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] templ = '''{0} @@ -920,15 +945,15 @@ void bar() {{ for m in membernames: members += 'foo.{};\n'.format(m) code = templ.format(prefix, typename, 'foo', members) - return self.compiles(code, env, extra_args) + return self.compiles(code, env, extra_args, dependencies) - def has_type(self, typename, prefix, env, extra_args): + def has_type(self, typename, prefix, env, extra_args, dependencies=None): templ = '''%s void bar() { sizeof(%s); }; ''' - return self.compiles(templ % (prefix, typename), env, extra_args) + return self.compiles(templ % (prefix, typename), env, extra_args, dependencies) def find_library(self, libname, env, extra_dirs): # First try if we can just add the library as -l. @@ -1723,7 +1748,7 @@ class VisualStudioCCompiler(CCompiler): self.always_args = ['/nologo', '/showIncludes'] self.warn_args = {'1': ['/W2'], '2': ['/W3'], - '3': ['/w4']} + '3': ['/W4']} self.base_options = ['b_pch'] # FIXME add lto, pgo and the like def get_always_args(self): @@ -1953,7 +1978,7 @@ class GnuCompiler: self.id = 'gcc' self.gcc_type = gcc_type self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage', - 'b_colorout'] + 'b_colorout', 'b_ndebug'] if self.gcc_type != GCC_OSX: self.base_options.append('b_lundef') self.base_options.append('b_asneeded') @@ -1963,6 +1988,14 @@ class GnuCompiler: return gnu_color_args[colortype][:] return [] + def get_warn_args(self, level): + args = super().get_warn_args(level) + if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args: + # -Wpedantic was added in 4.8.0 + # https://gcc.gnu.org/gcc-4.8/changes.html + args[args.index('-Wpedantic')] = '-pedantic' + return args + def get_pic_args(self): if self.gcc_type == GCC_MINGW: return [] # On Window gcc defaults to fpic being always on. @@ -2084,7 +2117,8 @@ class ClangCompiler(): def __init__(self, clang_type): self.id = 'clang' self.clang_type = clang_type - self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] + self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage', + 'b_ndebug'] if self.clang_type != CLANG_OSX: self.base_options.append('b_lundef') self.base_options.append('b_asneeded') diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 80617dd..385e07a 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -228,40 +228,44 @@ class ConfigurationDataHolder(InterpreterObject): def mark_used(self): self.used = True - def validate_args(self, args): + def validate_args(self, args, kwargs): if len(args) != 2: raise InterpreterException("Configuration set requires 2 arguments.") if self.used: raise InterpreterException("Can not set values on configuration object that has been used.") name = args[0] val = args[1] + desc = kwargs.get('description', None) if not isinstance(name, str): raise InterpreterException("First argument to set must be a string.") - return (name, val) + if desc is not None and not isinstance(desc, str): + raise InterpreterException('Description must be a string.') + + return (name, val, desc) def set_method(self, args, kwargs): - (name, val) = self.validate_args(args) - self.held_object.values[name] = val + (name, val, desc) = self.validate_args(args, kwargs) + self.held_object.values[name] = (val, desc) def set_quoted_method(self, args, kwargs): - (name, val) = self.validate_args(args) + (name, val, desc) = self.validate_args(args, kwargs) if not isinstance(val, str): raise InterpreterException("Second argument to set_quoted must be a string.") escaped_val = '\\"'.join(val.split('"')) - self.held_object.values[name] = '"' + escaped_val + '"' + self.held_object.values[name] = ('"' + escaped_val + '"', desc) def set10_method(self, args, kwargs): - (name, val) = self.validate_args(args) + (name, val, desc) = self.validate_args(args, kwargs) if val: - self.held_object.values[name] = 1 + self.held_object.values[name] = (1, desc) else: - self.held_object.values[name] = 0 + self.held_object.values[name] = (0, desc) def has_method(self, args, kwargs): return args[0] in self.held_object.values def get(self, name): - return self.held_object.values[name] + return self.held_object.values[name] # (val, desc) def keys(self): return self.held_object.values.keys() @@ -662,6 +666,25 @@ class CompilerHolder(InterpreterObject): args += mesonlib.stringlistify(kwargs.get('args', [])) return args + def determine_dependencies(self, kwargs, allowed_dep_types=None): + deps = kwargs.get('dependencies', None) + if allowed_dep_types is None: + allowed_dep_types = (dependencies.Dependency, dependencies.ExternalLibrary) + if deps is not None: + if not isinstance(deps, list): + deps = [deps] + final_deps = [] + for d in deps: + try: + d = d.held_object + except Exception: + pass + if not isinstance(d, allowed_dep_types): + raise InterpreterException('Dependencies must be external deps') + final_deps.append(d) + deps = final_deps + return deps + def alignment_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Alignment method takes exactly one positional argument.') @@ -681,7 +704,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') extra_args = self.determine_args(kwargs) - result = self.compiler.run(code, self.environment, extra_args) + deps = self.determine_dependencies(kwargs) + result = self.compiler.run(code, self.environment, extra_args, deps) if len(testname) > 0: if not result.compiled: h = mlog.red('DID NOT COMPILE') @@ -711,8 +735,9 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_member must be a string.') extra_args = self.determine_args(kwargs) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) had = self.compiler.has_members(typename, [membername], prefix, - self.environment, extra_args) + self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: @@ -729,8 +754,9 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_members must be a string.') extra_args = self.determine_args(kwargs) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) had = self.compiler.has_members(typename, membernames, prefix, - self.environment, extra_args) + self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: @@ -749,7 +775,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_function must be a string.') extra_args = self.determine_args(kwargs) - had = self.compiler.has_function(funcname, prefix, self.environment, extra_args) + deps = self.determine_dependencies(kwargs) + had = self.compiler.has_function(funcname, prefix, self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: @@ -766,7 +793,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_type must be a string.') extra_args = self.determine_args(kwargs) - had = self.compiler.has_type(typename, prefix, self.environment, extra_args) + deps = self.determine_dependencies(kwargs) + had = self.compiler.has_type(typename, prefix, self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: @@ -783,7 +811,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of sizeof must be a string.') extra_args = self.determine_args(kwargs) - esize = self.compiler.sizeof(element, prefix, self.environment, extra_args) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) + esize = self.compiler.sizeof(element, prefix, self.environment, extra_args, deps) mlog.log('Checking for size of "%s": %d' % (element, esize)) return esize @@ -796,7 +825,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') extra_args = self.determine_args(kwargs) - result = self.compiler.compiles(code, self.environment, extra_args) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) + result = self.compiler.compiles(code, self.environment, extra_args, deps) if len(testname) > 0: if result: h = mlog.green('YES') @@ -814,7 +844,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') extra_args = self.determine_args(kwargs) - result = self.compiler.links(code, self.environment, extra_args) + deps = self.determine_dependencies(kwargs) + result = self.compiler.links(code, self.environment, extra_args, deps) if len(testname) > 0: if result: h = mlog.green('YES') @@ -829,7 +860,8 @@ class CompilerHolder(InterpreterObject): check_stringlist(args) string = args[0] extra_args = self.determine_args(kwargs) - haz = self.compiler.has_header(string, self.environment, extra_args) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) + haz = self.compiler.has_header(string, self.environment, extra_args, deps) if haz: h = mlog.green('YES') else: @@ -847,7 +879,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_function must be a string.') extra_args = self.determine_args(kwargs) - haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, extra_args) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) + haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, extra_args, deps) if haz: h = mlog.green('YES') else: @@ -856,6 +889,7 @@ class CompilerHolder(InterpreterObject): return haz def find_library_method(self, args, kwargs): + # TODO add dependencies support? if len(args) != 1: raise InterpreterException('find_library method takes one argument.') libname = args[0] @@ -942,6 +976,7 @@ class MesonMain(InterpreterObject): 'add_postconf_script' : self.add_postconf_script_method, 'install_dependency_manifest': self.install_dependency_manifest_method, 'project_version': self.project_version_method, + 'version': self.version_method, 'project_name' : self.project_name_method, 'get_cross_property': self.get_cross_property_method, }) @@ -1040,6 +1075,9 @@ class MesonMain(InterpreterObject): def project_version_method(self, args, kwargs): return self.build.dep_manifest[self.interpreter.active_projectname]['version'] + def version_method(self, args, kwargs): + return coredata.version + def project_name_method(self, args, kwargs): return self.interpreter.active_projectname @@ -1810,9 +1848,12 @@ class Interpreter(): raise else: return None - dep = self.subprojects[dirname].get_variable_method([varname], {}) + try: + dep = self.subprojects[dirname].get_variable_method([varname], {}) + except KeyError: + raise InterpreterException('Fallback variable {!r} in the subproject {!r} does not exist'.format(varname, dirname)) if not isinstance(dep, (DependencyHolder, InternalDependencyHolder)): - raise InterpreterException('Fallback variable is not a dependency object.') + raise InterpreterException('Fallback variable {!r} in the subproject {!r} is not a dependency object.'.format(varname, dirname)) # Check if the version of the declared dependency matches what we want if 'version' in kwargs: wanted = kwargs['version'] @@ -2231,6 +2272,8 @@ class Interpreter(): self.coredata.target_guids[idname] = str(uuid.uuid4()).upper() def build_target(self, node, args, kwargs, targetholder): + if len(args) == 0: + raise InterpreterException('Target does not have a name.') name = args[0] sources = args[1:] if self.environment.is_cross_build(): diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index d06e4eb..7294a54 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -221,7 +221,7 @@ def do_replacement(regex, line, confdata): while match: varname = match.group(1) if varname in confdata.keys(): - var = confdata.get(varname) + (var, desc) = confdata.get(varname) if isinstance(var, str): pass elif isinstance(var, int): @@ -240,7 +240,7 @@ def do_mesondefine(line, confdata): raise MesonException('#mesondefine does not contain exactly two tokens: %s', line.strip()) varname = arr[1] try: - v = confdata.get(varname) + (v, desc) = confdata.get(varname) except KeyError: return '/* #undef %s */\n' % varname if isinstance(v, bool): @@ -289,7 +289,9 @@ def dump_conf_header(ofilename, cdata): ''') for k in sorted(cdata.keys()): - v = cdata.get(k) + (v, desc) = cdata.get(k) + if desc: + ofile.write('/* %s */\n' % desc) if isinstance(v, bool): if v: ofile.write('#define %s\n\n' % k) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 3609d2f..4f72d2f 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -45,6 +45,9 @@ class GnomeModule: if not isinstance(source_dirs, list): source_dirs = [source_dirs] + if len(args) < 2: + raise MesonException('Not enough arguments; The name of the resource and the path to the XML file are required') + ifile = args[1] if isinstance(ifile, mesonlib.File): ifile = os.path.join(ifile.subdir, ifile.fname) diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py index 4677d5f..1f0a391 100644 --- a/mesonbuild/scripts/gettext.py +++ b/mesonbuild/scripts/gettext.py @@ -19,6 +19,12 @@ from mesonbuild.scripts import destdir_join def run_potgen(src_sub, pkgname, args): listfile = os.path.join(src_sub, 'POTFILES') + if not os.path.exists(listfile): + listfile = os.path.join(src_sub, 'POTFILES.in') + if not os.path.exists(listfile): + print('Could not find file POTFILES in %s' % src_sub) + return 1 + ofile = os.path.join(src_sub, pkgname + '.pot') return subprocess.call(['xgettext', '--package-name=' + pkgname, '-p', src_sub, '-f', listfile, '-D', os.environ['MESON_SOURCE_ROOT'], '-k_', '-o', ofile] + args) diff --git a/test cases/common/118 allgenerate/converter.py b/test cases/common/118 allgenerate/converter.py new file mode 100755 index 0000000..f8e2ca0 --- /dev/null +++ b/test cases/common/118 allgenerate/converter.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys + +ifile = sys.argv[1] +ofile = sys.argv[2] + +open(ofile, 'w').write(open(ifile).read()) diff --git a/test cases/common/118 allgenerate/foobar.cpp.in b/test cases/common/118 allgenerate/foobar.cpp.in new file mode 100644 index 0000000..c64f3b5 --- /dev/null +++ b/test cases/common/118 allgenerate/foobar.cpp.in @@ -0,0 +1,6 @@ +#include<stdio.h> + +int main(int argc, char **argv) { + printf("I am a program.\n"); + return 0; +} diff --git a/test cases/common/118 allgenerate/meson.build b/test cases/common/118 allgenerate/meson.build new file mode 100644 index 0000000..1ec93e6 --- /dev/null +++ b/test cases/common/118 allgenerate/meson.build @@ -0,0 +1,20 @@ +# Must have two languages here to exercise linker language +# selection bug +project('all sources generated', 'c', 'cpp') + +comp = find_program('converter.py') + +g = generator(comp, + output : '@BASENAME@.cpp', + arguments : ['@INPUT@', '@OUTPUT@']) + +c = g.process('foobar.cpp.in') + +prog = executable('genexe', c) + +c2 = custom_target('c2gen', + output : 'c2gen.cpp', + input : 'foobar.cpp.in', + command : [comp, '@INPUT@', '@OUTPUT@']) + +prog2 = executable('genexe2', c2)
\ No newline at end of file diff --git a/test cases/common/16 configure file/meson.build b/test cases/common/16 configure file/meson.build index c00af40..ae3ad27 100644 --- a/test cases/common/16 configure file/meson.build +++ b/test cases/common/16 configure file/meson.build @@ -34,7 +34,7 @@ test('inctest2', executable('prog2', 'prog2.c')) # Generate a conf file without an input file. dump = configuration_data() -dump.set_quoted('SHOULD_BE_STRING', 'string') +dump.set_quoted('SHOULD_BE_STRING', 'string', description : 'A string') dump.set_quoted('SHOULD_BE_STRING2', 'A "B" C') dump.set_quoted('SHOULD_BE_STRING3', 'A "" C') dump.set_quoted('SHOULD_BE_STRING4', 'A " C') @@ -42,7 +42,7 @@ dump.set('SHOULD_BE_RETURN', 'return') dump.set('SHOULD_BE_DEFINED', true) dump.set('SHOULD_BE_UNDEFINED', false) dump.set('SHOULD_BE_ONE', 1) -dump.set('SHOULD_BE_ZERO', 0) +dump.set('SHOULD_BE_ZERO', 0, description : 'Absolutely zero') dump.set('SHOULD_BE_QUOTED_ONE', '"1"') configure_file(output : 'config3.h', configuration : dump) diff --git a/test cases/common/94 default options/meson.build b/test cases/common/94 default options/meson.build index 6299106..a718bcc 100644 --- a/test cases/common/94 default options/meson.build +++ b/test cases/common/94 default options/meson.build @@ -2,6 +2,7 @@ project('default options', 'cpp', 'c', default_options : [ 'buildtype=debugoptimized', 'cpp_std=c++03', 'cpp_eh=none', + 'warning_level=3', ]) cpp = meson.get_compiler('cpp') @@ -9,11 +10,16 @@ cpp = meson.get_compiler('cpp') assert(get_option('buildtype') == 'debugoptimized', 'Build type default value wrong.') if cpp.get_id() == 'msvc' - assert(get_option('cpp_eh') == 'none', 'MSVC eh value wrong.') + cpp_eh = get_option('cpp_eh') + assert(cpp_eh == 'none', 'MSVC eh value is "' + cpp_eh + '" instead of "none"') else - assert(get_option('cpp_std') == 'c++03', 'C++ std value wrong.') + cpp_std = get_option('cpp_std') + assert(cpp_std == 'c++03', 'C++ std value is "' + cpp_std + '" instead of c++03.') endif +w_level = get_option('warning_level') +assert(w_level == '3', 'warning level "' + w_level + '" instead of "3"') + # FIXME. Since we no longer accept invalid options to c_std etc, # there is no simple way to test this. Gcc does not seem to expose # the C std used in a preprocessor token so we can't check for it. diff --git a/test cases/linuxlike/9 compiler checks with dependencies/meson.build b/test cases/linuxlike/9 compiler checks with dependencies/meson.build new file mode 100644 index 0000000..2aa9015 --- /dev/null +++ b/test cases/linuxlike/9 compiler checks with dependencies/meson.build @@ -0,0 +1,31 @@ +project('compiler checks with dependencies', 'c') + +cc = meson.get_compiler('c') + +glib = dependency ('glib-2.0') +if glib.found() + assert (cc.has_header('glib.h', dependencies : glib), 'glib.h not found') + assert (cc.has_type('gint32', prefix : '#include <glib.h>', dependencies : glib), 'gint32 not found') + assert (cc.has_function('g_print', dependencies : glib), 'g_print not found') + assert (cc.has_member('GError', 'message', prefix : '#include <glib.h>', dependencies : glib), 'GError::message not found') + assert (cc.has_header_symbol('glib.h', 'gint32', dependencies : glib), 'gint32 symbol not found') + linkcode = '''#include <glib.h> +int main (int argc, char *argv[]) { + GError *error = g_error_new_literal (0, 0, NULL); + return error == NULL; +} + ''' + assert (cc.links(linkcode, dependencies : glib, name : 'Test link against glib'), 'Linking test against glib failed') +endif + +zlib = cc.find_library ('z') +if zlib.found() + linkcode = '''#include<zlib.h> +int main(int argc, char *argv[]) { + void *ptr = (void*)(deflate); + return ptr == 0; +} +''' + assert (cc.has_function('deflate', prefix : '#include<zlib.h>', dependencies : zlib, name : 'Test for function in zlib'), 'has_function test failed.') + assert (cc.links(linkcode, dependencies : zlib, name : 'Test link against zlib'), 'Linking test failed against zlib.') +endif |