I'd like my .exe to have access to a resource string with my svn version. I can type this in by hand, but I'd prefer an automated way to embed this at compile time. Is there any such capability in Visual Studio 2008?
I wanted a similar availability and found $Rev$ to be insufficient because it was only updated for a file if that file's revision was changed (which meant it would have to be edited and committed very time: not something I wanted to do.) Instead, I wanted something that was based on the repository's revision number.
For the project I'm working on now, I wrote a Perl script that runs svnversion -n from the top-most directory of my working copy and outputs the most recent revision information to a .h file (I actually compare it to a saved reversion in a non-versioned file in my working copy so that I'm not overwriting current revision information at every compile but whether you chose to do so is up to you.) This .h file (or a number of files if necessary, depending on your approach) is referenced both in my application code and in the resource files to get the information where I'd like it.
This script is run as a pre-build step so that everything is up-to-date before the build kicks off and the appropriate files are automatically rebuilt by your build tool.
How about using SubWCRev the command line tool that ships with TortoiseSVN. You create a template file with tokens in it like $WCREV$ $WCDATE$ etc. Then have a pre-build step that run SubWCRev on your template file to create the actual source file that is fed to the compiler.
You can get SVN to embed it for you, if that will solve the problem. See the $Rev$ keyword on that page.
Have a look at svn keyword substitution here. There is another SO question here which I found through google!
antik's solution is the one we use. Be careful of using environment variables, the .h file ensures you can have a dependency which will cause any files that need it to be recompiled when the svn rev number changes.
Related
I am working on a huge C++ project, targeting many platforms with several configurations for each platform.
Because of the long compilation time, build the entire project on every platform to test if a change compile successfully, isn't an option.
What I usually do, is compile the single cpp modules I modified on different combination of platform/configuration.
I'd like to automate this process, either using a script, a VS extension, whatever, I am open to evaluate different options.
What I need exactly is taking a list of cpp files and compile each file, for each platform and each configuration (basically iterating through all combination of the configuration manager).
Is this possible? any good suggestion on how to approach the problem?
EDIT:
I am aware that this is way far to be a perfect solution, and will spot only a subset of errors.
I will still have to face linking errors, compiler errors on other cpp units depended on a modified header, and so on..
I also, don't have any chance to modify the current build system, or project generation.
I am mostly interested in a local solution, to reduce the amount of possible issues and facing the huge building time process.
EDIT2
We have a build system. This has to be considered a pre-build system optimization, for my personal workflow.
Reasons:
Triggering a build system job requires time. It will be the final step, but instead of spending hours waiting, and maybe discover later that a given compiler on a given platform for a specific configuration raise an error, it would be much more efficient to anticipate those findings as much as possible.
Current manual workflow:
Open each cpp file I modified
Compile each cpp file as a single unit (not building the project. On VS Build-> Compile)
Change Platform and/or configuration and re-do point 2 again.
This is the manual workflow I'd like to optimize.
I would suggest that you "simply" write a script to do this (using Python for instance, which is very powerful for this kind of this)
You could:
Parse the .sln file to extract the list of configurations, platforms ( GlobalSection(SolutionConfigurationPlatforms) entry) and projects (Project entry)
If needed, you can parse every project to find the list of source files (that's easier than parsing the .sln, as vcxproj files are in xml). Look for ClCompile xml nodes to extract the list of .cpp files.
Then you can identify which projects needs some files to be recompiled (getting list of modified files as script input parameter or based on timestamp checking)
Finally, to rebuild, you have two options:
Call "msbuild " to recompile the whole project (vcxproj) (for instance msbuild project.vcxproj /p:Configuration=Debug;TargetFrameworkVersion=v3.5)
You could also recompile a single file (cl simple.cpp). To do so, you need to know what are the cl build options to be sure you compile the file exactly the same way as Visual Studio would. If you earlier did a full build of the solution (it could be a rquirement for your script to work), then you should be able to find that from Visual Studio logs (within the target folder). In my solutions, I can find for every project (vcxproj file) a build log per configuration (in %OUTPUT_DIR%\lib\%libname%\%libname%.dir\%configuration%\%libname%.tlog\CL.command.1.tlog), this file reports the exact cl arguments that were used to compile every file of the project. Then you can manually invoke cl command and this should end up recompiling the file the same way Visual Studio would do it.
Additionnaly, you could add a project in your Visual Studio solution that would fire this script as a custom command.
Such a script should be able to identify which projects has to be rebuilt and rebuild them.
This is a very common requirement, it is never solved this way. What you are proposing is not completely impossible, but it is certainly very painful to implement. You are overlooking what should happen when you modify a .h file, that can force a bunch of .cpp files to be recompiled. And you are not considering linker errors. While you'll have a shot at discovering .cpp files, discovering #include file dependencies is very gritty. You can't get them from the project or make file. Compiling with /showIncludes and parsing the build trace files is what it takes. Nothing off-the-shelf afaik.
Don't do this, you'll regret it. Use the solution that everybody uses: you need a build server. Preferably with a continuous integration feature so the server kicks-off the build for all target platforms as soon as you check-in a code change. Many to choose from, this Q+A talks about it.
I have a C++ project that builds on several platforms.
On Mac OSX and Linux, I use SConstruct, which allows me to have some "smartness" regarding the different compilation steps. Namely, I could put the program version in a file named VERSION at the root of the repository, whose content is simply:
2.0
In the build SConscript, I just have to open, read and parse that file and I can create dynamic defines based on it. For instance:
env.Append(CXXFLAGS=['-DVERSION_MAJOR=%s' % open('VERSION').read().split('.')[0]])
This is, for obvious reasons, very convenient. It also allows me to put today's date in an environment variable for instance.
Now for Windows, I have a .sln file with different .vcxproj files into which I'd like to do something similar, except I have no idea how.
To summarize, my question is: how can I have "smart" defines like that (reading, parsing a file and putting its content into several environment variables) without having to change the .sln/.vcxproj files manually on every version shift ?
I know I could use SCons on Windows too, but I'd like not to (mainly because it seems less popular on the platform, and I don't want to scare potential contributors that only know Windows-specific tools).
A common way to do this is to define your constants in an include file:
e.g.
// Version.h - Autogenerated, don't edit
#define VERSION_MAJOR 1
Next you write a script or a program (in your favourite language) to obtain version from somewhere and dynamically write Version.h. Possibly parse the old Version.h and increment or get it from some external source.
In visual studio, create a custom build step for Version.h and make it dependent on something that forces it to update on every build.
You could maintain the current solution, and for Windows, integrate it with Visual Studio solution and project files generated by SCons using the MSVSProject() builder or the MSVSSolution() builder.
You can find more info about these SCons builders here.
I've added a custom build step to my Visual Studio project files which generates the google protobuf .h/.cc files from the .proto input files. But I've been wondering if it's possible to start a compile only if the content of the proto files has changed?
Is there a way to tell VisualStudio from a custom build step exactly that? What is the optimal way to integrate proto files into a visual studio build solution?
At the moment, at every build the .proto file is updated which then also updates the time stamp of the output .h/.cc files ...which then issues a recompile of everything dependent from that. Is there a better way around it, while still building them directly from visual studio?
Follow these detailed instructions to specify Custom Build Tool.
Considering your proto file resides together with .h/.cpp files in standard project configuration, here are values to be inserted in Custom Build Tool:
Command Line:
path\to\protoc --proto_path=$(ProjectDir) --cpp_out=$(ProjectDir) %(FullPath)
Outputs:
$(ProjectDir)%(Filename).pb.h;$(ProjectDir)%(Filename).pb.cc
Please note usage of item metadata macros, which replaced some of deprecated macros (like $(InputDir) and $(InputName)).
Now Protocol Buffers compiler will be run only when Input file (i.e. %(FullPath)) is newer than "Outputs".
Maybe this helps. Especially look at the post of Igor Zavoychinskiy:
Solution of this nasty problem is actually simple: in outputs sections
you should specify full path(s). This isn't explicitly stated anywhere
but without this checker just fails to find the files and, hence,
assumes they don't exist. For example for protobuffers compiling
outputs section will be like this:
$(InputDir)\$(InputName).pb.cc;$(InputDir)\$(InputName).pb.h
and (maybe?) kmote00:
...
Bottom line: I just had to make sure my "Outputs" entry exactly
matched the Default Value in the (user-defined) "OutputFile" property.
(Thankfully this also obviated the need for a two-pass build, which
was another annoyance I had previously put up with.)
Is there any tool which can inject into an .exe or .dll information like File Version, Product name, Copyright, etc?
I did find a tool called StampVer but it can only modify resources that are already in the file itself. I could use it but would need to modify a bunch of Visual Studio projects to include some dummy information, and I would of course prefer to avoid that.
You can make a header file that would define some things like e.g. #define MAJOR_VERSION 2 and #define MINOR_VERSION 1 (same with build numbers and whatever you need there). Then, #include this header file from your .rc file.
Now, to the automation of the process. Your build script can output this header file, incrementing various values. After a successful build, the file is commited to VCS, and then can be used on next iteration. There are ways of accomplishing this even with plain .cmd files, using environment variables, however, if you can, use something more sophisticated like perl/python etc. for this task.
This works fine for producing releasable builds, and it's not the best solution if you need to increment a build number on every build you make on your development machine.
I ended up adding a dummy resource version and will be using StampVer.
How many projects do you have? I timed it, it takes 3 seconds in Visual Studio. Right-click project, Add, Resource, select "Version", New.
What kind of exe/dll are you creating? There are some easy solutions for .NET assemblies, and some difficult solutions for unmanaged assemblies.
For assemblies:
http://www.codeproject.com/KB/dotnet/ManagingAssemblyVersions.aspx
Not exactly after the build, but this is what we do:
We create an include file for C++ from a batch file & include it in the build process. The include has a define in it that is included in the resource file.
You can also use Visual studio to modify resources in a PE ( unmanged binary ). By hand you can modify all of the version resource.
We're looking for a way to include some sort of build ID automatically in our builds. This needs to be portable (VC++, g++ on Linux and Mac) and automatic. VC++ is what matters most, since in the other environments we use custom Python build scripts so I can do whatever I want.
We use SVN, so we were looking at using the output of svnversion to write the revision to a header and include it. This has problems : if we put the file in SVN, it will appear as modified every time, but it would be a superfluous commit and in a sense generate an infinite loop of increasing revisions. If we don't put the file in SVN and just create it as a pre-build step, the sources wouldn't be complete, as they'd need the pre-build step or Makefile to generate that file.
We could also use __DATE__ but we can't guarantee the file that uses the __DATE__ (ie writes it to a log file) will be compiled if some other file is modified - except if we "touch" it, but then we'd cause the project to be always out of date. We could touch it as the pre-build step, so it would get touched only if the rest of the project is out of date, thus not causing a spurious compile, but if VC++ computes the dependencies before the pre-build step, this wouldn't work (the file with __DATE__ won't get compiled)
Any interesting ideas?
We're using the output of svnversion, written to a header file and included. We omit the file from the repository and create it in a pre-build step; this has worked quite well for us. (I'm not sure why you object to using a pre-build step?)
We're currently using a Perl script to convert svnversion's output into a header file; I later found out that TortoiseSVN includes a subwcrev command (which has also been ported to Linux) that can do much of the same thing.
If you don't like the idea of an include file not in source control that is required for a build, consider a batch file or other build step that programmatically creates a file/include and call the svnversion within your build process.
basically GENERATE the file so you don't have an unversioned and required file.
EDIT
Josh's subwcrev is probably the best idea.
Before that was implemented I wrote my own hacky tool to do the same thing - do replacement in a template file.
It could be as simple as:
% make -DBUILD_NUMBER=`svnlook youngest /path/to/repo`
I'd look at SvnRev. You can use it as a custom pre-build step in VS, or call it from a makefile, or whatever else you need to do, and it generates a header file that you can include in your other files that will give you what you need. There's good documentation on the site.
SubWCRev is another option, though the Linux port is newer, and I don't know that a Mac version exists. It's very useful on Windows for .NET (which I'm guessing isn't an issue for you, but I'm adding this for future reference), because it allows you to create a template file that can be used to generate, for example, the Properties file for a .NET assembly.
Automatic builds can typically be full, clean builds. In that case, you start in a clean directory and there would be no issue with __DATE__ in any case. Otherwise, see Paul Beckinham's idea.
Why not tie a GUID to it, almost every language has support for generating one, or if your's doesn't there are alot of algorithms for that around.
(Although, if you do use subversion, I personally like Josh's idea better!)