Run time determination of compilation options
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 tes开发者_运维知识库t 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?
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 #ifdef
s.
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...
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.
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.
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.]
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.
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.
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.
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.
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:
- Build the .exe a different name for each configuration e.g App_d, App_super_optimized, etc
- Add a different symbol definition in each config that can be checked as #defined at startup
- 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.
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.
精彩评论