A useful post. A pity that CMake's scripting language is so atrocious, but it's good to see it's capable of this kind of thing.
Personally I tend to go the route wmu mentions in their comment: add a file named MyProject.h.in, to expose CMake variables in a generated header file. I use the C preprocessor's stringification [0] to transform version numbers into strings. My approach (really just CMake basics) doesn't expose any git specifics though - it's more basic than what the blog describes.
Modifying the source files in the build may break distributed builds(distcc) and cache(ccache). Maybe pass git version as defines add_compile_definitions/add_definitions aka (-DGITVER=yourvar) ?
I do not understand the "dummy output" technique. Since nothing depends on _version.cpp, why does its existence force the command to be re-run?
The usual technique is to have some script check the git version, then output two files: the version.cpp file, and a "witness" file which changes every run. The script should be careful to not perturb the mod date of version.cpp unless it has changed.
This is coupled with Ninja's "restat" option. Without that option, Ninja will observe that version.cpp will be recreated and schedule all of its dependents (such as linking). With that option, Ninja will behave more like Make, check if the file was actually modified.
versioning has always felt like something that should be first-class in programming languages, but isn't because language + buildsystem + VCS aren't tightly coupled
package managers, for example, should know the git sha
Once upon a time, we had version control systems that provided keyword expansion for something like %G% (SCCS, BitKeeper) or $Id$ (RCS, CVS come to mind). With git, this has fallen out of fashion, however, but I'm not sure why.
I'm glad it is gone. The useful uses of it are far outweighed by the abuses. If I never again have to page down through the entire history of a file in my editor to get to the code that will be fine with me. I have a version control system when I need to know history.
git still supports a variant of that (if you set the "ident" flag in gitattributes), though it uses the blob hash of that file, not the commit hash.
But in general, git doesn't look kindly on gratuitous modifications to source files. Those modifications can never occur in the actual files in the repository, since you can't hash something that contains its own hash (unless the hash is broken). And having the file in the working directory not match the file in the repository makes life difficult in various ways (diffs, etc).
Yes. When you checked a file into VSS it would expand the string $Id$ before actually writing the file into the repo, so it would be in the file you checked out. So if you had a copy of that file, you could know instantly what revision it was from. If you had blah.c on your disk and you had a Git repo it’s far harder to say “what commit did this copy of the file actually come from”?
This is better than the canonical approach of using CMake's configure_file as that runs at compile time while this runs at configure time. The problem with generating your version file at compile time is that it is always newer than an existing output, therefore every make causes a relink/re-ar.
If you're executing the script with add_custom_command, what's the benefit of writing the script itself in CMake's scripting language rather than (e.g.) bash or Python? The CMakeLists.txt file is treating the script as a black box anyway.
Personally I tend to go the route wmu mentions in their comment: add a file named MyProject.h.in, to expose CMake variables in a generated header file. I use the C preprocessor's stringification [0] to transform version numbers into strings. My approach (really just CMake basics) doesn't expose any git specifics though - it's more basic than what the blog describes.
The MyProject.h.in file looks like:
Getting CMake to process this file is simple enough: we just add configure_file(MyProjectConfig.h.in MyProjectConfig.h) to the CMakeLists.txt file.[0] https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification...