views:

248

answers:

10

I need to be able to determine at run time what compilation options were use to build the executable. Is there a way to do this?

EDIT: I'm particularly interested in detecting optimization settings. The reason is that I'm writing commercial software that must run as fast as possible. While I am just modifying and testing the system I don't do all the optimizations because it takes too long. But I am worried that I may accidentally go and release an unoptimized version of the program. What I'd like to do is have the program give me a visual warning at start up saying something like "This is the slow version - do not release".

EDIT: Maybe I could write some little utility to run as a pre-build step? Is the command line stored in some file somewhere? If it is then I could extract it, then write it to some include file as a string and hey presto!

EDIT: My choice is not between debug and release. Debug is way too slow - I reserve that strictly for debugging. My day to day choice is between optimized and super-optimized (including the slow-to-compile link time compilation, or even profile guided optimization).

EDIT: I often make changes to the complex compilation process, different libraries, different pre-defined macros, different source files etc. It seems clumsy to have to maintain multiple, almost-identical project files differing only in a couple of optimization flags. I would much prefer to just, as-and-when-required switch a couple of flags in a single project and re-compile. I just want the executable to self test how it was created.

EDIT: IIRC there is some way to ask the visual studio to create a makefile. Can I ask visual studio to create this makefile for me as a pre-build step?

+6  A: 

The best way I know of to pass information from the build system to a running program is via the preprocessor. You can pass preprocessor definitions on the command line, and inside use them to set the value of variables, select code, or whatever with #ifdefs.

So setup your build system to use something like DEBUG_SET for debug its debug builds, etc.


Addressing the second "EDIT", yes the command line for your prebuild and postbuild tools are put in the project's vcproj file. It is an XML file, and you should find it under at tag Configurations->Tool with a name attribute something like "VCPreBuildEventTool". Try adding one with the GUI and then opening the file in a text editor, and you should see.

It is fairly common around here to create tools to process vcproj files. I'm wondering if we couldn't use some of those property sheets mentioned in the comments instead though...

T.E.D.
If I was using a make file, that would be the perfect answer, but with a GUI, its a but clumsy.
Mick
Its not that bad (unless 2008 is way different than the 2005 we use). Right click on your project file and select properties. Then on the property page select Configuration Properties->C/C++0->Preprocessor. Then select Processor Definitions, and add your definition. Put the correct definition in each configuration you use, and you're there. This is the exact scheme we use here to tell our programs which configuration they were compiled under.
T.E.D.
To expand on T.E.D.'s answer, you can also use property sheets ( http://msdn.microsoft.com/en-us/library/a4xbdz1e%28VS.80%29.aspx ) to make management of various compiler flags much less painful. I have a "Release.settings" file that I attach to all the `Release` configurations and a "Debug.settings" that I attach to the `Debug` as well as tons of other property sheets for various things (a "Server" sheet detailing all the flags for server, such as not bothering to run any of the GUI things).
Travis Gockel
Property sheets are definitely the way forward for any non-trivial set of projects. It's made our configuration much easier (we have debug and release versions of 32-bit and 64-bit targets across around 100 projects, all of these share most of their settings).
Bids
+2  A: 

Would it be possible to store the compile options (or, the full command line, if there is such) in a text file while invoking the build, and making sure to ship that file along with the executable?

[This is certainly not elegant, but just wanted to check.]

ArunSaha
I have nothing in principle against such a trick - but I don't know how to do it. It would be great to be able to do some "pre-build step" where somehow the full command line gets copied to a file which then gets #included and made in to a string... or something...
Mick
@Mick: Thanks. But, I don't know VisualStudio, so I cannot tell you exactly "how" to do it. Sorry, it was just an idea. However, if available, my intention was to fopen the file and read the contents, possibly into a string.
ArunSaha
+3  A: 

Create multiple configurations for your project, for example Debug, Release & Production. Change the names of the output binaries for each configuration to match across configurations. For example MyApp_d.exe, MyDll_d.dll for debug, MyApp_r.exe, MyDll_r.dll for Release, and MyApp.exe & MyDll.dll for Production. This will help to keep all the different flavors straight without having to try to add code (which will be slow and brittle) that will detect at runtime which flavor is running and perform some magic then.

John Dibling
I wonder why this doesn't get more upvotes. Clearly looks to me like this answer addresses the real issue while the question goes into the wrong direction.
mxp
@mxp: I dont get it either. In my experience, this is clearly the way to go.
John Dibling
+2  A: 

Attempting to answer my own question...

If I search the visual studio help system for "predefined macros" I will get a page listing a variety of macros which are defined according to assorted compilation options. Its far from a complete answer, but it may be the best I'm going to get.

Mick
+1  A: 

Several compilers set different defines when compiling. These you can then use in your program. (its not really detecting at runtime, its just something that is 'baked' into your program during compilation).

For GCC they are shown here. These also contain the optimization level.

