diff options
71 files changed, 802 insertions, 47 deletions
diff --git a/docs/markdown/Contributing.md b/docs/markdown/Contributing.md index 354bf62..169bf4c 100644 --- a/docs/markdown/Contributing.md +++ b/docs/markdown/Contributing.md @@ -32,6 +32,37 @@ basis. Sometimes it may be easier to write the test than convince the maintainers that one is not needed. Exercise judgment and ask for help in problematic cases. +The tests are split into two different parts: unit tests and full +project tests. To run all tests, execute `./run_tests.py`. Unit tests +can be run with `./run_unittests.py` and project tests with +`./run_project_tests.py`. + +Each project test is a standalone project that can be compiled on its +own. They are all in `test cases` subdirectory. The simplest way to +run a single project test is to do something like `./meson.py test\ +cases/common/1\ trivial builddir`. The one exception to this is `test +cases/unit` directory discussed below. + +The test cases in the `common` subdirectory are meant to be run always +for all backends. They should only depend on C and C++, without any +external dependencies such as libraries. Tests that require those are +in the `test cases/frameworks` directory. If there is a need for an +external program in the common directory, such as a code generator, it +should be implemented as a Python script. The goal of test projects is +also to provide sample projects that end users can use as a base for +their own projects. + +All project tests follow the same pattern: they are compiled, tests +are run and finally install is run. Passing means that building and +tests succeed and installed files match the `installed_files.txt` file +in the test's source root. Any tests that require more thorough +analysis, such as checking that certain compiler arguments can be +found in the command line or that the generated pkg-config files +actually work should be done with a unit test. + +Projects needed by unit tests are in the `test cases/unit` +subdirectory. They are not run as part of `./run_project_tests.py`. + ## Documentation The `docs` directory contains the full documentation that will be used diff --git a/docs/markdown/Disabler.md b/docs/markdown/Disabler.md index bd2b322..81417f6 100644 --- a/docs/markdown/Disabler.md +++ b/docs/markdown/Disabler.md @@ -63,4 +63,4 @@ endif This concentrates the handling of this option in one place and other build definition files do not need to be sprinkled with `if` -statements.
\ No newline at end of file +statements. diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index f797da1..14c931d 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -483,7 +483,7 @@ Keyword arguments are the following: then use the `.found()` method on the returned object to check whether it was found or not. -- `native` defines how this executable should be searched. By default +- `native` *(since 0.43)* defines how this executable should be searched. By default it is set to `false`, which causes Meson to first look for the executable in the cross file (when cross building) and if it is not defined there, then from the system. If set to `true`, the cross diff --git a/docs/markdown/Release-notes-for-0.43.0.md b/docs/markdown/Release-notes-for-0.43.0.md index 3f981e8..7702f3c 100644 --- a/docs/markdown/Release-notes-for-0.43.0.md +++ b/docs/markdown/Release-notes-for-0.43.0.md @@ -1,6 +1,6 @@ --- title: Release 0.43 -short-description: Release notes for 0.43 (preliminary) +short-description: Release notes for 0.43 ... # Portability improvements to Boost Dependency diff --git a/docs/markdown/Release-notes-for-0.44.0.md b/docs/markdown/Release-notes-for-0.44.0.md index 93e224d..56956d7 100644 --- a/docs/markdown/Release-notes-for-0.44.0.md +++ b/docs/markdown/Release-notes-for-0.44.0.md @@ -71,10 +71,12 @@ Added a new keyword argument to the `subdir` command. It is given a list of dependency objects and the function will only recurse in the subdirectory if they are all found. Typical usage goes like this. - d1 = dependency('foo') # This is found - d2 = dependency('bar') # This is not found +```meson +d1 = dependency('foo') # This is found +d2 = dependency('bar') # This is not found - subdir('somedir', if_found : [d1, d2]) +subdir('somedir', if_found : [d1, d2]) +``` In this case the subdirectory would not be entered since `d2` could not be found. @@ -138,6 +140,8 @@ Meson now ships an internal version of Python in the MSI installer packages. This means that it can run Python scripts that are part of your build transparently. That is, if you do the following: - myprog = find_program('myscript.py') +```meson +myprog = find_program('myscript.py') +``` Then Meson will run the script with its internal Python version if necessary. diff --git a/docs/markdown/Using-wraptool.md b/docs/markdown/Using-wraptool.md index 8e5f898..08b1bfa 100644 --- a/docs/markdown/Using-wraptool.md +++ b/docs/markdown/Using-wraptool.md @@ -1,12 +1,20 @@ # Using wraptool -Wraptool is a helper tool that allows you to manage your source dependencies using the WrapDB database. It gives you all things you would expect, such as installing and updating dependencies. The wrap tool works on all platforms, the only limitation is that the wrap definition works on your target platform. If you find some Wraps that don't work, please file bugs or, even better, patches. +Wraptool is a helper tool that allows you to manage your source +dependencies using the WrapDB database. It gives you all things you +would expect, such as installing and updating dependencies. The wrap +tool works on all platforms, the only limitation is that the wrap +definition works on your target platform. If you find some Wraps that +don't work, please file bugs or, even better, patches. -All code examples here assume that you are running the commands in your top level source directory. Lines that start with the `$` mark are commands to type. +All code examples here assume that you are running the commands in +your top level source directory. Lines that start with the `$` mark +are commands to type. ## Simple querying -The simplest operation to do is to query the list of packages available. To list them all issue the following command: +The simplest operation to do is to query the list of packages +available. To list them all issue the following command: $ wraptool list box2d @@ -22,27 +30,35 @@ The simplest operation to do is to query the list of packages available. To list vorbis zlib -Usually you want to search for a specific package. This can be done with the `search` command: +Usually you want to search for a specific package. This can be done +with the `search` command: $ wraptool search jpeg libjpeg -To determine which versions of libjpeg are available to install, issue the `info` command: +To determine which versions of libjpeg are available to install, issue +the `info` command: $ wraptool info libjpeg Available versions of libjpeg: 9a 2 -The first number is the upstream release version, in this case `9a`. The second number is the Wrap revision number. They don't relate to anything in particular, but larger numbers imply newer releases. You should always use the newest available release. +The first number is the upstream release version, in this case +`9a`. The second number is the Wrap revision number. They don't relate +to anything in particular, but larger numbers imply newer +releases. You should always use the newest available release. ## Installing dependencies -Installing dependencies is just as straightforward. First just create the `subprojects` directory at the top of your source tree and issue the install command. +Installing dependencies is just as straightforward. First just create +the `subprojects` directory at the top of your source tree and issue +the install command. $ wraptool install libjpeg Installed libjpeg branch 9a revision 2 -Now you can issue a `subproject('libjpeg')` in your `meson.build` file to use it. +Now you can issue a `subproject('libjpeg')` in your `meson.build` file +to use it. To check if your projects are up to date you can issue the `status` command. @@ -51,9 +67,33 @@ To check if your projects are up to date you can issue the `status` command. libjpeg up to date. Branch 9a, revision 2. zlib not up to date. Have 1.2.8 2, but 1.2.8 4 is available. -In this case `zlib` has a newer release available. Updating it is straightforward: +In this case `zlib` has a newer release available. Updating it is +straightforward: $ wraptool update zlib Updated zlib to branch 1.2.8 revision 4 -Wraptool can do other things besides these. Documentation for these can be found in the command line help, which can be accessed by `wraptool --help`. +Wraptool can do other things besides these. Documentation for these +can be found in the command line help, which can be accessed by +`wraptool --help`. + +## Promoting dependencies + +Meson will only search for subprojects from the top level +`subprojects` directory. If you have subprojects that themselves have +subprojects, you must transfer them to the top level. This can be done +by going to your source root and issuing a promotion command. + + meson wrap promote projname + +This will cause Meson to go through your entire project tree, find an +embedded subproject and copy it to the top level. + +If there are multiple embedded copies of a subproject, Meson will not +try to guess which one you want. Instead it will print all the +possibilities. You can then manually select which one to promote by +writing it out fully. + + meson wrap promote subprojects/s1/subprojects/projname + +This functionality was added in Meson release 0.45.0. diff --git a/docs/markdown/snippets/wrap_promote.md b/docs/markdown/snippets/wrap_promote.md new file mode 100644 index 0000000..20fee47 --- /dev/null +++ b/docs/markdown/snippets/wrap_promote.md @@ -0,0 +1,11 @@ +# Can promote dependencies with wrap command + +The `promote` command makes it easy to copy nested dependencies to the top level. + + meson wrap promote scommon + +This will search the project tree for a subproject called `scommon` and copy it to the top level. + +If there are many embedded subprojects with the same name, you have to specify which one to promote manually like this: + + meson wrap promote subprojects/s1/subprojects/scommon diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index e872a04..6a587ac 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -29,10 +29,9 @@ from ..environment import Environment def autodetect_vs_version(build): vs_version = os.getenv('VisualStudioVersion', None) vs_install_dir = os.getenv('VSINSTALLDIR', None) - if not vs_version and not vs_install_dir: - raise MesonException('Could not detect Visual Studio: VisualStudioVersion and VSINSTALLDIR are unset!\n' - 'Are we inside a Visual Studio build environment? ' - 'You can also try specifying the exact backend to use.') + if not vs_install_dir: + raise MesonException('Could not detect Visual Studio: Environment variable VSINSTALLDIR is not set!\n' + 'Are you running meson from the Visual Studio Developer Command Prompt?') # VisualStudioVersion is set since Visual Studio 12.0, but sometimes # vcvarsall.bat doesn't set it, so also use VSINSTALLDIR if vs_version == '14.0' or 'Visual Studio 14' in vs_install_dir: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 7757300..4a35bec 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1776,7 +1776,7 @@ class CustomTargetIndex: def __repr__(self): return '<CustomTargetIndex: {!r}[{}]>'.format( - self.target, self.target.output.index(self.output)) + self.target, self.target.get_outputs().index(self.output)) def get_outputs(self): return [self.output] diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 3d50eb0..b14074b 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -49,7 +49,7 @@ cpp_suffixes = lang_suffixes['cpp'] + ('h',) c_suffixes = lang_suffixes['c'] + ('h',) # List of languages that can be linked with C code directly by the linker # used in build.py:process_compilers() and build.py:get_dynamic_linker() -clike_langs = ('objcpp', 'objc', 'd', 'cpp', 'c', 'fortran',) +clike_langs = ('d', 'objcpp', 'cpp', 'objc', 'c', 'fortran',) clike_suffixes = () for _l in clike_langs: clike_suffixes += lang_suffixes[_l] @@ -863,9 +863,17 @@ class Compiler: # Not needed on Windows or other platforms that don't use RPATH # https://github.com/mesonbuild/meson/issues/1897 lpaths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) - args += ['-Wl,-rpath-link,' + lpaths] + + # clang expands '-Wl,rpath-link,' to ['-rpath-link'] instead of ['-rpath-link',''] + # This eats the next argument, which happens to be 'ldstdc++', causing link failures. + # We can dodge this problem by not adding any rpath_paths if the argument is empty. + if lpaths.strip() != '': + args += ['-Wl,-rpath-link,' + lpaths] return args + def thread_flags(self, env): + return [] + GCC_STANDARD = 0 GCC_OSX = 1 diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index e7eac1b..ea0711f 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -71,11 +71,6 @@ class BoostDependency(ExternalDependency): self.is_multithreading = threading == "multi" self.requested_modules = self.get_requested(kwargs) - invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS] - if invalid_modules: - mlog.warning('Invalid Boost modules: ' + ', '.join(invalid_modules)) - self.log_fail() - return self.boost_root = None self.boost_roots = [] @@ -112,6 +107,24 @@ class BoostDependency(ExternalDependency): self.log_fail() return + invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS] + + # previous versions of meson allowed include dirs as modules + remove = [] + for m in invalid_modules: + if m in os.listdir(os.path.join(self.incdir, 'boost')): + mlog.warning('Requested boost library', mlog.bold(m), 'that doesn\'t exist. ' + 'This will be an error in the future') + remove.append(m) + + self.requested_modules = [x for x in self.requested_modules if x not in remove] + invalid_modules = [x for x in invalid_modules if x not in remove] + + if invalid_modules: + mlog.warning('Invalid Boost modules: ' + ', '.join(invalid_modules)) + self.log_fail() + return + mlog.debug('Boost library root dir is', mlog.bold(self.boost_root)) mlog.debug('Boost include directory is', mlog.bold(self.incdir)) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 858d31d..0c9a2f3 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -608,6 +608,7 @@ class Environment: p, out, err = Popen_safe(compiler + arg) except OSError as e: popen_exceptions[' '.join(compiler + arg)] = e + continue version = search_version(out) if 'Free Software Foundation' in out: defines = self.get_gnu_compiler_defines(compiler) @@ -634,6 +635,7 @@ class Environment: p, out, err = Popen_safe(compiler + arg) except OSError as e: popen_exceptions[' '.join(compiler + arg)] = e + continue version = search_version(out) if 'Free Software Foundation' in out: defines = self.get_gnu_compiler_defines(compiler) diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 93f4b1a..e5238a7 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1667,7 +1667,7 @@ external dependencies (including libraries) must go to "dependencies".''') search_dir = os.path.join(srcdir, self.subdir) prog = ExternalProgram(cmd, silent=True, search_dir=search_dir) if not prog.found(): - raise InterpreterException('Program or command {!r} not found' + raise InterpreterException('Program or command {!r} not found ' 'or not executable'.format(cmd)) cmd = prog cmd_path = os.path.relpath(cmd.get_path(), start=srcdir) @@ -1813,9 +1813,18 @@ to directly access options of other subprojects.''') if coredata.is_builtin_option(key): if self.subproject != '': continue # Only the master project is allowed to set global options. + # If this was set on the command line, do not override. if not self.environment.had_argument_for(key): self.coredata.set_builtin_option(key, value) - # If this was set on the command line, do not override. + # If we are setting the prefix, then other options which + # have prefix-dependent defaults need their value updating, + # if they haven't been explicitly set (i.e. have their + # default value) + if key == 'prefix': + for option in coredata.builtin_dir_noprefix_options: + if not (self.environment.had_argument_for(option) or + any([k.startswith(option + '=') for k in default_options])): + self.coredata.set_builtin_option(option, coredata.get_builtin_option_default(option, value)) else: # Option values set with subproject() default_options override those # set in project() default_options. @@ -2131,6 +2140,8 @@ to directly access options of other subprojects.''') # Check if we've already searched for and found this dep if identifier in self.coredata.deps: cached_dep = self.coredata.deps[identifier] + mlog.log('Cached dependency', mlog.bold(name), + 'found:', mlog.green('YES')) else: # Check if exactly the same dep with different version requirements # was found already. @@ -2172,13 +2183,26 @@ to directly access options of other subprojects.''') # a higher level project, try to use it first. if 'fallback' in kwargs: dirname, varname = self.get_subproject_infos(kwargs) + required = kwargs.get('required', True) + wanted = kwargs.get('version', 'undefined') + if not isinstance(required, bool): + raise DependencyException('Keyword "required" must be a boolean.') if dirname in self.subprojects: - subproject = self.subprojects[dirname] - try: - # Never add fallback deps to self.coredata.deps - return subproject.get_variable_method([varname], {}) - except KeyError: - pass + found = self.subprojects[dirname].held_object.project_version + valid_version = wanted == 'undefined' or mesonlib.version_compare(found, wanted) + if required and not valid_version: + m = 'Version {} of {} already loaded, requested incompatible version {}' + raise DependencyException(m.format(found, dirname, wanted)) + elif valid_version: + mlog.log('Found a', mlog.green('(cached)'), 'subproject', + mlog.bold(os.path.join(self.subproject_dir, dirname)), 'for', + mlog.bold(name)) + subproject = self.subprojects[dirname] + try: + # Never add fallback deps to self.coredata.deps + return subproject.get_variable_method([varname], {}) + except KeyError: + pass # We need to actually search for this dep exception = None @@ -2200,6 +2224,7 @@ to directly access options of other subprojects.''') # we won't actually read all the build files. return fallback_dep if not dep: + self.print_nested_info(name) assert(exception is not None) raise exception @@ -2213,6 +2238,28 @@ to directly access options of other subprojects.''') def func_disabler(self, node, args, kwargs): return Disabler() + def print_nested_info(self, dependency_name): + message_templ = '''\nDependency %s not found but it is available in a sub-subproject. +To use it in the current project, promote it by going in the project source +root and issuing %s. + +''' + sprojs = mesonlib.detect_subprojects('subprojects', self.source_root) + if dependency_name not in sprojs: + return + found = sprojs[dependency_name] + if len(found) > 1: + suffix = 'one of the following commands' + else: + suffix = 'the following command' + message = message_templ % (dependency_name, suffix) + cmds = [] + command_templ = 'meson wrap promote ' + for l in found: + cmds.append(command_templ + l[len(self.source_root)+1:]) + final_message = message + '\n'.join(cmds) + print(final_message) + def get_subproject_infos(self, kwargs): fbinfo = kwargs['fallback'] check_stringlist(fbinfo) diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 9ad0668..6bf31db 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -881,6 +881,31 @@ def windows_proof_rmtree(f): # Try one last time and throw if it fails. shutil.rmtree(f) + +def detect_subprojects(spdir_name, current_dir='', result=None): + if result is None: + result = {} + spdir = os.path.join(current_dir, spdir_name) + if not os.path.exists(spdir): + return result + for trial in glob(os.path.join(spdir, '*')): + basename = os.path.split(trial)[1] + if trial == 'packagecache': + continue + append_this = True + if os.path.isdir(trial): + detect_subprojects(spdir_name, trial, result) + elif trial.endswith('.wrap') and os.path.isfile(trial): + basename = os.path.splitext(basename)[0] + else: + append_this = False + if append_this: + if basename in result: + result[basename].append(trial) + else: + result[basename] = [trial] + return result + class OrderedSet(collections.MutableSet): """A set that preserves the order in which items are added, by first insertion. diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index f261935..20ec304 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -28,7 +28,7 @@ default_warning = '1' def add_builtin_argument(p, name, **kwargs): k = kwargs.get('dest', name.replace('-', '_')) c = coredata.get_builtin_option_choices(k) - b = True if kwargs.get('action', None) in ['store_true', 'store_false'] else False + b = kwargs.get('action', None) in ['store_true', 'store_false'] h = coredata.get_builtin_option_description(k) if not b: h = h.rstrip('.') + ' (default: %s).' % coredata.get_builtin_option_default(k) @@ -172,6 +172,7 @@ class MesonApp: elif self.options.backend == 'vs': from .backend import vs2010backend g = vs2010backend.autodetect_vs_version(b) + env.coredata.set_builtin_option('backend', g.name) mlog.log('Auto detected Visual Studio backend:', mlog.bold(g.name)) elif self.options.backend == 'vs2010': from .backend import vs2010backend diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 7a01abc..ad99c14 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -776,12 +776,39 @@ This will become a hard error in the future.''') args += self._unpack_args('--fixxrefargs=', 'fixxref_args', kwargs) args += self._unpack_args('--mkdbargs=', 'mkdb_args', kwargs) args += self._unpack_args('--html-assets=', 'html_assets', kwargs, state) - args += self._unpack_args('--content-files=', 'content_files', kwargs, state) + + depends = [] + content_files = [] + for s in mesonlib.extract_as_list(kwargs, 'content_files'): + if hasattr(s, 'held_object'): + s = s.held_object + if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): + depends.append(s) + content_files.append(os.path.join(state.environment.get_build_dir(), + state.backend.get_target_dir(s), + s.get_outputs()[0])) + elif isinstance(s, mesonlib.File): + content_files.append(s.rel_to_builddir(state.build_to_src)) + elif isinstance(s, build.GeneratedList): + depends.append(s) + for gen_src in s.get_outputs(): + content_files.append(os.path.join(state.environment.get_source_dir(), + state.subdir, + gen_src)) + elif isinstance(s, str): + content_files.append(os.path.join(state.environment.get_source_dir(), + state.subdir, + s)) + else: + raise MesonException( + 'Invalid object type: {!r}'.format(s.__class__.__name__)) + args += ['--content-files=' + '@@'.join(content_files)] + args += self._unpack_args('--expand-content-files=', 'expand_content_files', kwargs, state) args += self._unpack_args('--ignore-headers=', 'ignore_headers', kwargs) args += self._unpack_args('--installdir=', 'install_dir', kwargs, state) args += self._get_build_args(kwargs, state) - res = [build.RunTarget(targetname, command[0], command[1:] + args, [], state.subdir, state.subproject)] + res = [build.RunTarget(targetname, command[0], command[1:] + args, depends, state.subdir, state.subproject)] if kwargs.get('install', True): res.append(build.RunScript(command, args)) return ModuleReturnValue(None, res) diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index f8ccbe6..df945ab 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -15,6 +15,7 @@ import os, re import functools +from . import mlog from . import mparser from . import coredata from . import mesonlib @@ -146,6 +147,14 @@ class OptionInterpreter: e.colno = cur.colno e.file = os.path.join('meson_options.txt') raise e + bad = [o for o in sorted(self.cmd_line_options) if not + (o in list(self.options) + forbidden_option_names or + any(o.startswith(p) for p in forbidden_prefixes))] + if bad: + sub = 'In subproject {}: '.format(self.subproject) if self.subproject else '' + mlog.warning( + '{}Unknown command line options: "{}"\n' + 'This will become a hard error in a future Meson release.'.format(sub, ', '.join(bad))) def reduce_single(self, arg): if isinstance(arg, str): diff --git a/mesonbuild/scripts/scanbuild.py b/mesonbuild/scripts/scanbuild.py index 728214f..f381552 100644 --- a/mesonbuild/scripts/scanbuild.py +++ b/mesonbuild/scripts/scanbuild.py @@ -17,6 +17,7 @@ import subprocess import shutil import tempfile from ..environment import detect_ninja +from ..mesonlib import Popen_safe def scanbuild(exename, srcdir, blddir, privdir, logdir, args): with tempfile.TemporaryDirectory(dir=privdir) as scandir: @@ -34,7 +35,30 @@ def run(args): privdir = os.path.join(blddir, 'meson-private') logdir = os.path.join(blddir, 'meson-logs/scanbuild') shutil.rmtree(logdir, ignore_errors=True) - exename = os.environ.get('SCANBUILD', 'scan-build') + tools = [ + 'scan-build', # base + 'scan-build-5.0', 'scan-build50', # latest stable release + 'scan-build-4.0', 'scan-build40', # old stable releases + 'scan-build-3.9', 'scan-build39', + 'scan-build-3.8', 'scan-build38', + 'scan-build-3.7', 'scan-build37', + 'scan-build-3.6', 'scan-build36', + 'scan-build-3.5', 'scan-build35', + 'scan-build-6.0', 'scan-build-devel', # development snapshot + ] + toolname = 'scan-build' + for tool in tools: + try: + p, out = Popen_safe([tool, '--help'])[:2] + except (FileNotFoundError, PermissionError): + continue + if p.returncode != 0: + continue + else: + toolname = tool + break + + exename = os.environ.get('SCANBUILD', toolname) if not shutil.which(exename): print('Scan-build not installed.') return 1 diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py index 79b00e0..00115cb 100644 --- a/mesonbuild/wrap/wraptool.py +++ b/mesonbuild/wrap/wraptool.py @@ -21,6 +21,8 @@ from glob import glob from .wrap import API_ROOT, open_wrapdburl +from .. import mesonlib + help_templ = '''This program allows you to manage your Wrap dependencies using the online wrap database http://wrapdb.mesonbuild.com. @@ -142,6 +144,36 @@ def info(name): for v in versions: print(' ', v['branch'], v['revision']) +def do_promotion(from_path, spdir_name): + if os.path.isfile(from_path): + assert(from_path.endswith('.wrap')) + shutil.copy(from_path, spdir_name) + elif os.path.isdir(from_path): + sproj_name = os.path.split(from_path)[1] + outputdir = os.path.join(spdir_name, sproj_name) + if os.path.exists(outputdir): + sys.exit('Output dir %s already exists. Will not overwrite.' % outputdir) + shutil.copytree(from_path, outputdir, ignore=shutil.ignore_patterns('subprojects')) + +def promote(argument): + path_segment, subproject_name = os.path.split(argument) + spdir_name = 'subprojects' + sprojs = mesonlib.detect_subprojects(spdir_name) + if subproject_name not in sprojs: + sys.exit('Subproject %s not found in directory tree.' % subproject_name) + matches = sprojs[subproject_name] + if len(matches) == 1: + do_promotion(matches[0], spdir_name) + return + if path_segment == '': + print('There are many versions of %s in tree. Please specify which one to promote:\n' % subproject_name) + for s in matches: + print(s) + sys.exit(1) + system_native_path_argument = argument.replace('/', os.sep) + if system_native_path_argument in matches: + do_promotion(argument, spdir_name) + def status(): print('Subproject status') for w in glob('subprojects/*.wrap'): @@ -189,6 +221,11 @@ def run(args): print('info requires exactly one argument.') return 1 info(args[0]) + elif command == 'promote': + if len(args) != 1: + print('promote requires exactly one argument.') + return 1 + promote(args[0]) elif command == 'status': status() else: diff --git a/run_unittests.py b/run_unittests.py index acf029f..184386c 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -37,7 +37,7 @@ from mesonbuild.interpreter import ObjectHolder from mesonbuild.mesonlib import is_linux, is_windows, is_osx, is_cygwin, windows_proof_rmtree from mesonbuild.mesonlib import python_command, meson_command, version_compare from mesonbuild.environment import Environment -from mesonbuild.dependencies import DependencyException +from mesonbuild.mesonlib import MesonException, EnvironmentException from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram from run_tests import exe_suffix, get_fake_options @@ -468,6 +468,7 @@ class BasePlatformTests(unittest.TestCase): self.mconf_command = meson_command + ['configure'] self.mintro_command = meson_command + ['introspect'] self.mtest_command = meson_command + ['test', '-C', self.builddir] + self.wrap_command = meson_command + ['wrap'] # Backend-specific build commands self.build_command, self.clean_command, self.test_command, self.install_command, \ self.uninstall_command = get_backend_commands(self.backend) @@ -789,6 +790,45 @@ class AllPlatformTests(BasePlatformTests): self.assertEqual(value, expected[prefix][name]) self.wipe() + def test_default_options_prefix_dependent_defaults(self): + ''' + Tests that setting a prefix in default_options in project() sets prefix + dependent defaults for other options, and that those defaults can + be overridden in default_options or by the command line. + ''' + testdir = os.path.join(self.common_test_dir, '173 default options prefix dependent defaults') + expected = { + '': + {'prefix': '/usr', + 'sysconfdir': '/etc', + 'localstatedir': '/var', + 'sharedstatedir': '/sharedstate'}, + '--prefix=/usr': + {'prefix': '/usr', + 'sysconfdir': '/etc', + 'localstatedir': '/var', + 'sharedstatedir': '/sharedstate'}, + '--sharedstatedir=/var/state': + {'prefix': '/usr', + 'sysconfdir': '/etc', + 'localstatedir': '/var', + 'sharedstatedir': '/var/state'}, + '--sharedstatedir=/var/state --prefix=/usr --sysconfdir=sysconf': + {'prefix': '/usr', + 'sysconfdir': 'sysconf', + 'localstatedir': '/var', + 'sharedstatedir': '/var/state'}, + } + for args in expected: + self.init(testdir, args.split(), default_args=False) + opts = self.introspect('--buildoptions') + for opt in opts: + name = opt['name'] + value = opt['value'] + if name in expected[args]: + self.assertEqual(value, expected[args][name]) + self.wipe() + def test_static_library_overwrite(self): ''' Tests that static libraries are never appended to, always overwritten. @@ -1643,6 +1683,30 @@ int main(int argc, char **argv) { self.setconf("-Dfree_array_opt=['a,b', 'c,d']", will_build=False) self.opt_has('free_array_opt', ['a,b', 'c,d']) + def test_subproject_promotion(self): + testdir = os.path.join(self.unit_test_dir, '13 promote') + workdir = os.path.join(self.builddir, 'work') + shutil.copytree(testdir, workdir) + spdir = os.path.join(workdir, 'subprojects') + s3dir = os.path.join(spdir, 's3') + scommondir = os.path.join(spdir, 'scommon') + self.assertFalse(os.path.isdir(s3dir)) + subprocess.check_call(self.wrap_command + ['promote', 's3'], cwd=workdir) + self.assertTrue(os.path.isdir(s3dir)) + self.assertFalse(os.path.isdir(scommondir)) + self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'scommon'], + cwd=workdir, + stdout=subprocess.DEVNULL), 0) + self.assertFalse(os.path.isdir(scommondir)) + subprocess.check_call(self.wrap_command + ['promote', 'subprojects/s2/subprojects/scommon'], cwd=workdir) + self.assertTrue(os.path.isdir(scommondir)) + promoted_wrap = os.path.join(spdir, 'athing.wrap') + self.assertFalse(os.path.isfile(promoted_wrap)) + subprocess.check_call(self.wrap_command + ['promote', 'athing'], cwd=workdir) + self.assertTrue(os.path.isfile(promoted_wrap)) + self.init(workdir) + self.build() + class FailureTests(BasePlatformTests): ''' @@ -1680,7 +1744,7 @@ class FailureTests(BasePlatformTests): f.write(contents) # Force tracebacks so we can detect them properly os.environ['MESON_FORCE_BACKTRACE'] = '1' - with self.assertRaisesRegex(DependencyException, match, msg=contents): + with self.assertRaisesRegex(MesonException, match, msg=contents): # Must run in-process or we'll get a generic CalledProcessError self.init(self.srcdir, extra_args=extra_args, inprocess=True) @@ -1782,6 +1846,40 @@ class FailureTests(BasePlatformTests): ''' self.assertMesonRaises(code, "Method.*configtool.*is invalid.*internal") + def test_bad_option(self): + tdir = os.path.join(self.unit_test_dir, '19 bad command line options') + os.environ['MESON_FORCE_BACKTRACE'] = '1' + self.init(tdir, extra_args=['-Dopt=bar', '-Dc_args=-Wall'], inprocess=True) + self.wipe() + out = self.init(tdir, extra_args=['-Dfoo=bar', '-Dbad=true'], inprocess=True) + self.assertRegex( + out, r'Unknown command line options: "bad, foo"') + + def test_bad_option_subproject(self): + tdir = os.path.join(self.unit_test_dir, '19 bad command line options') + os.environ['MESON_FORCE_BACKTRACE'] = '1' + self.init(tdir, extra_args=['-Done:one=bar'], inprocess=True) + self.wipe() + out = self.init(tdir, extra_args=['-Done:two=bar'], inprocess=True) + self.assertRegex( + out, + r'In subproject one: Unknown command line options: "one:two"') + + def test_objc_cpp_detection(self): + ''' + Test that when we can't detect objc or objcpp, we fail gracefully. + ''' + env = Environment('', self.builddir, self.meson_command, + get_fake_options(self.prefix), []) + try: + objc = env.detect_objc_compiler(False) + objcpp = env.detect_objcpp_compiler(False) + except EnvironmentException: + code = "add_languages('objc')\nadd_languages('objcpp')" + self.assertMesonRaises(code, "Unknown compiler") + return + raise unittest.SkipTest("objc and objcpp found, can't test detection failure") + class WindowsTests(BasePlatformTests): ''' @@ -2299,11 +2397,18 @@ class LinuxlikeTests(BasePlatformTests): testdir = os.path.join(self.unit_test_dir, '11 build_rpath') self.init(testdir) self.build() + # C program RPATH build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar') self.install() install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog')) self.assertEqual(install_rpath, '/baz') + # C++ program RPATH + build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar') + self.install() + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx')) + self.assertEqual(install_rpath, 'baz') def test_pch_with_address_sanitizer(self): testdir = os.path.join(self.common_test_dir, '13 pch') diff --git a/test cases/common/173 default options prefix dependent defaults/meson.build b/test cases/common/173 default options prefix dependent defaults/meson.build new file mode 100644 index 0000000..9ca4ec5 --- /dev/null +++ b/test cases/common/173 default options prefix dependent defaults/meson.build @@ -0,0 +1 @@ +project('default options prefix dependent defaults ', 'c', default_options : ['sharedstatedir=/sharedstate', 'prefix=/usr']) diff --git a/test cases/failing/68 subproj different versions/main.c b/test cases/failing/68 subproj different versions/main.c new file mode 100644 index 0000000..8793c62 --- /dev/null +++ b/test cases/failing/68 subproj different versions/main.c @@ -0,0 +1,9 @@ +#include <stdio.h> +#include "a.h" +#include "b.h" + +int main(int argc, char **argv) { + int life = a_fun() + b_fun(); + printf("%d\n", life); + return 0; +} diff --git a/test cases/failing/68 subproj different versions/meson.build b/test cases/failing/68 subproj different versions/meson.build new file mode 100644 index 0000000..7690277 --- /dev/null +++ b/test cases/failing/68 subproj different versions/meson.build @@ -0,0 +1,9 @@ +project('super', 'c') + +# A will use version 1 of C +a_dep = dependency('a', fallback: ['a', 'a_dep']) + +# B will fail becuase it requests version 2 of C +b_dep = dependency('b', fallback: ['b', 'b_dep']) + +main = executable('main', files('main.c'), dependencies: [a_dep, b_dep]) diff --git a/test cases/failing/68 subproj different versions/subprojects/a/a.c b/test cases/failing/68 subproj different versions/subprojects/a/a.c new file mode 100644 index 0000000..cd41a65 --- /dev/null +++ b/test cases/failing/68 subproj different versions/subprojects/a/a.c @@ -0,0 +1,5 @@ +#include "c.h" + +int a_fun() { + return c_fun(); +} diff --git a/test cases/failing/68 subproj different versions/subprojects/a/a.h b/test cases/failing/68 subproj different versions/subprojects/a/a.h new file mode 100644 index 0000000..8f1d49e --- /dev/null +++ b/test cases/failing/68 subproj different versions/subprojects/a/a.h @@ -0,0 +1 @@ +int a_fun(); diff --git a/test cases/failing/68 subproj different versions/subprojects/a/meson.build b/test cases/failing/68 subproj different versions/subprojects/a/meson.build new file mode 100644 index 0000000..e84182a --- /dev/null +++ b/test cases/failing/68 subproj different versions/subprojects/a/meson.build @@ -0,0 +1,11 @@ +project('a', 'c') + +c_dep = dependency('c', version:'1', fallback: ['c', 'c_dep']) + +alib = library('a', 'a.c', + dependencies: c_dep) + +a_dep = declare_dependency( + link_with: alib, + include_directories: include_directories('.'), +) diff --git a/test cases/failing/68 subproj different versions/subprojects/b/b.c b/test cases/failing/68 subproj different versions/subprojects/b/b.c new file mode 100644 index 0000000..f85f8c3 --- /dev/null +++ b/test cases/failing/68 subproj different versions/subprojects/b/b.c @@ -0,0 +1,5 @@ +#include "c.h" + +int b_fun(){ +return c_fun(); +} diff --git a/test cases/failing/68 subproj different versions/subprojects/b/b.h b/test cases/failing/68 subproj different versions/subprojects/b/b.h new file mode 100644 index 0000000..eced786 --- /dev/null +++ b/test cases/failing/68 subproj different versions/subprojects/b/b.h @@ -0,0 +1 @@ +int b_fun(); diff --git a/test cases/failing/68 subproj different versions/subprojects/b/meson.build b/test cases/failing/68 subproj different versions/subprojects/b/meson.build new file mode 100644 index 0000000..0398340 --- /dev/null +++ b/test cases/failing/68 subproj different versions/subprojects/b/meson.build @@ -0,0 +1,11 @@ +project('b', 'c') + +c_dep = dependency('c', version:'2', fallback: ['c', 'c_dep']) + +blib = library('b', 'b.c', + dependencies: c_dep) + +b_dep = declare_dependency( + link_with: blib, + include_directories: include_directories('.'), +) diff --git a/test cases/failing/68 subproj different versions/subprojects/c/c.h b/test cases/failing/68 subproj different versions/subprojects/c/c.h new file mode 100644 index 0000000..2b15f60 --- /dev/null +++ b/test cases/failing/68 subproj different versions/subprojects/c/c.h @@ -0,0 +1,3 @@ +static int c_fun(){ + return 3; +} diff --git a/test cases/failing/68 subproj different versions/subprojects/c/meson.build b/test cases/failing/68 subproj different versions/subprojects/c/meson.build new file mode 100644 index 0000000..7184933 --- /dev/null +++ b/test cases/failing/68 subproj different versions/subprojects/c/meson.build @@ -0,0 +1,5 @@ +project('c', 'c', version:'1') + +c_dep = declare_dependency( + include_directories: include_directories('.') +) diff --git a/test cases/failing/69 wrong boost module/meson.build b/test cases/failing/69 wrong boost module/meson.build new file mode 100644 index 0000000..7fb3a40 --- /dev/null +++ b/test cases/failing/69 wrong boost module/meson.build @@ -0,0 +1,5 @@ +project('boosttest', 'cpp', + default_options : ['cpp_std=c++11']) + +# abc doesn't exist +linkdep = dependency('boost', modules : ['thread', 'system', 'test', 'abc']) diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build index b73f93a..771ecbc 100644 --- a/test cases/frameworks/1 boost/meson.build +++ b/test cases/frameworks/1 boost/meson.build @@ -9,7 +9,7 @@ add_project_arguments(['-DBOOST_LOG_DYN_LINK'], # within one project. The need to be independent of each other. # Use one without a library dependency and one with it. -linkdep = dependency('boost', modules : ['thread', 'system']) +linkdep = dependency('boost', modules : ['thread', 'system', 'test']) staticdep = dependency('boost', modules : ['thread', 'system'], static : true) testdep = dependency('boost', modules : ['unit_test_framework']) nomoddep = dependency('boost') diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml b/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml index 028b808..3894317 100644 --- a/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml +++ b/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml @@ -34,6 +34,7 @@ </para> </partintro> <xi:include href="xml/foo.xml"/> + <xi:include href="../include/bar.xml"/> <xi:include href="xml/foo-version.xml"/> </reference> diff --git a/test cases/frameworks/10 gtk-doc/doc/meson.build b/test cases/frameworks/10 gtk-doc/doc/meson.build index 5f08e89..7aeb98d 100644 --- a/test cases/frameworks/10 gtk-doc/doc/meson.build +++ b/test cases/frameworks/10 gtk-doc/doc/meson.build @@ -4,4 +4,8 @@ configure_file(input : 'version.xml.in', output : 'version.xml', configuration : cdata) -gnome.gtkdoc('foobar', src_dir : inc, main_sgml : 'foobar-docs.sgml', install : true) +gnome.gtkdoc('foobar', + src_dir : inc, + main_sgml : 'foobar-docs.sgml', + content_files : docbook, + install : true) diff --git a/test cases/frameworks/10 gtk-doc/include/generate-enums-docbook.py b/test cases/frameworks/10 gtk-doc/include/generate-enums-docbook.py new file mode 100644 index 0000000..41c6121 --- /dev/null +++ b/test cases/frameworks/10 gtk-doc/include/generate-enums-docbook.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 + +import sys + +DOC_HEADER = '''<?xml version='1.0'?> +<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> + +<refentry id="{0}"> + <refmeta> + <refentrytitle role="top_of_page" id="{0}.top_of_page">{0}</refentrytitle> + <refmiscinfo>{0}</refmiscinfo> + </refmeta> + <refnamediv> + <refname>{0}</refname> + <refpurpose></refpurpose> + </refnamediv> + + <refsect2 id="{1}" role="enum"> + <title>enum {1}</title> + <indexterm zone="{1}"> + <primary>{1}</primary> + </indexterm> + <para><link linkend="{1}">{1}</link></para> + <refsect3 role="enum_members"> + <title>Values</title> + <informaltable role="enum_members_table" pgwide="1" frame="none"> + <tgroup cols="4"> + <colspec colname="enum_members_name" colwidth="300px" /> + <colspec colname="enum_members_value" colwidth="100px"/> + <colspec colname="enum_members_description" /> + <tbody> +''' + +DOC_ENUM = ''' <row role="constant"> + <entry role="enum_member_name"><para>{0}</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>{1}</literal></para><para></para></entry> + <entry role="enum_member_description"></entry> + </row>''' + +DOC_FOOTER = ''' + </tbody> + </tgroup> + </informaltable> + </refsect3> + </refsect2> +</refentry> +''' + +if __name__ == '__main__': + if len(sys.argv) >= 4: + with open(sys.argv[1], 'w') as doc_out: + enum_name = sys.argv[2] + enum_type = sys.argv[3] + + doc_out.write(DOC_HEADER.format(enum_name, enum_type)) + for i, enum in enumerate(sys.argv[4:]): + doc_out.write(DOC_ENUM.format(enum, i)) + doc_out.write(DOC_FOOTER) + else: + print('Use: ' + sys.argv[0] + ' out name type [enums]') + + sys.exit(0) diff --git a/test cases/frameworks/10 gtk-doc/include/meson.build b/test cases/frameworks/10 gtk-doc/include/meson.build index 4c85b80..f6dd99f 100644 --- a/test cases/frameworks/10 gtk-doc/include/meson.build +++ b/test cases/frameworks/10 gtk-doc/include/meson.build @@ -8,3 +8,9 @@ configure_file(input : 'foo-version.h.in', configuration : cdata, install : true, install_dir : get_option('includedir')) + +generate_enums_docbook = find_program('generate-enums-docbook.py') + +docbook = custom_target('enum-docbook', + output : 'bar.xml', + command : [generate_enums_docbook, '@OUTPUT@', 'BAR', 'BAR_TYPE', 'BAR_FOO']) diff --git a/test cases/linuxlike/12 subprojects in subprojects/main.c b/test cases/linuxlike/12 subprojects in subprojects/main.c new file mode 100644 index 0000000..8793c62 --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/main.c @@ -0,0 +1,9 @@ +#include <stdio.h> +#include "a.h" +#include "b.h" + +int main(int argc, char **argv) { + int life = a_fun() + b_fun(); + printf("%d\n", life); + return 0; +} diff --git a/test cases/linuxlike/12 subprojects in subprojects/meson.build b/test cases/linuxlike/12 subprojects in subprojects/meson.build new file mode 100644 index 0000000..4014149 --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/meson.build @@ -0,0 +1,9 @@ +project('super', 'c') + +# A will use version 1 of C +a_dep = dependency('a', fallback: ['a', 'a_dep']) + +# B has an optional dependency on C version 2 and will therefore work +b_dep = dependency('b', fallback: ['b', 'b_dep']) + +main = executable('main', files('main.c'), dependencies: [a_dep, b_dep]) diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.c b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.c new file mode 100644 index 0000000..cd41a65 --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.c @@ -0,0 +1,5 @@ +#include "c.h" + +int a_fun() { + return c_fun(); +} diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.h b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.h new file mode 100644 index 0000000..8f1d49e --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.h @@ -0,0 +1 @@ +int a_fun(); diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/meson.build b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/meson.build new file mode 100644 index 0000000..5f579a3 --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/meson.build @@ -0,0 +1,11 @@ +project('a', 'c', version:'1.0') + +c_dep = dependency('c', version:'1', fallback: ['c', 'c_dep']) + +alib = library('a', 'a.c', + dependencies: c_dep) + +a_dep = declare_dependency( + link_with: alib, + include_directories: include_directories('.'), +) diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.c b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.c new file mode 100644 index 0000000..4824285 --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.c @@ -0,0 +1,11 @@ +#if defined(WITH_C) +#include "c.h" +#endif + +int b_fun(){ +#if defined(WITH_C) +return c_fun(); +#else +return 0; +#endif +} diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.h b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.h new file mode 100644 index 0000000..eced786 --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.h @@ -0,0 +1 @@ +int b_fun(); diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/meson.build b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/meson.build new file mode 100644 index 0000000..80903f3 --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/meson.build @@ -0,0 +1,17 @@ +project('b', 'c') + +c_dep = dependency('c', version:'2', fallback: ['c', 'c_dep'], required: false) + +assert(c_dep.found() == false, 'C project has the wrong version and should not be found') + +if c_dep.found() + add_global_arguments('-DWITH_C', language: 'c') +endif + +blib = library('b', 'b.c', + dependencies: c_dep) + +b_dep = declare_dependency( + link_with: blib, + include_directories: include_directories('.'), +) diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/c.h b/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/c.h new file mode 100644 index 0000000..2b15f60 --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/c.h @@ -0,0 +1,3 @@ +static int c_fun(){ + return 3; +} diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/meson.build b/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/meson.build new file mode 100644 index 0000000..7184933 --- /dev/null +++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/meson.build @@ -0,0 +1,5 @@ +project('c', 'c', version:'1') + +c_dep = declare_dependency( + include_directories: include_directories('.') +) diff --git a/test cases/linuxlike/5 dependency versions/meson.build b/test cases/linuxlike/5 dependency versions/meson.build index d4140b7..5d9eb32 100644 --- a/test cases/linuxlike/5 dependency versions/meson.build +++ b/test cases/linuxlike/5 dependency versions/meson.build @@ -41,6 +41,11 @@ assert(somelibver.type_name() == 'internal', 'somelibver should be of type "inte somelib = dependency('somelib', version : '== 0.1', fallback : ['somelib', 'some_dep']) +# Find an internal dependency again even if required = false +somelib_reqfalse = dependency('somelib', + required: false, + fallback : ['somelib', 'some_dep']) +assert(somelib_reqfalse.found(), 'somelib should have been found') # Find an internal dependency again with the same name and incompatible version somelibver = dependency('somelib', version : '>= 0.3', diff --git a/test cases/objc/6 c++ project objc subproject/master.cpp b/test cases/objc/6 c++ project objc subproject/master.cpp new file mode 100644 index 0000000..2f351d1 --- /dev/null +++ b/test cases/objc/6 c++ project objc subproject/master.cpp @@ -0,0 +1,11 @@ + +#include <iostream> + +extern "C" +int foo(); + +int main() { + std::cout << "Starting\n"; + std::cout << foo() << "\n"; + return 0; +} diff --git a/test cases/objc/6 c++ project objc subproject/meson.build b/test cases/objc/6 c++ project objc subproject/meson.build new file mode 100644 index 0000000..8a77ded --- /dev/null +++ b/test cases/objc/6 c++ project objc subproject/meson.build @@ -0,0 +1,6 @@ +project('master', ['cpp']) + +foo = subproject('foo') +dep = foo.get_variable('foo_dep') + +executable('master', 'master.cpp', dependencies: dep) diff --git a/test cases/objc/6 c++ project objc subproject/subprojects/foo/foo.m b/test cases/objc/6 c++ project objc subproject/subprojects/foo/foo.m new file mode 100644 index 0000000..e193b86 --- /dev/null +++ b/test cases/objc/6 c++ project objc subproject/subprojects/foo/foo.m @@ -0,0 +1,4 @@ + +int foo() { + return 42; +} diff --git a/test cases/objc/6 c++ project objc subproject/subprojects/foo/meson.build b/test cases/objc/6 c++ project objc subproject/subprojects/foo/meson.build new file mode 100644 index 0000000..2dbf8ab --- /dev/null +++ b/test cases/objc/6 c++ project objc subproject/subprojects/foo/meson.build @@ -0,0 +1,5 @@ +project('foo', ['objc']) + +l = static_library('foo', 'foo.m') + +foo_dep = declare_dependency(link_with : l) diff --git a/test cases/unit/11 build_rpath/meson.build b/test cases/unit/11 build_rpath/meson.build index b84c259..c0bc3bd 100644 --- a/test cases/unit/11 build_rpath/meson.build +++ b/test cases/unit/11 build_rpath/meson.build @@ -1,4 +1,4 @@ -project('build rpath', 'c') +project('build rpath', 'c', 'cpp') subdir('sub') executable('prog', 'prog.c', @@ -7,3 +7,10 @@ executable('prog', 'prog.c', install_rpath : '/baz', install : true, ) + +executable('progcxx', 'prog.cc', + link_with : l, + build_rpath : '/foo/bar', + install_rpath : 'baz', + install : true, + ) diff --git a/test cases/unit/11 build_rpath/prog.cc b/test cases/unit/11 build_rpath/prog.cc new file mode 100644 index 0000000..c7c2123 --- /dev/null +++ b/test cases/unit/11 build_rpath/prog.cc @@ -0,0 +1,8 @@ +#include <string> +#include <iostream> + +int main(int argc, char **argv) { + std::string* s = new std::string("Hello"); + delete s; + return 0; +} diff --git a/test cases/unit/13 promote/meson.build b/test cases/unit/13 promote/meson.build new file mode 100644 index 0000000..066cf36 --- /dev/null +++ b/test cases/unit/13 promote/meson.build @@ -0,0 +1,5 @@ +project('promotion test', 'c') + +subproject('s1') +subproject('s2') + diff --git a/test cases/unit/13 promote/subprojects/s1/meson.build b/test cases/unit/13 promote/subprojects/s1/meson.build new file mode 100644 index 0000000..88c467b --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s1/meson.build @@ -0,0 +1,7 @@ +project('s1', 'c') + +sc = subproject('scommon') +s3 = subproject('s3') + +executable('s1', 's1.c', + link_with : [sc.get_variable('clib'), s3.get_variable('l')]) diff --git a/test cases/unit/13 promote/subprojects/s1/s1.c b/test cases/unit/13 promote/subprojects/s1/s1.c new file mode 100644 index 0000000..7d1d775 --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s1/s1.c @@ -0,0 +1,6 @@ +int func(); +int func2(); + +int main(int argc, char **argv) { + return func() + func2(); +} diff --git a/test cases/unit/13 promote/subprojects/s1/subprojects/s3/meson.build b/test cases/unit/13 promote/subprojects/s1/subprojects/s3/meson.build new file mode 100644 index 0000000..894fe26 --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s1/subprojects/s3/meson.build @@ -0,0 +1,4 @@ +project('s3', 'c') + +l = static_library('s3', 's3.c') + diff --git a/test cases/unit/13 promote/subprojects/s1/subprojects/s3/s3.c b/test cases/unit/13 promote/subprojects/s1/subprojects/s3/s3.c new file mode 100644 index 0000000..0166603 --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s1/subprojects/s3/s3.c @@ -0,0 +1,3 @@ +int func2() { + return -42; +} diff --git a/test cases/unit/13 promote/subprojects/s1/subprojects/scommon/meson.build b/test cases/unit/13 promote/subprojects/s1/subprojects/scommon/meson.build new file mode 100644 index 0000000..231f275 --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s1/subprojects/scommon/meson.build @@ -0,0 +1,4 @@ +project('scommon', 'c') + +clib = static_library('scommon', 'scommon_broken.c') + diff --git a/test cases/unit/13 promote/subprojects/s1/subprojects/scommon/scommon_broken.c b/test cases/unit/13 promote/subprojects/s1/subprojects/scommon/scommon_broken.c new file mode 100644 index 0000000..3665a9c --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s1/subprojects/scommon/scommon_broken.c @@ -0,0 +1 @@ +#error This file must not be used. The other scommon one should be instead. diff --git a/test cases/unit/13 promote/subprojects/s2/meson.build b/test cases/unit/13 promote/subprojects/s2/meson.build new file mode 100644 index 0000000..32bcf8f --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s2/meson.build @@ -0,0 +1,6 @@ +project('s2', 'c') + +sc = subproject('scommon') + +executable('s2', 's2.c', link_with : sc.get_variable('clib')) + diff --git a/test cases/unit/13 promote/subprojects/s2/s2.c b/test cases/unit/13 promote/subprojects/s2/s2.c new file mode 100644 index 0000000..2a6d1e6 --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s2/s2.c @@ -0,0 +1,6 @@ +int func(); + + +int main(int argc, char **argv) { + return func() != 42; +} diff --git a/test cases/unit/13 promote/subprojects/s2/subprojects/athing.wrap b/test cases/unit/13 promote/subprojects/s2/subprojects/athing.wrap new file mode 100644 index 0000000..09ba4e8 --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s2/subprojects/athing.wrap @@ -0,0 +1,2 @@ +The contents of this wrap file are never evaluated so they +can be anything. diff --git a/test cases/unit/13 promote/subprojects/s2/subprojects/scommon/meson.build b/test cases/unit/13 promote/subprojects/s2/subprojects/scommon/meson.build new file mode 100644 index 0000000..e0d8c7d --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s2/subprojects/scommon/meson.build @@ -0,0 +1,4 @@ +project('scommon', 'c') + +clib = static_library('scommon', 'scommon_ok.c') + diff --git a/test cases/unit/13 promote/subprojects/s2/subprojects/scommon/scommon_ok.c b/test cases/unit/13 promote/subprojects/s2/subprojects/scommon/scommon_ok.c new file mode 100644 index 0000000..652f4eb --- /dev/null +++ b/test cases/unit/13 promote/subprojects/s2/subprojects/scommon/scommon_ok.c @@ -0,0 +1,3 @@ +int func() { + return 42; +} diff --git a/test cases/unit/19 bad command line options/meson.build b/test cases/unit/19 bad command line options/meson.build new file mode 100644 index 0000000..b1670c0 --- /dev/null +++ b/test cases/unit/19 bad command line options/meson.build @@ -0,0 +1,17 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +project('Bad command line options') + +one = subproject('one') diff --git a/test cases/unit/19 bad command line options/meson_options.txt b/test cases/unit/19 bad command line options/meson_options.txt new file mode 100644 index 0000000..fc09712 --- /dev/null +++ b/test cases/unit/19 bad command line options/meson_options.txt @@ -0,0 +1,16 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +option('opt', type : 'string', description : 'An argument') +option('good', type : 'boolean', value : true, description : 'another argument') diff --git a/test cases/unit/19 bad command line options/subprojects/one/meson.build b/test cases/unit/19 bad command line options/subprojects/one/meson.build new file mode 100644 index 0000000..39ae07e --- /dev/null +++ b/test cases/unit/19 bad command line options/subprojects/one/meson.build @@ -0,0 +1,15 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +project('one subproject') diff --git a/test cases/unit/19 bad command line options/subprojects/one/meson_options.txt b/test cases/unit/19 bad command line options/subprojects/one/meson_options.txt new file mode 100644 index 0000000..7d90fae --- /dev/null +++ b/test cases/unit/19 bad command line options/subprojects/one/meson_options.txt @@ -0,0 +1,15 @@ +# Copyright © 2017 Intel Corporation +# +# 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. + +option('one', type : 'string', description : 'an option') diff --git a/test cases/windows/5 resources/prog.c b/test cases/windows/5 resources/prog.c index 2c6f153..2bef6a2 100644 --- a/test cases/windows/5 resources/prog.c +++ b/test cases/windows/5 resources/prog.c @@ -9,6 +9,6 @@ WinMain( LPSTR lpszCmdLine, int nCmdShow) { HICON hIcon; - hIcon = LoadIcon(NULL, IDI_APPLICATION); + hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(MY_ICON)); return hIcon ? 0 : 1; } |