Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Version number of an executable

1,444 views
Skip to first unread message

Noob

unread,
May 31, 2013, 5:14:40 AM5/31/13
to
Hello,

AFAIU, on Windows platforms, some executables contain metadata, such
as the program's version number, date compiled, etc. This information
is displayed as the program's "Properties", and I suppose there is an
API to get the information.

I'm working in Linux with ELF executables, and I was wondering if
there is something equivalent?

A bit more on my use-case:

In the project I'm working on, someone needs to store the program's
version number in a plain-text file. (I don't know why.)

At the moment, the version number is defined in a C header file,
with the correct definition depending on the value of several
other macros:

#if FOO1
#define APP_VERSION (0x00010000)
#elif FOO2
#define APP_VERSION (0x00020000)
#elif FOO3
...
#endif

Once the executable is built (with -O0 and -g) they use
"readelf --debug-dump=macro prog" to dump every macro
definition in the debug section (!!) and then sort and
cut to extract the information from readelf's output o_O
IMO, this is an awful solution for several reasons
1) if the compiler does not include the macro definitions, it fails
2) if the output format of readelf changes, it fails
3) we have to spawn 4 processes, and parse the entire debug section
to get the info

Do you see a better way?

IMO, if the information is required outside of the compilation
process, it should be defined and made easily available
*in the general build environment* so that different tools
(compiler, others) may have access to it. Ergo, it should be
an environment var or a make var:

ifdef FOO1
APP_VERSION := 0x00010000
else ifdef FOO2
APP_VERSION := 0x00020000
else ifdef FOO3
...
endif

then add
CPPFLAGS += -DAPP_VERSION=$(APP_VERSION)

and writing the version to a file is as simple as
echo $(APP_VERSION) > the_file

Ideas? Opinions?

Regards.

Heinrich Wolf

unread,
May 31, 2013, 11:17:39 AM5/31/13
to

"Noob" <ro...@127.0.0.1> schrieb im Newsbeitrag
news:ko9pcp$l0h$1...@dont-email.me...
Hi,

on Unix we used to manage a global string with a marker "@(#)" e.g. static
char ident[] = "@(#)" __FILE__ " $Rev$ 142 " __DATE__ " " __TIME__; or
#pragma ident = "@(#)" __FILE__ " $Rev$ 142 " __DATE__ " " __TIME__; The
number after $Rev$ would be replaced by svn with the current revision
number. __FILE__ __DATE__ and __TIME__ would be replaced by the compiler
with the compile time values. Feel free to add every literal value. Many
library files also use such strings. Unix has a tool named "what", that
looks for the marker "@(#)" and prints those strings from the executable or
from a core file. This could look like that:

