CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Embedding version strings at build time

    This is sort of a C++ question, but also sort of a build-system question.

    I have a set of projects. Each one builds either a static library or an executable. What I'd like to do, is at build time I want to embed a version string representing the version of the executable as well as the version of each library. These version strings will come from an external source (in my case it's based on a "git describe" call, but that's beside the point). Embedding such strings can be highly valuable for traceability. (Versions of 3rd-party libraries are not necessary.)

    I'm using qmake as my build system, but this should work more or less similarly with any build tool. What I'd ideally like to do is define this process in such a self-contained way that a an absolutely minimal amount of additional code is required in order to leverage it. Preferably, nothing more than an include(version.pri) in each project's .pro file in order to collect the versions. (Retrieving them later, such as to respond to a --version command-line flag, can be done via traditional C++ methods.)

    What I've done so far is to define a singleton VersionTracker class, and then tweak the build system so that "MODULE" and "VERSION" are preprocessor symbols defined at build time. I've also tweaked the build system so that a file in each project, version.cpp, is rebuilt (and regenerated if necessary) on every build regardless of changes. This source file can capture the information in the preprocessor symbols into each static library and the executable.

    Now, here's the problem. How can I get the information from those version.cpp files into the VersionTracker class? I thought I could use a global object's constructor to do it, but it turns out the symbols are stripped out when the static libraries are linked so I only get the executable's version. I also found a page on stackoverflow detailing a very clever way to call a registration function at class definition time, but again the class definition appears to be stripped out if it's defined in the version.cpp file of a static library and not referenced elsewhere.

    Everything I've read basically says you either need to use linker flags to prevent symbol stripping entirely, which is probably an adoption-killer for this hack, or you need to use an explicit registration function called from the executable. I'd prefer to avoid this since it is just another thing a programmer could forget to update when a library dependency is added or removed.

    My last idea, which I haven't tried yet, would be to put each version.cpp into a separate static library from the one it is describing. This version-only library could be linked without symbol stripping. I don't love this concept but it might work.

    I haven't yet figured out how shared libraries can be worked into this framework at all. I'll worry about that after I get static libraries working.

    Any ideas?
    Last edited by Lindley; December 11th, 2013 at 06:30 PM.

  2. #2
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Embedding version strings at build time

    I'm probably missing something, but I don't understand your question: I use git too ( gitflow, more specifically ) and the whole versioning thing boils down to a build step generating an include with info about the latest commit of the working branch ( tag, revision, etc... ). A user just includes it and that's it. Why do you need to embed the version info as a linker symbol ?

  3. #3
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Embedding version strings at build time

    simple solution

    create a tool that extracts/builds all the version strings from git or whatever you want it from, and writes it out to a .h file with defines.

    such as
    Code:
    #define  PICTURES_LIB_VERSION "1.00"
    #define  ICONS_LIB_VERSION     "1.12"
    #define  INTERFACE_DLL_VERSION "3.88"
    //... etc etc
    then include that header in your projects and use the defines you need in each project.

  4. #4
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Embedding version strings at build time

    Quote Originally Posted by superbonzo View Post
    I'm probably missing something, but I don't understand your question: I use git too ( gitflow, more specifically ) and the whole versioning thing boils down to a build step generating an include with info about the latest commit of the working branch ( tag, revision, etc... ). A user just includes it and that's it. Why do you need to embed the version info as a linker symbol ?
    My first experience with gitflow taught me that it's a mistake to include completely orthogonal bits of software in a single repo, because bumping the release version reflects on the entire repo, not just the part that changed. Therefore, for this project I've adopted a policy of using a separate repo per independently versionable target (lib, app, etc).

    This leads to the problem of how you can coordinate all these versions. I'm handling this two ways: first, by creating a top-level repo that contains nothing except the others as submodules (submodules are pointers to other repos in a specified state, and so perfect for configuration management purposes). Second, by including the version from every dependent repo compiled into the final executable.

    Now, certainly I can create a header for each repo with version information. That isn't difficult. What I'd like to do is figure out a way to automatically pull in version information without having to explicitly include a particular header.

    Quote Originally Posted by OReubens View Post
    simple solution

    create a tool that extracts/builds all the version strings from git or whatever you want it from, and writes it out to a .h file with defines.

    such as
    Code:
    #define  PICTURES_LIB_VERSION "1.00"
    #define  ICONS_LIB_VERSION     "1.12"
    #define  INTERFACE_DLL_VERSION "3.88"
    //... etc etc
    then include that header in your projects and use the defines you need in each project.
    At the moment I'm creating the defines via -D flags in the Makefile, which means projects only see their own versions directly, and you need to jump through some hoops to see the versions of other modules. If I took this approach, it would alleviate that issue, but I'd still need to hard-code the list of libraries I want version information on somewhere; I'd prefer to derive that information from the library's presence directly.

  5. #5
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Embedding version strings at build time

    Quote Originally Posted by Lindley View Post
    This leads to the problem of how you can coordinate all these versions. I'm handling this two ways: first, by creating a top-level repo that contains nothing except the others as submodules (submodules are pointers to other repos in a specified state, and so perfect for configuration management purposes). Second, by including the version from every dependent repo compiled into the final executable.
    this is exactly what I do too and it works like a charm ; version "tracking" is done via a dedicated shell script invoked as a build step ( each repo has one ). Given that all important commits need automatic testing, the resulting version header is always up-to-date automatically ( this is certainly true for the master branch, or the commit a submodule is pointing to ).

    Now, excluding sporadic debugging needs, I never had the need of exposing that version info through the final executable, so to me #include <some_component/version.hpp> has always sufficed.

    Quote Originally Posted by Lindley View Post
    I'd prefer to derive that information from the library's presence directly.
    define "presence", if it means that it's used somehow for generating the final binary, some include must lie somewhere, so it's just a matter of strategically placing the "version.hpp" include in the right places ( like inside another header that is always included by users anyway ). In turn, in "version.hpp" one could place a "registration object" inside an anonymous namespace to perform per-translation-unit registration into a "VersionTarcker" singleton ...

  6. #6
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Embedding version strings at build time

    Perhaps the fact that I'm finding it difficult to decide which header(s) should include the version header indicates I need to split one of my repos because it has too many unrelated things in it. However, the main reason I'm resisting that temptation is because I'm trying to define a scheme which can be adopted by other programs at my work, and the fewer code changes required to use it, the more people will adopt it.

    I've changed the design so that a version header is generated for each library. However, it doesn't contain the version number directly: that is still compiled into version.cpp. The header calls a function to retrieve it from there. This doesn't make a difference most of the time, but it strikes me as more extensible to the shared library case (although I cant guarantee it will work with shared libraries as-is).

    I'm now trying to convince my qmake project to automatically generate the relevant #includes as part of the build process, so that they don't need to be added to controlled source code.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured