views:

85

answers:

6

Hi,

I have a big app using many static libs, which is platform independant and deployed under Windows and Linux.

All static libs and the main() itself are compiled with two defines:

-DVERSION=1.0.0 -DBUILD_DATE=00.00.0000

These defines are used by macros inside each static lib and inside the main to store the current lib version inside a registry-like class.

Under GCC / Linux this works very well - you can list all linked modules and display their real version and builddate, e.g.:

  • ImageReader 0.5.4 (12.01.2010)
  • Compress 1.0.1 (03.01.2010)
  • SQLReader 0.3.3 (22.12.2009)

But: When I link the exactly same code with VisualStudio 2005 SP1 I get only the version and build date of the last compiled module:

  • ImageReader 0.5.4 (12.01.2010)
  • Compress 0.5.4 (12.01.2010)
  • SQLReader 0.5.4 (12.01.2010)

Has anybody an idea? Is this an "optimization" issue of the VC++ linker?

Best Regards, Chris

A: 

Preprocessor defines are resolved by the preprocessor stage of the compiler, not the linker.

There could be an issue with precompiled headers though in VC++.

Otherwise, to really tell I'd like to see the source code doing the actual printing of the version (date).

A: 

This doesn't have anything to do with the Visual Studio linker; it's just a matter of preprocessor macros, so the problem is already at the very beginning, before the compiler even gets to work.

What does the compile line look like in your Visual Studio build? My first idea is that for some reason, the defines (-D arguments) are all added to a single command line, and the last one always wins.

Frerich Raabe
A: 

I'm assuming you have an app which then links to these libraries, and it's in this app that you're seeing the identical version numbers.

Make sure that the app doesn't have these -D switches as well. If not, then my guess is that VC compiler is being clever and triggering a build of the dependent projects with the same -D switch, rather than triggering the build via the project file.

Also, the best way to version these binaries is by employing macros in headers/source directly and giving them all unique names for each library. That way they can't interfere with each other (unless you clone one of the headers into an app, duplicating the Macro defs), and you're no longer dependent on the compiler to do it properly.

Andras Zoltan
+2  A: 

Well, Visual Studio supports solutions with multiple projects. And its dependency engine is capable of detecting that a changed macro value requires a project to be recompiled. Occam's razor says that the libs simply got rebuilt and acquired the new VERSION macro value.

Hans Passant
+1 for good use of Occam's Razor.
Dan Breslau
A: 

This can be a issue if you are using pre-compiled headers. Try building the application by disabling pre-compiled headers option.

Andy
A: 

"These defines are used by macros inside each static lib and inside the main to store the current lib version inside a registry-like class."

You're not violating the One Definition Rule by any chance? If you have one class, it should have one definition across all libraries. it sounds like the class definition depends on a version macro, that macro is defined differently in different part of your program, and thus you violate the ODR. The penalty for that is Undefined Behavior.

It seems that the MS linker takes advantage of the ODR by ignoring everything but the first definition. After all, if all definitions of X are the same, then you can ignore all but the first.

MSalters