diff options
57 files changed, 726 insertions, 163 deletions
diff --git a/contributing.txt b/contributing.txt index 094c5e6..b1c015c 100644 --- a/contributing.txt +++ b/contributing.txt @@ -1,70 +1,4 @@ Contributing to the Meson build system -There are two simple ways to submit your patches. The preferred way is -to send a github pull request. Small changes can also be sent as -patches as emails to the Meson mailing list. - - -Python Coding style - -Meson follows the basic Python coding style. Additional rules are the -following: - -- indent 4 spaces, no tabs ever -- indent meson.build files with two spaces -- try to keep the code as simple as possible -- contact the mailing list before embarking on large scale projects - to avoid wasted effort -- all new features must come with a test (or several if it is - a big feature) - -Meson uses Flake8 for style guide enforcement. The Flake8 options for -the project are contained in setup.cfg. - -To run Flake8 on your local clone of Meson: - - $ python3 -m pip install flake8 - $ cd meson - $ flake8 - -C/C++ coding style - -Meson has a bunch of test code in several languages. The rules for -those are simple. - -- indent 4 spaces, no tabs ever -- brace always on the same line as if/for/else/function definition - - -External dependencies - -The goal of Meson is to be as easily usable as possible. The user -experience should be "get Python3 and Ninja, run", even on -Windows. Unfortunately this means that we can't have dependencies on -projects outside of Python's standard library. This applies only to -core functionality, though. For additional helper programs etc the use -of external dependencies may be ok. If you feel that you are dealing -with this kind of case, please raise the issue on the mailing list -first. - - -What not to contribute? - -There are a few things that people seem to want to add to Meson but which -are not there by design and will not be added either. - -The first one is defining your own functions or a generalized for loop. -These are bad because they would make Meson's DSL Turing complete. The -second feature is a Make backend. - -The FAQ has specific information why these two features will not be -added to Meson: http://mesonbuild.com/FAQ.html - -Merge requests adding either of these two features will be automatically -rejected. Please save everyone's time (especially your own) and don't start -working on these features. - - -Do I need to sign a CLA? - -No. All contributions are welcome. +Contribution instructions can be found [on the +website](http://mesonbuild.com/Contributing.html). diff --git a/docs/markdown/Contributing.md b/docs/markdown/Contributing.md new file mode 100644 index 0000000..354bf62 --- /dev/null +++ b/docs/markdown/Contributing.md @@ -0,0 +1,144 @@ +--- +short-description: Contributing to Meson +... + +# Contributing to Meson + +A large fraction of Meson is contributed by people outside the core +team. This documentation explains some of the design rationales of +Meson as well as how to create and submit your patches for inclusion +to Meson. + +Thank you for your interest in participating to the development. + +## Submitting patches + +All changes must be submitted as [pull requests to +Github](https://github.com/mesonbuild/meson/pulls). This causes them +to be run through the CI system. All submissions must pass a full CI +test run before they are even considered for submission. + +## Tests + +All new features must come with automatic tests that throughly prove +that the feature is working as expected. Similarly bug fixes must come +with a unit test that demonstrates the bug, proves that it has been +fixed and prevents the feature from breaking in the future. + +Sometimes it is difficult to create a unit test for a given bug. If +this is the case, note this in your pull request. We may permit bug +fix merge requests in these cases. This is done on a case by case +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. + +## Documentation + +The `docs` directory contains the full documentation that will be used +to generate [the Meson web site](http://mesonbuild.com). Every change +in functionality must change the documentation pages. In most cases +this means updating the reference documentation page but bigger +changes might need changes in other documentation, too. + +All new functionality needs to have a mention in the release +notes. These features should be written in standalone files in the +`docs/markdown/snippets` directory. The release manager will combine +them into one page when doing the release. + +## Python Coding style + +Meson follows the basic Python coding style. Additional rules are the +following: + +- indent 4 spaces, no tabs ever +- indent meson.build files with two spaces +- try to keep the code as simple as possible +- contact the mailing list before embarking on large scale projects + to avoid wasted effort + +Meson uses Flake8 for style guide enforcement. The Flake8 options for +the project are contained in setup.cfg. + +To run Flake8 on your local clone of Meson: + +```console +$ python3 -m pip install flake8 +$ cd meson +$ flake8 +``` + +## C/C++ coding style + +Meson has a bunch of test code in several languages. The rules for +those are simple. + +- indent 4 spaces, no tabs ever +- brace always on the same line as if/for/else/function definition + + + +## External dependencies + +The goal of Meson is to be as easily usable as possible. The user +experience should be "get Python3 and Ninja, run", even on +Windows. Unfortunately this means that we can't have dependencies on +projects outside of Python's standard library. This applies only to +core functionality, though. For additional helper programs etc the use +of external dependencies may be ok. If you feel that you are dealing +with this kind of case, please contact the developers first with your +use case. + +## Turing completeness + +The main design principle of Meson is that the definition language is +not Turing complete. Any change that would make Meson Turing complete +is automatically rejected. In practice this means that defining your +own functions inside `meson.build` files and generalised loops will +not be added to the language. + +## Do I need to sign a CLA in order to contribute? + +No you don't. All contributions are welcome. + +## No lingering state + +Meson operates in much the same way as functional programming +languages. It has inputs, which include `meson.build` files, values of +options, compilers and so on. These are passed to a function, which +generates output build definition. This function is pure, which means that: + + - for any given input the output is always the same + - running Meson twice in a row _always_ produce the same output in both runs + +The latter one is important, because it enforces that there is no way +for "secret state" to pass between consecutive invocations of +Meson. This is the reason why, for example, there is no `set_option` +function even though there is a `get_option` one. + +If this were not the case, we could never know if the build output is +"stable". For example suppose there were a `set_option` function and a +boolean variable `flipflop`. Then you could do this: + +```meson +set_option('flipflop', not get_option('flipflop')) +``` + +This piece of code would never converge. Every Meson run would change +the value of the option and thus the output you get out of this build +definition would be random. + +Meson does not permit this by forbidding these sorts of covert channels. + +There is one exception to this rule. Users can call into external +commands with `run_command`. If the output of that command does not +behave like a pure function, this problem arises. Meson does not try +to guard against this case, it is the responsibility of the user to +make sure the commands they run behave like pure functions. + +## Environment variables + +Environment variables are like global variables, except that they are +also hidden by default. Envvars should be avoided whenever possible, +all functionality should be exposed in better ways such as command +line switches. + 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/index.md b/docs/markdown/index.md index 81c17ff..5f42cc7 100644 --- a/docs/markdown/index.md +++ b/docs/markdown/index.md @@ -6,9 +6,13 @@ render-subpages: false ## Overview -Meson is an open source build system meant to be both extremely fast, and, even more importantly, as user friendly as possible. +Meson is an open source build system meant to be both extremely fast, +and, even more importantly, as user friendly as possible. -The main design point of Meson is that every moment a developer spends writing or debugging build definitions is a second wasted. So is every second spent waiting for the build system to actually start compiling code. +The main design point of Meson is that every moment a developer spends +writing or debugging build definitions is a second wasted. So is every +second spent waiting for the build system to actually start compiling +code. ## Features @@ -22,12 +26,18 @@ The main design point of Meson is that every moment a developer spends writing o ## Community -There are two main methods of connecting with other Meson developers. The first one is the mailing list, which is hosted at [Google Groups](https://groups.google.com/forum/#!forum/mesonbuild). +There are two main methods of connecting with other Meson +developers. The first one is the mailing list, which is hosted at +[Google Groups](https://groups.google.com/forum/#!forum/mesonbuild). -The second way is via IRC. The channel to use is `#mesonbuild` at [Freenode](https://freenode.net/). +The second way is via IRC. The channel to use is `#mesonbuild` at +[Freenode](https://freenode.net/). ## Development -All development on Meson is done on [GitHub project](https://github.com/mesonbuild/meson). For further info look into the `contributing.txt` file that comes with Meson's source checkout. +All development on Meson is done on [GitHub +project](https://github.com/mesonbuild/meson). Instruction on +contributing can be found on the [contribution page](Contributing.md). + You do not need to sign a CLA to contribute to Meson. diff --git a/docs/markdown/snippets/if-release.md b/docs/markdown/snippets/if-release.md new file mode 100644 index 0000000..96e12ef --- /dev/null +++ b/docs/markdown/snippets/if-release.md @@ -0,0 +1,7 @@ +## b_ndebug : if-release + +The value `if-release` can be given for the `b_ndebug` project option. + +This will make the `NDEBUG` pre-compiler macro to be defined for release +type builds as if the `b_ndebug` project option had had the value `true` +defined for it. diff --git a/docs/sitemap.txt b/docs/sitemap.txt index 77a4e6f..b7ee136 100644 --- a/docs/sitemap.txt +++ b/docs/sitemap.txt @@ -90,5 +90,6 @@ index.md Use-of-Python.md Users.md Using-multiple-build-directories.md + Contributing.md legal.md Videos.md 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/c.py b/mesonbuild/compilers/c.py index 8753c56..233fc84 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -42,11 +42,11 @@ from .compilers import ( class CCompiler(Compiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None): + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs): # If a child ObjC or CPP class has already set it, don't set it ourselves if not hasattr(self, 'language'): self.language = 'c' - super().__init__(exelist, version) + super().__init__(exelist, version, **kwargs) self.id = 'unknown' self.is_cross = is_cross self.can_compile_suffixes.add('h') @@ -97,7 +97,7 @@ class CCompiler(Compiler): return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) def get_dependency_gen_args(self, outtarget, outfile): - return ['-MMD', '-MQ', outtarget, '-MF', outfile] + return ['-MD', '-MQ', outtarget, '-MF', outfile] def depfile_for_object(self, objfile): return objfile + '.' + self.get_depfile_suffix() @@ -800,8 +800,8 @@ class CCompiler(Compiler): class ClangCCompiler(ClangCompiler, CCompiler): - def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None, **kwargs): + CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) ClangCompiler.__init__(self, clang_type) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'1': default_warn_args, @@ -832,8 +832,8 @@ class ClangCCompiler(ClangCompiler, CCompiler): class GnuCCompiler(GnuCompiler, CCompiler): - def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs): + CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) GnuCompiler.__init__(self, gcc_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'1': default_warn_args, @@ -871,8 +871,8 @@ class GnuCCompiler(GnuCompiler, CCompiler): class IntelCCompiler(IntelCompiler, CCompiler): - def __init__(self, exelist, version, icc_type, is_cross, exe_wrapper=None): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + def __init__(self, exelist, version, icc_type, is_cross, exe_wrapper=None, **kwargs): + CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) IntelCompiler.__init__(self, icc_type) self.lang_header = 'c-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark', '-Wpch-messages'] diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 011c222..24ae3c9 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -224,9 +224,8 @@ base_options = {'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled he 'b_colorout': coredata.UserComboOption('b_colorout', 'Use colored output', ['auto', 'always', 'never'], 'always'), - 'b_ndebug': coredata.UserBooleanOption('b_ndebug', - 'Disable asserts', - False), + 'b_ndebug': coredata.UserComboOption('b_ndebug', 'Disable asserts', + ['true', 'false', 'if-release'], 'false'), 'b_staticpic': coredata.UserBooleanOption('b_staticpic', 'Build static libraries as position independent', True), @@ -313,7 +312,7 @@ def get_base_compile_args(options, compiler): except KeyError: pass try: - if options['b_ndebug'].value: + if options['b_ndebug'].value == 'true' or (options['b_ndebug'].value == 'if-release' and options['buildtype'] == 'release'): args += ['-DNDEBUG'] except KeyError: pass @@ -598,7 +597,7 @@ class Compiler: # compiler or the C library. Currently only used for MSVC. ignore_libs = () - def __init__(self, exelist, version): + def __init__(self, exelist, version, **kwargs): if isinstance(exelist, str): self.exelist = [exelist] elif isinstance(exelist, list): @@ -612,6 +611,10 @@ class Compiler: self.can_compile_suffixes = set(self.file_suffixes) self.default_suffix = self.file_suffixes[0] self.version = version + if 'full_version' in kwargs: + self.full_version = kwargs['full_version'] + else: + self.full_version = None self.base_options = [] def __repr__(self): @@ -860,7 +863,12 @@ 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 diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index cb4b055..5e32ace 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -28,11 +28,11 @@ from .compilers import ( ) class CPPCompiler(CCompiler): - def __init__(self, exelist, version, is_cross, exe_wrap): + def __init__(self, exelist, version, is_cross, exe_wrap, **kwargs): # If a child ObjCPP class has already set it, don't set it ourselves if not hasattr(self, 'language'): self.language = 'cpp' - CCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + CCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) def get_display_language(self): return 'C++' @@ -66,8 +66,8 @@ class CPPCompiler(CCompiler): class ClangCPPCompiler(ClangCompiler, CPPCompiler): - def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None, **kwargs): + CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) ClangCompiler.__init__(self, cltype) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'1': default_warn_args, @@ -92,8 +92,8 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler): class GnuCPPCompiler(GnuCompiler, CPPCompiler): - def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines, **kwargs): + CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) GnuCompiler.__init__(self, gcc_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'1': default_warn_args, @@ -133,8 +133,8 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler): class IntelCPPCompiler(IntelCompiler, CPPCompiler): - def __init__(self, exelist, version, icc_type, is_cross, exe_wrap): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + def __init__(self, exelist, version, icc_type, is_cross, exe_wrap, **kwargs): + CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) IntelCompiler.__init__(self, icc_type) self.lang_header = 'c++-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark', diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py index b8a4d13..dd7a433 100644 --- a/mesonbuild/compilers/cs.py +++ b/mesonbuild/compilers/cs.py @@ -19,9 +19,9 @@ from ..mesonlib import EnvironmentException from .compilers import Compiler, mono_buildtype_args class MonoCompiler(Compiler): - def __init__(self, exelist, version): + def __init__(self, exelist, version, **kwargs): self.language = 'cs' - super().__init__(exelist, version) + super().__init__(exelist, version, **kwargs) self.id = 'mono' self.monorunner = 'mono' diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 9739f28..9681a9f 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -42,9 +42,9 @@ d_feature_args = {'gcc': {'unittest': '-funittest', } class DCompiler(Compiler): - def __init__(self, exelist, version, is_cross): + def __init__(self, exelist, version, is_cross, **kwargs): self.language = 'd' - super().__init__(exelist, version) + super().__init__(exelist, version, **kwargs) self.id = 'unknown' self.is_cross = is_cross @@ -224,8 +224,8 @@ class DCompiler(Compiler): class GnuDCompiler(DCompiler): - def __init__(self, exelist, version, is_cross): - DCompiler.__init__(self, exelist, version, is_cross) + def __init__(self, exelist, version, is_cross, **kwargs): + DCompiler.__init__(self, exelist, version, is_cross, **kwargs) self.id = 'gcc' default_warn_args = ['-Wall', '-Wdeprecated'] self.warn_args = {'1': default_warn_args, @@ -267,8 +267,8 @@ class GnuDCompiler(DCompiler): class LLVMDCompiler(DCompiler): - def __init__(self, exelist, version, is_cross): - DCompiler.__init__(self, exelist, version, is_cross) + def __init__(self, exelist, version, is_cross, **kwargs): + DCompiler.__init__(self, exelist, version, is_cross, **kwargs) self.id = 'llvm' self.base_options = ['b_coverage', 'b_colorout'] @@ -321,8 +321,8 @@ class LLVMDCompiler(DCompiler): class DmdDCompiler(DCompiler): - def __init__(self, exelist, version, is_cross): - DCompiler.__init__(self, exelist, version, is_cross) + def __init__(self, exelist, version, is_cross, **kwargs): + DCompiler.__init__(self, exelist, version, is_cross, **kwargs) self.id = 'dmd' self.base_options = ['b_coverage', 'b_colorout'] diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 2957a7c..1b42bfa 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -31,9 +31,9 @@ from .compilers import ( ) class FortranCompiler(Compiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None): + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs): self.language = 'fortran' - super().__init__(exelist, version) + super().__init__(exelist, version, **kwargs) self.is_cross = is_cross self.exe_wrapper = exe_wrapper # Not really correct but I don't have Fortran compilers to test with. Sorry. @@ -99,7 +99,7 @@ end program prog def get_dependency_gen_args(self, outtarget, outfile): # Disabled until this is fixed: # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162 - # return ['-cpp', '-MMD', '-MQ', outtarget] + # return ['-cpp', '-MD', '-MQ', outtarget] return [] def get_output_args(self, target): @@ -149,8 +149,8 @@ end program prog class GnuFortranCompiler(FortranCompiler): - def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None): - super().__init__(exelist, version, is_cross, exe_wrapper=None) + def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs): + super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwargs) self.gcc_type = gcc_type self.defines = defines or {} self.id = 'gcc' @@ -181,8 +181,8 @@ class GnuFortranCompiler(FortranCompiler): class G95FortranCompiler(FortranCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None): - super().__init__(exelist, version, is_cross, exe_wrapper=None) + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): + super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'g95' def get_module_outdir_args(self, path): @@ -205,8 +205,8 @@ class G95FortranCompiler(FortranCompiler): class SunFortranCompiler(FortranCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None): - super().__init__(exelist, version, is_cross, exe_wrapper=None) + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): + super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'sun' def get_dependency_gen_args(self, outtarget, outfile): @@ -228,9 +228,9 @@ class SunFortranCompiler(FortranCompiler): class IntelFortranCompiler(IntelCompiler, FortranCompiler): std_warn_args = ['-warn', 'all'] - def __init__(self, exelist, version, is_cross, exe_wrapper=None): + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp') - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) # FIXME: Add support for OS X and Windows in detect_fortran_compiler so # we are sent the type of compiler IntelCompiler.__init__(self, ICC_STANDARD) @@ -246,8 +246,8 @@ class IntelFortranCompiler(IntelCompiler, FortranCompiler): class PathScaleFortranCompiler(FortranCompiler): std_warn_args = ['-fullwarn'] - def __init__(self, exelist, version, is_cross, exe_wrapper=None): - super().__init__(exelist, version, is_cross, exe_wrapper=None) + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): + super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'pathscale' def get_module_outdir_args(self, path): @@ -259,8 +259,8 @@ class PathScaleFortranCompiler(FortranCompiler): class PGIFortranCompiler(FortranCompiler): std_warn_args = ['-Minform=inform'] - def __init__(self, exelist, version, is_cross, exe_wrapper=None): - super().__init__(exelist, version, is_cross, exe_wrapper=None) + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): + super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'pgi' def get_module_incdir_args(self): @@ -279,8 +279,8 @@ class PGIFortranCompiler(FortranCompiler): class Open64FortranCompiler(FortranCompiler): std_warn_args = ['-fullwarn'] - def __init__(self, exelist, version, is_cross, exe_wrapper=None): - super().__init__(exelist, version, is_cross, exe_wrapper=None) + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): + super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'open64' def get_module_outdir_args(self, path): @@ -293,8 +293,8 @@ class Open64FortranCompiler(FortranCompiler): class NAGFortranCompiler(FortranCompiler): std_warn_args = [] - def __init__(self, exelist, version, is_cross, exe_wrapper=None): - super().__init__(exelist, version, is_cross, exe_wrapper=None) + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): + super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'nagfor' def get_module_outdir_args(self, path): diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index cf7df5e..d4a91a7 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +from . import mlog import pickle, os, uuid import sys from pathlib import PurePath @@ -148,6 +149,9 @@ class UserArrayOption(UserOption): newvalue = ast.literal_eval(value) else: newvalue = [v.strip() for v in value.split(',')] + if len(set(newvalue)) != len(newvalue): + mlog.log(mlog.red('DEPRECATION:'), '''Duplicated values in an array type is deprecated. +This will become a hard error in the future.''') if not isinstance(newvalue, list): raise MesonException('"{0}" should be a string array, but it is not'.format(str(newvalue))) for i in newvalue: diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index ce9313e..7ceda3e 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)) @@ -804,7 +817,7 @@ class CupsDependency(ExternalDependency): self.type_name = 'config-tool' self.version = ctdep.version self.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args') - self.link_args = ctdep.get_config_value(['--libs'], 'link_args') + self.link_args = ctdep.get_config_value(['--ldflags', '--libs'], 'link_args') self.is_found = True return except Exception as e: diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 0cb1450..858d31d 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -496,6 +496,7 @@ class Environment: popen_exceptions[' '.join(compiler + [arg])] = e continue version = search_version(out) + full_version = out.split('\n', 1)[0] if 'Free Software Foundation' in out: defines = self.get_gnu_compiler_defines(compiler) if not defines: @@ -504,7 +505,7 @@ class Environment: gtype = self.get_gnu_compiler_type(defines) version = self.get_gnu_version_from_defines(defines) cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler - return cls(ccache + compiler, version, gtype, is_cross, exe_wrap, defines) + return cls(ccache + compiler, version, gtype, is_cross, exe_wrap, defines, full_version=full_version) if 'clang' in out: if 'Apple' in out or mesonlib.for_darwin(want_cross, self): cltype = CLANG_OSX @@ -513,7 +514,7 @@ class Environment: else: cltype = CLANG_STANDARD cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler - return cls(ccache + compiler, version, cltype, is_cross, exe_wrap) + return cls(ccache + compiler, version, cltype, is_cross, exe_wrap, full_version=full_version) if 'Microsoft' in out or 'Microsoft' in err: # Latest versions of Visual Studio print version # number to stderr but earlier ones print version @@ -532,7 +533,7 @@ class Environment: # TODO: add microsoft add check OSX inteltype = ICC_STANDARD cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler - return cls(ccache + compiler, version, inteltype, is_cross, exe_wrap) + return cls(ccache + compiler, version, inteltype, is_cross, exe_wrap, full_version=full_version) self._handle_exceptions(popen_exceptions, compilers) def detect_c_compiler(self, want_cross): @@ -555,6 +556,7 @@ class Environment: continue version = search_version(out) + full_version = out.split('\n', 1)[0] if 'GNU Fortran' in out: defines = self.get_gnu_compiler_defines(compiler) @@ -563,29 +565,29 @@ class Environment: continue gtype = self.get_gnu_compiler_type(defines) version = self.get_gnu_version_from_defines(defines) - return GnuFortranCompiler(compiler, version, gtype, is_cross, exe_wrap, defines) + return GnuFortranCompiler(compiler, version, gtype, is_cross, exe_wrap, defines, full_version=full_version) if 'G95' in out: - return G95FortranCompiler(compiler, version, is_cross, exe_wrap) + return G95FortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) if 'Sun Fortran' in err: version = search_version(err) - return SunFortranCompiler(compiler, version, is_cross, exe_wrap) + return SunFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) if 'ifort (IFORT)' in out: - return IntelFortranCompiler(compiler, version, is_cross, exe_wrap) + return IntelFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) if 'PathScale EKOPath(tm)' in err: - return PathScaleFortranCompiler(compiler, version, is_cross, exe_wrap) + return PathScaleFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) if 'PGI Compilers' in out: - return PGIFortranCompiler(compiler, version, is_cross, exe_wrap) + return PGIFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) if 'Open64 Compiler Suite' in err: - return Open64FortranCompiler(compiler, version, is_cross, exe_wrap) + return Open64FortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) if 'NAG Fortran' in err: - return NAGFortranCompiler(compiler, version, is_cross, exe_wrap) + return NAGFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) self._handle_exceptions(popen_exceptions, compilers) def get_scratch_dir(self): @@ -665,8 +667,9 @@ class Environment: except OSError: raise EnvironmentException('Could not execute C# compiler "%s"' % ' '.join(exelist)) version = search_version(out) + full_version = out.split('\n', 1)[0] if 'Mono' in out: - return MonoCompiler(exelist, version) + return MonoCompiler(exelist, version, full_version=full_version) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') def detect_vala_compiler(self): @@ -721,12 +724,13 @@ class Environment: except OSError: raise EnvironmentException('Could not execute D compiler "%s"' % ' '.join(exelist)) version = search_version(out) + full_version = out.split('\n', 1)[0] if 'LLVM D compiler' in out: - return compilers.LLVMDCompiler(exelist, version, is_cross) + return compilers.LLVMDCompiler(exelist, version, is_cross, full_version=full_version) elif 'gdc' in out: - return compilers.GnuDCompiler(exelist, version, is_cross) + return compilers.GnuDCompiler(exelist, version, is_cross, full_version=full_version) elif 'Digital Mars' in out: - return compilers.DmdDCompiler(exelist, version, is_cross) + return compilers.DmdDCompiler(exelist, version, is_cross, full_version=full_version) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') def detect_swift_compiler(self): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 58bcf1d..444a6ee 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -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. @@ -2021,7 +2030,11 @@ to directly access options of other subprojects.''') continue else: raise - mlog.log('Native %s compiler: ' % comp.get_display_language(), mlog.bold(' '.join(comp.get_exelist())), ' (%s %s)' % (comp.id, comp.version), sep='') + if comp.full_version is not None: + version_string = ' (%s %s "%s")' % (comp.id, comp.version, comp.full_version) + else: + version_string = ' (%s %s)' % (comp.id, comp.version) + mlog.log('Native %s compiler: ' % comp.get_display_language(), mlog.bold(' '.join(comp.get_exelist())), version_string, sep='') if not comp.get_language() in self.coredata.external_args: (preproc_args, compile_args, link_args) = environment.get_args_from_envvars(comp) self.coredata.external_preprocess_args[comp.get_language()] = preproc_args @@ -2127,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. @@ -2168,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 diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index f261935..f811def 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) 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/run_project_tests.py b/run_project_tests.py index b94a976..323f9a3 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -312,10 +312,19 @@ def parse_test_args(testdir): pass return args +# Build directory name must be the same so CCache works over +# consecutive invocations. +def create_deterministic_builddir(src_dir): + import hashlib + rel_dirname = 'b ' + hashlib.sha256(src_dir.encode(errors='ignore')).hexdigest()[0:10] + os.mkdir(rel_dirname) + abs_pathname = os.path.join(os.getcwd(), rel_dirname) + return abs_pathname + def run_test(skipped, testdir, extra_args, compiler, backend, flags, commands, should_fail): if skipped: return None - with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: + with AutoDeletedDir(create_deterministic_builddir(testdir)) as build_dir: with AutoDeletedDir(tempfile.mkdtemp(prefix='i ', dir=os.getcwd())) as install_dir: try: return _run_test(testdir, build_dir, install_dir, extra_args, compiler, backend, flags, commands, should_fail) diff --git a/run_unittests.py b/run_unittests.py index d5dc36e..cf229da 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -790,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. @@ -1807,6 +1846,25 @@ 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"') + class WindowsTests(BasePlatformTests): ''' @@ -2294,11 +2352,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/frameworks/21 libwmf/meson.build b/test cases/frameworks/21 libwmf/meson.build index b39d8f4..1fdce2e 100644 --- a/test cases/frameworks/21 libwmf/meson.build +++ b/test cases/frameworks/21 libwmf/meson.build @@ -1,5 +1,10 @@ project('libwmf test', 'c') +wm = find_program('libwmf-config', required : false) +if not wm.found() + error('MESON_SKIP_TEST: libwmf-config not installed') +endif + libwmf_dep = dependency('libwmf', version : '>= 0.2.8') libwmf_ver = libwmf_dep.version() assert(libwmf_ver.split('.').length() > 1, 'libwmf version is "@0@"'.format(libwmf_ver)) 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/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/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') |