summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2022-07-04 17:56:32 +0200
committerAki <please@ignore.pl>2022-07-04 17:56:32 +0200
commitdca08dd45e24119a17ad7893aedaa40f3eceee07 (patch)
treeecd7147706b94273ebb2b118218214cb44230075
parent9651913c75269f83902ac2473c1a611dd4c77643 (diff)
downloadignore.pl-dca08dd45e24119a17ad7893aedaa40f3eceee07.zip
ignore.pl-dca08dd45e24119a17ad7893aedaa40f3eceee07.tar.gz
ignore.pl-dca08dd45e24119a17ad7893aedaa40f3eceee07.tar.bz2
Updated lets versions with a verbose example
-rw-r--r--lets_not_store_versions_in_versioned_files.html50
1 files changed, 44 insertions, 6 deletions
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 @@
<article>
<h1>Let's Not Store Versions in Versioned Files</h1>
-<p class="subtitle">Published on 2022-07-02 23:33:33+02:00
+<p class="subtitle">Published on 2022-07-02 23:33:33+02:00, last modified on 2022-07-04 18:00:00+02:00
<p>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: <a href="https://www.npmjs.com/">npm</a> makes it part of its regular
practices, python's <a href="https://setuptools.pypa.io/">setuptools</a> usually involves various hacks, be it normal
@@ -54,16 +54,54 @@ distribution, deployment, or packaging system.
<p>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 <b>git-describe</b>(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.
+<h3>Example CMake Project</h3>
+<p>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:
+<pre>
+#include &lt;iostream&gt;
+#include "version.h"
+
+int main(int, char*[])
+{
+ std::cout << version::full << std::endl;
+}
+</pre>
+<p>The <i>version.h</i> is just a namespace with an extern constant. To provide an actual value for the version number,
+let's write a <i>version.cpp.in</i> that will be processed by CMake to generate the actual source that will be added to
+the target:
+<pre>
+namespace version {
+const char* full = "@VERSION@";
+}
+</pre>
+<p>The <code>@VERSION@</code> is a pattern that is recognized by CMake's
+<a href="https://cmake.org/cmake/help/latest/command/configure_file.html">configure_file</a> which we will use to
+generate the actual source code that is intended for compilation just like we planned:
+<pre>
+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)
+</pre>
+<p>Now, CMake does not support this out-of-box sadly, so you need to implement <code>git_describe</code> yourself or get
+an external module for it. There is one in
+<a href="https://github.com/rpavlik/cmake-modules/blob/main/GetGitRevisionDescription.cmake">Ryan A. Pavlik's
+repository</a> and I have implemented
+<a href="https://git.ignore.pl/starshatter/tree/cmake/modules/GitDescribe.cmake">one for Starshatter</a> 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.
+<p>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.
+<h2>Final Thoughts</h2>
<p>Of course, a full-pledged support would be way nicer and stable, but surprisingly, we're not there yet.
<p>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.
<p>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!
</article>
<script src="https://stats.ignore.pl/track.js"></script>