1
2# Create a rule to generate a version string at compile time.
3#
4# An optional fifth argument can be used to add additional cmake defines.
5#
6# SRC is processed using the configure_file() cmake command
7# at build to produce DST with the following variable available:
8#
9# VERSION_SOURCES:
10#  List of (${var} ${file}) pairs.
11#
12# for each variable ${var}
13# - ${var}: The contents of the associated file
14# - ${var}_COUNT: Number of lines in the associated file
15# - ${var}_${i}: The ${i}-th line of the associated file
16# - ${var}_${i}_SHORTNAME: The first component of the ${i}-th line of the associated file
17# - ${var}_${i}_STRING: Everything except the first component of the ${i}-th line of the associated file
18# - ${var}_${i}_NAME: Everything except the last component of the ${i}-th line of the associated file
19# - ${var}_${i}_NUMBER: The last component of the ${i}-th line of the associated file
20# - ${var}_HEAD: The first paragraph of the associated file
21# - ${var}_TAIL: The remaining paragraphs of the associated file
22#
23# - GIT_COMMIT: The current git commit. (not defined if there is no GIT_DIR directory)
24# - GIT_COMMIT_PREFIX_${i}: The first ${i} characters of GIT_COMMIT (i=0..39)
25# For the exact syntax of SRC see the documentation of the configure_file() cmake command.
26# The version file is regenerated whenever VERSION_FILE or the current commit changes.
27function(version_file SRC DST VERSION_SOURCES GIT_DIR)
28
29	set(mode "variable")
30
31	set(args)
32	set(dependencies "${CMAKE_MODULE_PATH}/VersionScript.cmake")
33
34	foreach(arg IN LISTS VERSION_SOURCES)
35
36		if(mode STREQUAL "variable")
37			set(mode "file")
38		else()
39			get_filename_component(arg "${arg}" ABSOLUTE)
40			list(APPEND dependencies ${arg})
41			set(mode "variable")
42		endif()
43
44		list(APPEND args ${arg})
45
46	endforeach()
47
48	get_filename_component(abs_src "${SRC}" ABSOLUTE)
49	get_filename_component(abs_dst "${DST}" ABSOLUTE)
50	get_filename_component(abs_git_dir "${GIT_DIR}" ABSOLUTE)
51
52	set(defines)
53	if(${ARGC} GREATER 4)
54		set(defines ${ARGV4})
55	endif()
56
57	if(EXISTS "${abs_git_dir}/HEAD")
58		list(APPEND dependencies "${abs_git_dir}/HEAD")
59	endif()
60
61	if(EXISTS "${abs_git_dir}/logs/HEAD")
62		list(APPEND dependencies "${abs_git_dir}/logs/HEAD")
63	endif()
64
65	add_custom_command(
66		OUTPUT
67			"${abs_dst}"
68		COMMAND
69			${CMAKE_COMMAND}
70			"-DINPUT=${abs_src}"
71			"-DOUTPUT=${abs_dst}"
72			"-DVERSION_SOURCES=${args}"
73			"-DGIT_DIR=${abs_git_dir}"
74			${defines}
75			-P "${CMAKE_MODULE_PATH}/VersionScript.cmake"
76		MAIN_DEPENDENCY
77			"${abs_src}"
78		DEPENDS
79			${dependencies}
80		COMMENT ""
81		VERBATIM
82	)
83
84endfunction(version_file)
85