Commit 325a231a added stricter keyword argument checking, but didn't enable
keyword arguments for add_projects_link_arguments() and
add_global_link_arguments(). This makes them fail with this error:
Meson encountered an error in file meson.build, line 19, column 0:
Function does not take keyword arguments.
However, the language argument is required. Removing it produces this error
instead:
Meson encountered an error in file meson.build, line 19, column 0:
Missing language definition in add_project_link_arguments
Fix this by adding 'language' as a required keyword argument. Also add calls to
these in the "146 C and CPP link" test case.
This class now consolidates a lot of the logic that each external
dependency was duplicating in its class definition.
All external dependencies now set:
* self.version
* self.compile_args and self.link_args
* self.is_found (if found)
* self.sources
* etc
And the abstract ExternalDependency class defines the methods that
will fetch those properties. Some classes still override that for
various reasons, but those should also be migrated to properties as
far as possible.
Next step is to consolidate and standardize the way in which we call
'configuration binaries' such as sdl2-config, llvm-config, pkg-config,
etc. Currently each class has to duplicate code involved with that
even though the format is very similar.
Currently only pkg-config supports multiple version requirements, and
some classes don't even properly check the version requirement. That
will also become easier now.
This simplifies everything since it means we will always search for the
dependency again on the system if it wasn't found. This is particularly
important when running `ninja reconfigure` with an edited
PKG_CONFIG_PATH to point to a path that contains more pkg-config files.
The old caching was a mess of spaghetti code layered over pasta code.
The new code is well-commented, is clear about what it's trying to do,
and uses a blacklist of keyword arguments instead of a whitelist while
generating identifiers for dep caching which makes it much more robust
for future changes.
The only side-effect of forgetting about a new keyword argument would
be that the dependency would not be cached unless the values of that
keyword arguments were the same in the cached and new dependency.
There are also more tests which identify scenarios that were broken
earlier.
All our cached_dep magic was totally useless since we ended up using
the same identifier for native and cross deps. Just nuke all this
cached_dep code since it is very error-prone and improve the
identifier generation instead.
For instance, this is broken *right now* with the `type_name` kwarg.
Add a bunch of tests to ensure that all this actually works...
Closes https://github.com/mesonbuild/meson/issues/1736
Refactor to use ExternalProgram for the command instead of duplicating
that code (badly). Also improve messages to say "or not executable"
when a script/command is not found.
Also allow ExternalPrograms to be passed as arguments to
run_command(). The only thing we're doing by preventing that is
forcing people to use prog.path()
The file will always exist by the time run_command() is invoked, so
there is no reason why we should forbid it. Also allow using File
objects as the command to run since strings are also allowed.
Provide a proper error message, rather than the current
"Command cannot have '@INPUT0@', since no input files were specified"
which doesn't actually tell us where things are going wrong.
Meson has a common pattern of using 'if len(foo) == 0:' or
'if len(foo) != 0:', however, this is a common anti-pattern in python.
Instead tests for emptiness/non-emptiness should be done with a simple
'if foo:' or 'if not foo:'
Consider the following:
>>> import timeit
>>> timeit.timeit('if len([]) == 0: pass')
0.10730923599840025
>>> timeit.timeit('if not []: pass')
0.030033907998586074
>>> timeit.timeit('if len(['a', 'b', 'c', 'd']) == 0: pass')
0.1154778649979562
>>> timeit.timeit("if not ['a', 'b', 'c', 'd']: pass")
0.08259823200205574
>>> timeit.timeit('if len("") == 0: pass')
0.089759664999292
>>> timeit.timeit('if not "": pass')
0.02340641999762738
>>> timeit.timeit('if len("foo") == 0: pass')
0.08848102600313723
>>> timeit.timeit('if not "foo": pass')
0.04032287199879647
And for the one additional case of 'if len(foo.strip()) == 0', which can
be replaced with 'if not foo.isspace()'
>>> timeit.timeit('if len(" ".strip()) == 0: pass')
0.15294511600222904
>>> timeit.timeit('if " ".isspace(): pass')
0.09413968399894657
>>> timeit.timeit('if len(" abc".strip()) == 0: pass')
0.2023209120015963
>>> timeit.timeit('if " abc".isspace(): pass')
0.09571301700270851
In other words, it's always a win to not use len(), when you don't
actually want to check the length.
Ideally, all dependency objects should support this, but it's a lot of
work and isn't supported by all dependency types (like frameworks and
pkg-config), so for now just enable it for external libraries.
This would make it harder to parse an option to mesonconf such
as -Dfoo:bar:baz:fun=value since it could mean either of these:
* For subproject 'foo:bar:baz', set the option 'fun' to 'value'
* For subproject 'foo:bar', an invalid option 'baz:fun' was set
To differentiate between these two we'd need to create the list of
subprojects first and then parse their options later, which
complicates the parsing quite a bit.
You can now pass a list of strings to the install_dir: kwarg to
build_target and custom_target.
Custom Targets:
===============
Allows you to specify the installation directory for each
corresponding output. For example:
custom_target('different-install-dirs',
output : ['first.file', 'second.file'],
...
install : true,
install_dir : ['somedir', 'otherdir])
This would install first.file to somedir and second.file to otherdir.
If only one install_dir is provided, all outputs are installed there
(same behaviour as before).
To only install some outputs, pass `false` for the outputs that you
don't want installed. For example:
custom_target('only-install-second',
output : ['first.file', 'second.file'],
...
install : true,
install_dir : [false, 'otherdir])
This would install second.file to otherdir and not install first.file.
Build Targets:
==============
With build_target() (which includes executable(), library(), etc),
usually there is only one primary output. However some types of
targets have multiple outputs.
For example, while generating Vala libraries, valac also generates
a header and a .vapi file both of which often need to be installed.
This allows you to specify installation directories for those too.
# This will only install the library (same as before)
shared_library('somevalalib', 'somesource.vala',
...
install : true)
# This will install the library, the header, and the vapi into the
# respective directories
shared_library('somevalalib', 'somesource.vala',
...
install : true,
install_dir : ['libdir', 'incdir', 'vapidir'])
# This will install the library into the default libdir and
# everything else into the specified directories
shared_library('somevalalib', 'somesource.vala',
...
install : true,
install_dir : [true, 'incdir', 'vapidir'])
# This will NOT install the library, and will install everything
# else into the specified directories
shared_library('somevalalib', 'somesource.vala',
...
install : true,
install_dir : [false, 'incdir', 'vapidir'])
true/false can also be used for secondary outputs in the same way.
Valac can also generate a GIR file for libraries when the `vala_gir:`
keyword argument is passed to library(). In that case, `install_dir:`
must be given a list with four elements, one for each output.
Includes tests for all these.
Closes https://github.com/mesonbuild/meson/issues/705
Closes https://github.com/mesonbuild/meson/issues/891
Closes https://github.com/mesonbuild/meson/issues/892
Closes https://github.com/mesonbuild/meson/issues/1178
Closes https://github.com/mesonbuild/meson/issues/1193
The configure_file command raised an exception when an input was specified as a
File, because os.path.join does not take File objects directly. This patch
converts a File object to a string and adjusts the subsequent os.path.join
calls.
Points to the `mesonintrospect.py` script corresponding to the
currently-running version of Meson.
Includes a test for all three methods of running scripts/commands.
Closes https://github.com/mesonbuild/meson/issues/1385
Now as long as you have a C compiler available in the project, it will
be used to compile assembly even if the target contains a C++ compiler
and even if the target contains only assembly and C++ sources.
Earlier, the order in which sources appeared in a target would decide
which compiler would be used.
However, if the project only provides a C++ compiler, that will be
used for compiling assembly sources.
If this breaks your use-case, please tell us.
Includes a test that ensures that all of the above is adhered to.
Use an ordered dict for the compiler dictionary and sort it according
to a priority order: fortran, c, c++, etc.
This also ensures that builds are reproducible because it would be
a toss-up whether a C or a C++ compiler would be used based on the
order in which compilers.items() would return items.
Closes https://github.com/mesonbuild/meson/issues/1370
An empty / no-op dependency can be expressed as []. This works with
the dependencies kwarg in executable targets such as shared_library,
but now with declare_dependency, where it would error out with
"error: Dependencies must be external deps" because the deps are
not flattened in this case. This patch fixes that.
Fixes#1500
Special wrap modes:
nofallback: Don't download wraps for dependency() fallbacks
nodownload: Don't download wraps for all subproject() calls
Subprojects are used for two purposes:
1. To download and build dependencies by using .wrap files if they
are not provided by the system. This is usually expressed via
dependency(..., fallback: ...).
2. To download and build 'copylibs' which are meant to be used by
copying into your project. This is always done with an explicit
subproject() call.
--wrap-mode=nofallback will never do (1)
--wrap-mode=nodownload will do neither (1) nor (2)
If you are building from a release tarball, you should be able to
safely use 'nodownload' since upstream is expected to ship all
required sources with the tarball.
If you are building from a git repository, you will want to use
'nofallback' so that any 'copylib' wraps will be download as
subprojects.
Note that these options do not affect subprojects that are git
submodules since those are only usable in git repositories, and you
almost always want to download them.
This will benefit projects such as GNOME Recipes that prefer using
submodules over wraps because it's easier to maintain since git is
aware of it, and because it integrates with their existing
workflow. Without this, these projects have to manually initialize
the submodules which is completely unnecessary.
Closes https://github.com/mesonbuild/meson/issues/1449
The same substitutions and rules as custom_target().
Also generally fix it to actually work when run in a subdir and with
anything other than absolute paths for input and output files.
We now also log a message when configuring files.
Includes tests for all this.
Otherwise env is {} and we get a traceback trying to use the setup:
$ /home/cassidy/dev/meson/mesontest.py -C build --setup valgrind
ninja: Entering directory `/home/cassidy/dev/gst/master/gst-build/build'
ninja: no work to do.
Traceback (most recent call last):
File "/home/cassidy/dev/meson/mesontest.py", line 579, in <module>
sys.exit(run(sys.argv[1:]))
File "/home/cassidy/dev/meson/mesontest.py", line 575, in run
return th.doit()
File "/home/cassidy/dev/meson/mesontest.py", line 337, in doit
self.run_tests(tests)
File "/home/cassidy/dev/meson/mesontest.py", line 485, in run_tests
self.drain_futures(futures, logfile, jsonlogfile)
File "/home/cassidy/dev/meson/mesontest.py", line 504, in drain_futures
self.print_stats(numlen, tests, name, result.result(), i, logfile, jsonlogfile)
File "/usr/lib64/python3.5/concurrent/futures/_base.py", line 398, in result
return self.__get_result()
File "/usr/lib64/python3.5/concurrent/futures/_base.py", line 357, in __get_result
raise self._exception
File "/usr/lib64/python3.5/concurrent/futures/thread.py", line 55, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/cassidy/dev/meson/mesontest.py", line 216, in run_single_test
child_env.update(self.options.global_env.get_env(child_env))
AttributeError: 'dict' object has no attribute 'get_env'
There is no harm in doing this, and this is the simplest fix for this.
Closes https://github.com/mesonbuild/meson/issues/1371
Ever since we changed how we do library searching, the full path to the
library has not been available under `.fullpath`. This has been broken
for at least a year...
And actually test that prog.path() works. The earlier test was just
running the command without checking if it succeeded.
Also make everything use prog.get_command() or get_path() instead of
accessing the internal member prog.fullpath directly.
With the 'install_mode' kwarg, you can now specify the file and
directory permissions and the owner and the group to be used while
installing. You can pass either:
* A single string specifying just the permissions
* A list of strings with:
- The first argument a string of permissions
- The second argument a string specifying the owner or
an int specifying the uid
- The third argument a string specifying the group or
an int specifying the gid
Specifying `false` as any of the arguments skips setting that one.
The format of the permissions kwarg is the same as the symbolic
notation used by ls -l with the first character that specifies 'd',
'-', 'c', etc for the file type omitted since that is always obvious
from the context.
Includes unit tests for the same. Sadly these only run on Linux right
now, but we want them to run on all platforms. We do set the mode in the
integration tests for all platforms but we don't check if they were
actually set correctly.
Cache the absolute dir that the script is searched in and the name of
the script. These are the only two things that change.
Update the test to test for both #1235 and the case when a script of the
same name is in a different directory (which also covers the subproject
case).
Closes#1235
There is basically no such word in english, "nonexistant".
American people use "nonexistent" and British people used
to have "non-existent", but some time ago they did away with
the hyphens, so there is only one option really: "nonexistent".
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
Everywhere we use this object, we end up iterating over it and comparing
compiler.get_language() with something. Using a dict is the obvious
choice and simplifies a lot of code.
Check if the compiler prefixes an underscore to global symbols. This is
useful when linking to compiled assembly code, or other code that does
not have its C symbol mangling handled transparently by the compiler.
C symbol mangling is platform and architecture dependent, and a helper
function is needed to detect it. Eg: Windows 32-bit prefixes underscore,
but 64-bit does not. Linux does not prefix an underscore but OS X does.
Instead of adding it everywhere manually, create a wrapper called
mesonlib.Popen_safe and use that everywhere that we call an executable
and extract its output.
This will also allow us to tweak it to do more/different things if
needed for some locales and/or systems.
Closes#1079
Using 'mesonbuild' as the module can cause it to use the
system-installed module and can also break if we rename the directory,
so avoid that by always using relative imports.
This is already how it should've been, but:
a) The test for this was wrong since Dependency is a base class for all
dependencies and isinstance on an InternalDependency will also be true
b) Internal dependencies can't ever be used here anyway because compiler
checks are always run at configure time and internal dependencies are
only built after that.
Also did a bit of cleanup.
interpreter.py: There’s a catch all except clause at the line 1928, it didn’t give the user any information whatsoever about the exception it caught. Now it at least print it to the log as a warning.
Sometimes we want to restrict the acceptable versions to a list of
versions, or a smallest-version + largest-version, or both. For
instance, GStreamer's opencv plugin is only compatible with
3.1.0 >= opencv >= 2.3.0
Move CCompiler.compile to Compiler.compile so that ValaCompiler can use
it. Also rewrite ValaCompiler.sanity_check to use it since it does
a simple compile check.
At the same time, it enhances ExternalLibrary to support arguments for
languages other than C-like.
Includes a test for this that links against zlib through Vala.
Closes#983
* contributing: Use should instead of thould
* interpreter: Use exist_ok parameter in subdir function
We explicitly depend on python 3.4 or newer, which means the exist_ok
parameter is available. Use it instead of a try with a pass on except.
* authors: Add my name at the end of authors file
This is the common Python convention for private methods
so lets not expose these to build files as they are
implementation details and their behavior is undefined.
All assignments in meson should be by value, so mutable objects
(i.e. environment() and configuration_data()) should be copied
automatically on assignment.
Fixes#831.
We should only silently return from a dependency() call if the error is
transient (old version, wrap failed to download etc), not if the
subproject invocation or dependency name are incorrect.
For instance, if you use a dependency(..., fallback : ...) call in
a meson.build not in the root directory, we would always ignore the
call instead of erroring out due to invalid usage.
We should consider categorising our exceptions in this manner elsewhere
too.
If first checking for a dependency as not-required, and then later
checking for the same dependency again as required, we would not
error out saying the dependency is missing, but just silently
re-use the cached dependency object from the first check and then
likely fail at build time if the dependency is not actually there.
With test case.
Fixes#964.
Seems better to do this since the behaviour is compiler-specific. Would
be easier to extend this later too in case we want to do more
compiler-specific things.
The error message is misleading (talks about external dependencies), and
doesn't tell you what you need to do (use the output of
declare_dependency, dependency, or find_library). At the same time
rename add_external_deps to add_deps since it adds internal deps too.
Plus many more error message improvements all over the place.
Not only does extract_all_objects() now work properly again,
extract_objects() also works if you specify a subset of sources all of
which have been compiled into a single unified object.
So, for instance, this allows you to extract all the objects
corresponding to the C sources compiled into a target consisting of
C and C++ sources.
If a fallback dependency is not found just return None. The
caller can then raise the exception it already has if
required=True, or just continue on if required=False.
In the case the main project set a subproject for a dependency another
subprojects uses, that other subproject should rather use the first
subproject rather that using native dependency.
For example in gst-all we set all GStreamer modules as subprojects
and, gst-plugins-base is set after gstreamer core, and
we want gst-plugins-base to always use GStreamer core from the subproject
and not the possibly avalaible native one.