Can the meson project version be assigned dynamically? - versioning

I am new to Meson so please forgive me if this is a stupid question.
Simple Version of the Question:
I want to be able to assign a dynamic version number to the meson project version at build time. Essentially meson.project_version()=my_dynamic_var or project( 'my_cool_project', 'c', version : my_dynamic_var') (which of course won't work).
I would rather not pre-process the file if I don't have to.
Some background if anybody cares:
My build system dynamically comes up with a version number for the project. In my case, it is using a bash script. I have no problem getting that version into my top level meson.build file using run_command and scraping stdout from there. I have read that using doing it this way is bad form so if there is another way to do this.. I am all ears.
I am also able to create and pass the correct -DPRODUCT_VERSION="<my_dynamic_var>" via add_global_arguments so I COULD just settle for that.. but I would like the meson project itself to carry the same version for the logs and so I can use meson.project_version() to get the version in subprojects for languages other than c/c++.

The short answer, as noted in comments to the question, appears to be no. There is no direct way to set the version dynamically in the project call.
However, there are some work arounds, and the first looks promising for the simple case:
(1) use meson rewriting capability
$ meson rewrite kwargs set project / version 1.0.0
Then obviously use an environment variable instead of 1.0.0.
(2) write a wrapper script which reads the version from the environment and substitutes it into your meson.build file in the project call.
(3) adopt conan.io and have your meson files generated.
(4) use build options. This option, while not as good as (1) might work for other work flows.
Here's how option (4) works.
create a meson_options.txt file in your meson root directory
add the following line:
option('version', type : 'string', value : '0.0.0', description : 'project version')
then create a meson.build file that reads this option.
project('my_proj', 'cpp')
version = get_option('version')
message(version)
conf_data = configuration_data()
conf_data.set('version', version)
When you go to generate your project, you have an extra step of setting options.
$ meson build && cd build
$ meson configure -Dversion=$BUILD_VERSION
Now the version is available as a build option, then we use a configuration_data object to make it available for substitution into header/source files (which you might want to get it into shared libraries or what not).
configure_file(
input : 'config.hpp.in',
output : 'config.hpp',
configuration : conf_data
)
And config.hpp.in looks something like this:
#pragma once
#include <string>
const static std::string VERSION = "#version#";
When we do the configure_file call, #version# will get substituted for the version string we set in the meson configure step.
So this way is pretty convoluted, but like I said, you may still end up doing some of it, e.g. to print copyright info and what not.

As of 0.60.3 you may directly assign version from run_command which means the following will work without any meson_options.txt.
project('randomName', 'cpp',
version : run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip(),
default_options : [])
In particular, it is also possible to assign the result of a bash script, simply invoke it instead of git.

Related

GCC -D equivalent for iarbuild.exe

I have a build machine server I am maintaining which is using Makefiles infrastructure.
As part of that infrastructure, I'm passing a few arguments to the Makefile from the build machine (example: user, build-server name, and various build variables known only when compiling for a specific project).
Some of these variables are aggregated to the code using gcc -D directive
-DSOME_VAR=VAL
I've now been asked to migrate an Iar Project into my build system. That is not a problem in itself, only I can't find any way to introduce preprocessor defines using iarbuild.exe command line tool.
I guess I could use an existing H file and edit it before compiling (using sed for example), but that's an ugly hack I would rather avoid if I can.
How do I properly achieve this with IAR?
I recently solved this using a combination of option #2 and the -varfile argvarfile option to iarbuild.exe. For my case I am controlling the output of cpputest. I need easy to read outputs for IDE builds but junit formatted outputs for build server builds. Here's my setup as an example.
Create a global variable in the IDE. Tools->Configure Custom Argument Variables...
Select global tab. Create group JUNIT. Create variable USE_JUNIT. Set the value to 0.
In the Project->Options->C/C++ Compiler->Preprocessor section add an entry for
JUNIT_OUTPUT=$USE_JUNIT$
In the code use
#if JUNIT_OUTPUT == 1
#define FLAGS "-ojunit"
#else
#define FLAGS "-v"
#endif
Create a file called jUnitOut.txt and put the following into it.
<?xml version="1.0" encoding="iso-8859-1"?>
<iarUserArgVars>
<group active="true" name="JUNIT">
<variable>
<name>USE_JUNIT</name>
<value>1</value>
</variable>
</group>
</iarUserArgVars>
Call iarbuild.exe with the normal options plus -varfile jUnitOut.txt
Some observations
Regarding #1 you don't actually need to create a global variable but when you do IAR creates ...\AppData\Roaming\IAR Embedded Workbench\global.custom_argvars. This file must be present for iarbuild.exe to use the -varfile you provide. Also, you can create workspace variables as well. These are stored in a file in the local project directory. This file can be added to source control so global variables can be avoided. IDE builds use the global and workspace variables while iarbuild will use the -varfile
Regarding #4 I didn't find any documentation on how to format the argvarfile. So, I created a workspace variable in the IDE, found the file it created to store the variable and then cut/pasted from that file into my jUnitOut.txt
To my understanding iarbuild does not support passing such parameters directly.
There are two possibilities that were suggested by IAR support and that both work for me (using 7.40.2):
1) Use a preinclude file
Go to Project->Options->C/C++ Compiler->Preprocessor
Add a preinclude file (e.g. preinclude.h)
Now have your build script generate that preinclude file before starting iarbuild
2) Use "Defined symbols"
Go to Project->Options->C/C++ Compiler->Preprocessor
Add an option to "Defined symbols" and use environment variable, e.g. "SOMEVAR=$_SOMEVAL_$"
On the cmd line, set the environment variable, e.g. "set SOMEVAR=myvalue"
Run iarbuild
The 2nd method is little more elegant, but the build will fail if the environment variable is not set, so I'll probably go with the 1st method.
This may answer your question:
To see the command line parameters, enable the option IAR Embedded Workbench IDE > Tools > Options... > IDE Options > Messages > Show build messages > select 'All'.
which is part of the web page at:
http://supp.iar.com/Support/?Note=47884

Autotools suite misplaces "man" file leading to installation failure

