From dca08dd45e24119a17ad7893aedaa40f3eceee07 Mon Sep 17 00:00:00 2001 From: Aki Date: Mon, 4 Jul 2022 17:56:32 +0200 Subject: Updated lets versions with a verbose example --- lets_not_store_versions_in_versioned_files.html | 50 ++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'lets_not_store_versions_in_versioned_files.html') diff --git a/lets_not_store_versions_in_versioned_files.html b/lets_not_store_versions_in_versioned_files.html index 725decd..1d83793 100644 --- a/lets_not_store_versions_in_versioned_files.html +++ b/lets_not_store_versions_in_versioned_files.html @@ -13,7 +13,7 @@

Let's Not Store Versions in Versioned Files

-

Published on 2022-07-02 23:33:33+02:00 +

Published on 2022-07-02 23:33:33+02:00, last modified on 2022-07-04 18:00:00+02:00

It is a rather common practice to include version numbers directly in the meta files or sources that are stored inside a code repository. To list few examples: npm makes it part of its regular practices, python's setuptools usually involves various hacks, be it normal @@ -54,16 +54,54 @@ distribution, deployment, or packaging system.

Some of them support it better, some worse. Luckily, good chunk of them allow for arbitrary logic to be executed, so we can implement it by ourselves. Additionally, there is a good chance that the VCS provides some kind of helper for getting the human-readable tag-driven version description. In case of Git there is git-describe(1), which fits -this use case directly. We can just call it from CMake or setup.py and read its output. +this use case directly. We can just call it from CMake or setup.py and read its output. Very often we may be forced to +generate some full pledged files, so be ready to do it. +

Example CMake Project

+

Let's consider a C++ project built by CMake. It is intended to be packaged, but is also meant to support installing +it directly from the repository. The program itself is rather simple - it prints out its version. Every single time: +

+#include <iostream>
+#include "version.h"
+
+int main(int, char*[])
+{
+	std::cout << version::full << std::endl;
+}
+
+

The version.h is just a namespace with an extern constant. To provide an actual value for the version number, +let's write a version.cpp.in that will be processed by CMake to generate the actual source that will be added to +the target: +

+namespace version {
+const char* full = "@VERSION@";
+}
+
+

The @VERSION@ is a pattern that is recognized by CMake's +configure_file which we will use to +generate the actual source code that is intended for compilation just like we planned: +

+add_executable(version-print main.cpp)
+git_describe(VERSION)
+configure_file(version.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/version.cpp @ONLY)
+target_sources(version-print PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.cpp)
+
+

Now, CMake does not support this out-of-box sadly, so you need to implement git_describe yourself or get +an external module for it. There is one in +Ryan A. Pavlik's +repository and I have implemented +one for Starshatter at some point. +They are rather easy and fun to write (altough there is a variety of edge cases), but it's still a bit shame that they +are not part of the core CMake. +

Alternatively, you can consider using a define to, well, define the version number. I use this approach with separate +file that defines the variable for the sake of dependency checks and recompilation. +

Final Thoughts

Of course, a full-pledged support would be way nicer and stable, but surprisingly, we're not there yet.

Well, some of us are. To contrast the list of bad examples consider Go programming language, which recommends this method of versioning. Interestingly, it also uses code repositories as a form of package distribution, so any arguments saying that file with a version is needed because the repository is used as a means of distribution are baseless.

What to take away from this post? Next time when you will start a project, consider keeping meaningful version only in the VCS. If your building/distribution/whatever-else system does not support it fully out-of-box - try implementing -it. Once you have a working implementation - push it upstream. For instance, there are CMake modules that handle it, -but they are external and not part of main CMake for whatever reason. It would be much better to have it standardized -and part of the tool. Who knows, maybe in some time we might be able to have a consistent support in all across the -ecosystem. As for now, back to experimenting, and until next time! +it. Once you have a working implementation - push it upstream. Who knows, maybe in some time we might be able to have a +consistent support in all across the ecosystem. As for now, back to experimenting, and until next time!

-- cgit v1.1