diff options
35 files changed, 400 insertions, 300 deletions
@@ -16,6 +16,7 @@ __pycache__ .DS_Store *~ +*.swp packagecache /MANIFEST /build diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index 8137cff..b23cc94 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -21,21 +21,31 @@ Installation options are all relative to the prefix, except: * When the prefix is `/usr`: `sysconfdir` defaults to `/etc`, `localstatedir` defaults to `/var`, and `sharedstatedir` defaults to `/var/lib` * When the prefix is `/usr/local`: `localstatedir` defaults to `/var/local`, and `sharedstatedir` defaults to `/var/local/lib` -| Option | Default value | Description -| ------ | ------------- | ----------- -| prefix | see below | Installation prefix -| libdir | see below | Library directory -| libexecdir | libexec | Library executable directory -| bindir | bin | Executable directory -| sbindir | sbin | System executable directory -| includedir | include | Header file directory -| datadir | share | Data file directory -| mandir | share/man | Manual page directory -| infodir | share/info | Info page directory -| localedir | share/locale | Locale data directory -| sysconfdir | etc | Sysconf data directory -| localstatedir | var | Localstate data directory -| sharedstatedir | com | Architecture-independent data directory +| Option | Default value | Description | +| ------ | ------------- | ----------- | +| prefix | see below | Installation prefix | +| libdir | see below | Library directory | +| libexecdir | libexec | Library executable directory | +| bindir | bin | Executable directory | +| sbindir | sbin | System executable directory | +| includedir | include | Header file directory | +| datadir | share | Data file directory | +| mandir | share/man | Manual page directory | +| infodir | share/info | Info page directory | +| localedir | share/locale | Locale data directory | +| sysconfdir | etc | Sysconf data directory | +| localstatedir | var | Localstate data directory | +| sharedstatedir | com | Architecture-independent data directory | +| werror | false | Treat warnings as erros | +| warnlevel {1, 2, 3} | 1 | Set the warning level. From 1 = lowest to 3 = highest | +| layout {mirror,flat} | mirror | Build directory layout. | +| default-library {shared, static, both} | shared | Default library type. | +| backend {ninja, vs,<br>vs2010, vs2015, vs2017, xcode} | | Backend to use (default: ninja). | +| stdsplit | | Split stdout and stderr in test logs. | +| errorlogs | | Whether to print the logs from failing tests. | +| cross-file CROSS_FILE | | File describing cross compilation environment. | +| wrap-mode {default, nofallback, nodownload, forcefallback} | | Special wrap mode to use | + `prefix` defaults to `C:/` on Windows, and `/usr/local/` otherwise. You should always override this value. @@ -58,19 +68,19 @@ a builddir and then run `meson configure` on it with no options. The following options are available. Note that they may not be available on all platforms or with all compilers: -| Option | Default value | Possible values | Description -| ----------- | ------------- | --------------- | ----------- -| b_asneeded | true | true, false | Use -Wl,--as-needed when linking -| b_bitcode | false | true, false | Embed Apple bitcode, see below -| b_colorout | always | auto, always, never | Use colored output -| b_coverage | false | true, false | Enable coverage tracking -| b_lundef | true | true, false | Don't allow undefined symbols when linking -| b_lto | false | true, false | Use link time optimization -| b_ndebug | false | true, false, if-release | Disable asserts -| b_pch | true | true, false | Use precompiled headers -| b_pgo | off | off, generate, use | Use profile guided optimization -| b_sanitize | none | see below | Code sanitizer to use -| b_staticpic | true | true, false | Build static libraries as position independent +| Option | Default value | Possible values | Description | +| ----------- | ------------- | --------------- | ----------- | +| b_asneeded | true | true, false | Use -Wl,--as-needed when linking | +| b_bitcode | false | true, false | Embed Apple bitcode, see below | +| b_colorout | always | auto, always, never | Use colored output | +| b_coverage | false | true, false | Enable coverage tracking | +| b_lundef | true | true, false | Don't allow undefined symbols when linking | +| b_lto | false | true, false | Use link time optimization | +| b_ndebug | false | true, false, if-release | Disable asserts | +| b_pch | true | true, false | Use precompiled headers | +| b_pgo | off | off, generate, use | Use profile guided optimization | +| b_sanitize | none | see below | Code sanitizer to use | +| b_staticpic | true | true, false | Build static libraries as position independent | The value of `b_sanitize` can be one of: `none`, `address`, `thread`, `undefined`, `memory`, `address,undefined`. @@ -93,18 +103,18 @@ The following options are available. Note that both the options themselves and the possible values they can take will depend on the target platform or compiler being used: -| Option | Default value | Possible values | Description -| ------ | ------------- | --------------- | ----------- -| c_args | | free-form comma-separated list | C compile arguments to use -| c_link_args | | free-form comma-separated list | C link arguments to use -| c_std | none | none, c89, c99, c11, gnu89, gnu99, gnu11 | C language standard to use -| c_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against -| cpp_args | | free-form comma-separated list | C++ compile arguments to use -| cpp_link_args| | free-form comma-separated list | C++ link arguments to use -| cpp_std | none | none, c++98, c++03, c++11, c++14, c++17, <br/>c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z | C++ language standard to use -| cpp_debugstl | false | true, false | C++ STL debug mode -| cpp_eh | sc | none, a, s, sc | C++ exception handling type -| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against +| Option | Default value | Possible values | Description | +| ------ | ------------- | --------------- | ----------- | +| c_args | | free-form comma-separated list | C compile arguments to use | +| c_link_args | | free-form comma-separated list | C link arguments to use | +| c_std | none | none, c89, c99, c11, gnu89, gnu99, gnu11 | C language standard to use | +| c_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against | +| cpp_args | | free-form comma-separated list | C++ compile arguments to use | +| cpp_link_args| | free-form comma-separated list | C++ link arguments to use | +| cpp_std | none | none, c++98, c++03, c++11, c++14, c++17, <br/>c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z | C++ language standard to use | +| cpp_debugstl | false | true, false | C++ STL debug mode | +| cpp_eh | sc | none, a, s, sc | C++ exception handling type | +| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against | The default values of `c_winlibs` and `cpp_winlibs` are in compiler-specific argument forms, but the libraries are: kernel32, user32, gdi32, winspool, diff --git a/docs/markdown/Continuous-Integration.md b/docs/markdown/Continuous-Integration.md index 60e76d1..9ec46b2 100644 --- a/docs/markdown/Continuous-Integration.md +++ b/docs/markdown/Continuous-Integration.md @@ -85,7 +85,37 @@ test_script: ## Travis without Docker -This setup is not recommended but included here for completeness +You can cheat your way around docker by using **python** as language and setting your compiler in the build **matrix**. This example just uses **linux** and **c** but can be easily adapted to **c++** and **osx**. + +```yaml +sudo: false + +os: linux +dist: trusty + +language: python + +python: 3.6 + +matrix: + include: + - env: CC=gcc + - env: CC=clang + +install: + - export NINJA_LATEST=$(curl -s https://api.github.com/repos/ninja-build/ninja/releases/latest | grep browser_download_url | cut -d '"' -f 4 | grep ninja-linux.zip) + - wget "$NINJA_LATEST" + - unzip -q ninja-linux.zip -d build + - export PATH="$PWD/build:$PATH" + - pip install meson + +script: + - meson builddir + - ninja -C builddir + - ninja -C builddir test +``` + +This setup uses the **beta** group. It is not recommended but included here for completeness: ```yaml sudo: false diff --git a/docs/markdown/Design-rationale.md b/docs/markdown/Design-rationale.md index 7cf67a4..1c65fa8 100644 --- a/docs/markdown/Design-rationale.md +++ b/docs/markdown/Design-rationale.md @@ -193,7 +193,7 @@ keyword arguments. They look like this. ```meson project('compile several', 'c') -sources = ['main.c', 'file1.c', 'file2.c', 'file3.c'] +sourcelist = ['main.c', 'file1.c', 'file2.c', 'file3.c'] executable('program', sources : sourcelist) ``` @@ -202,7 +202,7 @@ External dependencies are simple to use. ```meson project('external lib', 'c') libdep = find_dep('extlibrary', required : true) -sources = ['main.c', 'file1.c', 'file2.c', 'file3.c'] +sourcelist = ['main.c', 'file1.c', 'file2.c', 'file3.c'] executable('program', sources : sourcelist, dep : libdep) ``` diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md index 634fe79..6b63f8a 100644 --- a/docs/markdown/Gnome-module.md +++ b/docs/markdown/Gnome-module.md @@ -40,8 +40,8 @@ file called `foobar.h`, which you can then include in your sources. * `install_dir`: (*Added 0.37.0*) location to install the header or bundle depending on previous options * `install_header`: (*Added 0.37.0*) if true, install the header file -* `source_dir`: a list of subdirectories where the resource compiler - should look up the files, relative to the location of the XML file +* `source_dir`: a list of directories where the resource compiler + should look up the files Returns an array containing: `[c_source, header_file]` or `[gresource_bundle]` diff --git a/docs/markdown/Module-reference.md b/docs/markdown/Module-reference.md deleted file mode 100644 index 60be7bd..0000000 --- a/docs/markdown/Module-reference.md +++ /dev/null @@ -1,20 +0,0 @@ -Meson has a selection of modules to make common requirements easy to use. -Modules can be thought of like the standard library of a programming language. -Currently Meson provides the following modules. - -* [Gnome](Gnome-module.md) -* [i18n](i18n-module.md) -* [Qt4](Qt4-module.md) -* [Qt5](Qt5-module.md) -* [Pkgconfig](Pkgconfig-module.md) -* [Python3](Python-3-module.md) -* [RPM](RPM-module.md) -* [Windows](Windows-module.md) - -In addition there are unstable modules. These are meant for testing new -functionality but note that they do *not* provide a stable API. It can -change in arbitrary ways between releases. The modules might also be removed -without warning in future releases. - - * [SIMD](Simd-module.md) - diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index df8531c..e3ae111 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -2045,6 +2045,9 @@ library. This object has the following methods: - `found` which returns whether the library was found. + - `type_name()` (*added 0.48.0*) which returns a string describing + the type of the dependency, which will be `library` in this case. + - `partial_dependency(compile_args : false, link_args : false, links : false, includes : false, source : false)` (*added 0.46.0*) returns a new dependency object with the same name, version, found status, diff --git a/docs/markdown/Running-Meson.md b/docs/markdown/Running-Meson.md index 7db22bf..00b70ed 100644 --- a/docs/markdown/Running-Meson.md +++ b/docs/markdown/Running-Meson.md @@ -10,6 +10,9 @@ directly from the source tree with the command the command is simply `meson`. In this manual we only use the latter format for simplicity. +Additionally, the invocation can pass options to meson. +The list of options is documented [here](Builtin-options.md). + At the time of writing only a command line version of Meson is available. This means that Meson must be invoked using the terminal. If you wish to use the MSVC compiler, you need to run Meson diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 2a20b36..d328b97 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -17,6 +17,7 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson). - [Dpdk](http://dpdk.org/browse/dpdk), Data plane development kit, a set of libraries and drivers for fast packet processing - [DXVK](https://github.com/doitsujin/dxvk), a Vulkan-based Direct3D 11 implementation for Linux using Wine - [Emeus](https://github.com/ebassi/emeus), Constraint based layout manager for GTK+ + - [ESP8266 Arduino sample project](https://github.com/trilader/arduino-esp8266-meson) Sample project for using the ESP8266 Arduino port with Meson - [Fractal](https://wiki.gnome.org/Apps/Fractal/), a Matrix messaging client for GNOME - [Frida](https://github.com/frida/frida-core), a dynamic binary instrumentation toolkit - [fwupd](https://github.com/hughsie/fwupd), a simple daemon to allow session software to update firmware diff --git a/docs/sitemap.txt b/docs/sitemap.txt index 5e8b50e..68f0a8f 100644 --- a/docs/sitemap.txt +++ b/docs/sitemap.txt @@ -5,6 +5,7 @@ index.md Manual.md Overview.md Running-Meson.md + Builtin-options.md Using-with-Visual-Studio.md Meson-sample.md Syntax.md diff --git a/man/mesonconf.1 b/man/mesonconf.1 deleted file mode 100644 index 5463c71..0000000 --- a/man/mesonconf.1 +++ /dev/null @@ -1,10 +0,0 @@ -.TH MESONCONF "1" "July 2018" "mesonconf 0.47.0" "User Commands" -.SH NAME -mesonconf - a tool to configure Meson builds -.SH DESCRIPTION - -This executable is deprecated and will be removed in the future. The -functionality that was in this executable can be invoked via the main Meson -command like this: - -.B meson configure <options> diff --git a/man/mesonintrospect.1 b/man/mesonintrospect.1 deleted file mode 100644 index 5d3eb42..0000000 --- a/man/mesonintrospect.1 +++ /dev/null @@ -1,13 +0,0 @@ -.TH MESONINTROSPECT "1" "July 2018" "mesonintrospect 0.47.0" "User Commands" -.SH NAME -mesonintrospect - a tool to extract information about a Meson build -.SH DESCRIPTION - -This executable is deprecated and will be removed in the future. The -functionality that was in this executable can be invoked via the main Meson -command like this: - -.B meson introspect <options> - -.SH SEE ALSO -http://mesonbuild.com/ diff --git a/man/mesontest.1 b/man/mesontest.1 deleted file mode 100644 index e231bf6..0000000 --- a/man/mesontest.1 +++ /dev/null @@ -1,13 +0,0 @@ -.TH MESON "1" "July 2018" "meson 0.47.0" "User Commands" -.SH NAME -mesontest - test tool for the Meson build system -.SH DESCRIPTION - -This executable is deprecated and will be removed in the future. The -functionality that was in this executable can be invoked via the main Meson -command like this: - -.B meson test <options> - -.SH SEE ALSO -http://mesonbuild.com/ diff --git a/man/wraptool.1 b/man/wraptool.1 deleted file mode 100644 index 7895e39..0000000 --- a/man/wraptool.1 +++ /dev/null @@ -1,13 +0,0 @@ -.TH WRAPTOOL "1" "July 2018" "meson 0.47.0" "User Commands" -.SH NAME -wraptool - source dependency downloader -.SH DESCRIPTION - -This executable is deprecated and will be removed in the future. The -functionality that was in this executable can be invoked via the main Meson -command like this: - -.B meson wrap <options> - -.SH SEE ALSO -http://wrapdb.mesonbuild.com/ diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 3ee543d..09c4904 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -12,7 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os, pickle, re, shlex, subprocess +import os +import re +import shlex +import pickle +import subprocess from collections import OrderedDict import itertools from pathlib import PurePath @@ -24,7 +28,7 @@ from .. import build from .. import mlog from .. import dependencies from .. import compilers -from ..compilers import CompilerArgs, get_macos_dylib_install_name +from ..compilers import CompilerArgs, CCompiler, get_macos_dylib_install_name from ..linkers import ArLinker from ..mesonlib import File, MesonException, OrderedSet from ..mesonlib import get_compiler_for_source, has_path_sep @@ -2476,13 +2480,18 @@ rule FORTRAN_DEP_HACK%s target_args = self.build_target_link_arguments(linker, target.link_whole_targets) return linker.get_link_whole_for(target_args) if len(target_args) else [] - def guess_library_absolute_path(self, libname, search_dirs, prefixes, suffixes): - for directory in search_dirs: - for suffix in suffixes: - for prefix in prefixes: - trial = os.path.join(directory, prefix + libname + '.' + suffix) - if os.path.isfile(trial): - return trial + @staticmethod + def guess_library_absolute_path(linker, libname, search_dirs, patterns): + for d in search_dirs: + for p in patterns: + trial = CCompiler._get_trials_from_pattern(p, d, libname) + if not trial: + continue + trial = CCompiler._get_file_from_list(trial) + if not trial: + continue + # Return the first result + return trial def guess_external_link_dependencies(self, linker, target, commands, internal): # Ideally the linker would generate dependency information that could be used. @@ -2531,17 +2540,19 @@ rule FORTRAN_DEP_HACK%s # TODO The get_library_naming requirement currently excludes link targets that use d or fortran as their main linker if hasattr(linker, 'get_library_naming'): search_dirs = list(search_dirs) + linker.get_library_dirs() - prefixes_static, suffixes_static = linker.get_library_naming(self.environment, 'static', strict=True) - prefixes_shared, suffixes_shared = linker.get_library_naming(self.environment, 'shared', strict=True) + static_patterns = linker.get_library_naming(self.environment, 'static', strict=True) + shared_patterns = linker.get_library_naming(self.environment, 'shared', strict=True) for libname in libs: # be conservative and record most likely shared and static resolution, because we don't know exactly # which one the linker will prefer - static_resolution = self.guess_library_absolute_path(libname, search_dirs, prefixes_static, suffixes_static) - shared_resolution = self.guess_library_absolute_path(libname, search_dirs, prefixes_shared, suffixes_shared) - if static_resolution: - guessed_dependencies.append(os.path.realpath(static_resolution)) - if shared_resolution: - guessed_dependencies.append(os.path.realpath(shared_resolution)) + staticlibs = self.guess_library_absolute_path(linker, libname, + search_dirs, static_patterns) + sharedlibs = self.guess_library_absolute_path(linker, libname, + search_dirs, shared_patterns) + if staticlibs: + guessed_dependencies.append(os.path.realpath(staticlibs)) + if sharedlibs: + guessed_dependencies.append(os.path.realpath(sharedlibs)) return guessed_dependencies + absolute_libs diff --git a/mesonbuild/build.py b/mesonbuild/build.py index aa6e70b..65438b0 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1741,7 +1741,7 @@ class CustomTarget(Target): if i.strip() == '': raise InvalidArguments('Output must not consist only of whitespace.') if has_path_sep(i): - raise InvalidArguments('Output must not contain a path segment.') + raise InvalidArguments('Output {!r} must not contain a path segment.'.format(i)) if '@INPUT@' in i or '@INPUT0@' in i: m = 'Output cannot contain @INPUT@ or @INPUT0@, did you ' \ 'mean @PLAINNAME@ or @BASENAME@?' diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 8af7abc..af3e2c4 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -12,14 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import subprocess, os.path, re +import re +import glob +import os.path +import subprocess from .. import mlog from .. import coredata from . import compilers from ..mesonlib import ( EnvironmentException, version_compare, Popen_safe, listify, - for_windows, for_darwin, for_cygwin, for_haiku, + for_windows, for_darwin, for_cygwin, for_haiku, for_openbsd, ) from .compilers import ( @@ -800,6 +803,22 @@ class CCompiler(Compiler): return False raise RuntimeError('BUG: {!r} check failed unexpectedly'.format(n)) + def _get_patterns(self, env, prefixes, suffixes, shared=False): + patterns = [] + for p in prefixes: + for s in suffixes: + patterns.append(p + '{}.' + s) + if shared and for_openbsd(self.is_cross, env): + # Shared libraries on OpenBSD can be named libfoo.so.X.Y: + # https://www.openbsd.org/faq/ports/specialtopics.html#SharedLibs + # + # This globbing is probably the best matching we can do since regex + # is expensive. It's wrong in many edge cases, but it will match + # correctly-named libraries and hopefully no one on OpenBSD names + # their files libfoo.so.9a.7b.1.0 + patterns.append('lib{}.so.[0-9]*.[0-9]*') + return patterns + def get_library_naming(self, env, libtype, strict=False): ''' Get library prefixes and suffixes for the target platform ordered by @@ -830,18 +849,54 @@ class CCompiler(Compiler): else: # Linux/BSDs shlibext = ['so'] + patterns = [] # Search priority if libtype in ('default', 'shared-static'): - suffixes = shlibext + stlibext + patterns += self._get_patterns(env, prefixes, shlibext, True) + patterns += self._get_patterns(env, prefixes, stlibext, False) elif libtype == 'static-shared': - suffixes = stlibext + shlibext + patterns += self._get_patterns(env, prefixes, stlibext, False) + patterns += self._get_patterns(env, prefixes, shlibext, True) elif libtype == 'shared': - suffixes = shlibext + patterns += self._get_patterns(env, prefixes, shlibext, True) elif libtype == 'static': - suffixes = stlibext + patterns += self._get_patterns(env, prefixes, stlibext, False) else: raise AssertionError('BUG: unknown libtype {!r}'.format(libtype)) - return prefixes, suffixes + return patterns + + @staticmethod + def _sort_shlibs_openbsd(libs): + filtered = [] + for lib in libs: + # Validate file as a shared library of type libfoo.so.X.Y + ret = lib.rsplit('.so.', maxsplit=1) + if len(ret) != 2: + continue + try: + float(ret[1]) + except ValueError: + continue + filtered.append(lib) + float_cmp = lambda x: float(x.rsplit('.so.', maxsplit=1)[1]) + return sorted(filtered, key=float_cmp, reverse=True) + + @classmethod + def _get_trials_from_pattern(cls, pattern, directory, libname): + f = os.path.join(directory, pattern.format(libname)) + # Globbing for OpenBSD + if '*' in pattern: + # NOTE: globbing matches directories and broken symlinks + # so we have to do an isfile test on it later + return cls._sort_shlibs_openbsd(glob.glob(f)) + return [f] + + @staticmethod + def _get_file_from_list(files): + for f in files: + if os.path.isfile(f): + return f + return None def find_library_real(self, libname, env, extra_dirs, code, libtype): # First try if we can just add the library as -l. @@ -851,36 +906,38 @@ class CCompiler(Compiler): args = ['-l' + libname] if self.links(code, env, extra_args=args): return args - # Search in the system libraries too - system_dirs = self.get_library_dirs() # Not found or we want to use a specific libtype? Try to find the # library file itself. - prefixes, suffixes = self.get_library_naming(env, libtype) - # Triply-nested loops! + patterns = self.get_library_naming(env, libtype) for d in extra_dirs: - for suffix in suffixes: - for prefix in prefixes: - trial = os.path.join(d, prefix + libname + '.' + suffix) - if os.path.isfile(trial): - return [trial] - for d in system_dirs: - for suffix in suffixes: - for prefix in prefixes: - trial = os.path.join(d, prefix + libname + '.' + suffix) - # When searching the system paths used by the compiler, we - # need to check linking with link-whole, as static libs - # (.a) need to be checked to ensure they are the right - # architecture, e.g. 32bit or 64-bit. - # Just a normal test link won't work as the .a file doesn't - # seem to be checked by linker if there are no unresolved - # symbols from the main C file. - extra_link_args = self.get_link_whole_for([trial]) - extra_link_args = self.linker_to_compiler_args(extra_link_args) - if (os.path.isfile(trial) and - self.links(code, env, - extra_args=extra_link_args)): - return [trial] - # XXX: For OpenBSD and macOS we (may) need to search for libfoo.x{,.y.z}.ext + for p in patterns: + trial = self._get_trials_from_pattern(p, d, libname) + if not trial: + continue + trial = self._get_file_from_list(trial) + if not trial: + continue + return [trial] + # Search in the system libraries too + for d in self.get_library_dirs(): + for p in patterns: + trial = self._get_trials_from_pattern(p, d, libname) + if not trial: + continue + trial = self._get_file_from_list(trial) + if not trial: + continue + # When searching the system paths used by the compiler, we + # need to check linking with link-whole, as static libs + # (.a) need to be checked to ensure they are the right + # architecture, e.g. 32bit or 64-bit. + # Just a normal test link won't work as the .a file doesn't + # seem to be checked by linker if there are no unresolved + # symbols from the main C file. + extra_link_args = self.get_link_whole_for([trial]) + extra_link_args = self.linker_to_compiler_args(extra_link_args) + if self.links(code, env, extra_args=extra_link_args): + return [trial] return None def find_library_impl(self, libname, env, extra_dirs, code, libtype): diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 21aab11..25835a3 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1561,6 +1561,9 @@ class IntelCompiler: else: return ['-openmp'] + def get_link_whole_for(self, args): + return GnuCompiler.get_link_whole_for(self, args) + class ArmCompiler: # Functionality that is common to all ARM family compilers. diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 126900a..7344114 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -111,7 +111,7 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler): def get_options(self): opts = CPPCompiler.get_options(self) opts.update({'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', - ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17' + ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'gnu++98', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17'], 'none')}) return opts diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 6254a6a..d6e41e3 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -173,8 +173,11 @@ class FortranCompiler(Compiler): def run(self, code, env, extra_args=None, dependencies=None): return CCompiler.run(self, code, env, extra_args, dependencies) - def get_library_naming(self, env, libtype, strict=False): - return CCompiler.get_library_naming(self, env, libtype, strict) + def _get_patterns(self, *args, **kwargs): + return CCompiler._get_patterns(self, *args, **kwargs) + + def get_library_naming(self, *args, **kwargs): + return CCompiler.get_library_naming(self, *args, **kwargs) def find_library_real(self, *args): return CCompiler.find_library_real(self, *args) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 63b817a..0fe702f 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -995,7 +995,7 @@ class NonExistingExternalProgram(ExternalProgram): class ExternalLibrary(ExternalDependency): def __init__(self, name, link_args, environment, language, silent=False): - super().__init__('external', environment, language, {}) + super().__init__('library', environment, language, {}) self.name = name self.language = language self.is_found = False diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 5cadbe9..94f7bfe 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -483,6 +483,7 @@ class ExternalLibraryHolder(InterpreterObject, ObjectHolder): InterpreterObject.__init__(self) ObjectHolder.__init__(self, el, pv) self.methods.update({'found': self.found_method, + 'type_name': self.type_name_method, 'partial_dependency': self.partial_dependency_method, }) @@ -491,6 +492,11 @@ class ExternalLibraryHolder(InterpreterObject, ObjectHolder): @noPosargs @permittedKwargs({}) + def type_name_method(self, args, kwargs): + return self.held_object.type_name + + @noPosargs + @permittedKwargs({}) def found_method(self, args, kwargs): return self.found() diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index efb8d11..e8e5049 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -363,6 +363,18 @@ def for_haiku(is_cross, env): return env.cross_info.config['host_machine']['system'] == 'haiku' return False +def for_openbsd(is_cross, env): + """ + Host machine is OpenBSD? + + Note: 'host' is the machine on which compiled binaries will run + """ + if not is_cross: + return is_openbsd() + elif env.cross_info.has_host(): + return env.cross_info.config['host_machine']['system'] == 'openbsd' + return False + def exe_exists(arglist): try: p = subprocess.Popen(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE) diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 1aca9c6..011ac14 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -41,8 +41,8 @@ def create_parser(): help='Special wrap mode to use') p.add_argument('--profile-self', action='store_true', dest='profile', help=argparse.SUPPRESS) - p.add_argument('builddir', nargs='?', default='..') - p.add_argument('sourcedir', nargs='?', default='.') + p.add_argument('builddir', nargs='?', default=None) + p.add_argument('sourcedir', nargs='?', default=None) return p def wrapmodetype(string): @@ -331,6 +331,15 @@ def run(original_args, mainfile): dir1 = options.builddir dir2 = options.sourcedir try: + if dir1 is None: + if dir2 is None: + if not os.path.exists('meson.build') and os.path.exists('../meson.build'): + dir2 = '..' + else: + raise MesonException('Must specify at least one directory name.') + dir1 = os.getcwd() + if dir2 is None: + dir2 = os.getcwd() app = MesonApp(dir1, dir2, handshake, options) except Exception as e: # Log directory does not exist, so just print diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index f3eabda..1459ffe 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -1017,7 +1017,7 @@ This will become a hard error in the future.''') output = namebase + '-docbook' outputs = [] for f in xml_files: - outputs.append('{}-{}'.format(docbook, f)) + outputs.append('{}-{}'.format(docbook, os.path.basename(str(f)))) if mesonlib.version_compare(glib_version, '>= 2.56.2'): custom_kwargs = {'input': xml_files, diff --git a/mesonconf.py b/mesonconf.py deleted file mode 100755 index 894ec01..0000000 --- a/mesonconf.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2016 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. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys - -if __name__ == '__main__': - sys.exit('Error: This executable is no more. Use "meson configure" instead.') diff --git a/mesonintrospect.py b/mesonintrospect.py deleted file mode 100755 index 9ef1535..0000000 --- a/mesonintrospect.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2016 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. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys - -if __name__ == '__main__': - sys.exit('Error: This executable is no more. Use "meson introspect" instead.') diff --git a/mesonrewriter.py b/mesonrewriter.py deleted file mode 100755 index ef47e57..0000000 --- a/mesonrewriter.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2016 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. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This class contains the basic functionality needed to run any interpreter -# or an interpreter-based tool. - -# This tool is used to manipulate an existing Meson build definition. -# -# - add a file to a target -# - remove files from a target -# - move targets -# - reindent? - -import sys - -if __name__ == '__main__': - sys.exit('Error: This executable is no more. Use "meson rewrite" instead.') diff --git a/mesontest.py b/mesontest.py deleted file mode 100755 index e973d56..0000000 --- a/mesontest.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2016-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. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# A tool to run tests in many different ways. - -import sys - -if __name__ == '__main__': - sys.exit('Error: This executable is no more. Use "meson test" instead.') diff --git a/run_unittests.py b/run_unittests.py index 52e7780..dd109aa 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -35,7 +35,7 @@ import mesonbuild.coredata import mesonbuild.modules.gnome from mesonbuild.interpreter import ObjectHolder from mesonbuild.mesonlib import ( - is_windows, is_osx, is_cygwin, is_dragonflybsd, + is_windows, is_osx, is_cygwin, is_dragonflybsd, is_openbsd, windows_proof_rmtree, python_command, version_compare, grab_leading_numbers, BuildDirLock ) @@ -94,6 +94,25 @@ def skipIfNoPkgconfig(f): return f(*args, **kwargs) return wrapped +class PatchModule: + ''' + Fancy monkey-patching! Whee! Can't use mock.patch because it only + patches in the local namespace. + ''' + def __init__(self, func, name, impl): + self.func = func + assert(isinstance(name, str)) + self.func_name = name + self.old_impl = None + self.new_impl = impl + + def __enter__(self): + self.old_impl = self.func + exec('{} = self.new_impl'.format(self.func_name)) + + def __exit__(self, *args): + exec('{} = self.old_impl'.format(self.func_name)) + class InternalTests(unittest.TestCase): @@ -496,6 +515,92 @@ class InternalTests(unittest.TestCase): deps.add_pub_reqs([mock]) self.assertEqual(deps.format_reqs(deps.pub_reqs), "some_name") + def _test_all_naming(self, cc, env, patterns, platform): + shr = patterns[platform]['shared'] + stc = patterns[platform]['static'] + p = cc.get_library_naming(env, 'shared') + self.assertEqual(p, shr) + p = cc.get_library_naming(env, 'static') + self.assertEqual(p, stc) + p = cc.get_library_naming(env, 'static-shared') + self.assertEqual(p, stc + shr) + p = cc.get_library_naming(env, 'shared-static') + self.assertEqual(p, shr + stc) + p = cc.get_library_naming(env, 'default') + self.assertEqual(p, shr + stc) + # Test find library by mocking up openbsd + if platform != 'openbsd': + return + with tempfile.TemporaryDirectory() as tmpdir: + with open(os.path.join(tmpdir, 'libfoo.so.6.0'), 'w') as f: + f.write('') + with open(os.path.join(tmpdir, 'libfoo.so.5.0'), 'w') as f: + f.write('') + with open(os.path.join(tmpdir, 'libfoo.so.54.0'), 'w') as f: + f.write('') + with open(os.path.join(tmpdir, 'libfoo.so.66a.0b'), 'w') as f: + f.write('') + with open(os.path.join(tmpdir, 'libfoo.so.70.0.so.1'), 'w') as f: + f.write('') + found = cc.find_library_real('foo', env, [tmpdir], '', 'default') + self.assertEqual(os.path.basename(found[0]), 'libfoo.so.54.0') + + def test_find_library_patterns(self): + ''' + Unit test for the library search patterns used by find_library() + ''' + unix_static = ['lib{}.a', '{}.a'] + msvc_static = ['lib{}.a', 'lib{}.lib', '{}.a', '{}.lib'] + # This is the priority list of pattern matching for library searching + patterns = {'openbsd': {'shared': ['lib{}.so', '{}.so', 'lib{}.so.[0-9]*.[0-9]*'], + 'static': unix_static}, + 'linux': {'shared': ['lib{}.so', '{}.so'], + 'static': unix_static}, + 'darwin': {'shared': ['lib{}.dylib', '{}.dylib'], + 'static': unix_static}, + 'cygwin': {'shared': ['cyg{}.dll', 'cyg{}.dll.a', 'lib{}.dll', + 'lib{}.dll.a', '{}.dll', '{}.dll.a'], + 'static': ['cyg{}.a'] + unix_static}, + 'windows-msvc': {'shared': ['lib{}.lib', '{}.lib'], + 'static': msvc_static}, + 'windows-mingw': {'shared': ['lib{}.dll.a', 'lib{}.lib', 'lib{}.dll', + '{}.dll.a', '{}.lib', '{}.dll'], + 'static': msvc_static}} + env = Environment('', '', get_fake_options('')) + cc = env.detect_c_compiler(False) + if is_osx(): + self._test_all_naming(cc, env, patterns, 'darwin') + elif is_cygwin(): + self._test_all_naming(cc, env, patterns, 'cygwin') + elif is_windows(): + if cc.get_id() == 'msvc': + self._test_all_naming(cc, env, patterns, 'windows-msvc') + else: + self._test_all_naming(cc, env, patterns, 'windows-mingw') + else: + self._test_all_naming(cc, env, patterns, 'linux') + # Mock OpenBSD since we don't have tests for it + true = lambda x, y: True + if not is_openbsd(): + with PatchModule(mesonbuild.compilers.c.for_openbsd, + 'mesonbuild.compilers.c.for_openbsd', true): + self._test_all_naming(cc, env, patterns, 'openbsd') + else: + self._test_all_naming(cc, env, patterns, 'openbsd') + with PatchModule(mesonbuild.compilers.c.for_darwin, + 'mesonbuild.compilers.c.for_darwin', true): + self._test_all_naming(cc, env, patterns, 'darwin') + with PatchModule(mesonbuild.compilers.c.for_cygwin, + 'mesonbuild.compilers.c.for_cygwin', true): + self._test_all_naming(cc, env, patterns, 'cygwin') + with PatchModule(mesonbuild.compilers.c.for_windows, + 'mesonbuild.compilers.c.for_windows', true): + self._test_all_naming(cc, env, patterns, 'windows-mingw') + cc.id = 'msvc' + with PatchModule(mesonbuild.compilers.c.for_windows, + 'mesonbuild.compilers.c.for_windows', true): + self._test_all_naming(cc, env, patterns, 'windows-msvc') + class BasePlatformTests(unittest.TestCase): def setUp(self): @@ -2271,6 +2376,21 @@ recommended as it is not supported on some platforms''') arches = set(arches[1:]) self.assertEqual(arches, set(mesonbuild.environment.known_cpu_families)) + @unittest.skipIf(not os.path.isdir('docs'), 'Doc dir not found, presumably because this is a tarball release.') + def test_markdown_files_in_sitemap(self): + ''' + Test that each markdown files in docs/markdown is referenced in sitemap.txt + ''' + with open("docs/sitemap.txt") as f: + md = f.read() + self.assertIsNotNone(md) + toc = list(m.group(1) for m in re.finditer(r"^\s*(\w.*)$", md, re.MULTILINE)) + markdownfiles = [f.name for f in Path("docs/markdown").iterdir() if f.is_file() and f.suffix == '.md'] + exceptions = ['_Sidebar.md'] + for f in markdownfiles: + if f not in exceptions: + self.assertIn(f, toc) + def test_feature_check_usage_subprojects(self): testdir = os.path.join(self.unit_test_dir, '34 featurenew subprojects') out = self.init(testdir) @@ -2306,6 +2426,24 @@ recommended as it is not supported on some platforms''') self.assertEqual(f.read().strip(), b'') self.assertRegex(out, r"DEPRECATION:.*\['array'\] is invalid.*dict") + def test_dirs(self): + with tempfile.TemporaryDirectory() as containing: + with tempfile.TemporaryDirectory(dir=containing) as srcdir: + mfile = os.path.join(srcdir, 'meson.build') + of = open(mfile, 'w') + of.write("project('foobar', 'c')\n") + of.close() + pc = subprocess.run(self.setup_command, + cwd=srcdir, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + self.assertIn(b'Must specify at least one directory name', pc.stdout) + with tempfile.TemporaryDirectory(dir=srcdir) as builddir: + subprocess.run(self.setup_command, + check=True, + cwd=builddir, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) class FailureTests(BasePlatformTests): ''' @@ -71,17 +71,9 @@ setup(name='meson', 'mesonbuild.modules', 'mesonbuild.scripts', 'mesonbuild.wrap'], - scripts=['meson.py', - 'mesonconf.py', - 'mesontest.py', - 'mesonintrospect.py', - 'wraptool.py'], + scripts=['meson.py'], cmdclass={'install_scripts': install_scripts}, - data_files=[('share/man/man1', ['man/meson.1', - 'man/mesonconf.1', - 'man/mesonintrospect.1', - 'man/mesontest.1', - 'man/wraptool.1']), + data_files=[('share/man/man1', ['man/meson.1']), ('share/polkit-1/actions', ['data/com.mesonbuild.install.policy'])], classifiers=['Development Status :: 5 - Production/Stable', 'Environment :: Console', diff --git a/test cases/common/146 C and CPP link/meson.build b/test cases/common/146 C and CPP link/meson.build index 2dd3364..55c1b87 100644 --- a/test cases/common/146 C and CPP link/meson.build +++ b/test cases/common/146 C and CPP link/meson.build @@ -44,6 +44,8 @@ configure_file( command : stlib_cmd) libstcppext = cxx.find_library('stcppext', dirs : meson.current_build_dir()) +lib_type_name = libstcppext.type_name() +assert(lib_type_name == 'library', 'type name is ' + lib_type_name) libfooext = shared_library( 'fooext', diff --git a/test cases/frameworks/7 gnome/gdbus/com.example.Sample.xml b/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml index 9ece885..9ece885 100644 --- a/test cases/frameworks/7 gnome/gdbus/com.example.Sample.xml +++ b/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml diff --git a/test cases/frameworks/7 gnome/gdbus/meson.build b/test cases/frameworks/7 gnome/gdbus/meson.build index 8238e73..2de172f 100644 --- a/test cases/frameworks/7 gnome/gdbus/meson.build +++ b/test cases/frameworks/7 gnome/gdbus/meson.build @@ -1,4 +1,5 @@ -gdbus_src = gnome.gdbus_codegen('generated-gdbus-no-docbook', 'com.example.Sample.xml', +gdbus_src = gnome.gdbus_codegen('generated-gdbus-no-docbook', + 'data/com.example.Sample.xml', interface_prefix : 'com.example.', namespace : 'Sample', annotations : [ @@ -10,7 +11,7 @@ assert(gdbus_src[0].full_path().endswith('.c'), 'expected 1 c source file') assert(gdbus_src[1].full_path().endswith('.h'), 'expected 1 c header file') gdbus_src = gnome.gdbus_codegen('generated-gdbus', - sources : 'com.example.Sample.xml', + sources : files('data/com.example.Sample.xml'), interface_prefix : 'com.example.', namespace : 'Sample', annotations : [ diff --git a/wraptool.py b/wraptool.py deleted file mode 100755 index a5ee9ef..0000000 --- a/wraptool.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2016 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. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from mesonbuild.wrap import wraptool -import sys - -if __name__ == '__main__': - print('Warning: This executable is deprecated. Use "meson wrap" instead.', - file=sys.stderr) - sys.exit(wraptool.run(sys.argv[1:])) |