In a software I have to tweak, the man file is located under doc/ along with a simple Makefile.am file:
man_MANS = software.1
EXTRA_DIST = $(man_MANS)
Upon installation, I expect make install to copy the manual under /usr/local/share/man/, but the script - instead - will try to install the man under /usr/local/share/man/man1 - which does not exist - throwing an error and stopping the process.
I would expect a similar behavior if I assigned software.1 to man1_MANS, though.
What is going on ? How is this possible that automake does not create non-existing folders ?
man_MANS will try to figure out in which section to put the manual depending on the extension you gave it, so it is correct in this case that it would install into ${mandir}/man1.
Since you say that MKDIR_P is empty in your output, try to ensure that AC_PROG_MKDIR_P is being called in your configure.ac (it should be automatically called by AM_INIT_AUTOMAKE but since you said it's old it might have some issues).

how to get doxygen to produce call & caller graphs for c functions

I've spent some time reviewing the docs and going through my doxy config file from end to end. I cut doxygen loose on my config file and it produces documentation and indices for structs and cpp classes but I don't see call or caller graphs for the multitude of c functions in my source tree.
Can anybody tell me how to configure doxygen to produces these call and caller trees ? I do have graphviz installed.
You have to set HAVE_DOT, CALL_GRAPH and CALLER_GRAPH to YES.
Also make sure the path to dot is in your PATH variable.
If that still doesn't work, you might have to set EXTRACT_ALL and/or EXTRACT_STATIC, depending on your functions.
For MacOS users:
Install Doxygen and Graphviz as:
brew install doxygen
brew install graphviz
Go to your project folder, and from Terminal set to this path run
doxygen -g
A doxygen file will be generated, named as Doxyfile. Go ahead and open up this file in any editor and find these parameters and replace their values to YES at their locations:
HAVE_DOT = YES
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
CALL_GRAPH = YES
CALLER_GRAPH = YES
DISABLE_INDEX = YES
GENERATE_TREEVIEW = YES
RECURSIVE = YES
You can also set name of your project in this Doxyfile. Save the file and then run this command in the terminal:
doxygen Doxyfile
This will generate two more folders named as html and latex. Go to the html folder and open annotated.html to view all details of your project. You will also view png images of the call graphs embedded in the html that are relevant (to some functions/classes for example).
Setting the path to "dot" (/usr/local/bin/) via the "Expert" tab controls in the GUI did the trick!
doxywizard is also useful. It gives you all the options in a GUI. Selecting any option shows quick help about that option.
You might also be interested in COLLABORATION_GRAPH or GRAPHICAL_HIERARCHY.
Quite convenient.
I had the same problem for my C global functions. Enabling CLANG_ASSISTED_PARSING did help display callgraphs for some functions, yet not all of them.

Injecting mercurial changeset as version information in a C executable

I would like the executables for a project I am working on to have the latest mercurial changeset recorded so that when a user complains about buggy behavior, I can track which version they are using. Some of my executables are Python and others are compiled C. Is there a way to automate this, or can you point me to projects that exhibit solutions that I can look at?
I am using autoconf in my project... in case that makes the solution easier.
Thanks!
Setjmp
A common way to do this is with m4_esyscmd. For example, autoconf distributes a script in build-aux which generates a version number from the git repo and invokes AC_INIT as:
AC_INIT([GNU Autoconf], m4_esyscmd([build-aux/git-version-gen .tarball-version]),
[bug-autoconf#gnu.org])
You can often get away without distributing the script and do something simple like:
AC_INIT([Package name], m4_esyscmd([git describe --dirty | tr -d '\012']),
[bug-report-address])
Instead of git-describe, use whatever command you want to generate the version number. One important detail is that it should not have a trailing newline (hence the tr following git-describe).
A major drawback with this technique is that the version number is only generated when you run autoconf.
Add this to configure.ac:
AM_CONDITIONAL([IS_HG_REPO], [test -d "$srcdir/.hg"])
Add the following lines to Makefile.am:
if IS_HG_REPO
AM_CPPFLAGS = -DHGVERSION="\"$(PACKAGE) `hg parents --template 'hgid: {node|short}'`\""
else
AM_CPPFLAGS = -DHGVERSION=PACKAGE_STRING
endif
This will define HGVERSION as a string of the form APPNAME hgid: 24d0921ee4bd or APPNAME VERSION, if building from a release tarball.
See wiki page on versioning with make

Howto get include directories (ruby.h) for Linux Ruby C extension project?

I'm using scons to build a linux C based ruby extension. What is the "right" way to get the include paths right? By "right" I mean it works out of the box on 1.9 and 1.8.
I don't want to use the mkmf/Makefile solution.
Thanks! Dave
If you were using autoconf, you could borrow ruby.ac from rice:
http://github.com/jameskilton/rice/blob/master/ruby.ac
or since you are using a different build system, you can duplicate its behavior. To summarize what it does:
We use the rbconfig module to get ruby config variables like this:
$RUBY -rrbconfig -e "puts(Config::CONFIG['$1'] || '')" <variable>
where $RUBY is the ruby interpreter (sometimes interpreters get installed with a different name, e.g. ruby1.8 or ruby1.9) and <variable> is the desired config variable
We then set our build variables:
if ${ruby_config_rubyhdrdir} is empty: (e.g. ruby 1.8)
CPPFLAGS="-I${ruby_config_archdir}
else:
CPPFLAGS="-I${ruby_config_rubyhdrdir} ${ruby_config_rubyhdrdir}/${arch}
CFLAGS="${ruby_config_CFLAGS} ${ruby_config_CCDLFLAGS}"
LDFLAGS="-L${ruby_config_archdir} -L${ruby_config_libdir} ${ruby_config_LDFLAGS}"
LIBS="${ruby_config_LIBS} ${ruby_config_DLDLIBS}"
where the variables ${ruby_config_*} are determined using the config command above, e.g.:
ruby_config_foo=$RUBY -rrbconfig -e "puts(Config::CONFIG['$1'] || '')" foo
We also need to link with the ruby library, so we append ${ruby_config_LIBRUBYARG}.
The above variables are for compiling and linking; you may also need to install. Ruby library files should be installed to ${ruby_config_sitelibdir}. Ruby extensions should be installed to ${ruby_config_sitearchdir}.
There's also some magic in ruby.ac for building with mingw and linking against the one-click installer on windows (which used to be built with vc6; I'm not sure if it still is or not).

Resources