diff options
44 files changed, 467 insertions, 207 deletions
diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md index 54905d5..cb7b19e 100644 --- a/docs/markdown/Build-options.md +++ b/docs/markdown/Build-options.md @@ -42,11 +42,16 @@ prefix = get_option('prefix') ``` It should be noted that you can not set option values in your Meson -scripts. They have to be set externally with the `mesonconf` command -line tool. Running `mesonconf` without arguments in a build dir shows -you all options you can set. To change their values use the `-D` +scripts. They have to be set externally with the `meson configure` command +line tool. Running `meson configure` without arguments in a build dir shows +you all options you can set. + +To change their values use the `-D` option: ```console -$ mesonconf -Doption=newvalue +$ meson configure -Doption=newvalue ``` + + +**NOTE:** If you cannot call `meson configure` you likely have a old version of Meson. In that case you can call `mesonconf` instead, but that is deprecated in newer versions diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 7afd32b..7aa4bca 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1309,9 +1309,9 @@ the following methods: - `get_id()` returns a string identifying the compiler. For example, `gcc`, `msvc`, [and more](Compiler-properties.md#compiler-id). -- `get_supported_arguments(list_of_string)` returns an array - containing only the arguments supported by the compiler, as if - `has_argument` were called on them individually. +- `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. - `has_argument(argument_name)` returns true if the compiler accepts the specified command line argument, that is, can compile code @@ -1440,7 +1440,9 @@ are immutable, all operations return their results as a new string. - `startswith(string)` returns true if string starts with the string specified as the argument -- `strip()` removes whitespace at the beginning and end of the string +- `strip()` removes whitespace at the beginning and end of the string + *(added 0.43.0)* optionally can take one positional string argument, + and all characters in that string will be stripped - `to_int` returns the string converted to an integer (error if string is not a number) @@ -1511,7 +1513,10 @@ A build target is either an [executable](#executable), files with custom flags. To use the object file(s) in another build target, use the `objects:` keyword argument. -- `full_path()` returns a full path pointing to the result target file +- `full_path()` returns a full path pointing to the result target file. + NOTE: In most cases using the object itself will do the same job as + this and will also allow Meson to setup inter-target dependencies + correctly. Please file a bug if that doesn't work for you. - `private_dir_include()` returns a opaque value that works like `include_directories` but points to the private directory of this @@ -1557,7 +1562,10 @@ cause a syntax error. This object is returned by [`custom_target`](#custom_target) and contains a target with the following methods: -- `full_path()` returns a full path pointing to the result target file +- `full_path()` returns a full path pointing to the result target file + NOTE: In most cases using the object itself will do the same job as + this and will also allow Meson to setup inter-target dependencies + correctly. Please file a bug if that doesn't work for you. ### `dependency` object diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md index 7949522..6ded714 100644 --- a/docs/markdown/Unit-tests.md +++ b/docs/markdown/Unit-tests.md @@ -57,42 +57,42 @@ Sometimes a test can only determine at runtime that it can not be run. The GNU s ## Testing tool -In version 0.37.0 a new tool called `mesontest` was added. The goal of this tool is to provide a simple way to run tests in a variety of different ways. The tool is designed to be run in the build directory. +The goal of the meson test tool is to provide a simple way to run tests in a variety of different ways. The tool is designed to be run in the build directory. The simplest thing to do is just to run all tests, which is equivalent to running `ninja test`. ```console -$ mesontest +$ meson test ``` You can also run only a single test by giving its name: ```console -$ mesontest testname +$ meson test testname ``` Sometimes you need to run the tests multiple times, which is done like this: ```console -$ mesontest --repeat=10 +$ meson test --repeat=10 ``` Invoking tests via a helper executable such as Valgrind can be done with the `--wrap` argument ```console -$ mesontest --wrap=valgrind testname +$ meson test --wrap=valgrind testname ``` Arguments to the wrapper binary can be given like this: ```console -$ mesontest --wrap='valgrind --tool=helgrind' testname +$ meson test --wrap='valgrind --tool=helgrind' testname ``` Meson also supports running the tests under GDB. Just doing this: ```console -$ mesontest --gdb testname +$ meson test --gdb testname ``` Mesontest will launch `gdb` all set up to run the test. Just type `run` in the GDB command prompt to start the program. @@ -100,9 +100,11 @@ Mesontest will launch `gdb` all set up to run the test. Just type `run` in the G The second use case is a test that segfaults only rarely. In this case you can invoke the following command: ```console -$ mesontest --gdb --repeat=10000 testname +$ meson test --gdb --repeat=10000 testname ``` This runs the test up to 10 000 times under GDB automatically. If the program crashes, GDB will halt and the user can debug the application. Note that testing timeouts are disabled in this case so mesontest will not kill `gdb` while the developer is still debugging it. The downside is that if the test binary freezes, the test runner will wait forever. For further information see the command line help of Mesontest by running `mesontest -h`. + +**NOTE:** If `meson test` does not work for you, you likely have a old version of Meson. In that case you should call `mesontest` instead. If `mesontest` doesn't work either you have a very old version prior to 0.37.0 and should upgrade. diff --git a/docs/markdown/i18n-module.md b/docs/markdown/i18n-module.md index 5e6004a..1144e29 100644 --- a/docs/markdown/i18n-module.md +++ b/docs/markdown/i18n-module.md @@ -32,6 +32,8 @@ argument which is the name of the gettext module. [source](https://github.com/mesonbuild/meson/blob/master/mesonbuild/modules/i18n.py) for for their value +* `install`: (*Added 0.43.0*) if false, do not install the built translations. + This function also defines targets for maintainers to use: **Note**: These output to the source directory @@ -14,6 +14,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +# ghwt - GitHub WrapTool +# +# An emergency wraptool(1) replacement downloader that downloads +# directly from GitHub in case wrapdb.mesonbuild.com is down. + import urllib.request, json, sys, os, shutil, subprocess import configparser, hashlib @@ -24,7 +24,7 @@ def main(): # encoding, so we can just warn about it. e = locale.getpreferredencoding() if e.upper() != 'UTF-8' and not mesonlib.is_windows(): - print('Warning: You are using {!r} which is not a a Unicode-compatible ' + print('Warning: You are using {!r} which is not a Unicode-compatible ' 'locale.'.format(e), file=sys.stderr) print('You might see errors if you use UTF-8 strings as ' 'filenames, as strings, or as file contents.', file=sys.stderr) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 7088c1e..41b93cb 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os, pickle, re, shlex, shutil, subprocess, sys +import os, pickle, re, shlex, subprocess, sys from collections import OrderedDict from . import backends @@ -83,10 +83,9 @@ class NinjaBuildElement: def write(self, outfile): self.check_outputs() - line = 'build %s: %s %s' % ( - ' '.join([ninja_quote(i) for i in self.outfilenames]), - self.rule, - ' '.join([ninja_quote(i) for i in self.infilenames])) + line = 'build %s: %s %s' % (' '.join([ninja_quote(i) for i in self.outfilenames]), + self.rule, + ' '.join([ninja_quote(i) for i in self.infilenames])) if len(self.deps) > 0: line += ' | ' + ' '.join([ninja_quote(x) for x in self.deps]) if len(self.orderdeps) > 0: @@ -721,8 +720,7 @@ int dummy; # On toolchains/platforms that use an import library for # linking (separate from the shared library with all the # code), we need to install that too (dll.a/.lib). - if (isinstance(t, build.SharedLibrary) or - isinstance(t, build.Executable)) and t.get_import_filename(): + if (isinstance(t, build.SharedLibrary) or isinstance(t, build.Executable)) and t.get_import_filename(): if custom_install_dir: # If the DLL is installed into a custom directory, # install the import library into the same place so @@ -856,8 +854,9 @@ int dummy; self.create_target_alias('meson-test', outfile) # And then benchmarks. - cmd = self.environment.get_build_command(True) + ['test', '--benchmark', '--logbase', - 'benchmarklog', '--num-processes=1', '--no-rebuild'] + cmd = self.environment.get_build_command(True) + [ + 'test', '--benchmark', '--logbase', + 'benchmarklog', '--num-processes=1', '--no-rebuild'] elem = NinjaBuildElement(self.all_outputs, 'meson-benchmark', 'CUSTOM_COMMAND', ['all', 'PHONY']) elem.add_item('COMMAND', cmd) elem.add_item('DESC', 'Running benchmark suite.') @@ -1576,9 +1575,10 @@ int dummy; def generate_swift_compile_rules(self, compiler, outfile): rule = 'rule %s_COMPILER\n' % compiler.get_language() full_exe = [ninja_quote(x) for x in self.environment.get_build_command()] + [ - '--internal', - 'dirchanger', - '$RUNDIR'] + '--internal', + 'dirchanger', + '$RUNDIR', + ] invoc = (' '.join(full_exe) + ' ' + ' '.join(ninja_quote(i) for i in compiler.get_exelist())) command = ' command = %s $ARGS $in\n' % invoc @@ -1784,7 +1784,6 @@ rule FORTRAN_DEP_HACK exe_arr = self.exe_object_to_cmd_array(exe) infilelist = genlist.get_inputs() outfilelist = genlist.get_outputs() - base_args = generator.get_arglist() extra_dependencies = [os.path.join(self.build_to_src, i) for i in genlist.extra_depends] source_target_dir = self.get_target_source_dir(target) for i in range(len(infilelist)): @@ -1794,6 +1793,7 @@ rule FORTRAN_DEP_HACK sole_output = '' curfile = infilelist[i] infilename = curfile.rel_to_builddir(self.build_to_src) + base_args = generator.get_arglist(infilename) outfiles = genlist.get_outputs_for(curfile) outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles] if generator.depfile is None: @@ -1818,7 +1818,7 @@ rule FORTRAN_DEP_HACK elem.add_item('DEPFILE', depfile) if len(extra_dependencies) > 0: elem.add_dep(extra_dependencies) - elem.add_item('DESC', 'Generating $out') + elem.add_item('DESC', 'Generating {!r}.'.format(sole_output)) if isinstance(exe, build.BuildTarget): elem.add_dep(self.get_target_filename(exe)) elem.add_item('COMMAND', cmdlist) @@ -2527,10 +2527,11 @@ rule FORTRAN_DEP_HACK def generate_dist(self, outfile): elem = NinjaBuildElement(self.all_outputs, 'meson-dist', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('DESC', 'Creating source packages') - elem.add_item('COMMAND', self.environment.get_build_command() + - ['--internal', 'dist', - self.environment.source_dir, - self.environment.build_dir] + self.environment.get_build_command()) + elem.add_item('COMMAND', self.environment.get_build_command() + [ + '--internal', 'dist', + self.environment.source_dir, + self.environment.build_dir, + ] + self.environment.get_build_command()) elem.add_item('pool', 'console') elem.write(outfile) # Alias that runs the target defined above diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 0bbc17c..22c1779 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -22,7 +22,6 @@ from .. import build from .. import dependencies from .. import mlog from .. import compilers -from ..build import BuildTarget from ..compilers import CompilerArgs from ..mesonlib import MesonException, File from ..environment import Environment @@ -106,7 +105,6 @@ class Vs2010Backend(backends.Backend): infilelist = genlist.get_inputs() outfilelist = genlist.get_outputs() exe_arr = self.exe_object_to_cmd_array(exe) - base_args = generator.get_arglist() idgroup = ET.SubElement(parent_node, 'ItemGroup') for i in range(len(infilelist)): if len(infilelist) == len(outfilelist): @@ -115,6 +113,7 @@ class Vs2010Backend(backends.Backend): sole_output = '' curfile = infilelist[i] infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src)) + base_args = generator.get_arglist(infilename) outfiles_rel = genlist.get_outputs_for(curfile) outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel] generator_output_files += outfiles @@ -383,8 +382,7 @@ class Vs2010Backend(backends.Backend): cmd = [sys.executable, os.path.join(self.environment.get_script_dir(), 'commandrunner.py'), self.environment.get_build_dir(), self.environment.get_source_dir(), - self.get_target_dir(target)] + \ - self.environment.get_build_command() + self.get_target_dir(target)] + self.environment.get_build_command() for i in cmd_raw: if isinstance(i, build.BuildTarget): cmd.append(os.path.join(self.environment.get_build_dir(), self.get_target_filename(i))) @@ -926,8 +924,7 @@ class Vs2010Backend(backends.Backend): ofile.text = '$(OutDir)%s' % target.get_filename() subsys = ET.SubElement(link, 'SubSystem') subsys.text = subsystem - if (isinstance(target, build.SharedLibrary) or - isinstance(target, build.Executable)) and target.get_import_filename(): + if (isinstance(target, build.SharedLibrary) or isinstance(target, build.Executable)) and target.get_import_filename(): # DLLs built with MSVC always have an import library except when # they're data-only DLLs, but we don't support those yet. ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename() diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 281b060..c54abbd 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -359,6 +359,7 @@ class BuildTarget(Target): self.check_unknown_kwargs(kwargs) if not self.sources and not self.generated and not self.objects: raise InvalidArguments('Build target %s has no sources.' % name) + self.process_compilers_late() self.validate_sources() self.validate_cross_install(environment) @@ -439,6 +440,39 @@ class BuildTarget(Target): removed = True return removed + def process_compilers_late(self): + """Processes additional compilers after kwargs have been evaluated. + + This can add extra compilers that might be required by keyword + arguments, such as link_with or dependencies. It will also try to guess + which compiler to use if one hasn't been selected already. + """ + # Populate list of compilers + if self.is_cross: + compilers = self.environment.coredata.cross_compilers + else: + compilers = self.environment.coredata.compilers + + # If this library is linked against another library we need to consider + # the languages of those libraries as well. + if self.link_targets or self.link_whole_targets: + extra = set() + for t in itertools.chain(self.link_targets, self.link_whole_targets): + for name, compiler in t.compilers.items(): + if name in clike_langs: + extra.add((name, compiler)) + for name, compiler in sorted(extra, key=lambda p: sort_clike(p[0])): + self.compilers[name] = compiler + + if not self.compilers: + # No source files or parent targets, target consists of only object + # files of unknown origin. Just add the first clike compiler + # that we have and hope that it can link these objects + for lang in clike_langs: + if lang in compilers: + self.compilers[lang] = compilers[lang] + break + def process_compilers(self): ''' Populate self.compilers, which is the list of compilers that this @@ -487,14 +521,7 @@ class BuildTarget(Target): # 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 - # that it can link these objects - for lang in clike_langs: - if lang in compilers: - self.compilers[lang] = compilers[lang] - break + # If all our sources are Vala, our target also needs the C compiler but # it won't get added above. if 'vala' in self.compilers and 'c' not in self.compilers: @@ -1048,8 +1075,10 @@ class Generator: basename = os.path.splitext(plainname)[0] return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) - def get_arglist(self): - return self.arglist + def get_arglist(self, inname): + plainname = os.path.split(inname)[1] + basename = os.path.splitext(plainname)[0] + return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist] def process_files(self, name, files, state, extra_args=[]): output = GeneratedList(self, extra_args=extra_args) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 255a506..82b1ef0 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -482,6 +482,34 @@ class CCompiler(Compiler): # minus the extra newline at the end return p.stdo.split(delim + '\n')[-1][:-1] + def get_return_value(self, fname, rtype, prefix, env, extra_args, dependencies): + if rtype == 'string': + fmt = '%s' + cast = '(char*)' + elif rtype == 'int': + fmt = '%lli' + cast = '(long long int)' + else: + raise AssertionError('BUG: Unknown return type {!r}'.format(rtype)) + fargs = {'prefix': prefix, 'f': fname, 'cast': cast, 'fmt': fmt} + code = '''{prefix} + #include <stdio.h> + int main(int argc, char *argv[]) {{ + printf ("{fmt}", {cast} {f}()); + }}'''.format(**fargs) + res = self.run(code, env, extra_args, dependencies) + if not res.compiled: + m = 'Could not get return value of {}()' + raise EnvironmentException(m.format(fname)) + if rtype == 'string': + return res.stdout + elif rtype == 'int': + try: + return int(res.stdout.strip()) + except: + m = 'Return value of {}() is not an int' + raise EnvironmentException(m.format(fname)) + @staticmethod def _no_prototype_templ(): """ @@ -896,6 +924,9 @@ class VisualStudioCCompiler(CCompiler): def get_linker_search_args(self, dirname): return ['/LIBPATH:' + dirname] + def get_gui_app_args(self): + return ['/SUBSYSTEM:WINDOWS'] + def get_pic_args(self): return [] # PIC is handled by the loader on Windows @@ -1025,5 +1056,3 @@ class VisualStudioCCompiler(CCompiler): # and the can not be called. return None return vs32_instruction_set_args.get(instruction_set, None) - - diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index c431194..89208e0 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -252,7 +252,7 @@ vs32_instruction_set_args = {'mmx': ['/arch:SSE'], # There does not seem to be a 'avx': ['/arch:AVX'], 'avx2': ['/arch:AVX2'], 'neon': None, -} + } # The 64 bit compiler defaults to /arch:avx. vs64_instruction_set_args = {'mmx': ['/arch:AVX'], diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index c0ac5a8..c2b6dbd 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -575,6 +575,7 @@ class Python3Dependency(ExternalDependency): else: return [DependencyMethods.PKGCONFIG] + class PcapDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('pcap', environment, None, kwargs) @@ -598,23 +599,12 @@ class PcapDependency(ExternalDependency): self.compile_args = stdo.strip().split() stdo = Popen_safe(['pcap-config', '--libs'])[1] self.link_args = stdo.strip().split() - self.version = '0' + self.version = self.get_pcap_lib_version() self.is_found = True mlog.log('Dependency', mlog.bold('pcap'), 'found:', mlog.green('YES'), '(%s)' % pcapconf) return mlog.debug('Could not find pcap-config binary, trying next.') - if DependencyMethods.EXTRAFRAMEWORK in self.methods: - if mesonlib.is_osx(): - fwdep = ExtraFrameworkDependency('pcap', False, None, self.env, - self.language, kwargs) - if fwdep.found(): - self.is_found = True - self.compile_args = fwdep.get_compile_args() - self.link_args = fwdep.get_link_args() - self.version = '2' # FIXME - return - mlog.log('Dependency', mlog.bold('pcap'), 'found:', mlog.red('NO')) def get_methods(self): if mesonlib.is_osx(): @@ -622,6 +612,11 @@ class PcapDependency(ExternalDependency): else: return [DependencyMethods.PKGCONFIG, DependencyMethods.PCAPCONFIG] + def get_pcap_lib_version(self): + return self.compiler.get_return_value('pcap_lib_version', 'string', + '#include <pcap.h>', self.env, [], [self]) + + class CupsDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('cups', environment, None, kwargs) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 69c49c2..2148bed 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -881,7 +881,7 @@ class CompilerHolder(InterpreterObject): extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) value = self.compiler.get_define(element, prefix, self.environment, extra_args, deps) - mlog.log('Checking for value of define "%s": %s' % (element, value)) + mlog.log('Fetching value of define "%s": %s' % (element, value)) return value def compiles_method(self, args, kwargs): @@ -1028,7 +1028,6 @@ class CompilerHolder(InterpreterObject): h) return result - def first_supported_argument_method(self, args, kwargs): for i in mesonlib.stringlistify(args): if self.compiler.has_argument(i, self.environment): @@ -1245,48 +1244,50 @@ class MesonMain(InterpreterObject): pch_kwargs = set(['c_pch', 'cpp_pch']) -lang_arg_kwargs = set(['c_args', - 'cpp_args', - 'd_args', - 'd_import_dirs', - 'd_unittest', - 'd_module_versions', - 'fortran_args', - 'java_args', - 'objc_args', - 'objcpp_args', - 'rust_args', - 'vala_args', - 'cs_args', - ]) +lang_arg_kwargs = set([ + 'c_args', + 'cpp_args', + 'd_args', + 'd_import_dirs', + 'd_unittest', + 'd_module_versions', + 'fortran_args', + 'java_args', + 'objc_args', + 'objcpp_args', + 'rust_args', + 'vala_args', + 'cs_args', +]) vala_kwargs = set(['vala_header', 'vala_gir', 'vala_vapi']) rust_kwargs = set(['rust_crate_type']) -cs_kwargs = set(['resources']) - -buildtarget_kwargs = set(['build_by_default', - 'build_rpath', - 'dependencies', - 'extra_files', - 'gui_app', - 'link_with', - 'link_whole', - 'link_args', - 'link_depends', - 'implicit_include_directories', - 'include_directories', - 'install', - 'install_rpath', - 'install_dir', - 'name_prefix', - 'name_suffix', - 'native', - 'objects', - 'override_options', - 'pic', - 'sources', - 'vs_module_defs', - ]) +cs_kwargs = set(['resources', 'cs_args']) + +buildtarget_kwargs = set([ + 'build_by_default', + 'build_rpath', + 'dependencies', + 'extra_files', + 'gui_app', + 'link_with', + 'link_whole', + 'link_args', + 'link_depends', + 'implicit_include_directories', + 'include_directories', + 'install', + 'install_rpath', + 'install_dir', + 'name_prefix', + 'name_suffix', + 'native', + 'objects', + 'override_options', + 'pic', + 'sources', + 'vs_module_defs', +]) build_target_common_kwargs = ( buildtarget_kwargs | @@ -2013,11 +2014,11 @@ class Interpreter(InterpreterBase): if not isinstance(use_native, bool): raise InvalidArguments('Argument to "native" must be a boolean.') if not use_native: - progobj = self.program_from_cross_file(args) + progobj = self.program_from_cross_file(args) if progobj is None: progobj = self.program_from_system(args) if required and (progobj is None or not progobj.found()): - raise InvalidArguments('Program "%s" not found or not executable' % exename) + raise InvalidArguments('Program "%s" not found or not executable' % args[0]) if progobj is None: return ExternalProgramHolder(dependencies.ExternalProgram('nonexistingprogram')) return progobj diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index d2e2ab3..1dd2f02 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -450,9 +450,25 @@ class InterpreterBase: else: raise InterpreterException('Unknown method "%s" for an integer.' % method_name) + @staticmethod + def _get_one_string_posarg(posargs, method_name): + if len(posargs) > 1: + m = '{}() must have zero or one arguments' + raise InterpreterException(m.format(method_name)) + elif len(posargs) == 1: + s = posargs[0] + if not isinstance(s, str): + m = '{}() argument must be a string' + raise InterpreterException(m.format(method_name)) + return s + return None + def string_method_call(self, obj, method_name, args): (posargs, _) = self.reduce_arguments(args) if method_name == 'strip': + s = self._get_one_string_posarg(posargs, 'strip') + if s is not None: + return obj.strip(s) return obj.strip() elif method_name == 'format': return self.format_string(obj, args) @@ -463,15 +479,10 @@ class InterpreterBase: elif method_name == 'underscorify': return re.sub(r'[^a-zA-Z0-9]', '_', obj) elif method_name == 'split': - if len(posargs) > 1: - raise InterpreterException('Split() must have at most one argument.') - elif len(posargs) == 1: - s = posargs[0] - if not isinstance(s, str): - raise InterpreterException('Split() argument must be a string') + s = self._get_one_string_posarg(posargs, 'split') + if s is not None: return obj.split(s) - else: - return obj.split() + return obj.split() elif method_name == 'startswith' or method_name == 'contains' or method_name == 'endswith': s = posargs[0] if not isinstance(s, str): diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 1657ddd..45e6026 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -122,11 +122,11 @@ class MesonApp: if os.path.exists(priv_dir): if not handshake: print('Directory already configured, exiting Meson. Just run your build command\n' - '(e.g. ninja) and Meson will regenerate as necessary. If ninja fails, run ninja\n' - 'reconfigure to force Meson to regenerate.\n' - '\nIf build failures persist, manually wipe your build directory to clear any\n' - 'stored system data.\n' - '\nTo change option values, run meson configure instead.') + '(e.g. ninja) and Meson will regenerate as necessary. If ninja fails, run ninja\n' + 'reconfigure to force Meson to regenerate.\n' + '\nIf build failures persist, manually wipe your build directory to clear any\n' + 'stored system data.\n' + '\nTo change option values, run meson configure instead.') sys.exit(0) else: if handshake: diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 8b5b210..364bc45 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -4,7 +4,6 @@ from .. import build from .. import dependencies from .. import mlog from ..mesonlib import MesonException -from ..interpreterbase import permittedKwargs, noKwargs class permittedSnippetKwargs: diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 137d380..1ab075b 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -17,7 +17,6 @@ functionality such as gobject-introspection, gresources and gtk-doc''' from .. import build import os -import sys import copy import subprocess from . import ModuleReturnValue @@ -30,7 +29,7 @@ from .. import interpreter from . import GResourceTarget, GResourceHeaderTarget, GirTarget, TypelibTarget, VapiTarget from . import find_program, get_include_args from . import ExtensionModule -from . import noKwargs, permittedKwargs +from ..interpreterbase import noKwargs, permittedKwargs # gresource compilation is broken due to the way # the resource compiler and Ninja clash about it @@ -697,18 +696,22 @@ This will become a hard error in the future.''') args.append('--langs=' + '@@'.join(langs)) inscript = build.RunScript(script, args) - potargs = state.environment.get_build_command() + ['--internal', 'yelphelper', 'pot', - '--subdir=' + state.subdir, - '--id=' + project_id, - '--sources=' + source_str] + potargs = state.environment.get_build_command() + [ + '--internal', 'yelphelper', 'pot', + '--subdir=' + state.subdir, + '--id=' + project_id, + '--sources=' + source_str, + ] pottarget = build.RunTarget('help-' + project_id + '-pot', potargs[0], potargs[1:], [], state.subdir) - poargs = state.environment.get_build_command() + ['--internal', 'yelphelper', 'update-po', - '--subdir=' + state.subdir, - '--id=' + project_id, - '--sources=' + source_str, - '--langs=' + '@@'.join(langs)] + poargs = state.environment.get_build_command() + [ + '--internal', 'yelphelper', 'update-po', + '--subdir=' + state.subdir, + '--id=' + project_id, + '--sources=' + source_str, + '--langs=' + '@@'.join(langs), + ] potarget = build.RunTarget('help-' + project_id + '-update-po', poargs[0], poargs[1:], [], state.subdir) diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index 2af09de..c1dd837 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys import shutil from os import path @@ -20,7 +19,7 @@ from .. import coredata, mesonlib, build from ..mesonlib import MesonException from . import ModuleReturnValue from . import ExtensionModule -from . import permittedKwargs +from ..interpreterbase import permittedKwargs PRESET_ARGS = { 'glib': [ @@ -72,8 +71,10 @@ class I18nModule(ExtensionModule): datadirs = self._get_data_dirs(state, mesonlib.stringlistify(kwargs.pop('data_dirs', []))) datadirs = '--datadirs=' + ':'.join(datadirs) if datadirs else None - command = state.environment.get_build_command() + ['--internal', 'msgfmthelper', - '@INPUT@', '@OUTPUT@', file_type, podir] + command = state.environment.get_build_command() + [ + '--internal', 'msgfmthelper', + '@INPUT@', '@OUTPUT@', file_type, podir + ] if datadirs: command.append(datadirs) @@ -81,7 +82,7 @@ class I18nModule(ExtensionModule): ct = build.CustomTarget(kwargs['output'] + '_merge', state.subdir, kwargs) return ModuleReturnValue(ct, [ct]) - @permittedKwargs({'po_dir', 'data_dirs', 'type', 'languages', 'args', 'preset'}) + @permittedKwargs({'po_dir', 'data_dirs', 'type', 'languages', 'args', 'preset', 'install'}) def gettext(self, state, args, kwargs): if len(args) != 1: raise coredata.MesonException('Gettext requires one positional argument (package name).') @@ -126,16 +127,21 @@ class I18nModule(ExtensionModule): updatepoargs.append(extra_args) updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs[0], updatepoargs[1:], [], state.subdir) - script = state.environment.get_build_command() - args = ['--internal', 'gettext', 'install', - '--subdir=' + state.subdir, - '--localedir=' + state.environment.coredata.get_builtin_option('localedir'), - pkg_arg] - if lang_arg: - args.append(lang_arg) - iscript = build.RunScript(script, args) - - return ModuleReturnValue(None, [pottarget, gmotarget, iscript, updatepotarget]) + targets = [pottarget, gmotarget, updatepotarget] + + install = kwargs.get('install', True) + if install: + script = state.environment.get_build_command() + args = ['--internal', 'gettext', 'install', + '--subdir=' + state.subdir, + '--localedir=' + state.environment.coredata.get_builtin_option('localedir'), + pkg_arg] + if lang_arg: + args.append(lang_arg) + iscript = build.RunScript(script, args) + targets.append(iscript) + + return ModuleReturnValue(None, targets) def initialize(): return I18nModule() diff --git a/mesonbuild/modules/modtest.py b/mesonbuild/modules/modtest.py index dd2f215..758eeae 100644 --- a/mesonbuild/modules/modtest.py +++ b/mesonbuild/modules/modtest.py @@ -14,7 +14,7 @@ from . import ModuleReturnValue from . import ExtensionModule -from . import noKwargs +from ..interpreterbase import noKwargs class TestModule(ExtensionModule): diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 824ba78..aaed820 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -19,7 +19,7 @@ from .. import mesonlib from .. import mlog from . import ModuleReturnValue from . import ExtensionModule -from . import permittedKwargs +from ..interpreterbase import permittedKwargs class PkgConfigModule(ExtensionModule): diff --git a/mesonbuild/modules/python3.py b/mesonbuild/modules/python3.py index 94db75c..4fae88b 100644 --- a/mesonbuild/modules/python3.py +++ b/mesonbuild/modules/python3.py @@ -18,7 +18,8 @@ from .. import mesonlib, dependencies from . import ExtensionModule from mesonbuild.modules import ModuleReturnValue -from . import noKwargs, permittedSnippetKwargs +from . import permittedSnippetKwargs +from ..interpreterbase import noKwargs from ..interpreter import shlib_kwargs mod_kwargs = set() diff --git a/mesonbuild/modules/qt4.py b/mesonbuild/modules/qt4.py index 37e630b..a63aff8 100644 --- a/mesonbuild/modules/qt4.py +++ b/mesonbuild/modules/qt4.py @@ -20,7 +20,7 @@ from ..dependencies import Qt4Dependency from . import ExtensionModule import xml.etree.ElementTree as ET from . import ModuleReturnValue -from . import permittedKwargs +from ..interpreterbase import permittedKwargs class Qt4Module(ExtensionModule): tools_detected = False diff --git a/mesonbuild/modules/qt5.py b/mesonbuild/modules/qt5.py index ef3d52f..08ce662 100644 --- a/mesonbuild/modules/qt5.py +++ b/mesonbuild/modules/qt5.py @@ -20,7 +20,7 @@ from ..dependencies import Qt5Dependency from . import ExtensionModule import xml.etree.ElementTree as ET from . import ModuleReturnValue -from . import permittedKwargs +from ..interpreterbase import permittedKwargs class Qt5Module(ExtensionModule): tools_detected = False diff --git a/mesonbuild/modules/rpm.py b/mesonbuild/modules/rpm.py index b0a8db9..dbb01f7 100644 --- a/mesonbuild/modules/rpm.py +++ b/mesonbuild/modules/rpm.py @@ -22,7 +22,7 @@ from .. import mlog from . import GirTarget, TypelibTarget from . import ModuleReturnValue from . import ExtensionModule -from . import noKwargs +from ..interpreterbase import noKwargs import os diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index ab215dc..c16d7a8 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -20,7 +20,7 @@ from ..mesonlib import MesonException, extract_as_list from . import get_include_args from . import ModuleReturnValue from . import ExtensionModule -from . import permittedKwargs +from ..interpreterbase import permittedKwargs class WindowsModule(ExtensionModule): diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index b88c5ef..b88c5ef 100755..100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py index f978be4..985b0e9 100644 --- a/mesonbuild/scripts/meson_install.py +++ b/mesonbuild/scripts/meson_install.py @@ -227,7 +227,9 @@ def install_man(d): if outfilename.endswith('.gz') and not full_source_filename.endswith('.gz'): with open(outfilename, 'wb') as of: with open(full_source_filename, 'rb') as sf: - of.write(gzip.compress(sf.read())) + # Set mtime and filename for reproducibility. + with gzip.GzipFile(fileobj=of, mode='wb', filename='', mtime=0) as gz: + gz.write(sf.read()) shutil.copystat(full_source_filename, outfilename) append_to_log(outfilename) else: diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index ac84d0e..14529ab 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -14,7 +14,7 @@ from .. import mlog import contextlib -import urllib.request, os, hashlib, shutil +import urllib.request, os, hashlib, shutil, tempfile, stat import subprocess import sys from pathlib import Path @@ -230,6 +230,8 @@ class Resolver: def get_data(self, url): blocksize = 10 * 1024 + h = hashlib.sha256() + tmpfile = tempfile.NamedTemporaryFile(mode='wb', dir=self.cachedir, delete=False) if url.startswith('https://wrapdb.mesonbuild.com'): resp = open_wrapdburl(url) else: @@ -241,26 +243,34 @@ class Resolver: dlsize = None if dlsize is None: print('Downloading file of unknown size.') - return resp.read() + while True: + block = resp.read(blocksize) + if block == b'': + break + h.update(block) + tmpfile.write(block) + hashvalue = h.hexdigest() + return hashvalue, tmpfile.name print('Download size:', dlsize) print('Downloading: ', end='') sys.stdout.flush() printed_dots = 0 - blocks = [] downloaded = 0 while True: block = resp.read(blocksize) if block == b'': break downloaded += len(block) - blocks.append(block) + h.update(block) + tmpfile.write(block) ratio = int(downloaded / dlsize * 10) while printed_dots < ratio: print('.', end='') sys.stdout.flush() printed_dots += 1 print('') - return b''.join(blocks) + hashvalue = h.hexdigest() + return hashvalue, tmpfile.name def get_hash(self, data): h = hashlib.sha256() @@ -272,34 +282,51 @@ class Resolver: ofname = os.path.join(self.cachedir, p.get('source_filename')) if os.path.exists(ofname): mlog.log('Using', mlog.bold(packagename), 'from cache.') - return - srcurl = p.get('source_url') - mlog.log('Downloading', mlog.bold(packagename), 'from', mlog.bold(srcurl)) - srcdata = self.get_data(srcurl) - dhash = self.get_hash(srcdata) - expected = p.get('source_hash') - if dhash != expected: - raise RuntimeError('Incorrect hash for source %s:\n %s expected\n %s actual.' % (packagename, expected, dhash)) - with open(ofname, 'wb') as f: - f.write(srcdata) + else: + srcurl = p.get('source_url') + mlog.log('Downloading', mlog.bold(packagename), 'from', mlog.bold(srcurl)) + dhash, tmpfile = self.get_data(srcurl) + expected = p.get('source_hash') + if dhash != expected: + os.remove(tmpfile) + raise RuntimeError('Incorrect hash for source %s:\n %s expected\n %s actual.' % (packagename, expected, dhash)) + os.rename(tmpfile, ofname) if p.has_patch(): purl = p.get('patch_url') mlog.log('Downloading patch from', mlog.bold(purl)) - pdata = self.get_data(purl) - phash = self.get_hash(pdata) + phash, tmpfile = self.get_data(purl) expected = p.get('patch_hash') if phash != expected: + os.remove(tmpfile) raise RuntimeError('Incorrect hash for patch %s:\n %s expected\n %s actual' % (packagename, expected, phash)) filename = os.path.join(self.cachedir, p.get('patch_filename')) - with open(filename, 'wb') as f: - f.write(pdata) + os.rename(tmpfile, filename) else: mlog.log('Package does not require patch.') + def copy_tree(self, root_src_dir, root_dst_dir): + """ + Copy directory tree. Overwrites also read only files. + """ + for src_dir, dirs, files in os.walk(root_src_dir): + dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1) + if not os.path.exists(dst_dir): + os.makedirs(dst_dir) + for file_ in files: + src_file = os.path.join(src_dir, file_) + dst_file = os.path.join(dst_dir, file_) + if os.path.exists(dst_file): + try: + os.remove(dst_file) + except PermissionError as exc: + os.chmod(dst_file, stat.S_IWUSR) + os.remove(dst_file) + shutil.copy2(src_file, dst_dir) + def extract_package(self, package): if sys.version_info < (3, 5): try: - import lzma + import lzma # noqa: F401 del lzma except ImportError: pass @@ -322,4 +349,9 @@ class Resolver: pass shutil.unpack_archive(os.path.join(self.cachedir, package.get('source_filename')), extract_dir) if package.has_patch(): - shutil.unpack_archive(os.path.join(self.cachedir, package.get('patch_filename')), self.subdir_root) + try: + shutil.unpack_archive(os.path.join(self.cachedir, package.get('patch_filename')), self.subdir_root) + except Exception: + with tempfile.TemporaryDirectory() as workdir: + shutil.unpack_archive(os.path.join(self.cachedir, package.get('patch_filename')), workdir) + self.copy_tree(workdir, self.subdir_root) diff --git a/mesonrewriter.py b/mesonrewriter.py index 426d878..e6f2637 100755 --- a/mesonrewriter.py +++ b/mesonrewriter.py @@ -23,11 +23,10 @@ # - move targets # - reindent? -from mesonbuild import mesonmain, mlog +from mesonbuild import mesonmain import sys if __name__ == '__main__': print('Warning: This executable is deprecated. Use "meson rewrite" instead.', file=sys.stderr) sys.exit(mesonmain.run(['rewrite'] + sys.argv[1:])) - diff --git a/msi/License.rtf b/msi/License.rtf index 9b58df9..9b58df9 100755..100644 --- a/msi/License.rtf +++ b/msi/License.rtf diff --git a/msi/createmsi.py b/msi/createmsi.py index 13b4081..dd92e50 100755 --- a/msi/createmsi.py +++ b/msi/createmsi.py @@ -56,7 +56,7 @@ class PackageGenerator: 'Title': 'Meson', 'Description': 'Meson executables', 'Level': '1', - 'Absent': 'disallow', + 'Absent': 'disallow', }, self.staging_dirs[1]: { 'Id': 'NinjaProgram', @@ -109,7 +109,7 @@ class PackageGenerator: 'Language': '1033', 'Codepage': '1252', 'Version': self.version, - }) + }) package = ET.SubElement(product, 'Package', { 'Id': '*', @@ -121,7 +121,7 @@ class PackageGenerator: 'Languages': '1033', 'Compressed': 'yes', 'SummaryCodepage': '1252', - }) + }) if self.bytesize == 64: package.set('Platform', 'x64') @@ -129,25 +129,26 @@ class PackageGenerator: 'Id': '1', 'Cabinet': 'meson.cab', 'EmbedCab': 'yes', - }) + }) targetdir = ET.SubElement(product, 'Directory', { 'Id': 'TARGETDIR', 'Name': 'SourceDir', - }) + }) progfiledir = ET.SubElement(targetdir, 'Directory', { - 'Id' : self.progfile_dir, - }) + 'Id': self.progfile_dir, + }) installdir = ET.SubElement(progfiledir, 'Directory', { 'Id': 'INSTALLDIR', - 'Name': 'Meson'}) + 'Name': 'Meson', + }) ET.SubElement(product, 'Property', { 'Id': 'WIXUI_INSTALLDIR', 'Value': 'INSTALLDIR', - }) + }) ET.SubElement(product, 'UIRef', { 'Id': 'WixUI_FeatureTree', - }) + }) for sd in self.staging_dirs: assert(os.path.isdir(sd)) top_feature = ET.SubElement(product, 'Feature', { @@ -157,7 +158,7 @@ class PackageGenerator: 'Display': 'expand', 'Level': '1', 'ConfigurableDirectory': 'INSTALLDIR', - }) + }) for sd in self.staging_dirs: nodes = {} for root, dirs, files in os.walk(sd): @@ -165,7 +166,7 @@ class PackageGenerator: nodes[root] = cur_node self.create_xml(nodes, sd, installdir, sd) self.build_features(nodes, top_feature, sd) - ET.ElementTree(self.root).write(self.main_xml, encoding='utf-8',xml_declaration=True) + ET.ElementTree(self.root).write(self.main_xml, encoding='utf-8', xml_declaration=True) # ElementTree can not do prettyprinting so do it manually import xml.dom.minidom doc = xml.dom.minidom.parse(self.main_xml) @@ -177,8 +178,7 @@ class PackageGenerator: for component_id in self.feature_components[staging_dir]: ET.SubElement(feature, 'ComponentRef', { 'Id': component_id, - }) - + }) def create_xml(self, nodes, current_dir, parent_xml_node, staging_dir): cur_node = nodes[current_dir] @@ -187,7 +187,7 @@ class PackageGenerator: comp_xml_node = ET.SubElement(parent_xml_node, 'Component', { 'Id': component_id, 'Guid': gen_guid(), - }) + }) self.feature_components[staging_dir].append(component_id) if self.bytesize == 64: comp_xml_node.set('Win64', 'yes') @@ -208,14 +208,14 @@ class PackageGenerator: 'Id': file_id, 'Name': f, 'Source': os.path.join(current_dir, f), - }) + }) for dirname in cur_node.dirs: dir_id = os.path.join(current_dir, dirname).replace('\\', '_').replace('/', '_') dir_node = ET.SubElement(parent_xml_node, 'Directory', { 'Id': dir_id, 'Name': dirname, - }) + }) self.create_xml(nodes, os.path.join(current_dir, dirname), dir_node, staging_dir) def build_package(self): diff --git a/run_project_tests.py b/run_project_tests.py index 71770f3..426e2c7 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -585,7 +585,7 @@ def check_file(fname): with open(fname, 'rb') as f: lines = f.readlines() for line in lines: - if b'\t' in line: + if line.startswith(b'\t'): print("File %s contains a literal tab on line %d. Only spaces are permitted." % (fname, linenum)) sys.exit(1) if b'\r' in line: diff --git a/run_unittests.py b/run_unittests.py index 2626931..b217714 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1946,7 +1946,7 @@ cpu = 'armv7' # Not sure if correct. endian = 'little' ''' % os.path.join(testdir, 'some_cross_tool.py')) crossfile.flush() - self.init(testdir, ['--cross-file='+crossfile.name]) + self.init(testdir, ['--cross-file=' + crossfile.name]) def test_reconfigure(self): testdir = os.path.join(self.unit_test_dir, '13 reconfigure') @@ -14,8 +14,10 @@ ignore = E305, # E401: multiple imports on one line E401, - # too many leading '#' for block comment + # E266: too many leading '#' for block comment E266, - # module level import not at top of file - E402 + # E402: module level import not at top of file + E402, + # E731: do not assign a lambda expression, use a def (too many false positives) + E731 max-line-length = 120 diff --git a/test cases/common/146 C and CPP link/dummy.c b/test cases/common/146 C and CPP link/dummy.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/146 C and CPP link/dummy.c diff --git a/test cases/common/146 C and CPP link/meson.build b/test cases/common/146 C and CPP link/meson.build index db84445..2dd3364 100644 --- a/test cases/common/146 C and CPP link/meson.build +++ b/test cases/common/146 C and CPP link/meson.build @@ -65,10 +65,44 @@ libfoo = shared_library( # # VS2010 lacks the /WHOLEARCHIVE option that later versions of MSVC support, so # don't run this tests on that backend. -if meson.backend() != 'vs2010' +if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19')) libfoowhole = shared_library( 'foowhole', ['foobar.c', 'foobar.h'], link_whole : [libc, libcpp], ) endif + +# Test sublinking (linking C and C++, then linking that to C) +libfoo_static = static_library( + 'foo_static', + ['foobar.c', 'foobar.h'], + link_with : [libc, libcpp], +) + +libsub = shared_library( + 'sub', + ['sub.c', 'sub.h'], + link_with : libfoo_static, +) + +if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19')) + libsubwhole = shared_library( + 'subwhole', + ['sub.c', 'sub.h'], + link_whole : libfoo_static, + ) +endif + +# Test that it really is recursive +libsub_static = static_library( + 'sub_static', + ['sub.c', 'sub.h'], + link_with : libfoo_static, +) + +libsubsub = shared_library( + 'subsub', + ['dummy.c'], + link_with : libsub_static, +) diff --git a/test cases/common/146 C and CPP link/sub.c b/test cases/common/146 C and CPP link/sub.c new file mode 100644 index 0000000..7c078f8 --- /dev/null +++ b/test cases/common/146 C and CPP link/sub.c @@ -0,0 +1,19 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ +#include "sub.h" + +float a_half(void) { + return .5; +} diff --git a/test cases/common/146 C and CPP link/sub.h b/test cases/common/146 C and CPP link/sub.h new file mode 100644 index 0000000..5b02e17 --- /dev/null +++ b/test cases/common/146 C and CPP link/sub.h @@ -0,0 +1,16 @@ +/* Copyright © 2017 Dylan Baker + * + * 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. + */ + +float a_half(void); diff --git a/test cases/common/147 mesonintrospect from scripts/check_env.py b/test cases/common/147 mesonintrospect from scripts/check_env.py index 9bd64d7..2d46d88 100644 --- a/test cases/common/147 mesonintrospect from scripts/check_env.py +++ b/test cases/common/147 mesonintrospect from scripts/check_env.py @@ -16,8 +16,8 @@ mesonintrospect = os.environ['MESONINTROSPECT'] introspect_arr = shlex.split(mesonintrospect) -#print(mesonintrospect) -#print(introspect_arr) +# print(mesonintrospect) +# print(introspect_arr) some_executable = introspect_arr[0] diff --git a/test cases/common/42 string operations/meson.build b/test cases/common/42 string operations/meson.build index 5d7a73d..d9f8130 100644 --- a/test cases/common/42 string operations/meson.build +++ b/test cases/common/42 string operations/meson.build @@ -67,3 +67,10 @@ assert(not version_number.version_compare('!=1.2.8'), 'Version_compare neq broke assert(version_number.version_compare('<2.0'), 'Version_compare major less broken') assert(version_number.version_compare('>0.9'), 'Version_compare major greater broken') + +assert(' spaces tabs '.strip() == 'spaces tabs', 'Spaces and tabs badly stripped') +assert(''' +multiline string '''.strip() == '''multiline string''', 'Newlines badly stripped') +assert('"1.1.20"'.strip('"') == '1.1.20', '" badly stripped') +assert('"1.1.20"'.strip('".') == '1.1.20', '". badly stripped') +assert('"1.1.20" '.strip('" ') == '1.1.20', '". badly stripped') diff --git a/test cases/common/98 gen extra/meson.build b/test cases/common/98 gen extra/meson.build index 52ed847..772f52e 100644 --- a/test cases/common/98 gen extra/meson.build +++ b/test cases/common/98 gen extra/meson.build @@ -11,3 +11,20 @@ g2 = gen.process('name.dat', extra_args: '--upper') test('basic', executable('basic', 'plain.c', g1)) test('upper', executable('upper', 'upper.c', g2)) + +prog2 = find_program('srcgen2.py') +basename_gen = generator(prog2, + output : ['@BASENAME@.tab.c', '@BASENAME@.tab.h'], + arguments : ['@BUILD_DIR@', '@BASENAME@', '@INPUT@']) + +basename_src = basename_gen.process('name.l') + +test('basename', executable('basename', basename_src)) + +plainname_gen = generator(prog2, + output : ['@PLAINNAME@.tab.c', '@PLAINNAME@.tab.h'], + arguments : ['@BUILD_DIR@', '@PLAINNAME@', '@INPUT@']) + +plainname_src = plainname_gen.process('name.l') + +test('plainname', executable('plainname', plainname_src)) diff --git a/test cases/common/98 gen extra/name.l b/test cases/common/98 gen extra/name.l new file mode 100644 index 0000000..3adda4f --- /dev/null +++ b/test cases/common/98 gen extra/name.l @@ -0,0 +1,3 @@ +int main() { +return 0; +} diff --git a/test cases/common/98 gen extra/srcgen2.py b/test cases/common/98 gen extra/srcgen2.py new file mode 100644 index 0000000..9cdf12d --- /dev/null +++ b/test cases/common/98 gen extra/srcgen2.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import os +import sys +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument('target_dir', + help='the target dir') +parser.add_argument('stem', + help='the stem') +parser.add_argument('input', + help='the input file') + +options = parser.parse_args(sys.argv[1:]) + +with open(options.input) as f: + content = f.read() + + +output_c = os.path.join(options.target_dir, options.stem + ".tab.c") +with open(output_c, 'w') as f: + f.write(content) + + +output_h = os.path.join(options.target_dir, options.stem + ".tab.h") +h_content = '''#pragma once + +int myfun(void); +''' +with open(output_h, 'w') as f: + f.write(h_content) diff --git a/test cases/frameworks/19 pcap/meson.build b/test cases/frameworks/19 pcap/meson.build index 909d7cd..c505960 100644 --- a/test cases/frameworks/19 pcap/meson.build +++ b/test cases/frameworks/19 pcap/meson.build @@ -2,6 +2,9 @@ project('pcap test', 'c') pcap_dep = dependency('pcap', version : '>=1.0') +pcap_ver = pcap_dep.version() +assert(pcap_ver.split('.').length() > 1, 'pcap version is "@0@"'.format(pcap_ver)) + e = executable('pcap_prog', 'pcap_prog.c', dependencies : pcap_dep) test('pcaptest', e) |