Meson: Provide a way to get pkg-version from compiler

Created on 11 Feb 2019  路  19Comments  路  Source: mesonbuild/meson

Allow for getting pkg-version from compiler.
Currently if a custom package version is set when building GCC it can't be recovered by .version()

E.g.

jakob@devtank~/t/bin> ./gcc --version
gcc (example) 8.2.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Using

project('test','c')

cc = meson.get_compiler('c')
message(cc.version())
The Meson build system
Version: 0.49.1
Source dir: /home/jakob/tmp/bin
Build dir: /home/jakob/tmp/bin/build
Build type: native build
Project name: test
Project version: undefined
Native C compiler: /home/jakob/tmp/bin/gcc (gcc 8.2.0 "gcc (example) 8.2.0")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Message: 8.2.0
Build targets in project: 0
Found ninja-1.8.2 at /usr/bin/ninja

It would be nice to have a pkg_version method or similar.

Most helpful comment

All API and features have to be maintained by volunteers, and so we only add API that is useful to a significant number of people.

There is already a way to get the information you need in a way that is literally exactly what you'd do in any other build system (CMake, Autotools, etc). Run the compiler and get the output.

All 19 comments

I had a go myself and this was the patch

diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 2eb07200..4d93d765 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -977,8 +977,13 @@ class CompilerHolder(InterpreterObject):
         return tpl.format(', '.join(names)) + endl

     @noPosargs
-    @permittedKwargs({})
+    @permittedKwargs({'full'})
     def version_method(self, args, kwargs):
+        full = kwargs.get('full', False)
+        if full:
+            if self.compiler.full_version is None:
+                raise InterpreterException('Full version requested but not set on compiler.')
+            return self.compiler.full_version
         return self.compiler.version

     @noPosargs

If we can squeeze this in for 0.50 that would be very helpful as its a blocker for adoption with us.

What is the specific part of the string that you need and what do you need it for, specifically?

tl;dr; gcc (xxx) 8.2.1 20181127 the bit in the brackets in this line.

We have some conditions about the environment and the compiler we use.
We have a blessed compiler that we build ourselves and it must be the compiler that is used for blessed builds, my project lead is telling me unless we can enforce a specific compiler inside meson.build he can't bless meson to replace make.

By default GCC will kick out

jakob@devtank~/t/bin> gcc --version
gcc (GCC) 8.2.1 20181127
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Our compiler kicks out

jakob@devtank~/t/bin> ./gcc --version
gcc (velo) 8.2.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

The bit in the brackets (w) are specified when building GCC as pkg-version.

Its also used heavily by package mangers for setting their own version numbers when distributing GCC.

It would be very powerful to us to have logic similar to

cc = meson.get_compiler('c')
if cc.get_version(pkg:true).contains('velo') 
...

Would it be an option to make the blessed compiler set a certain define instead?

@tp-m My lead wants it to be strictly defined as the default in the build file. I can emulate this by checking the pkg-version

It might also be the case in the future we add patches and extra support mainline gcc wont have so we need to detect when we are on our own compiler.

Would it be sufficient to have a config file that points at your compiler and just alias meson to load that config?

I have proposed this but its outside of the "norm"
To contribute to projects I should be able to install our toolchain, install meson then run meson build and just have everything working.

As is the current usecase with make.

For such a specialized case, why not do something like this?

cc = meson.get_compiler('c')
cc_version_out = run_command(cc.cmd_array() + ['--version'], check: true).stdout()
if cc_version_out.contains('velo')
...

I can't see it being unusual to get the full version string from meson itself?

The support is already there on Compiler object its just not exposed to the interpreter.

All API and features have to be maintained by volunteers, and so we only add API that is useful to a significant number of people.

There is already a way to get the information you need in a way that is literally exactly what you'd do in any other build system (CMake, Autotools, etc). Run the compiler and get the output.

@nirbheek But the functionality already exists its just not exposed to the user. All this issue is asking is that the full_version is exposed to the Compiler object. Its not like its an entirely new feature with no ground work.

Its a ~7 line change with 100% backwards compatibility.

What's the problem with using the code snippet I pasted? It's the same number of lines of build file code and is guaranteed to always work.

Adding this to Meson core is more work than you might imagine. We would have to specify answers to the following questions:

  • What would the string contain? Is it everything? Only a part? Which part?
  • What if the compiler writes some output to stdout and some to stderr?
  • What about compilers that do not write anything usable?
  • What about compilers that write tens of lines of text? How should we handle that?

And further we'd need to maintain this for eternity and for every compiler that we support (some of which have not yet been created). This is a problem that is easy to solve for one use case and one compiler (by doing the call yourself) but a _lot_ of work to make it work generally and portably.

There's also the question of what encoding the output is in, and what to do with characters that aren't ASCII when the encoding is not utf-8 compatible. Meson strings are always utf-8.

Let's say we pick 'replace with surrogates'. What if the user then expects to be able to find non-ASCII output in the compiler version on non-UTF-8 compatible encodings? The correct solution to this in the absence of built-in Meson support would be to call a script that does that work for you.

But even if none of these applied to this use-case, the trade-off (in the most optimistic case) is ~10 lines of code inside Meson vs a 1 line change in your build file. We come across hundreds of different edge-cases like this one. If we always said yes, we'd have thousands of lines of code that we can't really test or refactor without breaking someone's build files.

The more edge-cases a project caters to, the more exponentially harder maintenance becomes. That's why we can only add features that will be used widely. Sometimes something we thought was an edge-case turns out to be a popular scenario and we add it then.

It's easier to add features than to remove them. In the meantime, people can always write Python scripts to do whatever Meson can't do. These things are rarely a blocker.

I would totally agree with you on any other feature.

But the work for grabbing the full version string, (which is displayed when meson is first setup) already exists, its going to have to be supported no matter what happens with this issue ticket. All I am asking for is the ability to expose that to the user inside the interpreter. Hell you don't even need to support the subset, you can just provide the full version string and allow the caller to chop it up how they want.

The difference is that currently there are no guarantees that the 'full version' being displayed is correct or complete or even exists at all since it's only in user-visible output (as a status indicator), and not in a machine-readable form.

Transforming it to machine-readable immediately adds all the problems Jussi and I listed. The problems aren't unsolvable, but one project's team-specific issues that have a very simple workaround are never a good reason to add code to a FOSS project.

I'll ask again, what's the problem with using the code snippet I pasted?

There is nothing technically wrong with it I grant you.
I was trying to propose this in a way that wouldn't sound like "one teams technical issues"
I don't think getting the full version of a compiler (or that --version for any given compiler) will ever be non machine readable nor a individual usecase.

For conciseness lets leave this to be closed at your disgression and we will go with the snippet above, but it feels like a needless step behind the veil that meson provides to get some simple information.

Trying to frame a use-case as a general problem is a good first step to figuring out whether a feature should be added, so that's good. However, we are not yet convinced that that's true here. We might change our opinion in the future based on further reports and use-cases. All the best with your meson porting!

Was this page helpful?
0 / 5 - 0 ratings