diff options
22 files changed, 102 insertions, 36 deletions
diff --git a/.travis.yml b/.travis.yml index fb86292..724f9ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,7 +47,7 @@ script: ci_env=`bash <(curl -s https://codecov.io/env)` docker run $ci_env -v ${PWD}/.coverage:/root/.coverage \ withgit \ - /bin/sh -c "cd /root && CC=$CC CXX=$CXX OBJC=$CC OBJCXX=$CXX ./run_tests.py --cov -- $MESON_ARGS; chmod -R a+rwX .coverage" + /bin/sh -c "cd /root && CC=$CC CXX=$CXX OBJC=$CC OBJCXX=$CXX ./run_tests.py --cov -- $MESON_ARGS && chmod -R a+rwX .coverage" fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) OBJC=$CC OBJCXX=$CXX ./run_tests.py --cov --backend=ninja -- $MESON_ARGS ; fi diff --git a/docs/markdown/Adding-arguments.md b/docs/markdown/Adding-arguments.md index e049e82..0bf5944 100644 --- a/docs/markdown/Adding-arguments.md +++ b/docs/markdown/Adding-arguments.md @@ -15,7 +15,7 @@ Global compiler arguments are set with the following command. As an example you add_global_arguments('-DFOO=bar', language : 'c') ``` -This makes Meson add the define to all C compilations. Usually you would use this setting for flags for global settings. Note that for setting the C/C++ language standard (the `-std=c99` argument in GCC), you would probably want to use a default option of the `project()` function. For details see the [reference manual](Reference manual). +This makes Meson add the define to all C compilations. Usually you would use this setting for flags for global settings. Note that for setting the C/C++ language standard (the `-std=c99` argument in GCC), you would probably want to use a default option of the `project()` function. For details see the [reference manual](Reference-manual.md). Global arguments have certain limitations. They all have to be defined before any build targets are specified. This ensures that the global flags are the same for every single source file built in the entire project with one exception. Compilation tests that are run as part of your project configuration do not use these flags. The reason for that is that you may need to run a test compile with and without a given flag to determine your build setup. For this reason tests do not use these global arguments. diff --git a/docs/markdown/Comparisons.md b/docs/markdown/Comparisons.md index 4ceb930..eb0e4dd 100644 --- a/docs/markdown/Comparisons.md +++ b/docs/markdown/Comparisons.md @@ -50,7 +50,7 @@ Implemented in Java. Poor Windows support. Heavily focused on Google's way of do ### Pros ### -The fastest build system [see measurements](Performance comparison), user friendly, designed to be as invisible to the developer as possible, native support for modern tools (precompiled headers, coverage, Valgrind etc). Not Turing complete so build definition files are easy to read and understand. +The fastest build system [see measurements](Performance-comparison.md), user friendly, designed to be as invisible to the developer as possible, native support for modern tools (precompiled headers, coverage, Valgrind etc). Not Turing complete so build definition files are easy to read and understand. ### Cons ### diff --git a/docs/markdown/Compiler-properties.md b/docs/markdown/Compiler-properties.md index c33d917..83fc0d9 100644 --- a/docs/markdown/Compiler-properties.md +++ b/docs/markdown/Compiler-properties.md @@ -10,7 +10,7 @@ Here we extract the C compiler. We could also have given the argument `cpp` to g ## System information -This is a bit complex and more thoroughly explained on the page on [cross compilation](Cross compilation). But if you just want to know the operating system your code will run on, issue this command: +This is a bit complex and more thoroughly explained on the page on [cross compilation](Cross-compilation.md). But if you just want to know the operating system your code will run on, issue this command: ```meson host_machine.system() diff --git a/docs/markdown/Creating-Linux-binaries.md b/docs/markdown/Creating-Linux-binaries.md index 13940b5..3c48122 100644 --- a/docs/markdown/Creating-Linux-binaries.md +++ b/docs/markdown/Creating-Linux-binaries.md @@ -50,7 +50,7 @@ Old distros might have too old versions of some tools. For Meson this could incl ## Adding dependencies -You want to embed and statically link every dependency you can (especially C++ dependencies). Meson's [Wrap package manager might be of use here](Wrap dependency system manual). This is equivalent to what you would do on Windows, OSX, Android etc. Sometimes static linking is not possible. In these cases you need to copy the .so files inside your package. Let's use SDL2 as an example. First we download and install it as usual giving it our custom install prefix (that is, `./configure --prefix=${HOME}/devroot`). This makes Meson's dependency detector pick it up automatically. +You want to embed and statically link every dependency you can (especially C++ dependencies). Meson's [Wrap package manager](Wrap-dependency-system-manual.md) might be of use here. This is equivalent to what you would do on Windows, OSX, Android etc. Sometimes static linking is not possible. In these cases you need to copy the .so files inside your package. Let's use SDL2 as an example. First we download and install it as usual giving it our custom install prefix (that is, `./configure --prefix=${HOME}/devroot`). This makes Meson's dependency detector pick it up automatically. ## Building and installing diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index c835f6f..29c073c 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -124,7 +124,7 @@ When a list of strings is passed to the `command:` keyword argument, it takes an These are all the supported keyword arguments: - `input` the input file name. If it's not specified in configuration mode, all the variables in the `configuration:` object (see above) are written to the `output:` file. -- `output` the output file name. In configuration mode, the permissions of the input file (if it is specified) are copied to the output file. +- `output` the output file name (since v0.41.0, may contain `@PLAINNAME@` or `@BASENAME@` substitutions). In configuration mode, the permissions of the input file (if it is specified) are copied to the output file. - `configuration` as explained above, this is where you pass the configuration data object as returned by `configuration_data()` - `command` as explained above, if specified, Meson does not create the file itself but rather runs the specified command, which allows you to do fully custom file generation - `install_dir` the subdirectory to install the generated file to (e.g. `share/myproject`), if omitted the file is not installed. @@ -345,7 +345,7 @@ If you want to generate files for general purposes such as for generating header value get_option(option_name) ``` -Obtains the value of the [project build option](Build options) specified in the positional argument. +Obtains the value of the [project build option](Build-options.md) specified in the positional argument. ### get_variable() diff --git a/docs/markdown/Release-notes-for-0.41.0.md b/docs/markdown/Release-notes-for-0.41.0.md index 7da9ed7..f995cc5 100644 --- a/docs/markdown/Release-notes-for-0.41.0.md +++ b/docs/markdown/Release-notes-for-0.41.0.md @@ -61,3 +61,13 @@ Targets for building rust now take a `rust_args` keyword. Code coverage can be generated for tests by passing the `--cov` argument to the `run_tests.py` test runner. Note, since multiple processes are used, coverage must be combined before producing a report (`coverage3 combine`.) + +## Reproducible builds + +All known issues have been fixed and Meson can now build reproducible Debian +packages out of the box. + +## Extended template substitution in configure_file + +The output argument of `configure_file()` is parsed for @BASENAME@ and +@PLAINNAME@ substitutions. diff --git a/docs/markdown/Subprojects.md b/docs/markdown/Subprojects.md index b91366d..2dd012e 100644 --- a/docs/markdown/Subprojects.md +++ b/docs/markdown/Subprojects.md @@ -69,4 +69,4 @@ This uses the system dependency when available and the self built version if not # Obtaining subprojects -Meson ships with a dependency system to automatically obtain dependency subprojects. It is documented in the [Wrap dependency system manual](Wrap dependency system manual). +Meson ships with a dependency system to automatically obtain dependency subprojects. It is documented in the [Wrap dependency system manual](Wrap-dependency-system-manual.md). diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md index 2a7428b..5bbae7e 100644 --- a/docs/markdown/Syntax.md +++ b/docs/markdown/Syntax.md @@ -8,8 +8,7 @@ The syntax of Meson's specification language has been kept as simple as possible The main building blocks of the language are *variables*, *numbers*, *booleans*, *strings*, *arrays*, *function calls*, *method calls*, *if statements* and *includes*. -Usually one Meson statement takes just one line. There is no way to have multiple statements on one line as in e.g. *C*. Function and method calls' argument lists can be split over multiple lines. Meson will autodetect this case and do the right thing. Apart from line ending whitespace has no syntactical meaning. - +Usually one Meson statement takes just one line. There is no way to have multiple statements on one line as in e.g. *C*. Function and method calls' argument lists can be split over multiple lines. Meson will autodetect this case and do the right thing. In other cases you can get multi-line statements by ending the line with a `\`. Apart from line ending whitespace has no syntactic meaning. Variables -- diff --git a/docs/markdown/i18n-module.md b/docs/markdown/i18n-module.md index 9388be8..172f73e 100644 --- a/docs/markdown/i18n-module.md +++ b/docs/markdown/i18n-module.md @@ -19,6 +19,8 @@ This function also defines targets for maintainers to use: **Note**: These output to the source directory * `<project_id>-pot`: runs `xgettext` to regenerate the pot file +* `<project_id>-update-po`: regenerates the `.po` files from current `.pot` file +* `<project_id>-gmo`: builds the translations without installing ### i18n.merge_file() diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 29179aa..40a05bf 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2307,7 +2307,16 @@ rule FORTRAN_DEP_HACK commands += linker.get_option_link_args(self.environment.coredata.compiler_options) # Set runtime-paths so we can run executables without needing to set # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows. + if '/' in target.name or '\\' in target.name: + # Target names really should not have slashes in them, but + # unfortunately we did not check for that and some downstream projects + # now have them. Once slashes are forbidden, remove this bit. + target_slashname_workaround_dir = os.path.join(os.path.split(target.name)[0], + self.get_target_dir(target)) + else: + target_slashname_workaround_dir = self.get_target_dir(target) commands += linker.build_rpath_args(self.environment.get_build_dir(), + target_slashname_workaround_dir, self.determine_rpath_dirs(target), target.install_rpath) # Add libraries generated by custom targets diff --git a/mesonbuild/build.py b/mesonbuild/build.py index eb1b826..2c55ed4 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -271,7 +271,10 @@ class EnvironmentVariables: class Target: def __init__(self, name, subdir, build_by_default): if '/' in name or '\\' in name: - raise InvalidArguments('Target name must not contain a path separator.') + # Fix failing test 53 when this becomes an error. + mlog.warning('''Target "%s" has a path separator in its name. +This is not supported, it can cause unexpected failures and will become +a hard error in the future.''' % name) self.name = name self.subdir = subdir self.build_by_default = build_by_default diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index d0f3349..06b0a59 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -317,10 +317,20 @@ def get_base_link_args(options, linker, is_shared_module): pass return args -def build_unix_rpath_args(build_dir, rpath_paths, install_rpath): +def build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath): if not rpath_paths and not install_rpath: return [] - paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) + # The rpaths we write must be relative, because otherwise + # they have different length depending on the build + # directory. This breaks reproducible builds. + rel_rpaths = [] + for p in rpath_paths: + if p == from_dir: + relative = '' # relpath errors out in this case + else: + relative = os.path.relpath(p, from_dir) + rel_rpaths.append(relative) + paths = ':'.join([os.path.join('$ORIGIN', p) for p in rel_rpaths]) if len(paths) < len(install_rpath): padding = 'X' * (len(install_rpath) - len(paths)) if not paths: @@ -793,8 +803,8 @@ class CCompiler(Compiler): # The default behavior is this, override in # OSX and MSVC. - def build_rpath_args(self, build_dir, rpath_paths, install_rpath): - return build_unix_rpath_args(build_dir, rpath_paths, install_rpath) + def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + return build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath) def get_dependency_gen_args(self, outtarget, outfile): return ['-MMD', '-MQ', outtarget, '-MF', outfile] @@ -1402,10 +1412,10 @@ class CCompiler(Compiler): for suffix in suffixes: trial = os.path.join(d, 'lib' + libname + '.' + suffix) if os.path.isfile(trial): - return trial + return [trial] trial2 = os.path.join(d, libname + '.' + suffix) if os.path.isfile(trial2): - return trial2 + return [trial2] return None def thread_flags(self): @@ -1932,7 +1942,7 @@ class DCompiler(Compiler): def get_std_exe_link_args(self): return [] - def build_rpath_args(self, build_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): # This method is to be used by LDC and DMD. # GDC can deal with the verbatim flags. if not rpath_paths and not install_rpath: @@ -2055,8 +2065,8 @@ class GnuDCompiler(DCompiler): def get_buildtype_args(self, buildtype): return d_gdc_buildtype_args[buildtype] - def build_rpath_args(self, build_dir, rpath_paths, install_rpath): - return build_unix_rpath_args(build_dir, rpath_paths, install_rpath) + def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + return build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath) def get_unittest_args(self): return ['-funittest'] @@ -2264,7 +2274,7 @@ class VisualStudioCCompiler(CCompiler): "The name of the outputted import library" return ['/IMPLIB:' + implibname] - def build_rpath_args(self, build_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): return [] # FIXME, no idea what these should be. @@ -3013,8 +3023,8 @@ end program prog def get_std_exe_link_args(self): return [] - def build_rpath_args(self, build_dir, rpath_paths, install_rpath): - return build_unix_rpath_args(build_dir, rpath_paths, install_rpath) + def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + return build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath) def module_name_to_filename(self, module_name): return module_name.lower() + '.mod' @@ -3194,7 +3204,7 @@ class VisualStudioLinker(StaticLinker): def get_linker_always_args(self): return VisualStudioLinker.always_args - def build_rpath_args(self, build_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): return [] def thread_link_flags(self): @@ -3223,7 +3233,7 @@ class ArLinker(StaticLinker): else: self.std_args = ['csr'] - def build_rpath_args(self, build_dir, rpath_paths, install_rpath): + def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): return [] def get_exelist(self): diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index bf58472..7c83ed6 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -481,6 +481,8 @@ class Environment: if 'clang' in out: if 'Apple' in out or for_darwin(want_cross, self): cltype = CLANG_OSX + elif 'windows' in out or for_windows(want_cross, self): + cltype = CLANG_WIN else: cltype = CLANG_STANDARD cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index ca3cf75..39d596f 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2344,6 +2344,10 @@ class Interpreter(InterpreterBase): output = kwargs['output'] if not isinstance(output, str): raise InterpreterException('Output file name must be a string') + if ifile_abs: + values = mesonlib.get_filenames_templates_dict([ifile_abs], None) + outputs = mesonlib.substitute_values([output], values) + output = outputs[0] if os.path.split(output)[0] != '': raise InterpreterException('Output file name must not contain a subdirectory.') (ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output)) @@ -2595,14 +2599,7 @@ different subdirectory. else: mlog.debug('Unknown target type:', str(targetholder)) raise RuntimeError('Unreachable code') - # Fix failing test 53 when removing this. - if '/' in name or '\\' in name: - mlog.warning('Target name must not contain a path separator. This will become a hard error in a future release.') - subpart, name = os.path.split(name) - subdir = os.path.join(self.subdir, subpart) - else: - subdir = self.subdir - target = targetclass(name, subdir, self.subproject, is_cross, sources, objs, self.environment, kwargs) + target = targetclass(name, self.subdir, self.subproject, is_cross, sources, objs, self.environment, kwargs) if is_cross: self.add_cross_stdlib_info(target) l = targetholder(target, self) diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py index f8b538c..ef4f42a 100644 --- a/mesonbuild/scripts/gettext.py +++ b/mesonbuild/scripts/gettext.py @@ -88,7 +88,7 @@ def run(args): options = parser.parse_args(args) subcmd = options.command langs = options.langs.split('@@') if options.langs else None - extra_args = options.extra_args.split('@@') + extra_args = options.extra_args.split('@@') if options.extra_args else [] subdir = os.environ.get('MESON_SUBDIR', '') if options.subdir: subdir = options.subdir diff --git a/test cases/common/16 configure file/config4a.h.in b/test cases/common/16 configure file/config4a.h.in new file mode 100644 index 0000000..aafd195 --- /dev/null +++ b/test cases/common/16 configure file/config4a.h.in @@ -0,0 +1,2 @@ +/* Dummy file */ +#define RESULTA @ZERO@ diff --git a/test cases/common/16 configure file/config4b.h.in b/test cases/common/16 configure file/config4b.h.in new file mode 100644 index 0000000..3408bab --- /dev/null +++ b/test cases/common/16 configure file/config4b.h.in @@ -0,0 +1,2 @@ +/* Dummy file */ +#define RESULTB @ZERO@ diff --git a/test cases/common/16 configure file/meson.build b/test cases/common/16 configure file/meson.build index 8ffc28c..0d0e461 100644 --- a/test cases/common/16 configure file/meson.build +++ b/test cases/common/16 configure file/meson.build @@ -74,3 +74,15 @@ configure_file(output : 'config3.h', configuration : dump) test('Configless.', executable('dumpprog', 'dumpprog.c')) + + +# Config file generation in a loop with @BASENAME@ substitution +dump = configuration_data() +dump.set('ZERO', 0) +config_templates = files(['config4a.h.in', 'config4b.h.in']) +foreach config_template : config_templates + configure_file(input : config_template, output : '@BASENAME@', + configuration : dump) +endforeach + +test('Substituted', executable('prog4', 'prog4.c')) diff --git a/test cases/common/16 configure file/prog4.c b/test cases/common/16 configure file/prog4.c new file mode 100644 index 0000000..92dc7cb --- /dev/null +++ b/test cases/common/16 configure file/prog4.c @@ -0,0 +1,6 @@ +#include <config4a.h> +#include <config4b.h> + +int main(int argc, char **argv) { + return RESULTA + RESULTB; +} diff --git a/test cases/frameworks/6 gettext/po/POTFILES b/test cases/frameworks/6 gettext/po/POTFILES index f49cecd..8ac0de5 100644 --- a/test cases/frameworks/6 gettext/po/POTFILES +++ b/test cases/frameworks/6 gettext/po/POTFILES @@ -1,2 +1,2 @@ src/intlmain.c -data/test.desktop +data/test.desktop.in diff --git a/test cases/frameworks/6 gettext/po/intltest.pot b/test cases/frameworks/6 gettext/po/intltest.pot index d65e2c1..2d0a4cc 100644 --- a/test cases/frameworks/6 gettext/po/intltest.pot +++ b/test cases/frameworks/6 gettext/po/intltest.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: intltest\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-03-28 19:59+0300\n" +"POT-Creation-Date: 2017-05-31 05:16-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -20,3 +20,15 @@ msgstr "" #: src/intlmain.c:15 msgid "International greeting." msgstr "" + +#: data/test.desktop.in:3 +msgid "Test" +msgstr "" + +#: data/test.desktop.in:4 +msgid "Application" +msgstr "" + +#: data/test.desktop.in:5 +msgid "Test Application" +msgstr "" |