Here is the list for Visual Studio. However I do not think it contains the optimization level, perhaps it has other info you can use.

Since this is the most common way to pass information from the compiler to the executable. I don't think this is possible for visual studio.


Thirler
A: 

Visual Studio 2008 has already set this up for you. When you create a new project, it sets up two build configurations for you: Debug and Release. You can switch between these configurations with a toolbar control.

Debug has settings tailored for debugging, in particular optimization turned off.

Release has settings tailored for release, in particular optimization turned on.

The preprocessor macro DEBUG is only defined in the Debug configuration, so you can easily do someting like:

#ifdef DEBUG
::MessageBox("You are using the debug version", "Warning - Slow", MB_OK);
#endif

Note also, that these configurations put their output in different folders, so it's easy to tell them apart.

oefe
+4  A: 

I think you might be going about this the wrong way...

See, while Visual Studio starts off giving you just Debug and Release configurations, there's nothing stopping you from adding as many as you like, with whatever compilation settings you like.

Certainly, for day-to-day use, you shouldn't be fiddling with compiler settings and so on. Just set them up once and switch configurations as needed.

To add more configurations, use the Build->Configuration Manager page. There you'll the default Debug and Release, and you can create your own "Super Release" or whatever you want to call it.

Dean Harding
A: 

I have a trick for checking that I do not release Debug versions of my programs. I compare the size of the executables and DLLs to the sizes of the same binaries of the last release. They must be of similar, usually slightly increased size. If I have the Debug version of a file, the size is x3 or x4 thi size of the Release version.

Didier Trosset
A: 

It sounds like you already have multiple configurations set up, and you just want to know for sure which one the current .exe was built with, rather than know exactly which compiler options were picked?

If so then the following are some options:

  1. Build the .exe a different name for each configuration e.g App_d, App_super_optimized, etc
  2. Add a different symbol definition in each config that can be checked as #defined at startup
  3. Perhaps in conjunction with 2. make all but your release build require some file to be present, which you don't distribute. That way, your users CAN'T run a slow version even if you do release it by accident.
John
@john: I already have debug and release. But I currently don't have separate optimized vs super-optimized configurations. I simply use release and manually flip a couple of flags to turn on link time code generation and sometimes even profile guided optimization.
Mick
Well then I think that's precisely the problem. MSVC++ makes it very easy to create a new build configuration by cloning your existing release config. Many libraries do exactly this - static Vs DLL builds, etc.
John
I am not very expert on visual studio... I have just discovered the "configuration manager" and see that I can make a new project with "copy settings from:"... I'm confused about whether or not to tick the "Create new solution configurations" checkbox or not.
Mick
John
Or, ask Codeka to elaborate on his answer.
John
+1  A: 

To do this right you will need to create an additional configuration called, say "SuperOptimised". You now have the standard configurations ("Debug" and "Release") and a third "SuperOptimised". The problem with this is that it makes the configuration management of the project much harder, to change a common setting between the three configurations, you need to make that change in three places.

The solution to that is to use "Property Sheets" (".vsprops" files) and the "Property Manager" tab. You can create a property sheet that is common across all three configurations, and specific sheets for Release, Debug and SuperOptimised. Combine the common settings with the specific settings (using property inheritance) to manage the configurations - the "Property Manager" tab allows you to do this. You can change the ".vsprops" files to change common settings across configurations without changing the configurations themselves.

More info on Property Sheets here:

http://msdn.microsoft.com/en-us/library/a4xbdz1e(VS.80).aspx

Finally if you want to check which configuration was build at runtime, use the preprocessor to define a macro value in the "SuperOptimised" .vsprops file, say "SUPEROPTIMISED". You can then check whether you have the right build with:

#ifndef SUPEROPTIMISED
    // Warn the user that this is not a shipping build
#endif

This may all seem like a lot of work, but managing non-trivial projects (and especially multi-project workspaces) through property sheets greatly reduces the chance of error when making configuration changes.

Bids
I am tempted to mark this as the correct answer, it feels like it's problem solved... My only problem being that Microsoft documentation is so incredibly unhelpful that I don't know how I will ever get property sheets up and running. It shows an example line in the sheet stating "<UserMacro Name="VCROOT" Value="$(DDROOT)\vc" /> "... I have no idea what that means and I have no idea how to find out what that means. I was hoping to see things that looked more like "link-time-compilation=ON".. or whatever.
Mick
The property sheets do look nasty but they are not so bad. You create new property sheets in the "Property Manager" tab, you can save them as ".vsprops" files. Once they are saved you can add them to existing configurations as a hierarchy. To edit a property sheet, just double-click it in the "Property Manager" and you get the normal VS properties window (you don't need to edit them as text). You can set the macro in C/C++ -> Preprocessor - just type "SUPEROPTIMISED" in this box. Macros are separated with a ";".
Bids
@bids: "you don't need to edit them as text" thank god for that!
Mick