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
Related
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.
I have a BitBake recipe (example_0.1.bb) with a do_install task where I attempt to install a .so file:
do_install() {
install -d ${D}${libdir}
install -m 0644 ${S}/example.so ${D}${libdir}
}
FILES_${PN} += "${libdir}/example.so"
This fails during the build process and returns:
ERROR: example not found in the base feeds
However, if I add a test file to the package, both the .so file and the test file are added to the rootfs.
do_install() {
install -d ${D}${libdir}
install -m 0644 ${S}/example.so ${D}${libdir}
echo "bar" >> ${TOPDIR}/foo
install -m 0644 ${TOPDIR}/foo ${D}${libdir}
}
FILES_${PN} += "${libdir}/libceill.so"
FILES_${PN} += "${libdir}/foo"
How can I add only the .so file without the junk test file?
So you've got a library that is non-standard in that it's not installing a versioned library (libfoo.so.1.2.3, maybe symlinks such as libfoo.so.1 -> libfoo.so.1.2.3), and then an unversioned symlink for compilation time (libfoo.so -> libfoo.so.1). The default packaging rules assume standard libraries.
What's happening is that packages are populated by their order in PACKAGES, which has PN-dev before PN. FILES_PN-dev by default contains /usr/lib/lib*.so, and FILES_PN contains /usr/lib/lib*.so.. When you add /usr/lib/lib.so to FILES_PN what you want to happen isn't happening because PN-dev has already taken the files.
If your library doesn't come with any development files at all (e.g. no headers) then you can set FILES_${PN}-dev = "" to empty that package, and then your addition of lib*.so to FILES_${PN} will work as expected.
Yes, this is something that we should make easier (I've been thinking about a small class for libraries like this) and warn in sanity checks when it happens.
Oh and I'm surprised that the library ends up in the image in your second example, as example will contain /usr/lib/foo and example-dev will contains /usr/lib/libceill.so. Unless of course you've got dev-pkgs enabled, which will automatically install example-dev if you've got example in an image.
Add the line
FILES_SOLIBSDEV = ""
An explanation from the Yocto mailing list:
I had FILES_${PN} += “${libdir}/.so” in there and that didn't work.
Maybe it was because I was missing the FILES_SOLIBSDEV = “" you mentioned.
I'll play with it some more and see what happens. I first started out with
FILES_${PN} += “${libdir}/.so” and when that didn't work I tried other
things in the FILES_${PN} = line to try and get it picked up. When I
couldn't get any of it to work and then saw others (well, at least the link
I provided) were seeing the same thing I figured it was time to quit
spinning my wheels and consult the big guns :)
Heh :) The issue there is that the patterns are matched in the order of the
PACKAGES variable. The first package to include a file gets it, and
${PN}-dev is in PACKAGES before ${PN}. By emptying FILES_SOLIBSDEV, that’ll
remove the .so from FILES_${PN}-dev, letting the ${PN} package get it
instead.
Add the line:
FILES_${PN}_dev_remove="${FILES_SOLIBDEV} "
It will move out the package for development path.
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).
I have an open source project that relies on another open source project (let's call that other project X). Both are written in C. I've had to hack pieces of X to get multi-threading to work. This causes some issues when trying to package up the code for distribution. To make things easier, I've just included the entirety of X within mine along with the few little hacks I've made.
I'd like to do something more sophisticated now in order to keep the improved functionality of X (it has frequent releases and mine does not) without having to repackage the whole project (with my hacks) within my project again each time that X has a release.
There are only 3 or 4 functions in that need to override. I can follow what is going on in this IBM Tutorial, but how can I modify my Makefile.am to generate the Makefile changes suggested in that article? To summarize, the article suggests writing my own functions with the same signatures as the ones I want to override (in a file called libfuncs.c) and then add the following 'libs' target to the makefile:
all: libs setresgid-tester
libs: libfuncs.c
gcc -shared -Wl,-soname,libfuncs.so.1 -o libfuncs.so.1.0 libfuncs.c
ln -s libfuncs.so.1.0 libfuncs.so.1
ln -s libfuncs.so.1 libfuncs.so
setresgid-tester: setresgid-tester.c
gcc -o setresgid-tester setresgid-tester.c
All of that makes sense to me. What I need to do, however, is to have this 'libs' target created for me with the autotools. I have a Makefile.am works well right now. How do I modify it to produce the desired results above? It was difficult to find in the autotools documentation, but I may just not have known exactly what to look for.
I'm happy to provide more details if helpful. Thanks in advance.
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).