heiner@linux$ what my_app
or
heiner@linux$ what core
@(#)my_app.h $Rev$ 139 13/05/31 16:05:12
@(#)my_app.c $Rev$ 142 13/05/31 16:05:13
@(#)ftp.h 8.1 (Berkeley) 6/2/93

My Fedora 14 linux does not know the what tool. Instead I can use
heiner@linux$ strings my_app | grep "@(#)"

I found "@(#)ftp.h 8.1 (Berkeley) 6/2/93" on my Fedora 14 linux in
/usr/include/arpa/ftp.h

regards
Heiner

Heinrich Wolf

unread,
May 31, 2013, 11:24:25 AM5/31/13
to

"Heinrich Wolf" <inv...@invalid.invalid> schrieb im Newsbeitrag
news:koaeun$q8t$1...@news.m-online.net...
...
> #pragma ident = "@(#)" __FILE__ " $Rev$ 142 " __DATE__ " " __TIME__; The
#pragma ident "@(#)" __FILE__ " $Rev$ 142 " __DATE__ " " __TIME__; The
without =
...

Lew Pitcher

unread,
May 31, 2013, 11:41:35 AM5/31/13
to
On Friday 31 May 2013 05:14, in comp.unix.programmer, ro...@127.0.0.1 wrote:

> Hello,
>
> AFAIU, on Windows platforms, some executables contain metadata, such
> as the program's version number, date compiled, etc. This information
> is displayed as the program's "Properties", and I suppose there is an
> API to get the information.
>
> I'm working in Linux with ELF executables, and I was wondering if
> there is something equivalent?

The general Unix environment (and the general Linux environment, for that
matter) does not support a /native/ method to set or inquire about an
executable's "version number" metadata. Neither the operating system nor
the standard interface library provide such a facility.

However, there are a number of /non-native/ methods of accomplishing the
same:
- readelf[1] will extract and display the "versions" sections of the
elf-format executable, if they exist. This, of course, requires that the
language compiler tools set the elf "versions" sections accordingly.

- The FSF GNU standards recommend that each executable provide a single
invocation option (a "flag") that causes the executable to report it's
version number to stdout. Many executables in a Linux system use this
method of version reporting.

- Many source code control systems provide a "version" string metavariable
that may be embedded into the source, and compiled into a string that
strings[1] can extract. The string usually contains a sentinel value
that makes it easy to identify.

> A bit more on my use-case:
>
> In the project I'm working on, someone needs to store the program's
> version number in a plain-text file. (I don't know why.)
>
> At the moment, the version number is defined in a C header file,
> with the correct definition depending on the value of several
> other macros:
>
> #if FOO1
> #define APP_VERSION (0x00010000)
> #elif FOO2
> #define APP_VERSION (0x00020000)
> #elif FOO3
> ...
> #endif
>
> Once the executable is built (with -O0 and -g) they use
> "readelf --debug-dump=macro prog" to dump every macro
> definition in the debug section (!!) and then sort and
> cut to extract the information from readelf's output o_O
> IMO, this is an awful solution for several reasons
> 1) if the compiler does not include the macro definitions, it fails
> 2) if the output format of readelf changes, it fails
> 3) we have to spawn 4 processes, and parse the entire debug section
> to get the info
>
> Do you see a better way?

Define "better". I see a number of alternatives to this approach, all with
benefits /and/ drawbacks.

> IMO, if the information is required outside of the compilation
> process, it should be defined and made easily available
> *in the general build environment* so that different tools
> (compiler, others) may have access to it. Ergo, it should be
> an environment var or a make var:

I would disagree. The "general build environment" may not be synchronized
with the target binary (think: compile a binary, change the environment,
determine the version -or- set the environment, compile ignores
environment, determine the version)

It would be better that the final executable provide it's version
information directly as it directly represents the executable's version.
Indirect methods (such as a mutually-derived version, like you suggest) can
get "out of sync", and report incorrectly.

[snip]

> Ideas? Opinions?

WRT the current 'readelf' process, I agree with your overall conclusion. I
specifically agree with your reason regarding "debug" sections and macro
definitions, and marginally agree with your reason regarding readelf output
formats. However, the one-time cost of four processes, and a lengthy "debug
section" seem insignificant to me, and do not contribute to the "awfulness"
of this solution.

If you really are concerned with the existing readelf solution, I suggest
that you try, instead, either the "executing process reports own version"
solution or the "version string embedded in executable" solution suggested
above.

HTH
--
Lew Pitcher
"In Skills, We Trust"

Gordon Burditt

unread,
May 31, 2013, 11:06:16 PM5/31/13
to
> AFAIU, on Windows platforms, some executables contain metadata, such
> as the program's version number, date compiled, etc. This information
> is displayed as the program's "Properties", and I suppose there is an
> API to get the information.
>
> I'm working in Linux with ELF executables, and I was wondering if
> there is something equivalent?

No. At least nothing with an officially supported API.
What is the purpose of a version number anyway?

One purpose I can see is that is an extension of source code control,
in which case the version of the executable consists of the versions
of all the pieces of code that went into it, and the version numbers
of tools used to build it. Including all the OS libraries and
header files. That can add up to a lot of data. I'd want an
official API (like Windows has) to support at least up to 1,000
distinct compilation dates, as there can be at least that many
compiled pieces linked into one executable.

You can put stamps into executables merely by putting strings in
the code. There is no official API for this, and a program can
fish these out of the executable by scanning for a pattern, without
much chance for a false positive. This program does not necessarily
know much of anything about the format of an executable - it probably
doesn't have to care whether it is operating on an executable or
source code. In order to prevent the optimizer from deleting them,
provide a command-line option (like --version) to print them. There
are a couple of different patterns in common use. One, the SCCS
style starts with @(#) (and can be extracted with the "what" command.
Another, the RCS/CVS style, consists of $Keyword: ... text ...$ .
It can be extracted with the ident command. You might put code in
each module like:
static char RCSid[] = "$Header$";
which gets expanded when checked in to something like:
static char RCSid[[ = "$Header: <filename> <version> <date> <time> <user> <status> $";

Another use for a version number is to identify the version to the
public, and for the public to use in bug reports, or to figure out
if they need to upgrade. Typically the format is something like
X.Y.Z, where X, Y, and Z are integers, and especially X and Y are
likely to be heavily influenced by marketing and internal politics.
It is desirable to have another component for the development team
to use, and I think a time stamp that only nerds interpret as a
time stamp would be suitable here. For this you might put code
like this in your Makefile:

MAJOR = 4
MINOR = 12
PATCH = 3
VERSION = $(MAJOR).$(MINOR).$(PATCH).`date +'%s'`

CFLAGS = -DPRODUCTVERSION=$(VERSION)

That stuff with the date command produces the UNIX time (in decimal),
so VERSION might come out as 4.12.3.1370052376. If you can get the
time down to nanoseconds, that would be preferable. This does NOT,
however, guarantee a consistent version, as if you "make", it stops
on an error, you fix it (and properly check in the modified code)
and restart "make", you get a mixture of versions in the various pieces.
If the entire build produces one and only one executable, the final
step might be to put the version number in a short piece of source
code, compile it, and link the whole thing.

> A bit more on my use-case:
>
> In the project I'm working on, someone needs to store the program's
> version number in a plain-text file. (I don't know why.)

Invoking:
program --version
ought to output the program's version number, perhaps with some
identifying text around it, like:
$ gnurgf --version
GNU Robotic Girlfriend, Version 2.1.7
$

You might format the text so it's really easy for tools like grep
and sed to fish the version number out of the output.

> At the moment, the version number is defined in a C header file,
> with the correct definition depending on the value of several
> other macros:
>
> #if FOO1
> #define APP_VERSION (0x00010000)
> #elif FOO2
> #define APP_VERSION (0x00020000)
> #elif FOO3
> ...
> #endif
>
> Once the executable is built (with -O0 and -g) they use
> "readelf --debug-dump=macro prog" to dump every macro
> definition in the debug section (!!) and then sort and
> cut to extract the information from readelf's output o_O
> IMO, this is an awful solution for several reasons
> 1) if the compiler does not include the macro definitions, it fails
> 2) if the output format of readelf changes, it fails
> 3) we have to spawn 4 processes, and parse the entire debug section
> to get the info
(4) if this code is closed-source, all that debug info
may give away a large part of the source code when it is
released/sold to the public. Therefore, your lawyers may
refuse to let you release it that way.

> Do you see a better way?
>
> IMO, if the information is required outside of the compilation
> process, it should be defined and made easily available
> *in the general build environment* so that different tools
> (compiler, others) may have access to it. Ergo, it should be
> an environment var or a make var:

I assume that you need it way far outside of the compilation process,
as in more than 20 years after compilation finished, and in a country
that did not exist at the time of compilation, and possibly in outer
space.

>
> ifdef FOO1
> APP_VERSION := 0x00010000
> else ifdef FOO2
> APP_VERSION := 0x00020000
> else ifdef FOO3
> ...
> endif
>
> then add
> CPPFLAGS += -DAPP_VERSION=$(APP_VERSION)
>
> and writing the version to a file is as simple as
> echo $(APP_VERSION) > the_file
>
> Ideas? Opinions?

Code like the above can get out of sync with reality, especially
if the version number is demanded after the code has been compiled,
released, sold, and is in the hands of a customer trying to make a
bug report. Also, upgrade procedures should warn the customer if
he's about to downgrade.

In this case, "program --version" to get the version number is an
easy thing to tell the customer to run. If the application is
hopelessly GUI, you could stick the information on the Help | About
page, but I still think you could make "program --version" work
and have the rest of the program be hopelessly GUI.

James K. Lowden

unread,
Jun 1, 2013, 3:06:08 PM6/1/13
to
On Fri, 31 May 2013 11:14:40 +0200
Noob <ro...@127.0.0.1> wrote:

> AFAIU, on Windows platforms, some executables contain metadata, such
> as the program's version number, date compiled, etc. This information
> is displayed as the program's "Properties", and I suppose there is an
> API to get the information.
>
> I'm working in Linux with ELF executables, and I was wondering if
> there is something equivalent?

I'm surprised no one mentioned ident(1), which has been around since
the late Pleistocene. Given its symbiotic relationship with CVS, it
seem unfortunately destined for extinction.

--jkl

wil...@wilbur.25thandclement.com

unread,
Jun 2, 2013, 1:21:08 AM6/2/13
to
Gordon Burditt <gordon...@burditt.org> wrote:
>> AFAIU, on Windows platforms, some executables contain metadata, such
>> as the program's version number, date compiled, etc. This information
>> is displayed as the program's "Properties", and I suppose there is an
>> API to get the information.
>>
>> I'm working in Linux with ELF executables, and I was wondering if
>> there is something equivalent?
>
>>
>> In the project I'm working on, someone needs to store the program's
>> version number in a plain-text file. (I don't know why.)
>
> Invoking:
> program --version
> ought to output the program's version number, perhaps with some
> identifying text around it, like:
> $ gnurgf --version
> GNU Robotic Girlfriend, Version 2.1.7
> $
>
> You might format the text so it's really easy for tools like grep
> and sed to fish the version number out of the output.
>

GNU defines a loose format for this:

http://www.gnu.org/prep/standards/html_node/_002d_002dversion.html

Here's the somewhat non-conformant output from one of my applications:

% ./xera --version
xera (XERA) 20130311 (head:92573d08192d5a97 diff:src/ask.describe.lua,src/ask.tr.lua,src/avtr.c,src/sdp.lua,src/stats.c)

I include the Git revision and a list of files changed since checkout. This
latter information is much more valuable, IMO. Release numbers, like
comments, often lie.

Does the RCS method indicate whether the file has been edited?

Casper H.S. Dik

unread,
Jun 2, 2013, 5:50:21 AM6/2/13
to
<wil...@wilbur.25thandClement.com> writes:

>I include the Git revision and a list of files changed since checkout. This
>latter information is much more valuable, IMO. Release numbers, like
>comments, often lie.

>Does the RCS method indicate whether the file has been edited?

Possibly, however the sccs or rcs versions are always *per file*
wherewas a git or mercurial "head" includes all of the sources.

Casper

Jorgen Grahn

unread,
Jun 2, 2013, 3:57:03 PM6/2/13
to
On Fri, 2013-05-31, Heinrich Wolf wrote:
>
> "Noob" <ro...@127.0.0.1> schrieb im Newsbeitrag
> news:ko9pcp$l0h$1...@dont-email.me...
>> Hello,
>>
>> AFAIU, on Windows platforms, some executables contain metadata, such
>> as the program's version number, date compiled, etc. This information
>> is displayed as the program's "Properties", and I suppose there is an
>> API to get the information.
>>
>> I'm working in Linux with ELF executables, and I was wondering if
>> there is something equivalent?

> on Unix we used to manage a global string with a marker "@(#)" e.g. static
> char ident[] = "@(#)" __FILE__ " $Rev$ 142 " __DATE__ " " __TIME__; or
> #pragma ident = "@(#)" __FILE__ " $Rev$ 142 " __DATE__ " " __TIME__; The
> number after $Rev$ would be replaced by svn with the current revision
> number.

It's not just Subversion: it got that from CVS, which got it from RCS.
These tools use the $Rev$ syntax. @(#) comes from the even older tool
SCCS, which tended to come with different non-free Unixes.

...
> My Fedora 14 linux does not know the what tool. Instead I can use
> heiner@linux$ strings my_app | grep "@(#)"

what(1) probably came with SCCS, and you don't have it installed.
You could install the free clone CSSC, or you could install RCS and
use its ident(1) utility instead. But yeah, strings+grep is an option
too.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Jorgen Grahn

unread,
Jun 3, 2013, 10:35:59 AM6/3/13
to
ident(1) comes with RCS, so even though it's just as useful with
CVS there are no guarantees that it's installed.

I don't know about extinction -- RCS has existed for 30+ years and is
still readily available. But the trend seems to be moving away from
magic keyword expansion performed by the revision control tool.

Jorgen Grahn

unread,
Jun 3, 2013, 3:48:07 PM6/3/13
to
On Fri, 2013-05-31, Noob wrote:
> Hello,
>
> AFAIU, on Windows platforms, some executables contain metadata, such
> as the program's version number, date compiled, etc. This information
> is displayed as the program's "Properties", and I suppose there is an
> API to get the information.
>
> I'm working in Linux with ELF executables, and I was wondering if
> there is something equivalent?
>
> A bit more on my use-case:
>
> In the project I'm working on, someone needs to store the program's
> version number in a plain-text file. (I don't know why.)

Unrelated to Unix programming, but: if you don't know why, you should
find out. Perhaps the need is imaginary. Perhaps there is a need
which can be solved by more normal means, e.g. they really want to
know which version of 'foobar' is installed, and you ship your
software as Debian packages, or ...

You can do a much better job if you understand the /real/ needs,
and people are notoriously bad at explaining them.
0 new messages