changeset 880:fe350b24465d

cmake: rework version & hg commit getting hg archive generated tarballs include a .hg_archival.txt file which includes the commit hash, latest tag, and distance from latest tag. These values can be combined to create a string much like the template-based version string. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sun, 12 May 2024 11:10:42 -0400
parents 5dd01b60e33b
children 136b22000744
files CMakeLists.txt cmake/hg.cmake
diffstat 2 files changed, 64 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Wed Jan 31 13:50:28 2024 -0500
+++ b/CMakeLists.txt	Sun May 12 11:10:42 2024 -0400
@@ -211,6 +211,8 @@
 
 add_custom_command(TARGET revisiontag
 	COMMAND ${CMAKE_COMMAND}
+		-DINCLUDE_GUARD_NAME=__LIBJEFFPC_INTERNAL_VERSION_H
+		-DHG_ARCHIVAL=${CMAKE_SOURCE_DIR}/.hg_archival.txt
 		-DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
 		-DBINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
 		-DJEFFPC_VERSION=v${JEFFPC_VERSION}
--- a/cmake/hg.cmake	Wed Jan 31 13:50:28 2024 -0500
+++ b/cmake/hg.cmake	Sun May 12 11:10:42 2024 -0400
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017-2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+# Copyright (c) 2017-2019,2024 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -20,48 +20,83 @@
 # SOFTWARE.
 #
 
-find_package(Hg)
-
-macro(gethgrev varname template defstr)
-	set(${varname} "${defstr}")
+# SOURCE_DIR = current source directory
+# BINARY_DIR = current binary directory
+# HG_ARCHIVAL = expected path to .hg_archival.txt
+# INCLUDE_GUARD_NAME = name of #define to use as include guard
 
-	if(HG_FOUND)
-		execute_process(
-			COMMAND ${HG_EXECUTABLE} log -r . --template ${template}
-			WORKING_DIRECTORY ${SOURCE_DIR}
-			OUTPUT_VARIABLE ${varname}
-			RESULT_VARIABLE res_var
-		)
-		if(NOT ${res_var} EQUAL 0)
-			set(${varname} "${defstr}")
-		endif()
+macro(gethgrev varname template)
+	set(res_var "")
+	execute_process(
+		COMMAND ${HG_EXECUTABLE} log -r . --template ${template}
+		WORKING_DIRECTORY ${SOURCE_DIR}
+		OUTPUT_VARIABLE ${varname}
+		RESULT_VARIABLE res_var
+	)
+	if(NOT ${res_var} EQUAL 0)
+		unset(varname)
 	endif()
 endmacro()
 
-gethgrev(HG_COMMIT_STR "{node}" "0000000000000000000000000000000000000000")
+if(EXISTS "${HG_ARCHIVAL}")
+	set(tag "unknown")
+	set(node "")
+	set(dist 0)
+
+	# read in the archival key-value pairs & pick out interesting ones
+	file(STRINGS "${HG_ARCHIVAL}" blob)
+	foreach(x ${blob})
+		if("${x}" MATCHES "^node: ([0-9a-f]*)$")
+			set(node ${CMAKE_MATCH_1})
+		elseif("${x}" MATCHES "^latesttag: (.*)$")
+			set(tag ${CMAKE_MATCH_1})
+		elseif("${x}" MATCHES "^latesttagdistance: ([0-9]*)$")
+			set(dist ${CMAKE_MATCH_1})
+		endif()
+	endforeach()
 
-# TODO: if there are uncommitted changes, append -dirty
-gethgrev(VERSION
-	"{ifeq(latesttagdistance,0,\"{latesttag}\",\"{latesttag}+{latesttagdistance}-{node|short}\")}"
-	"${JEFFPC_VERSION}")
+	# set HG_COMMIT_STR and VERSION to mimic the hg templates
+	if(NOT ${node} STREQUAL "")
+		set(HG_COMMIT_STR "${node}")
+		if(${dist} EQUAL 0)
+			set(VERSION "${tag}")
+		else()
+			string(SUBSTRING ${node} 0 12 shortnode)
+			set(VERSION "${tag}+${dist}-${shortnode}")
+		endif()
+	endif()
+else()
+	find_package(Hg)
 
-if(${HG_COMMIT_STR} STREQUAL "0000000000000000000000000000000000000000")
-	message(WARNING "Failed to get revision info from Mercurial.")
+	if(HG_FOUND)
+		gethgrev(HG_COMMIT_STR "{node}")
+
+		# TODO: if there are uncommitted changes, append -dirty
+		gethgrev(VERSION
+			"{ifeq(latesttagdistance,0,\"{latesttag}\",\"{latesttag}+{latesttagdistance}-{node|short}\")}")
+	else()
+		message(FATAL_ERROR "Could not find Mercurial to get version info")
+	endif()
 endif()
 
-set(HG_COMMIT "")
+if(NOT DEFINED HG_COMMIT_STR OR NOT DEFINED VERSION)
+	message(FATAL_ERROR "Could not determine source code version information")
+endif()
+
+# convert ASCII hex commit hash to C byte array values
+set(HG_COMMIT_BIN "")
 set(HEX ${HG_COMMIT_STR})
 while("${HEX}" MATCHES ".")
 	string(SUBSTRING ${HEX} 0 2 COMMIT_BYTE)
 	string(SUBSTRING ${HEX} 2 -1 HEX)
-	set(HG_COMMIT "${HG_COMMIT}0x${COMMIT_BYTE},")
+	set(HG_COMMIT_BIN "${HG_COMMIT_BIN}0x${COMMIT_BYTE},")
 endwhile()
 
 set(vstring "/* hgversion.h - Generated by cmake. Changes will be lost! */\n"
-	"#ifndef __LIBJEFFPC_INTERNAL_VERSION_H\n"
-	"#define __LIBJEFFPC_INTERNAL_VERSION_H\n"
+	"#ifndef ${INCLUDE_GUARD_NAME}\n"
+	"#define ${INCLUDE_GUARD_NAME}\n"
 	"#define HG_COMMIT_STR \"${HG_COMMIT_STR}\"\n"
-	"#define HG_COMMIT_BIN { ${HG_COMMIT} }\n"
+	"#define HG_COMMIT_BIN { ${HG_COMMIT_BIN} }\n"
 	"#define VERSION \"${VERSION}\"\n"
 	"#endif\n")