forked from timescale/timescaledb
-
Notifications
You must be signed in to change notification settings - Fork 1
/
GenerateScripts.cmake
202 lines (185 loc) · 7.28 KB
/
GenerateScripts.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# Functions and macros to generate upgrade and downgrade scripts
# concatenate_files(<output> <file> ...)
#
# Concatenate a list of files into <output>
function(concatenate_files OUTPUT_FILE FIRST_FILE)
file(READ ${FIRST_FILE} _contents)
file(WRITE ${OUTPUT_FILE} "${_contents}")
foreach(_file ${ARGN})
file(READ ${_file} _contents)
file(APPEND ${OUTPUT_FILE} "${_contents}")
endforeach()
endfunction()
# generate_script(...)
#
# Generate a script file and install it into the script directory.
#
# VERSION <version>
#
# Version to use for shared libraryx.
#
# SCRIPT <file>
#
# File name for script file.
#
# OUTPUT_DIRECTORY <dir>
#
# Directory for where script file should be written. Defaults to
# CMAKE_CURRENT_BINARY_DIR.
#
# FILES <file> ...
#
# List of files to include, in order, in the script file.
function(generate_script)
set(options)
set(oneValueArgs VERSION SCRIPT OUTPUT_DIRECTORY)
set(multiValueArgs FILES)
cmake_parse_arguments(_generate "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
if(NOT _generate_OUTPUT_DIRECTORY)
set(_generate_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
# Set the necessary variables, generate the real files, and append the output
# to the final update script. Ideally, the template files should have a '.in'
# suffix so that we can keep the template file and the final file available
# for debugging, but for some reason it was decided to not use the '.in'
# suffix for template files so now we're stuck with it.
set(MODULE_PATHNAME "$libdir/timescaledb-${_generate_VERSION}")
set(LOADER_PATHNAME "$libdir/timescaledb")
# Process all files. They are template files and should end with '.in' but for
# some reason they do not, so we append '.gen' instead to indicate generated
# files.
set(_result_files)
foreach(_file ${_generate_FILES})
configure_file(${_file} ${_file}.gen @ONLY)
list(APPEND _result_files ${_file}.gen)
endforeach()
# Concatenate the real files into the update file.
message(STATUS "Generating script ${_generate_SCRIPT}")
concatenate_files(${_generate_OUTPUT_DIRECTORY}/${_generate_SCRIPT}
${_result_files})
install(FILES ${_generate_OUTPUT_DIRECTORY}/${_generate_SCRIPT}
DESTINATION "${PG_SHAREDIR}/extension")
endfunction()
# generate_downgrade_script(<options>)
#
# Create a downgrade script from a source version to a target version. To figure
# out what files are necessary, the ScriptFiles.cmake manifest is read from the
# target version. If that file does not exist in the target version, the
# manifest in the current version is used, but it is assumed that files are only
# added. This situation only occur in the first version where we start to
# generate downgrade scripts and in this case files were only added, so we can
# safely ignore them.
#
# SOURCE_VERSION <version>
#
# Version to generate downgrade script from.
#
# TARGET_VERSION <version>
#
# Version to generate downgrade script to.
#
# OUTPUT_DIRECTORY <dir>
#
# Output directory for script file. Defaults to CMAKE_CURRENT_BINARY_DIR.
#
# INPUT_DIRECTORY <dir>
#
# Input directory for downgrade files. Defaults to CMAKE_CURRENT_SOURCE_DIR.
#
# FILES <file> ...
#
# Files to include, in order, when generating the downgrade script.
#
# The downgrade script is generated by creating a new file of the format
# "timescaledb--<current>--<version>.sql" consisting of the sequence of files:
#
# 1. Generated prolog from the target version
# 2. Generated downgrade files from the source version
# 3. Generated epilog from the target version
#
# The files provided are assumed to be configure templates and configure_files
# will be run on them with the following variables set:
#
# LOADER_PATHNAME: Pathname to loader shared library. This is the same as in the
# update.
#
# MODULE_PATHNAME: Pathname to timescale extension of the version being
# dowgraded to. This can be used to load "old" functions from the correct
# library.
function(generate_downgrade_script)
set(options)
set(oneValueArgs SOURCE_VERSION TARGET_VERSION OUTPUT_DIRECTORY
INPUT_DIRECTORY FILES)
cmake_parse_arguments(_downgrade "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
if(NOT _downgrade_OUTPUT_DIRECTORY)
set(_downgrade_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
if(NOT _downgrade_INPUT_DIRECTORY)
set(_downgrade_INPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endif()
foreach(_downgrade_file ${_downgrade_FILES})
if(NOT EXISTS ${_downgrade_INPUT_DIRECTORY}/${_downgrade_file})
message(FATAL_ERROR "No downgrade file ${_downgrade_file} found!")
endif()
endforeach()
# Fetch manifest with list of files for the prolog and epilog from the target
# version, if we are in a version that supports downgrades. Otherwise, take
# the one in the current version.
#
# We have a specific exception where we allow a missing manifest for the first
# version that supports downgrades and assume that the files to include are
# the same in the target version as the current one.
if(_downgrade_TARGET_VERSION VERSION_GREATER 2.3)
git_versioned_get(VERSION ${_downgrade_TARGET_VERSION} FILES
${CMAKE_SOURCE_DIR}/cmake/ScriptFiles.cmake)
else()
file(MAKE_DIRECTORY
"${CMAKE_BINARY_DIR}/v${_downgrade_TARGET_VERSION}/cmake")
file(COPY "${CMAKE_SOURCE_DIR}/cmake/ScriptFiles.cmake"
DESTINATION "${CMAKE_BINARY_DIR}/v${_downgrade_TARGET_VERSION}/cmake")
endif()
# This will include the variables in this scope, but not in the parent scope
# so we can read them locally without affecting the parent scope.
include(
${CMAKE_BINARY_DIR}/v${_downgrade_TARGET_VERSION}/cmake/ScriptFiles.cmake)
set(_downgrade_PRE_FILES ${PRE_DOWNGRADE_FILES})
set(_downgrade_POST_FILES "${PRE_INSTALL_FUNCTION_FILES};${SOURCE_FILES}" ${SET_POST_UPDATE_STAGE}
${POST_UPDATE_FILES} ${UNSET_UPDATE_STAGE})
# Fetch epilog from target version.
git_versioned_get(
VERSION
${_downgrade_TARGET_VERSION}
FILES
${_downgrade_POST_FILES}
RESULT_FILES
_epilog_files
IGNORE_ERRORS)
foreach(_downgrade_file ${_downgrade_PRE_FILES})
get_filename_component(_downgrade_filename ${_downgrade_file} NAME)
configure_file(${_downgrade_file} ${_downgrade_INPUT_DIRECTORY}/${_downgrade_filename} COPYONLY)
list(APPEND _files ${_downgrade_INPUT_DIRECTORY}/${_downgrade_filename})
endforeach()
foreach(_downgrade_file ${_downgrade_FILES})
list(APPEND _files ${_downgrade_INPUT_DIRECTORY}/${_downgrade_file})
endforeach()
list(APPEND _files ${_epilog_files})
# Save the current PROJECT_VERSION_MOD
set(SAVED_PROJECT_VERSION_MOD ${PROJECT_VERSION_MOD})
# To use PROJECT_VERSION_MOD variable as a target version in downgrade scripts
# we should set it as the DOWNGRADE_TO_VERSION because it means the target version
# when executing the downgrade scripts
set(PROJECT_VERSION_MOD ${DOWNGRADE_TO_VERSION})
generate_script(
VERSION
${_downgrade_TARGET_VERSION}
SCRIPT
timescaledb--${_downgrade_SOURCE_VERSION}--${_downgrade_TARGET_VERSION}.sql
OUTPUT_DIRECTORY
${_downgrade_OUTPUT_DIRECTORY}
FILES
${_files})
# Restore the original PROJECT_VERSION_MOD
set(PROJECT_VERSION_MOD ${SAVED_PROJECT_VERSION_MOD})
endfunction()