diff options
70 files changed, 812 insertions, 173 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/contributing.txt b/contributing.txt index fc6e0ba..925109a 100644 --- a/contributing.txt +++ b/contributing.txt @@ -19,6 +19,14 @@ following: - 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 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/Cross-compilation.md b/docs/markdown/Cross-compilation.md index c6817eb..b7ef354 100644 --- a/docs/markdown/Cross-compilation.md +++ b/docs/markdown/Cross-compilation.md @@ -58,6 +58,13 @@ c_link_args = ['-some_link_arg'] In most cases you don't need the size and alignment settings, Meson will detect all these by compiling and running some sample programs. If your build requires some piece of data that is not listed here, Meson will stop and write an error message describing how to fix the issue. If you need extra compiler arguments to be used during cross compilation you can set them with `[langname]_args = [args]`. Just remember to specify the args as an array and not as a single string (i.e. not as `'-DCROSS=1 -DSOMETHING=3'`). +One important thing to note, if you did not define an `exe_wrapper` in the previous section, is that Meson will make a best-effort guess at whether it can run the generated binaries on the build machine. It determines whether this is possible by looking at the `system` and `cpu_family` of build vs host. There will however be cases where they do match up, but the build machine is actually not compatible with the host machine. Typically this will happen if the libc used by the build and host machines are incompatible, or the code relies on kernel features not available on the build machine. One concrete example is a macOS build machine producing binaries for an iOS Simulator x86-64 host. They're both `darwin` and the same architecture, but their binaries are not actually compatible. In such cases you may use the `needs_exe_wrapper` property to override the auto-detection: + +```ini +[properties] +needs_exe_wrapper = true +``` + The last bit is the definition of host and target machines. Every cross build definition must have one or both of them. If it had neither, the build would not be a cross build but a native build. You do not need to define the build machine, as all necessary information about it is extracted automatically. The definitions for host and target machines look the same. Here is a sample for host machine. ```ini 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..b24e03f 100644 --- a/docs/markdown/Release-notes-for-0.41.0.md +++ b/docs/markdown/Release-notes-for-0.41.0.md @@ -61,3 +61,22 @@ 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. + +## Cross-config property for overriding whether an exe wrapper is needed + +The new `needs_exe_wrapper` property allows overriding auto-detection for +cases where `build_machine` appears to be compatible with `host_machine`, +but actually isn't. For example when: +- `build_machine` is macOS and `host_machine` is the iOS Simulator +- the `build_machine`'s libc is glibc but the `host_machine` libc is uClibc +- code relies on kernel features not available on the `build_machine` 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..09369e6 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 -- @@ -318,3 +317,8 @@ Most source trees have multiple subdirectories to process. These can be handled test_data_dir = 'data' subdir('tests') ``` + +User-defined functions and methods +-- + +Meson does not currently support user-defined functions or methods. The addition of user-defined functions would make Meson Turing-complete which would make it harder to reason about and more difficult to integrate with tools like IDEs. More details about this are [in the FAQ](FAQ.md#why-is-meson-not-just-a-python-module-so-i-could-code-my-build-setup-in-python). If because of this limitation you find yourself copying and pasting code a lot you may be able to use a [`foreach` loop instead](#foreach-statements). 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/manual tests/2 multiwrap/meson.build b/manual tests/2 multiwrap/meson.build index 81337ad..741a899 100644 --- a/manual tests/2 multiwrap/meson.build +++ b/manual tests/2 multiwrap/meson.build @@ -1,18 +1,12 @@ -project('multiwrap', 'c') +project('multiwrap', 'c', + default_options : 'c_std=c99') # Using multiple downloaded projects for great justice. -if meson.get_compiler('c').get_id() != 'msvc' - add_global_arguments('-std=c99', language : 'c') - extra_libs = ['-lm'] -else - extra_libs = [] -endif +cc = meson.get_compiler('c') -luap = subproject('lua') -pngp = subproject('libpng') +luadep = dependency('lua', fallback : ['lua', 'lua_dep']) +pngdep = dependency('libpng', fallback : ['libpng', 'pngdep']) executable('prog', 'prog.c', -include_directories : [pngp.get_variable('incdir'), luap.get_variable('incdir')], -link_with :[pngp.get_variable('libpng'), luap.get_variable('lualib')], -link_args : extra_libs) + dependencies : [pngdep, luadep]) diff --git a/manual tests/2 multiwrap/subprojects/libpng.wrap b/manual tests/2 multiwrap/subprojects/libpng.wrap index 45e639e..fb34a89 100644 --- a/manual tests/2 multiwrap/subprojects/libpng.wrap +++ b/manual tests/2 multiwrap/subprojects/libpng.wrap @@ -1,10 +1,10 @@ [wrap-file] -directory = libpng-1.6.16 +directory = libpng-1.6.17 -source_url = ftp://ftp.simplesystems.org/pub/libpng/png/src/history/libpng16/libpng-1.6.16.tar.gz -source_filename = libpng-1.6.16.tar.gz -source_hash = 02f96b6bad5a381d36d7ba7a5d9be3b06f7fe6c274da00707509c23592a073ad +source_url = ftp://ftp.simplesystems.org/pub/libpng/png/src/history/libpng16/libpng-1.6.17.tar.xz +source_filename = libpng-1.6.17.tar.xz +source_hash = 98507b55fbe5cd43c51981f2924e4671fd81fe35d52dc53357e20f2c77fa5dfd -patch_url = https://dl.dropboxusercontent.com/u/37517477/libpng-meson.tar.gz -patch_filename = libpng-meson.tar.gz -patch_hash = b91d1abb19711a5aaa4b8581000df0e15420e46d9ce6ecf688e33144ea688f06 +patch_url = https://wrapdb.mesonbuild.com/v1/projects/libpng/1.6.17/6/get_zip +patch_filename = libpng-1.6.17-6-wrap.zip +patch_hash = 8bd272e28e6ae84691935e84bca9f5eb02632221e6faccf427eb71bf745a7295 diff --git a/manual tests/2 multiwrap/subprojects/lua.wrap b/manual tests/2 multiwrap/subprojects/lua.wrap index cf2db19..c1a179a 100644 --- a/manual tests/2 multiwrap/subprojects/lua.wrap +++ b/manual tests/2 multiwrap/subprojects/lua.wrap @@ -6,6 +6,6 @@ source_filename = lua-5.3.0.tar.gz source_hash = ae4a5eb2d660515eb191bfe3e061f2b8ffe94dce73d32cfd0de090ddcc0ddb01 -patch_url = http://wrapdb.mesonbuild.com/v1/projects/lua/5.3.0/2/get_zip -patch_filename = lua-5.3.0-2-wrap.zip -patch_hash = f7bc18b6a6487dd7d78b5d3b2d49861a76212dfd79b40e32f4b1e5655361ffb5 +patch_url = https://wrapdb.mesonbuild.com/v1/projects/lua/5.3.0/5/get_zip +patch_filename = lua-5.3.0-5-wrap.zip +patch_hash = 439038309a0700adfb67d764b3fe935ed8601b31f819fc369e1438c6e79334dd diff --git a/manual tests/2 multiwrap/subprojects/zlib.wrap b/manual tests/2 multiwrap/subprojects/zlib.wrap index 319a0d1..6d5896f 100644 --- a/manual tests/2 multiwrap/subprojects/zlib.wrap +++ b/manual tests/2 multiwrap/subprojects/zlib.wrap @@ -1,10 +1,10 @@ [wrap-file] directory = zlib-1.2.8 -source_url = http://zlib.net/zlib-1.2.8.tar.gz +source_url = http://zlib.net/fossils/zlib-1.2.8.tar.gz source_filename = zlib-1.2.8.tar.gz source_hash = 36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d -patch_url = http://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/4/get_zip -patch_filename = zlib-1.2.8-4-wrap.zip -patch_hash = 2327a42c8f73a4289ee8c9cd4abc43b324d0decc28d6e609e927f0a50321af4a +patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/8/get_zip +patch_filename = zlib-1.2.8-8-wrap.zip +patch_hash = 17c52a0e0c59ce926d3959005d5cd8178c6c7e2c9a4a1304279a8320c955ac60 diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 75974a5..3044ce6 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -453,15 +453,11 @@ class Backend: for d in deps: if not isinstance(d, (build.StaticLibrary, build.SharedLibrary)): raise RuntimeError('Tried to link with a non-library target "%s".' % d.get_basename()) - if isinstance(compiler, compilers.LLVMDCompiler) or isinstance(compiler, compilers.DmdDCompiler): - args += ['-L' + self.get_target_filename_for_linking(d)] + if isinstance(compiler, (compilers.LLVMDCompiler, compilers.DmdDCompiler)): + d_arg = '-L' + self.get_target_filename_for_linking(d) else: - args.append(self.get_target_filename_for_linking(d)) - # If you have executable e that links to shared lib s1 that links to shared library s2 - # you have to specify s2 as well as s1 when linking e even if e does not directly use - # s2. Gcc handles this case fine but Clang does not for some reason. Thus we need to - # explictly specify all libraries every time. - args += self.build_target_link_arguments(compiler, d.get_dependencies()) + d_arg = self.get_target_filename_for_linking(d) + args.append(d_arg) return args def determine_windows_extra_paths(self, target): @@ -629,7 +625,6 @@ class Backend: return True return False - def get_custom_target_sources(self, target): ''' Custom target sources can be of various object types; strings, File, diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 8ab57ea..40a05bf 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -12,6 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +import shlex +import os, sys, pickle, re +import subprocess, shutil +from collections import OrderedDict + from . import backends from .. import modules from .. import environment, mesonlib @@ -24,16 +29,13 @@ from ..mesonlib import File, MesonException, OrderedSet from ..mesonlib import get_meson_script, get_compiler_for_source from .backends import CleanTrees, InstallData from ..build import InvalidArguments -import os, sys, pickle, re -import subprocess, shutil -from collections import OrderedDict if mesonlib.is_windows(): - quote_char = '"' + quote_func = lambda s: '"{}"'.format(s) execute_wrapper = 'cmd /c' rmfile_prefix = 'del /f /s /q {} &&' else: - quote_char = "'" + quote_func = shlex.quote execute_wrapper = '' rmfile_prefix = 'rm -f {} &&' @@ -58,22 +60,22 @@ class NinjaBuildElement: self.infilenames = [infilenames] else: self.infilenames = infilenames - self.deps = [] - self.orderdeps = [] + self.deps = set() + self.orderdeps = set() self.elems = [] self.all_outputs = all_outputs def add_dep(self, dep): if isinstance(dep, list): - self.deps += dep + self.deps.update(dep) else: - self.deps.append(dep) + self.deps.add(dep) def add_orderdep(self, dep): if isinstance(dep, list): - self.orderdeps += dep + self.orderdeps.update(dep) else: - self.orderdeps.append(dep) + self.orderdeps.add(dep) def add_item(self, name, elems): if isinstance(elems, str): @@ -105,18 +107,17 @@ class NinjaBuildElement: (name, elems) = e should_quote = name not in raw_names line = ' %s = ' % name - q_templ = quote_char + "%s" + quote_char noq_templ = "%s" newelems = [] for i in elems: if not should_quote or i == '&&': # Hackety hack hack - templ = noq_templ + quoter = ninja_quote else: - templ = q_templ + quoter = lambda x: ninja_quote(quote_func(x)) i = i.replace('\\', '\\\\') - if quote_char == '"': + if quote_func('') == '""': i = i.replace('"', '\\"') - newelems.append(templ % ninja_quote(i)) + newelems.append(quoter(i)) line += ' '.join(newelems) line += '\n' outfile.write(line) @@ -854,12 +855,12 @@ int dummy; outfile.write(' depfile = $DEPFILE\n') outfile.write(' restat = 1\n\n') outfile.write('rule REGENERATE_BUILD\n') - c = (quote_char + ninja_quote(sys.executable) + quote_char, - quote_char + ninja_quote(self.environment.get_build_command()) + quote_char, + c = (ninja_quote(quote_func(sys.executable)), + ninja_quote(quote_func(self.environment.get_build_command())), '--internal', 'regenerate', - quote_char + ninja_quote(self.environment.get_source_dir()) + quote_char, - quote_char + ninja_quote(self.environment.get_build_dir()) + quote_char) + ninja_quote(quote_func(self.environment.get_source_dir())), + ninja_quote(quote_func(self.environment.get_build_dir()))) outfile.write(" command = %s %s %s %s %s %s --backend ninja\n" % c) outfile.write(' description = Regenerating build files.\n') outfile.write(' generator = 1\n\n') @@ -1515,7 +1516,7 @@ rule FORTRAN_DEP_HACK pass return [] - def generate_compile_rule_for(self, langname, compiler, qstr, is_cross, outfile): + def generate_compile_rule_for(self, langname, compiler, is_cross, outfile): if langname == 'java': if not is_cross: self.generate_java_compile_rule(compiler, outfile) @@ -1547,7 +1548,7 @@ rule FORTRAN_DEP_HACK quoted_depargs = [] for d in depargs: if d != '$out' and d != '$in': - d = qstr % d + d = quote_func(d) quoted_depargs.append(d) cross_args = self.get_cross_info_lang_args(langname, is_cross) if mesonlib.is_windows(): @@ -1576,7 +1577,7 @@ rule FORTRAN_DEP_HACK outfile.write(description) outfile.write('\n') - def generate_pch_rule_for(self, langname, compiler, qstr, is_cross, outfile): + def generate_pch_rule_for(self, langname, compiler, is_cross, outfile): if langname != 'c' and langname != 'cpp': return if is_cross: @@ -1595,7 +1596,7 @@ rule FORTRAN_DEP_HACK quoted_depargs = [] for d in depargs: if d != '$out' and d != '$in': - d = qstr % d + d = quote_func(d) quoted_depargs.append(d) if compiler.get_id() == 'msvc': output = '' @@ -1621,12 +1622,11 @@ rule FORTRAN_DEP_HACK outfile.write('\n') def generate_compile_rules(self, outfile): - qstr = quote_char + "%s" + quote_char for langname, compiler in self.build.compilers.items(): if compiler.get_id() == 'clang': self.generate_llvm_ir_compile_rule(compiler, False, outfile) - self.generate_compile_rule_for(langname, compiler, qstr, False, outfile) - self.generate_pch_rule_for(langname, compiler, qstr, False, outfile) + self.generate_compile_rule_for(langname, compiler, False, outfile) + self.generate_pch_rule_for(langname, compiler, False, outfile) if self.environment.is_cross_build(): # In case we are going a target-only build, make the native compilers # masquerade as cross compilers. @@ -1637,8 +1637,8 @@ rule FORTRAN_DEP_HACK for langname, compiler in cclist.items(): if compiler.get_id() == 'clang': self.generate_llvm_ir_compile_rule(compiler, True, outfile) - self.generate_compile_rule_for(langname, compiler, qstr, True, outfile) - self.generate_pch_rule_for(langname, compiler, qstr, True, outfile) + self.generate_compile_rule_for(langname, compiler, True, outfile) + self.generate_pch_rule_for(langname, compiler, True, outfile) outfile.write('\n') def generate_generator_list_rules(self, target, outfile): @@ -1989,7 +1989,7 @@ rule FORTRAN_DEP_HACK rel_src = os.path.join(src.subdir, src.fname) if os.path.isabs(rel_src): assert(rel_src.startswith(self.environment.get_build_dir())) - rel_src = rel_src[len(self.environment.get_build_dir())+1:] + rel_src = rel_src[len(self.environment.get_build_dir()) + 1:] abs_src = os.path.join(self.environment.get_build_dir(), rel_src) elif isinstance(src, mesonlib.File): rel_src = src.rel_to_builddir(self.build_to_src) @@ -2008,7 +2008,7 @@ rule FORTRAN_DEP_HACK src_filename = os.path.join(src.subdir, src.fname) if os.path.isabs(src_filename): assert(src_filename.startswith(self.environment.get_build_dir())) - src_filename = src_filename[len(self.environment.get_build_dir())+1:] + src_filename = src_filename[len(self.environment.get_build_dir()) + 1:] else: src_filename = src.fname elif os.path.isabs(src): @@ -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/backend/vs2015backend.py b/mesonbuild/backend/vs2015backend.py index eb543ee..29b33fb 100644 --- a/mesonbuild/backend/vs2015backend.py +++ b/mesonbuild/backend/vs2015backend.py @@ -21,4 +21,3 @@ class Vs2015Backend(Vs2010Backend): self.name = 'vs2015' self.platform_toolset = 'v140' self.vs_version = '2015' - diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 35c0d84..c48fb07 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -335,16 +335,16 @@ class XCodeBackend(backends.Backend): for tname, t in self.build.targets.items(): self.ofile.write('\n/* Begin PBXFrameworksBuildPhase section */\n') self.indent_level += 1 - self.write_line('%s /* %s */ = {\n' %(t.buildphasemap['Frameworks'], 'Frameworks')) + self.write_line('%s /* %s */ = {\n' % (t.buildphasemap['Frameworks'], 'Frameworks')) self.indent_level += 1 self.write_line('isa = PBXFrameworksBuildPhase;\n') - self.write_line('buildActionMask = %s;\n' %(2147483647)) + self.write_line('buildActionMask = %s;\n' % (2147483647)) self.write_line('files = (\n') self.indent_level += 1 for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: - self.write_line('%s /* %s.framework in Frameworks */,\n' %(self.native_frameworks[f], f)) + self.write_line('%s /* %s.framework in Frameworks */,\n' % (self.native_frameworks[f], f)) self.indent_level -= 1 self.write_line(');\n') self.write_line('runOnlyForDeploymentPostprocessing = 0;\n') diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 2426417..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 @@ -633,11 +636,11 @@ class BuildTarget(Target): self.add_compiler_args('vala', valalist) objclist = kwargs.get('objc_args', []) if not isinstance(objclist, list): - objclist = [objclist] + objclist = [objclist] self.add_compiler_args('objc', objclist) objcpplist = kwargs.get('objcpp_args', []) if not isinstance(objcpplist, list): - objcpplist = [objcpplist] + objcpplist = [objcpplist] self.add_compiler_args('objcpp', objcpplist) fortranlist = kwargs.get('fortran_args', []) if not isinstance(fortranlist, list): @@ -1101,7 +1104,7 @@ class Executable(BuildTarget): if not hasattr(self, 'suffix'): # Executable for Windows or C#/Mono if (for_windows(is_cross, environment) or - for_cygwin(is_cross, environment) or 'cs' in self.compilers): + for_cygwin(is_cross, environment) or 'cs' in self.compilers): self.suffix = 'exe' else: self.suffix = '' diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index e7c02b2..c9cfb46 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import re import shutil import contextlib import subprocess, os.path @@ -316,18 +317,6 @@ def get_base_link_args(options, linker, is_shared_module): pass return args -def build_unix_rpath_args(build_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]) - if len(paths) < len(install_rpath): - padding = 'X' * (len(install_rpath) - len(paths)) - if not paths: - paths = padding - else: - paths = paths + ':' + padding - return ['-Wl,-rpath,' + paths] - class CrossNoRunException(MesonException): pass @@ -375,10 +364,15 @@ class CompilerArgs(list): # Arg prefixes that override by prepending instead of appending prepend_prefixes = ('-I', '-L') # Arg prefixes and args that must be de-duped by returning 2 - dedup2_prefixes = ('-I', '-L', '-D') + dedup2_prefixes = ('-I', '-L', '-D', '-U') + dedup2_suffixes = () dedup2_args = () # Arg prefixes and args that must be de-duped by returning 1 - dedup1_prefixes = () + dedup1_prefixes = ('-l',) + dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') + # Match a .so of the form path/to/libfoo.so.0.1.0 + # Only UNIX shared libraries require this. Others have a fixed extension. + dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread') compiler = None @@ -416,7 +410,7 @@ class CompilerArgs(list): def _can_dedup(cls, arg): ''' Returns whether the argument can be safely de-duped. This is dependent - on two things: + on three things: a) Whether an argument can be 'overriden' by a later argument. For example, -DFOO defines FOO and -UFOO undefines FOO. In this case, we @@ -430,10 +424,20 @@ class CompilerArgs(list): a particular argument is present. This can matter for symbol resolution in static or shared libraries, so we cannot de-dup or reorder them. For these we return `0`. This is the default. + + In addition to these, we handle library arguments specially. + With GNU ld, we surround library arguments with -Wl,--start/end-group + to recursively search for symbols in the libraries. This is not needed + with other linkers. ''' - if arg.startswith(cls.dedup2_prefixes) or arg in cls.dedup2_args: + if arg in cls.dedup2_args or \ + arg.startswith(cls.dedup2_prefixes) or \ + arg.endswith(cls.dedup2_suffixes): return 2 - if arg.startswith(cls.dedup1_prefixes) or arg in cls.dedup1_args: + if arg in cls.dedup1_args or \ + arg.startswith(cls.dedup1_prefixes) or \ + arg.endswith(cls.dedup1_suffixes) or \ + re.search(cls.dedup1_regex, arg): return 1 return 0 @@ -444,6 +448,21 @@ class CompilerArgs(list): return False def to_native(self): + # Check if we need to add --start/end-group for circular dependencies + # between static libraries. + if get_compiler_uses_gnuld(self.compiler): + group_started = False + for each in self: + if not each.startswith('-l') and not each.endswith('.a'): + continue + i = self.index(each) + if not group_started: + # First occurance of a library + self.insert(i, '-Wl,--start-group') + group_started = True + # Last occurance of a library + if group_started: + self.insert(i + 1, '-Wl,--end-group') return self.compiler.unix_args_to_native(self) def __add__(self, args): @@ -711,6 +730,37 @@ class Compiler: return [] raise EnvironmentException('Language %s does not support linking whole archives.' % self.language) + def build_unix_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + if not rpath_paths and not install_rpath: + return [] + # 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: + paths = padding + else: + paths = paths + ':' + padding + args = ['-Wl,-rpath,' + paths] + if get_compiler_is_linuxlike(self): + # Rpaths to use while linking must be absolute. These are not + # written to the binary. Needed only with GNU ld: + # https://sourceware.org/bugzilla/show_bug.cgi?id=16936 + # 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] + return args + class CCompiler(Compiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None): # If a child ObjC or CPP class has already set it, don't set it ourselves @@ -760,10 +810,9 @@ class CCompiler(Compiler): def split_shlib_to_parts(self, fname): return None, fname - # 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) + # The default behavior is this, override in MSVC + def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath): + return self.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] @@ -1371,10 +1420,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): @@ -1901,7 +1950,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: @@ -2024,8 +2073,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 self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath) def get_unittest_args(self): return ['-funittest'] @@ -2233,7 +2282,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. @@ -2402,6 +2451,15 @@ def get_compiler_is_linuxlike(compiler): return True return False +def get_compiler_uses_gnuld(c): + # FIXME: Perhaps we should detect the linker in the environment? + # FIXME: Assumes that *BSD use GNU ld, but they might start using lld soon + if (getattr(c, 'gcc_type', None) in (GCC_STANDARD, GCC_MINGW, GCC_CYGWIN)) or \ + (getattr(c, 'clang_type', None) in (CLANG_STANDARD, CLANG_WIN)) or \ + (getattr(c, 'icc_type', None) in (ICC_STANDARD, ICC_WIN)): + return True + return False + def get_largefile_args(compiler): ''' Enable transparent large-file-support for 32-bit UNIX systems @@ -2973,8 +3031,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 self.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' @@ -3154,7 +3212,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): @@ -3183,7 +3241,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/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 10f7ad3..76d6691 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -162,11 +162,19 @@ class LLVMDependency(Dependency): # Ordered list of llvm-config binaries to try. Start with base, then try # newest back to oldest (3.5 is abitrary), and finally the devel version. + # Please note that llvm-config-5.0 is a development snapshot and it should + # not be moved to the beginning of the list. The only difference between + # llvm-config-5.0 and llvm-config-devel is that the former is used by + # Debian and the latter is used by FreeBSD. llvm_config_bins = [ - 'llvm-config', 'llvm-config-4.0', 'llvm-config-3.9', 'llvm-config39', - 'llvm-config-3.8', 'llvm-config38', 'llvm-config-3.7', 'llvm-config37', - 'llvm-config-3.6', 'llvm-config36', 'llvm-config-3.5', 'llvm-config35', - 'llvm-config-devel', + 'llvm-config', # base + 'llvm-config-4.0', 'llvm-config40', # latest stable release + 'llvm-config-3.9', 'llvm-config39', # old stable releases + 'llvm-config-3.8', 'llvm-config38', + 'llvm-config-3.7', 'llvm-config37', + 'llvm-config-3.6', 'llvm-config36', + 'llvm-config-3.5', 'llvm-config35', + 'llvm-config-5.0', 'llvm-config-devel', # development snapshot ] llvmconfig = None _llvmconfig_found = False diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 3e0b558..6a76ba6 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -1,4 +1,4 @@ -# Copyright 2013-2017 The Meson development team +# Copyright 2013-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -37,6 +37,7 @@ class BoostDependency(Dependency): self.name = 'boost' self.environment = environment self.libdir = '' + self.static = kwargs.get('static', False) if 'native' in kwargs and environment.is_cross_build(): self.want_cross = not kwargs['native'] else: @@ -123,8 +124,12 @@ class BoostDependency(Dependency): # For now, use -isystem for all includes except for some # typical defaults (which don't need to be included at all - # since they are in the default include paths) - if include_dir != '/usr/include' and include_dir != '/usr/local/include': + # since they are in the default include paths). These typical + # defaults include the usual directories at the root of the + # filesystem, but also any path that ends with those directory + # names in order to handle cases like cross-compiling where we + # might have a different sysroot. + if not include_dir.endswith(('/usr/include', '/usr/local/include')): args.append("".join(self.cpp_compiler.get_include_args(include_dir, True))) return args @@ -194,7 +199,7 @@ class BoostDependency(Dependency): return libdir = libdir[0] self.libdir = libdir - globber = 'boost_*-gd-*.lib' # FIXME + globber = 'libboost_*-gd-*.lib' if self.static else 'boost_*-gd-*.lib' # FIXME for entry in glob.glob(os.path.join(libdir, globber)): (_, fname) = os.path.split(entry) base = fname.split('_', 1)[1] @@ -202,7 +207,9 @@ class BoostDependency(Dependency): self.lib_modules_mt[modname] = fname def detect_lib_modules_nix(self): - if mesonlib.is_osx() and not self.want_cross: + if self.static: + libsuffix = 'a' + elif mesonlib.is_osx() and not self.want_cross: libsuffix = 'dylib' else: libsuffix = 'so' @@ -220,7 +227,7 @@ class BoostDependency(Dependency): name = lib.split('.')[0].split('_', 1)[-1] # I'm not 100% sure what to do here. Some distros # have modules such as thread only as -mt versions. - if entry.endswith('-mt.so'): + if entry.endswith('-mt.{}'.format(libsuffix)): self.lib_modules_mt[name] = True else: self.lib_modules[name] = True diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index bf58472..d21c6cc 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 @@ -906,6 +908,9 @@ class CrossBuildInfo: return 'host_machine' in self.config def need_exe_wrapper(self): + value = self.config['properties'].get('needs_exe_wrapper', None) + if value is not None: + return value # Can almost always run 32-bit binaries on 64-bit natively if the host # and build systems are the same. We don't pass any compilers to # detect_cpu_family() here because we always want to know the OS diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 63725ab..39d596f 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2227,6 +2227,8 @@ class Interpreter(InterpreterBase): raise InvalidArguments('Subdir contains ..') if self.subdir == '' and args[0] == self.subproject_dir: raise InvalidArguments('Must not go into subprojects dir with subdir(), use subproject() instead.') + if self.subdir == '' and args[0].startswith('meson-'): + raise InvalidArguments('The "meson-" prefix is reserved and cannot be used for top-level subdir().') prev_subdir = self.subdir subdir = os.path.join(prev_subdir, args[0]) if os.path.isabs(subdir): @@ -2342,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)) @@ -2593,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/mesonmain.py b/mesonbuild/mesonmain.py index 70f4027..dacc478 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -68,7 +68,7 @@ parser.add_argument('-D', action='append', dest='projectoptions', default=[], me help='Set the value of an option, can be used several times to set multiple options.') parser.add_argument('-v', '--version', action='version', version=coredata.version) - # See the mesonlib.WrapMode enum for documentation +# See the mesonlib.WrapMode enum for documentation parser.add_argument('--wrap-mode', default=WrapMode.default, type=lambda t: getattr(WrapMode, t), choices=WrapMode, help='Special wrap mode to use') diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py index 2de50ba..1169b7e 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -103,7 +103,7 @@ class SectionHeader(DataSizes): self.sh_addralign = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] else: self.sh_addralign = struct.unpack(self.Word, ifile.read(self.WordSize))[0] -#Elf64_Xword +# Elf64_Xword if is_64: self.sh_entsize = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] else: diff --git a/mesonbuild/scripts/dist.py b/mesonbuild/scripts/dist.py index 064708e..325a882 100644 --- a/mesonbuild/scripts/dist.py +++ b/mesonbuild/scripts/dist.py @@ -83,8 +83,8 @@ def create_dist(dist_name, src_root, bld_root, dist_sub): with tarfile.open(xzname, 'w:xz') as tf: tf.add(distdir, os.path.split(distdir)[1]) # Create only .tar.xz for now. - #zipname = distdir + '.zip' - #create_zip(zipname, distdir) + # zipname = distdir + '.zip' + # create_zip(zipname, distdir) shutil.rmtree(distdir) return (xzname, ) 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/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index af90daa..ac84d0e 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -50,7 +50,7 @@ def open_wrapdburl(urlstring): global ssl_warning_printed if has_ssl: try: - return urllib.request.urlopen(urlstring)#, context=build_ssl_context()) + return urllib.request.urlopen(urlstring)# , context=build_ssl_context()) except urllib.error.URLError: if not ssl_warning_printed: print('SSL connection failed. Falling back to unencrypted connections.') diff --git a/run_unittests.py b/run_unittests.py index e3b7c5c..496c6bc 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -22,6 +22,7 @@ import os import shutil import sys import unittest +from configparser import ConfigParser from glob import glob from pathlib import PurePath import mesonbuild.compilers @@ -36,16 +37,26 @@ from run_tests import get_builddir_target_args, get_backend_commands, Backend from run_tests import ensure_backend_detects_changes -def get_soname(fname): - # HACK, fix to not use shell. - raw_out = subprocess.check_output(['readelf', '-a', fname], - universal_newlines=True) - pattern = re.compile('soname: \[(.*?)\]') +def get_dynamic_section_entry(fname, entry): + try: + raw_out = subprocess.check_output(['readelf', '-d', fname], + universal_newlines=True) + except FileNotFoundError: + # FIXME: Try using depfixer.py:Elf() as a fallback + raise unittest.SkipTest('readelf not found') + pattern = re.compile(entry + r': \[(.*?)\]') for line in raw_out.split('\n'): m = pattern.search(line) if m is not None: return m.group(1) - raise RuntimeError('Could not determine soname:\n\n' + raw_out) + raise RuntimeError('Could not determine {}:\n\n'.format(entry) + raw_out) + +def get_soname(fname): + return get_dynamic_section_entry(fname, 'soname') + +def get_rpath(fname): + return get_dynamic_section_entry(fname, r'(?:rpath|runpath)') + class InternalTests(unittest.TestCase): @@ -139,7 +150,7 @@ class InternalTests(unittest.TestCase): self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) ## Test that reflected addition works - # Test that adding to a list with just one old arg works and DOES NOT yield the same array + # Test that adding to a list with just one old arg works and yields the same array a = ['-Ifoo'] + a self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) # Test that adding to a list with just one new arg that is not pre-pended works @@ -148,6 +159,19 @@ class InternalTests(unittest.TestCase): # Test that adding to a list with two new args preserves the order a = ['-Ldir', '-Lbah'] + a self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall']) + # Test that adding to a list with old args does nothing + a = ['-Ibar', '-Ibaz', '-Ifoo'] + a + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall']) + + ## Test that adding libraries works + l = cargsfunc(c, ['-Lfoodir', '-lfoo']) + self.assertEqual(l, ['-Lfoodir', '-lfoo']) + # Adding a library and a libpath appends both correctly + l += ['-Lbardir', '-lbar'] + self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar']) + # Adding the same library again does nothing + l += ['-lbar'] + self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar']) def test_commonpath(self): from os.path import sep @@ -323,6 +347,35 @@ class InternalTests(unittest.TestCase): cmd = ['@OUTPUT@.out', 'ordinary', 'strings'] self.assertRaises(ME, substfunc, cmd, d) + def test_needs_exe_wrapper_override(self): + config = ConfigParser() + config['binaries'] = { + 'c': '\'/usr/bin/gcc\'', + } + config['host_machine'] = { + 'system': '\'linux\'', + 'cpu_family': '\'arm\'', + 'cpu': '\'armv7\'', + 'endian': '\'little\'', + } + + with tempfile.NamedTemporaryFile(mode='w+') as configfile: + config.write(configfile) + configfile.flush() + detected_value = mesonbuild.environment.CrossBuildInfo(configfile.name).need_exe_wrapper() + + desired_value = not detected_value + config['properties'] = { + 'needs_exe_wrapper': 'true' if desired_value else 'false' + } + + with tempfile.NamedTemporaryFile(mode='w+') as configfile: + config.write(configfile) + configfile.flush() + forced_value = mesonbuild.environment.CrossBuildInfo(configfile.name).need_exe_wrapper() + + self.assertEqual(forced_value, desired_value) + class BasePlatformTests(unittest.TestCase): def setUp(self): @@ -1117,6 +1170,25 @@ int main(int argc, char **argv) { self.assertTrue(os.path.exists(distfile)) self.assertTrue(os.path.exists(checksumfile)) + def test_rpath_uses_ORIGIN(self): + ''' + Test that built targets use $ORIGIN in rpath, which ensures that they + are relocatable and ensures that builds are reproducible since the + build directory won't get embedded into the built binaries. + ''' + if is_windows() or is_cygwin(): + raise unittest.SkipTest('Windows PE/COFF binaries do not use RPATH') + testdir = os.path.join(self.common_test_dir, '46 library chain') + self.init(testdir) + self.build() + for each in ('prog', 'subdir/liblib1.so', 'subdir/subdir2/liblib2.so', + 'subdir/subdir3/liblib3.so'): + rpath = get_rpath(os.path.join(self.builddir, each)) + self.assertTrue(rpath) + for path in rpath.split(':'): + self.assertTrue(path.startswith('$ORIGIN'), msg=(each, path)) + + class WindowsTests(BasePlatformTests): ''' Tests that should run on Cygwin, MinGW, and MSVC @@ -1253,15 +1325,15 @@ class LinuxlikeTests(BasePlatformTests): self.assertIsNotNone(vala_command) self.assertIsNotNone(c_command) # -w suppresses all warnings, should be there in Vala but not in C - self.assertIn("'-w'", vala_command) - self.assertNotIn("'-w'", c_command) + self.assertIn(" -w ", vala_command) + self.assertNotIn(" -w ", c_command) # -Wall enables all warnings, should be there in C but not in Vala - self.assertNotIn("'-Wall'", vala_command) - self.assertIn("'-Wall'", c_command) + self.assertNotIn(" -Wall ", vala_command) + self.assertIn(" -Wall ", c_command) # -Werror converts warnings to errors, should always be there since it's # injected by an unrelated piece of code and the project has werror=true - self.assertIn("'-Werror'", vala_command) - self.assertIn("'-Werror'", c_command) + self.assertIn(" -Werror ", vala_command) + self.assertIn(" -Werror ", c_command) def test_qt5dependency_pkgconfig_detection(self): ''' @@ -1306,14 +1378,6 @@ class LinuxlikeTests(BasePlatformTests): mesonlog = self.get_meson_log() self.assertTrue(msg in mesonlog or msg2 in mesonlog) - def get_soname(self, fname): - output = subprocess.check_output(['readelf', '-a', fname], - universal_newlines=True) - for line in output.split('\n'): - if 'SONAME' in line: - return line.split('[')[1].split(']')[0] - raise RuntimeError('Readelf gave no SONAME.') - def _test_soname_impl(self, libpath, install): testdir = os.path.join(self.unit_test_dir, '1 soname') self.init(testdir) @@ -1325,28 +1389,28 @@ class LinuxlikeTests(BasePlatformTests): nover = os.path.join(libpath, 'libnover.so') self.assertTrue(os.path.exists(nover)) self.assertFalse(os.path.islink(nover)) - self.assertEqual(self.get_soname(nover), 'libnover.so') + self.assertEqual(get_soname(nover), 'libnover.so') self.assertEqual(len(glob(nover[:-3] + '*')), 1) # File with version set verset = os.path.join(libpath, 'libverset.so') self.assertTrue(os.path.exists(verset + '.4.5.6')) self.assertEqual(os.readlink(verset), 'libverset.so.4') - self.assertEqual(self.get_soname(verset), 'libverset.so.4') + self.assertEqual(get_soname(verset), 'libverset.so.4') self.assertEqual(len(glob(verset[:-3] + '*')), 3) # File with soversion set soverset = os.path.join(libpath, 'libsoverset.so') self.assertTrue(os.path.exists(soverset + '.1.2.3')) self.assertEqual(os.readlink(soverset), 'libsoverset.so.1.2.3') - self.assertEqual(self.get_soname(soverset), 'libsoverset.so.1.2.3') + self.assertEqual(get_soname(soverset), 'libsoverset.so.1.2.3') self.assertEqual(len(glob(soverset[:-3] + '*')), 2) # File with version and soversion set to same values settosame = os.path.join(libpath, 'libsettosame.so') self.assertTrue(os.path.exists(settosame + '.7.8.9')) self.assertEqual(os.readlink(settosame), 'libsettosame.so.7.8.9') - self.assertEqual(self.get_soname(settosame), 'libsettosame.so.7.8.9') + self.assertEqual(get_soname(settosame), 'libsettosame.so.7.8.9') self.assertEqual(len(glob(settosame[:-3] + '*')), 2) # File with version and soversion set to different values @@ -1354,7 +1418,7 @@ class LinuxlikeTests(BasePlatformTests): self.assertTrue(os.path.exists(bothset + '.1.2.3')) self.assertEqual(os.readlink(bothset), 'libbothset.so.1.2.3') self.assertEqual(os.readlink(bothset + '.1.2.3'), 'libbothset.so.4.5.6') - self.assertEqual(self.get_soname(bothset), 'libbothset.so.1.2.3') + self.assertEqual(get_soname(bothset), 'libbothset.so.1.2.3') self.assertEqual(len(glob(bothset[:-3] + '*')), 3) def test_soname(self): @@ -1392,7 +1456,7 @@ class LinuxlikeTests(BasePlatformTests): self.init(testdir, ['-D' + std_opt]) cmd = self.get_compdb()[0]['command'] if v != 'none': - cmd_std = "'-std={}'".format(v) + cmd_std = " -std={} ".format(v) self.assertIn(cmd_std, cmd) try: self.build() @@ -1407,7 +1471,7 @@ class LinuxlikeTests(BasePlatformTests): os.environ[env_flags] = cmd_std self.init(testdir) cmd = self.get_compdb()[0]['command'] - qcmd_std = "'{}'".format(cmd_std) + qcmd_std = " {} ".format(cmd_std) self.assertIn(qcmd_std, cmd) with self.assertRaises(subprocess.CalledProcessError, msg='{} should have failed'.format(qcmd_std)): diff --git a/test cases/common/153 recursive linking/3rdorderdeps/lib.c.in b/test cases/common/153 recursive linking/3rdorderdeps/lib.c.in new file mode 100644 index 0000000..461f859 --- /dev/null +++ b/test cases/common/153 recursive linking/3rdorderdeps/lib.c.in @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_@DEPENDENCY@dep_value (void); + +SYMBOL_EXPORT +int get_@LIBTYPE@@DEPENDENCY@dep_value (void) { + return get_@DEPENDENCY@dep_value (); +} diff --git a/test cases/common/153 recursive linking/3rdorderdeps/main.c.in b/test cases/common/153 recursive linking/3rdorderdeps/main.c.in new file mode 100644 index 0000000..8155f35 --- /dev/null +++ b/test cases/common/153 recursive linking/3rdorderdeps/main.c.in @@ -0,0 +1,16 @@ +#include <stdio.h> + +#include "../lib.h" + +SYMBOL_IMPORT int get_@LIBTYPE@@DEPENDENCY@dep_value (void); + +int main(int argc, char *argv[]) { + int val; + + val = get_@LIBTYPE@@DEPENDENCY@dep_value (); + if (val != @VALUE@) { + printf("@LIBTYPE@@DEPENDENCY@ was %i instead of @VALUE@\n", val); + return -1; + } + return 0; +} diff --git a/test cases/common/153 recursive linking/3rdorderdeps/meson.build b/test cases/common/153 recursive linking/3rdorderdeps/meson.build new file mode 100644 index 0000000..d4ef745 --- /dev/null +++ b/test cases/common/153 recursive linking/3rdorderdeps/meson.build @@ -0,0 +1,49 @@ +dep3_libs = [] + +# Permutate all combinations of shared and static libraries up to three levels +# executable -> shared -> static -> shared (etc) +foreach dep2 : ['sh', 'st'] + foreach dep1 : ['sh', 'st'] + foreach libtype : ['sh', 'st'] + name = libtype + dep1 + dep2 + if dep2 == 'sh' + libret = 1 + elif dep2 == 'st' + libret = 2 + else + error('Unknown dep2 "@0@"'.format(dep2)) + endif + + if libtype == 'sh' + target = 'shared_library' + build_args = [] + elif libtype == 'st' + target = 'static_library' + build_args = ['-DMESON_STATIC_BUILD'] + else + error('Unknown libtype "@0@"'.format(libtype)) + endif + + cdata = configuration_data() + cdata.set('DEPENDENCY', dep1 + dep2) + cdata.set('LIBTYPE', libtype) + cdata.set('VALUE', libret) + + lib_c = configure_file(input : 'lib.c.in', + output : name + '-lib.c', + configuration : cdata) + dep = get_variable(dep1 + dep2 + 'dep') + dep3_lib = build_target(name, lib_c, link_with : dep, + target_type : target, + c_args : build_args) + dep3_libs += [dep3_lib] + + main_c = configure_file(input : 'main.c.in', + output : name + '-main.c', + configuration : cdata) + dep3_bin = executable(name, main_c, link_with : dep3_lib, + c_args : build_args) + test(name + 'test', dep3_bin) + endforeach + endforeach +endforeach diff --git a/test cases/common/153 recursive linking/circular/lib1.c b/test cases/common/153 recursive linking/circular/lib1.c new file mode 100644 index 0000000..38889cf --- /dev/null +++ b/test cases/common/153 recursive linking/circular/lib1.c @@ -0,0 +1,6 @@ +int get_st2_prop (void); +int get_st3_prop (void); + +int get_st1_value (void) { + return get_st2_prop () + get_st3_prop (); +} diff --git a/test cases/common/153 recursive linking/circular/lib2.c b/test cases/common/153 recursive linking/circular/lib2.c new file mode 100644 index 0000000..31cd37c --- /dev/null +++ b/test cases/common/153 recursive linking/circular/lib2.c @@ -0,0 +1,6 @@ +int get_st1_prop (void); +int get_st3_prop (void); + +int get_st2_value (void) { + return get_st1_prop () + get_st3_prop (); +} diff --git a/test cases/common/153 recursive linking/circular/lib3.c b/test cases/common/153 recursive linking/circular/lib3.c new file mode 100644 index 0000000..67d473a --- /dev/null +++ b/test cases/common/153 recursive linking/circular/lib3.c @@ -0,0 +1,6 @@ +int get_st1_prop (void); +int get_st2_prop (void); + +int get_st3_value (void) { + return get_st1_prop () + get_st2_prop (); +} diff --git a/test cases/common/153 recursive linking/circular/main.c b/test cases/common/153 recursive linking/circular/main.c new file mode 100644 index 0000000..5f797a5 --- /dev/null +++ b/test cases/common/153 recursive linking/circular/main.c @@ -0,0 +1,28 @@ +#include <stdio.h> + +#include "../lib.h" + +int get_st1_value (void); +int get_st2_value (void); +int get_st3_value (void); + +int main(int argc, char *argv[]) { + int val; + + val = get_st1_value (); + if (val != 5) { + printf("st1 value was %i instead of 5\n", val); + return -1; + } + val = get_st2_value (); + if (val != 4) { + printf("st2 value was %i instead of 4\n", val); + return -2; + } + val = get_st3_value (); + if (val != 3) { + printf("st3 value was %i instead of 3\n", val); + return -3; + } + return 0; +} diff --git a/test cases/common/153 recursive linking/circular/meson.build b/test cases/common/153 recursive linking/circular/meson.build new file mode 100644 index 0000000..b7a70a8 --- /dev/null +++ b/test cases/common/153 recursive linking/circular/meson.build @@ -0,0 +1,5 @@ +st1 = static_library('st1', 'lib1.c', 'prop1.c') +st2 = static_library('st2', 'lib2.c', 'prop2.c') +st3 = static_library('st3', 'lib3.c', 'prop3.c') + +test('circular', executable('circular', 'main.c', link_with : [st1, st2, st3])) diff --git a/test cases/common/153 recursive linking/circular/prop1.c b/test cases/common/153 recursive linking/circular/prop1.c new file mode 100644 index 0000000..4e571f5 --- /dev/null +++ b/test cases/common/153 recursive linking/circular/prop1.c @@ -0,0 +1,3 @@ +int get_st1_prop (void) { + return 1; +} diff --git a/test cases/common/153 recursive linking/circular/prop2.c b/test cases/common/153 recursive linking/circular/prop2.c new file mode 100644 index 0000000..ceabba0 --- /dev/null +++ b/test cases/common/153 recursive linking/circular/prop2.c @@ -0,0 +1,3 @@ +int get_st2_prop (void) { + return 2; +} diff --git a/test cases/common/153 recursive linking/circular/prop3.c b/test cases/common/153 recursive linking/circular/prop3.c new file mode 100644 index 0000000..246206c --- /dev/null +++ b/test cases/common/153 recursive linking/circular/prop3.c @@ -0,0 +1,3 @@ +int get_st3_prop (void) { + return 3; +} diff --git a/test cases/common/153 recursive linking/lib.h b/test cases/common/153 recursive linking/lib.h new file mode 100644 index 0000000..b54bf36 --- /dev/null +++ b/test cases/common/153 recursive linking/lib.h @@ -0,0 +1,17 @@ +#if defined _WIN32 + #ifdef MESON_STATIC_BUILD + #define SYMBOL_EXPORT + #define SYMBOL_IMPORT + #else + #define SYMBOL_IMPORT __declspec(dllimport) + #define SYMBOL_EXPORT __declspec(dllexport) + #endif +#else + #define SYMBOL_IMPORT + #if defined __GNUC__ + #define SYMBOL_EXPORT __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define SYMBOL_EXPORT + #endif +#endif diff --git a/test cases/common/153 recursive linking/main.c b/test cases/common/153 recursive linking/main.c new file mode 100644 index 0000000..0851611 --- /dev/null +++ b/test cases/common/153 recursive linking/main.c @@ -0,0 +1,46 @@ +#include <stdio.h> + +#include "lib.h" + +int get_stnodep_value (void); +int get_stshdep_value (void); +int get_ststdep_value (void); +SYMBOL_IMPORT int get_shnodep_value (void); +SYMBOL_IMPORT int get_shshdep_value (void); +SYMBOL_IMPORT int get_shstdep_value (void); + +int main(int argc, char *argv[]) { + int val; + + val = get_shnodep_value (); + if (val != 1) { + printf("shnodep was %i instead of 1\n", val); + return -1; + } + val = get_stnodep_value (); + if (val != 2) { + printf("stnodep was %i instead of 2\n", val); + return -2; + } + val = get_shshdep_value (); + if (val != 1) { + printf("shshdep was %i instead of 1\n", val); + return -3; + } + val = get_shstdep_value (); + if (val != 2) { + printf("shstdep was %i instead of 2\n", val); + return -4; + } + val = get_stshdep_value (); + if (val != 1) { + printf("shstdep was %i instead of 1\n", val); + return -5; + } + val = get_ststdep_value (); + if (val != 2) { + printf("ststdep was %i instead of 2\n", val); + return -6; + } + return 0; +} diff --git a/test cases/common/153 recursive linking/meson.build b/test cases/common/153 recursive linking/meson.build new file mode 100644 index 0000000..4cecd57 --- /dev/null +++ b/test cases/common/153 recursive linking/meson.build @@ -0,0 +1,26 @@ +project('recursive dependencies', 'c') + +# Test that you can link a shared executable to: +# - A shared library with no other deps +subdir('shnodep') +# - A static library with no other deps +subdir('stnodep') +# - A shared library with a shared library dep +subdir('shshdep') +# - A shared library with a static library dep +subdir('shstdep') +# - A static library with a shared library dep +subdir('stshdep') +# - A static library with a static library dep +subdir('ststdep') + +test('alldeps', + executable('alldeps', 'main.c', + link_with : [shshdep, shstdep, ststdep, stshdep])) + +# More combinations of static and shared libraries +subdir('3rdorderdeps') + +# Circular dependencies between static libraries +# This requires the use of --start/end-group with GNU ld +subdir('circular') diff --git a/test cases/common/153 recursive linking/shnodep/lib.c b/test cases/common/153 recursive linking/shnodep/lib.c new file mode 100644 index 0000000..a3b7993 --- /dev/null +++ b/test cases/common/153 recursive linking/shnodep/lib.c @@ -0,0 +1,6 @@ +#include "../lib.h" + +SYMBOL_EXPORT +int get_shnodep_value (void) { + return 1; +} diff --git a/test cases/common/153 recursive linking/shnodep/meson.build b/test cases/common/153 recursive linking/shnodep/meson.build new file mode 100644 index 0000000..796f0dd --- /dev/null +++ b/test cases/common/153 recursive linking/shnodep/meson.build @@ -0,0 +1 @@ +shnodep = shared_library('shnodep', 'lib.c') diff --git a/test cases/common/153 recursive linking/shshdep/lib.c b/test cases/common/153 recursive linking/shshdep/lib.c new file mode 100644 index 0000000..715d120 --- /dev/null +++ b/test cases/common/153 recursive linking/shshdep/lib.c @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_shnodep_value (void); + +SYMBOL_EXPORT +int get_shshdep_value (void) { + return get_shnodep_value (); +} diff --git a/test cases/common/153 recursive linking/shshdep/meson.build b/test cases/common/153 recursive linking/shshdep/meson.build new file mode 100644 index 0000000..020b481 --- /dev/null +++ b/test cases/common/153 recursive linking/shshdep/meson.build @@ -0,0 +1 @@ +shshdep = shared_library('shshdep', 'lib.c', link_with : shnodep) diff --git a/test cases/common/153 recursive linking/shstdep/lib.c b/test cases/common/153 recursive linking/shstdep/lib.c new file mode 100644 index 0000000..5da8d0b --- /dev/null +++ b/test cases/common/153 recursive linking/shstdep/lib.c @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_stnodep_value (void); + +SYMBOL_EXPORT +int get_shstdep_value (void) { + return get_stnodep_value (); +} diff --git a/test cases/common/153 recursive linking/shstdep/meson.build b/test cases/common/153 recursive linking/shstdep/meson.build new file mode 100644 index 0000000..008f9f8 --- /dev/null +++ b/test cases/common/153 recursive linking/shstdep/meson.build @@ -0,0 +1 @@ +shstdep = shared_library('shstdep', 'lib.c', link_with : stnodep) diff --git a/test cases/common/153 recursive linking/stnodep/lib.c b/test cases/common/153 recursive linking/stnodep/lib.c new file mode 100644 index 0000000..4bc50be --- /dev/null +++ b/test cases/common/153 recursive linking/stnodep/lib.c @@ -0,0 +1,6 @@ +#include "../lib.h" + +SYMBOL_EXPORT +int get_stnodep_value (void) { + return 2; +} diff --git a/test cases/common/153 recursive linking/stnodep/meson.build b/test cases/common/153 recursive linking/stnodep/meson.build new file mode 100644 index 0000000..77f7129 --- /dev/null +++ b/test cases/common/153 recursive linking/stnodep/meson.build @@ -0,0 +1,2 @@ +stnodep = static_library('stnodep', 'lib.c', + c_args : '-DMESON_STATIC_BUILD') diff --git a/test cases/common/153 recursive linking/stshdep/lib.c b/test cases/common/153 recursive linking/stshdep/lib.c new file mode 100644 index 0000000..3cfa12b --- /dev/null +++ b/test cases/common/153 recursive linking/stshdep/lib.c @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_shnodep_value (void); + +SYMBOL_EXPORT +int get_stshdep_value (void) { + return get_shnodep_value (); +} diff --git a/test cases/common/153 recursive linking/stshdep/meson.build b/test cases/common/153 recursive linking/stshdep/meson.build new file mode 100644 index 0000000..0967c1c --- /dev/null +++ b/test cases/common/153 recursive linking/stshdep/meson.build @@ -0,0 +1,2 @@ +stshdep = static_library('stshdep', 'lib.c', link_with : shnodep, + c_args : '-DMESON_STATIC_BUILD') diff --git a/test cases/common/153 recursive linking/ststdep/lib.c b/test cases/common/153 recursive linking/ststdep/lib.c new file mode 100644 index 0000000..fca8706 --- /dev/null +++ b/test cases/common/153 recursive linking/ststdep/lib.c @@ -0,0 +1,8 @@ +#include "../lib.h" + +int get_stnodep_value (void); + +SYMBOL_EXPORT +int get_ststdep_value (void) { + return get_stnodep_value (); +} diff --git a/test cases/common/153 recursive linking/ststdep/meson.build b/test cases/common/153 recursive linking/ststdep/meson.build new file mode 100644 index 0000000..3602442 --- /dev/null +++ b/test cases/common/153 recursive linking/ststdep/meson.build @@ -0,0 +1,2 @@ +ststdep = static_library('ststdep', 'lib.c', link_with : stnodep, + c_args : '-DMESON_STATIC_BUILD') 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/failing/54 reserved meson prefix/meson-foo/meson.build b/test cases/failing/54 reserved meson prefix/meson-foo/meson.build new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/failing/54 reserved meson prefix/meson-foo/meson.build diff --git a/test cases/failing/54 reserved meson prefix/meson.build b/test cases/failing/54 reserved meson prefix/meson.build new file mode 100644 index 0000000..1339035 --- /dev/null +++ b/test cases/failing/54 reserved meson prefix/meson.build @@ -0,0 +1,3 @@ +project('test') + +subdir('meson-foo') diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build index 6f9b16f..338dd78 100644 --- a/test cases/frameworks/1 boost/meson.build +++ b/test cases/frameworks/1 boost/meson.build @@ -7,15 +7,18 @@ project('boosttest', 'cpp', nolinkdep = dependency('boost', modules: 'utility') linkdep = dependency('boost', modules : ['thread', 'system']) +staticdep = dependency('boost', modules : ['thread', 'system'], static : true) testdep = dependency('boost', modules : 'test') nomoddep = dependency('boost') nolinkexe = executable('nolinkedexe', 'nolinkexe.cc', dependencies : nolinkdep) linkexe = executable('linkedexe', 'linkexe.cc', dependencies : linkdep) +staticexe = executable('staticlinkedexe', 'linkexe.cc', dependencies : staticdep) unitexe = executable('utf', 'unit_test.cpp', dependencies: testdep) nomodexe = executable('nomod', 'nomod.cpp', dependencies : nomoddep) -test('Boost nolinktext', nolinkexe) -test('Boost linktext', linkexe) +test('Boost nolinktest', nolinkexe) +test('Boost linktest', linkexe) +test('Boost statictest', staticexe) test('Boost UTF test', unitexe) test('Boost nomod', nomodexe) 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 "" diff --git a/test cases/frameworks/7 gnome/gir/meson.build b/test cases/frameworks/7 gnome/gir/meson.build index f3a4534..2758541 100644 --- a/test cases/frameworks/7 gnome/gir/meson.build +++ b/test cases/frameworks/7 gnome/gir/meson.build @@ -12,7 +12,7 @@ girlib = shared_library( girexe = executable( 'girprog', sources : 'prog.c', - dependencies : [glib, gobj, gir], + dependencies : [glib, gobj, gir, dep1_dep], link_with : girlib ) diff --git a/test cases/vala/11 generated vapi/meson.build b/test cases/vala/11 generated vapi/meson.build index 82f0c44..d5f38ca 100644 --- a/test cases/vala/11 generated vapi/meson.build +++ b/test cases/vala/11 generated vapi/meson.build @@ -6,7 +6,7 @@ subdir('libbar') vapiexe = executable('vapigen-test', 'main.vala', - dependencies: [dependency('gobject-2.0'), libbar_vapi], + dependencies: [dependency('gobject-2.0'), libfoo_vapi, libbar_vapi], install: true, ) diff --git a/tools/ac_converter.py b/tools/ac_converter.py index 0531e98..cf00fd0 100755 --- a/tools/ac_converter.py +++ b/tools/ac_converter.py @@ -192,26 +192,169 @@ function_data = \ 'HAVE_STRCMP': ('strcmp', 'string.h'), 'HAVE_STRNCMP': ('strncmp', 'string.h'), 'HAVE_VSSCANF': ('vsscanf', 'stdio.h'), + 'HAVE_CHROOT': ('chroot', 'unistd.h'), + 'HAVE_CLOCK': ('clock', 'time.h'), + 'HAVE_CLOCK_GETRES': ('clock_getres', 'time.h'), + 'HAVE_CLOCK_GETTIME': ('clock_gettime', 'time.h'), + 'HAVE_CLOCK_SETTIME': ('clock_settime', 'time.h'), + 'HAVE_CONFSTR': ('confstr', 'time.h'), + 'HAVE_CTERMID': ('ctermid', 'stdio.h'), + 'HAVE_DIRFD': ('dirfd', 'dirent.h'), + 'HAVE_DLOPEN': ('dlopen', 'dlfcn.h'), + 'HAVE_DUP2': ('dup2', 'unistd.h'), + 'HAVE_DUP3': ('dup3', 'unistd.h'), + 'HAVE_EPOLL_CREATE1': ('epoll_create1', 'sys/epoll.h'), + 'HAVE_ERF': ('erf', 'math.h'), + 'HAVE_ERFC': ('erfc', 'math.h'), + 'HAVE_EXECV': ('execv', 'unistd.h'), + 'HAVE_FACCESSAT': ('faccessat', 'unistd.h'), + 'HAVE_FCHDIR': ('fchdir', 'unistd.h'), + 'HAVE_FCHMODAT': ('fchmodat', 'sys/stat.h'), + 'HAVE_FDATASYNC': ('fdatasync', 'unistd.h'), + 'HAVE_FDOPENDIR': ('fdopendir', 'dirent.h'), + 'HAVE_FEXECVE': ('fexecve', 'unistd.h'), + 'HAVE_FLOCK': ('flock', 'sys/file.h'), + 'HAVE_FORKPTY': ('forkpty', 'pty.h'), + 'HAVE_FPATHCONF': ('fpathconf', 'unistd.h'), + 'HAVE_FSTATAT': ('fstatat', 'unistd.h'), + 'HAVE_FSTATVFS': ('fstatvfs', 'sys/statvfs.h'), + 'HAVE_FTELLO': ('ftello', 'stdio.h'), + 'HAVE_FTIME': ('ftime', 'sys/timeb.h'), + 'HAVE_FTRUNCATE': ('ftruncate', 'unistd.h'), + 'HAVE_FUTIMENS': ('futimens', 'sys/stat.h'), + 'HAVE_FUTIMES': ('futimes', 'sys/time.h'), + 'HAVE_GAI_STRERROR': ('gai_strerror', 'netdb.h'), + 'HAVE_GETGROUPLIST': ('getgrouplist', 'grp.h'), + 'HAVE_GETHOSTBYNAME': ('gethostbyname', 'netdb.h'), + 'HAVE_GETHOSTBYNAME_R': ('gethostbyname_r', 'netdb.h'), + 'HAVE_GETITIMER': ('getitimer', 'sys/time.h'), + 'HAVE_GETLOADAVG': ('getloadavg', 'stdlib.h'), + 'HAVE_GETLOGIN': ('getlogin', 'unistd.h'), + 'HAVE_GETNAMEINFO': ('getnameinfo', 'netdb.h'), + 'HAVE_GETPEERNAME': ('getpeername', 'sys/socket.h'), + 'HAVE_GETPGID': ('getpgid', 'unistd.h'), + 'HAVE_GETPGRP': ('getpgrp', 'unistd.h'), + 'HAVE_GETPID': ('getpid', 'unistd.h'), + 'HAVE_GETPRIORITY': ('getpriority', 'sys/resource.h'), + 'HAVE_GETPWENT': ('getpwent', 'pwd.h'), + 'HAVE_GETRANDOM': ('getrandom', 'linux/random.h'), + 'HAVE_GETRESGID': ('getresgid', 'unistd.h'), + 'HAVE_GETSID': ('getsid', 'unistd.h'), + 'HAVE_GETSPENT': ('getspent', 'shadow.h'), + 'HAVE_GETSPNAM': ('getspnam', 'shadow.h'), + 'HAVE_GETWD': ('getwd', 'unistd.h'), + 'HAVE_HSTRERROR': ('hstrerror', 'netdb.h'), + 'HAVE_HTOLE64': ('htole64', 'endian.h'), + 'HAVE_IF_NAMEINDEX': ('if_nameindex', 'net/if.h'), + 'HAVE_INET_ATON': ('inet_aton', 'arpa/inet.h'), + 'HAVE_INET_PTON': ('inet_pton', 'arpa/inet.h'), + 'HAVE_INITGROUPS': ('initgroups', 'grp.h'), + 'HAVE_KILL': ('kill', 'signal.h'), + 'HAVE_KILLPG': ('killpg', 'signal.h'), + 'HAVE_LINKAT': ('linkat', 'unistd.h'), + 'HAVE_LOCKF': ('lockf', 'unistd.h'), + 'HAVE_LUTIMES': ('lutimes', 'sys/time.h'), + 'HAVE_MAKEDEV': ('makedev', 'sys/sysmacros.h'), + 'HAVE_MBRTOWC': ('mbrtowc', 'wchar.h'), + 'HAVE_MEMRCHR': ('memrchr', 'string.h'), + 'HAVE_MKDIRAT': ('mkdirat', 'sys/stat.h'), + 'HAVE_MKFIFOAT': ('mkfifoat', 'sys/stat.h'), + 'HAVE_MKNOD': ('mknod', 'unistd.h'), + 'HAVE_MKNODAT': ('mknodat', 'unistd.h'), + 'HAVE_MKTIME': ('mktime', 'unistd.h'), + 'HAVE_MKREMAP': ('mkremap', 'sys/mman.h'), + 'HAVE_NICE': ('nice', 'unistd.h'), + 'HAVE_OPENAT': ('openat', 'fcntl.h'), + 'HAVE_OPENPTY': ('openpty', 'pty.h'), + 'HAVE_PATHCONF': ('pathconf', 'unistd.h'), + 'HAVE_PAUSE': ('pause', 'unistd.h'), + 'HAVE_PREAD': ('pread', 'unistd.h'), + 'HAVE_PTHREAD_KILL': ('pthread_kill', 'signal.h'), + 'HAVE_PTHREAD_SIGMASK': ('pthread_sigmask', 'signal.h'), + 'HAVE_PWRITE': ('pwrite', 'unistd.h'), + 'HAVE_READLINKAT': ('readlinkat', 'unistd.h'), + 'HAVE_READV': ('readv', 'sys/uio.h'), + 'HAVE_RENAMEAT': ('renamat', 'stdio.h'), + 'HAVE_SCHED_GET_PRIORITY_MAX': ('sched_get_priority_max', 'sched.h'), + 'HAVE_SCHED_RR_GET_INTERVAL': ('sched_rr_get_interval', 'sched.h'), + 'HAVE_SCHED_SETAFFINITY': ('sched_setaffinity', 'sched.h'), + 'HAVE_SCHED_SETPARAM': ('sched_setparam', 'sched.h'), + 'HAVE_SCHED_SETSCHEDULER': ('sched_setscheduler', 'sched.h'), + 'HAVE_SELECT': ('select', 'sys/select.h'), + 'HAVE_SEM_GETVALUE': ('sem_getvalue', 'semaphore.h'), + 'HAVE_SEM_OPEN': ('sem_open', 'semaphore.h'), + 'HAVE_SEM_TIMEDWAIT': ('sem_timedwait', 'semaphore.h'), + 'HAVE_SEM_UNLINK': ('sem_unlink', 'semaphore.h'), + 'HAVE_SENDFILE': ('sendfile', 'sys/sendfile.h'), + 'HAVE_SETGID': ('setgid', 'unistd.h'), + 'HAVE_SETGROUPS': ('setgroups', 'grp.h'), + 'HAVE_SETHOSTNAME': ('sethostname', 'unistd.h'), + 'HAVE_SETITIMER': ('setitimer', 'sys/time.h'), + 'HAVE_SETLOCALE': ('setlocale', 'locale.h'), + 'HAVE_SETPGRP': ('setpgrp', 'unistd.h'), + 'HAVE_SETPRIORITY': ('setpriority', 'sys/resource.h'), + 'HAVE_SETREUID': ('setreuid', 'unistd.h'), + 'HAVE_SETSID': ('setsid', 'unistd.h'), + 'HAVE_SETUID': ('setuid', 'unistd.h'), + 'HAVE_SETVBUF': ('setvbuf', 'unistd.h'), + 'HAVE_SIGALTSTACK': ('sigaltstack', 'signal.h'), + 'HAVE_SIGINTERRUPT': ('siginterrupt', 'signal.h'), + 'HAVE_SIGPENDING': ('sigpending', 'signal.h'), + 'HAVE_SIGRELSE': ('sigrelse', 'signal.h'), + 'HAVE_SIGTIMEDWAIT': ('sigtimedwait', 'signal.h'), + 'HAVE_SIGWAIT': ('sigwait', 'signal.h'), + 'HAVE_SIGWAITINFO': ('sigwaitinfo', 'signal.h'), + 'HAVE_SOCKETPAIR': ('socketpair', 'sys/socket.h'), + 'HAVE_STRFTIME': ('strftime', 'time.h'), + 'HAVE_SYMLINKAT': ('symlinkat', 'unistd.h'), + 'HAVE_SYNC': ('sync', 'unistd.h'), + 'HAVE_TCGETPGRP': ('tcgetpgrp', 'unistd.h'), + 'HAVE_TCSETPGRP': ('tcsetpgrp', 'unistd.h'), + 'HAVE_TEMPNAM': ('tempnam', 'stdio.h'), + 'HAVE_TIMES': ('times', 'sys/times.h'), + 'HAVE_TEMPFILE': ('tempfile', 'stdio.h'), + 'HAVE_TMPNAM': ('tmpnam', 'stdio.h'), + 'HAVE_TMPNAM_R': ('tmpnam_r', 'stdio.h'), + 'HAVE_TRUNCATE': ('truncate', 'unistd.h'), + 'HAVE_TZNAME': ('tzname', 'time.h'), + 'HAVE_UNAME': ('uname', 'sys/utsname.h'), + 'HAVE_UNLINKAT': ('unlinkat', 'unistd.h'), + 'HAVE_UTIMENSAT': ('utimensat', 'sys/stat.h'), + 'HAVE_WAIT3': ('wait3', 'sys/wait.h'), + 'HAVE_WAIT4': ('wait4', 'sys/wait.h'), + 'HAVE_WAITID': ('waitid', 'sys/wait.h'), + 'HAVE_WRITEV': ('writev', 'sys/uio.h'), + 'HAVE_WMEMCMP': ('wmemcmp', 'wchar.h'), 'HAVE_ATAN': ('atan', 'math.h'), 'HAVE_ATAN2': ('atan2', 'math.h'), 'HAVE_ACOS': ('acos', 'math.h'), + 'HAVE_ACOSH': ('acosh', 'math.h'), 'HAVE_ASIN': ('asin', 'math.h'), 'HAVE_ASINH': ('asinh', 'math.h'), + 'HAVE_ATANH': ('atanh', 'math.h'), 'HAVE_CEIL': ('ceil', 'math.h'), 'HAVE_COPYSIGN': ('copysign', 'math.h'), 'HAVE_COS': ('cos', 'math.h'), 'HAVE_COSH': ('cosh', 'math.h'), 'HAVE_COSF': ('cosf', 'math.h'), + 'HAVE_EXPM1': ('expm1', 'math.h'), 'HAVE_FABS': ('fabs', 'math.h'), + 'HAVE_FINITE': ('finite', 'math.h'), 'HAVE_FLOOR': ('floor', 'math.h'), + 'HAVE_GAMMA': ('gamma', 'math.h'), + 'HAVE_HYPOT': ('hypot', 'math.h'), 'HAVE_ISINF': ('isinf', 'math.h'), 'HAVE_LOG': ('log', 'math.h'), + 'HAVE_LOG1P': ('log1p', 'math.h'), + 'HAVE_LOG2': ('log2', 'math.h'), + 'HAVE_LGAMMA': ('lgamma', 'math.h'), 'HAVE_POW': ('pow', 'math.h'), 'HAVE_SCALBN': ('scalbn', 'math.h'), 'HAVE_SIN': ('sin', 'math.h'), 'HAVE_SINF': ('sinf', 'math.h'), 'HAVE_SINH': ('sinh', 'math.h'), 'HAVE_SQRT': ('sqrt', 'math.h'), + 'HAVE_TGAMMA': ('tgamma', 'math.h'), 'HAVE_FSEEKO': ('fseeko', 'stdio.h'), 'HAVE_FSEEKO64': ('fseeko64', 'stdio.h'), 'HAVE_SETJMP': ('setjmp', 'setjmp.h'), |