Skip to content

Commit 963112d

Browse files
committed
Better version string
1 parent 0f4fc7f commit 963112d

File tree

1 file changed

+109
-20
lines changed

1 file changed

+109
-20
lines changed

cmake/VersionString.cmake

Lines changed: 109 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -239,54 +239,143 @@ function(write_version_header dir)
239239

240240
# Check the revision string, if it matches we fill in the required info
241241
if(REVISION_STRING MATCHES "build-([0-9]+)-g([0-9a-f]+)(-dirty)?")
242-
set(REVISION_GIT_TAGREF "${CMAKE_MATCH_2}")
242+
set(BUILD_NUMBER ${CMAKE_MATCH_1})
243243
if(CMAKE_MATCH_3)
244-
set(REVISION_STRING "${CMAKE_MATCH_1}*")
244+
set(REVISION_GIT_TAGREF "${CMAKE_MATCH_2}*")
245245
else()
246-
set(REVISION_STRING "${CMAKE_MATCH_1}")
246+
set(REVISION_GIT_TAGREF "${CMAKE_MATCH_2}")
247247
endif()
248248

249249
string(TIMESTAMP REVISION_DATE_TIME "%Y-%m-%dT%H:%M:%SZ" UTC)
250250
else()
251251
message(STATUS "no git info available, cannot update version string")
252252

253253
set(REVISION_GIT_TAGREF "")
254-
set(REVISION_STRING "")
254+
set(BUILD_NUMBER 0)
255255
set(REVISION_DATE_TIME "")
256256
endif()
257257

258258
if(VERSION_STRING_OPTION_VAR_PREFIX)
259259
set(VAR_PREFIX "${VERSION_STRING_OPTION_VAR_PREFIX}")
260260
endif()
261261

262-
file(WRITE "${VERSION_STRING_DATA}/${file_name}.in" [[// Generated revision file
262+
file(WRITE "${VERSION_STRING_DATA}/${file_name}.in" [[
263+
264+
265+
// Generated revision file
263266
264267
#pragma once
265268
266269
#include <ostream>
267270
268-
const char k@VAR_PREFIX@ProjectName[] = "@PROJECT_NAME@";
269-
const char k@VAR_PREFIX@VersionNumber[] = "@PROJECT_VERSION@";
270-
const char k@VAR_PREFIX@RevisionGitTag[] = "@REVISION_GIT_TAGREF@";
271-
const char k@VAR_PREFIX@RevisionInfo[] = "@REVISION_STRING@";
272-
const char k@VAR_PREFIX@RevisionDate[] = "@REVISION_DATE_TIME@";
271+
constexpr const char k@VAR_PREFIX@ProjectName[] = "@PROJECT_NAME@";
272+
constexpr const char k@VAR_PREFIX@VersionNumber[] = "@PROJECT_VERSION@";
273+
constexpr const char k@VAR_PREFIX@RevisionGitTag[] = "@REVISION_GIT_TAGREF@";
274+
constexpr int k@VAR_PREFIX@BuildNumber = @BUILD_NUMBER@;
275+
constexpr const char k@VAR_PREFIX@RevisionDate[] = "@REVISION_DATE_TIME@";
273276
274-
inline void write_version_string(std::ostream &os, bool verbose)
277+
#ifndef VERSION_INFO_DEFINED
278+
#define VERSION_INFO_DEFINED 1
279+
280+
#define CONCAT(a, b, c) a_ ## b ## c
281+
#define CREATE_INSTANCE_NAME(prefix) CONCAT(k, prefix, instance)
282+
#define CREATE_CLASS_NAME(prefix) CONCAT(version_info_, prefix, impl)
283+
284+
class version_info_base
275285
{
276-
os << k@VAR_PREFIX@ProjectName << " version " << k@VAR_PREFIX@VersionNumber << std::endl;
277-
if (verbose)
286+
public:
287+
virtual ~version_info_base() = default;
288+
289+
static void write(std::ostream &os, bool verbose)
278290
{
279-
if (k@VAR_PREFIX@RevisionInfo[0] != 0)
291+
for (auto inst = head(); inst != nullptr; inst = inst->m_next)
280292
{
281-
os << "build: " << k@VAR_PREFIX@RevisionInfo << ' ' << k@VAR_PREFIX@RevisionDate << std::endl;
282-
if (k@VAR_PREFIX@RevisionGitTag[0] != 0)
283-
os << "git tag: " << k@VAR_PREFIX@RevisionGitTag << std::endl;
293+
os << inst->m_name << " version " << inst->m_version << std::endl;
294+
295+
if (verbose)
296+
{
297+
if (inst->m_build != 0)
298+
{
299+
os << "build: " << inst->m_build << ' ' << inst->m_revision_date << std::endl;
300+
if (inst->m_git_tag[0] != 0)
301+
os << "git tag: " << inst->m_git_tag << std::endl;
302+
}
303+
else
304+
os << "No revision information available" << std::endl;
305+
}
306+
307+
if (inst->m_next != nullptr)
308+
os << std::endl;
284309
}
285-
else
286-
os << "No revision information available" << std::endl;
287310
}
311+
312+
protected:
313+
314+
struct instance
315+
{
316+
const char *m_name;
317+
const char *m_version;
318+
const char *m_git_tag;
319+
int m_build;
320+
const char *m_revision_date;
321+
322+
instance *m_next = nullptr;
323+
};
324+
325+
using instance_ptr = instance *;
326+
327+
static instance_ptr &head()
328+
{
329+
static instance_ptr s_head = nullptr;
330+
return s_head;
331+
}
332+
};
333+
334+
template<typename T>
335+
class version_info : public version_info_base
336+
{
337+
public:
338+
339+
using implementation_type = T;
340+
341+
protected:
342+
version_info()
343+
{
344+
auto &s_head = head();
345+
static instance s_next{
346+
implementation_type::name(),
347+
implementation_type::version(),
348+
implementation_type::git_tag(),
349+
implementation_type::build_number(),
350+
implementation_type::revision_date(),
351+
s_head };
352+
s_head = &s_next;
353+
}
354+
};
355+
356+
inline void write_version_string(std::ostream &os, bool verbose)
357+
{
358+
version_info_base::write(os, verbose);
288359
}
289-
]])
360+
361+
#endif
362+
363+
#define INSTANCE_NAME CREATE_INSTANCE_NAME(VAR_PREFIX)
364+
#define CLASS_NAME CREATE_CLASS_NAME(VAR_PREFIX)
365+
366+
class CLASS_NAME : public version_info<CLASS_NAME>
367+
{
368+
public:
369+
370+
static constexpr const char *name() { return k@VAR_PREFIX@ProjectName; }
371+
static constexpr const char *version() { return k@VAR_PREFIX@VersionNumber; }
372+
static constexpr const char *git_tag() { return k@VAR_PREFIX@RevisionGitTag; }
373+
static constexpr int build_number() { return k@VAR_PREFIX@BuildNumber; }
374+
static constexpr const char *revision_date() { return k@VAR_PREFIX@RevisionDate; }
375+
} INSTANCE_NAME;
376+
377+
378+
]])
290379
configure_file("${VERSION_STRING_DATA}/${file_name}.in" "${dir}/${file_name}" @ONLY)
291380
endfunction()
292381

0 commit comments

Comments
 (0)