-
Notifications
You must be signed in to change notification settings - Fork 16
/
ExportTools.cmake
344 lines (315 loc) · 13.6 KB
/
ExportTools.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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# ============================================================================
# Copyright (c) 2011-2012 University of Pennsylvania
# Copyright (c) 2013-2014 Andreas Schuh
# All rights reserved.
#
# See COPYING file for license information or visit
# http://opensource.andreasschuh.com/cmake-basis/download.html#license
# ============================================================================
##############################################################################
# @file ExportTools.cmake
# @brief Functions and macros for the export of targets.
#
# @ingroup CMakeTools
##############################################################################
if (__BASIS_EXPORTIMPORTTOOLS_INCLUDED)
return ()
else ()
set (__BASIS_EXPORTIMPORTTOOLS_INCLUDED TRUE)
endif ()
## @addtogroup CMakeUtilities
# @{
# ----------------------------------------------------------------------------
## @brief Add target to export set.
#
# Targets of a subproject are added to the export set named after the subproject
# itself. All other targets, including in particular those of other modules,
# are added to the export set named after the top-level project.
#
# @param[out] EXPORT_OPTION Export option for install() command including
# the EXPORT option name. Set to an empty string
# if target is not installed.
# @param[in] TARGET_UID UID of target to be exported.
# @param[in] IS_TEST Whether given target is a test executable or library.
# @param[in] ARGN Optional installation destinations.
function (basis_add_export_target EXPORT_OPTION TARGET_UID IS_TEST)
if (PROJECT_IS_SUBPROJECT)
set (EXPORT_SET "${PROJECT_NAME}")
else ()
set (EXPORT_SET "${TOPLEVEL_PROJECT_NAME}")
endif ()
if (IS_TEST)
basis_set_project_property (PROJECT "${EXPORT_SET}" APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
else ()
basis_set_project_property (PROJECT "${EXPORT_SET}" APPEND PROPERTY EXPORT_TARGETS "${TARGET_UID}")
if (ARGN)
basis_set_project_property (PROJECT "${EXPORT_SET}" APPEND PROPERTY INSTALL_EXPORT_TARGETS "${TARGET_UID}")
endif ()
set (EXPORT_OPT "EXPORT;${EXPORT_SET}" PARENT_SCOPE)
endif ()
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add target to custom export set.
#
# Targets of a subproject are added to the export set named after the subproject
# itself. All other targets, including in particular those of other modules,
# are added to the export set named after the top-level project.
#
# @param[in] TARGET_UID UID of target to add to the export set.
# @param[in] IS_TEST Whether given target is a test executable or library.
function (basis_add_custom_export_target TARGET_UID IS_TEST)
if (PROJECT_IS_SUBPROJECT)
set (EXPORT_SET "${PROJECT_NAME}")
else ()
set (EXPORT_SET "${TOPLEVEL_PROJECT_NAME}")
endif ()
if (IS_TEST)
basis_set_project_property (PROJECT "${EXPORT_SET}" APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
else ()
basis_set_project_property (PROJECT "${EXPORT_SET}" APPEND PROPERTY CUSTOM_EXPORT_TARGETS "${TARGET_UID}")
endif ()
endfunction ()
# ----------------------------------------------------------------------------
## @brief Get soname of object file.
#
# This function extracts the soname from object files in the ELF format on
# systems where the objdump command is available. On all other systems,
# an empty string is returned.
#
# @param [out] SONAME The soname of the object file.
# @param [in] OBJFILE Object file in ELF format.
function (basis_get_soname SONAME OBJFILE)
# get absolute path of object file
basis_get_target_uid (TARGET_UID ${OBJFILE})
if (TARGET TARGET_UID)
basis_get_target_location (OBJFILE ${TARGET_UID} ABSOLUTE)
string (REPLACE "$<${BASIS_GE_CONFIG}>" "${CMAKE_BUILD_TYPE}" OBJFILE "${OBJFILE}")
else ()
get_filename_component (OBJFILE "${OBJFILE}" ABSOLUTE)
endif ()
# usually CMake did this already
find_program (CMAKE_OBJDUMP NAMES objdump DOC "The objdump command")
# run objdump and extract soname
execute_process (
COMMAND ${CMAKE_OBJDUMP} -p "${OBJFILE}"
COMMAND sed -n "-e's/^[[:space:]]*SONAME[[:space:]]*//p'"
RESULT_VARIABLE STATUS
OUTPUT_VARIABLE SONAME_OUT
ERROR_QUIET
)
# return
if (STATUS EQUAL 0)
set (${SONAME} "${SONAME_OUT}" PARENT_SCOPE)
else ()
set (${SONAME} "" PARENT_SCOPE)
endif ()
endfunction ()
# ----------------------------------------------------------------------------
## @brief Generate header of exports file.
function (basis_export_header CODE)
set (C "# Generated by BASIS\n\n")
set (C "${C}if (\"\${CMAKE_MAJOR_VERSION}.\${CMAKE_MINOR_VERSION}\" LESS 2.8)\n")
set (C "${C} message (FATAL_ERROR \"CMake >= 2.8.4 required\")\n")
set (C "${C}endif ()\n")
set (C "${C}cmake_policy (PUSH)\n")
set (C "${C}cmake_policy (VERSION 2.8.4)\n")
set (C "${C}#----------------------------------------------------------------\n")
set (C "${C}# Generated CMake target import file.\n")
set (C "${C}#----------------------------------------------------------------\n")
set (C "${C}\n# Commands may need to know the format version.\n")
set (C "${C}set (CMAKE_IMPORT_FILE_VERSION 1)\n")
set (${CODE} "${C}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add code to compute prefix relative to @c INSTALL_CONFIG_DIR.
function (basis_export_prefix CODE)
set (C "\n# Compute the installation prefix relative to this file.\n")
set (C "${C}get_filename_component (_IMPORT_PREFIX \"\${CMAKE_CURRENT_LIST_FILE}\" PATH)\n")
string (REGEX REPLACE "[/\\]" ";" DIRS "${INSTALL_CONFIG_DIR}")
foreach (D IN LISTS DIRS)
set (C "${C}get_filename_component (_IMPORT_PREFIX \"\${_IMPORT_PREFIX}\" PATH)\n")
endforeach ()
set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add code to add import targets.
function (basis_export_import_targets CODE)
set (C)
foreach (T IN LISTS ARGN)
basis_get_fully_qualified_target_uid (UID "${T}")
set (C "${C}\n# Create import target \"${UID}\"\n")
get_target_property (BASIS_TYPE ${T} "BASIS_TYPE")
if (BASIS_TYPE MATCHES "EXECUTABLE")
set (C "${C}add_executable (${UID} IMPORTED)\n")
elseif (BASIS_TYPE MATCHES "LIBRARY|MODULE|MEX")
if (BASIS_TYPE MATCHES "MEX|MCC")
set (TYPE SHARED)
elseif (BASIS_TYPE MATCHES "SCRIPT")
set (TYPE UNKNOWN)
else ()
string (REGEX REPLACE "_LIBRARY" "" TYPE "${BASIS_TYPE}")
endif ()
set (C "${C}add_library (${UID} ${TYPE} IMPORTED)\n")
else ()
message (FATAL_ERROR "Cannot export target ${T} of type ${BASIS_TYPE}! Use NOEXPORT option.")
endif ()
set (C "${C}set_target_properties (${UID} PROPERTIES BASIS_TYPE \"${BASIS_TYPE}\")\n")
endforeach ()
set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add code to set properties of imported targets for build tree.
function (basis_export_build_properties CODE)
set (C)
if (CMAKE_BUILD_TYPE)
set (CONFIG "${CMAKE_BUILD_TYPE}")
else ()
set (CONFIG "noconfig")
endif ()
string (TOUPPER "${CONFIG}" CONFIG_U)
foreach (T IN LISTS ARGN)
basis_get_fully_qualified_target_uid (UID "${T}")
get_target_property (BASIS_TYPE ${T} BASIS_TYPE)
set (C "${C}\n# Import target \"${UID}\" for configuration \"${CONFIG}\"\n")
set (C "${C}set_property (TARGET ${UID} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${CONFIG_U})\n")
set (C "${C}set_target_properties (${UID} PROPERTIES\n")
if (BASIS_TYPE MATCHES "SCRIPT|LIBRARY|MEX")
get_target_property (LANGUAGE ${T} LANGUAGE)
if (LANGUAGE)
set (C "${C} IMPORTED_LINK_INTERFACE_LANGUAGES_${CONFIG_U} \"${LANGUAGE}\"\n")
endif ()
get_target_property (LINK_DEPENDS ${T} LINK_DEPENDS)
set (LINK_UIDS)
foreach (LINK_DEPEND IN LISTS LINK_DEPENDS)
basis_get_fully_qualified_target_uid (LINK_UID ${LINK_DEPEND})
list (APPEND LINK_UIDS "${LINK_UID}")
endforeach ()
set (C "${C} IMPORTED_LINK_INTERFACE_LIBRARIES_${CONFIG_U} \"${LINK_UIDS}\"\n")
endif ()
basis_get_target_location (LOCATION ${T} ABSOLUTE)
string (REPLACE "$<${BASIS_GE_CONFIG}>" "${CONFIG}" LOCATION "${LOCATION}")
set (C "${C} IMPORTED_LOCATION_${CONFIG_U} \"${LOCATION}\"\n")
set (C "${C} )\n")
endforeach ()
set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add code to set properties of imported targets for installation.
function (basis_export_install_properties CODE)
set (C)
if (CMAKE_BUILD_TYPE)
set (CONFIG "${CMAKE_BUILD_TYPE}")
else ()
set (CONFIG "noconfig")
endif ()
string (TOUPPER "${CONFIG}" CONFIG_U)
foreach (T IN LISTS ARGN)
basis_get_fully_qualified_target_uid (UID "${T}")
get_target_property (BASIS_TYPE ${T} BASIS_TYPE)
set (C "${C}\n# Import target \"${UID}\" for configuration \"${CONFIG}\"\n")
set (C "${C}set_property (TARGET ${UID} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${CONFIG_U})\n")
set (C "${C}set_target_properties (${UID} PROPERTIES\n")
basis_get_target_location (LOCATION ${T} POST_INSTALL_RELATIVE)
set (C "${C} IMPORTED_LOCATION_${CONFIG_U} \"\${_IMPORT_PREFIX}/${LOCATION}\"\n")
if (BASIS_TYPE MATCHES "SCRIPT|LIBRARY|MEX")
get_target_property (LANGUAGE ${T} LANGUAGE)
if (LANGUAGE)
set (C "${C} IMPORTED_LINK_INTERFACE_LANGUAGES_${CONFIG_U} \"${LANGUAGE}\"\n")
endif ()
get_target_property (LINK_DEPENDS ${T} LINK_DEPENDS)
set (LINK_UIDS)
foreach (LINK_DEPEND IN LISTS LINK_DEPENDS)
basis_get_fully_qualified_target_uid (LINK_UID ${LINK_DEPEND})
list (APPEND LINK_UIDS "${LINK_UID}")
endforeach ()
set (C "${C} IMPORTED_LINK_INTERFACE_LIBRARIES_${CONFIG_U} \"${LINK_UIDS}\"\n")
endif ()
set (C "${C} )\n")
endforeach ()
set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add footer of exports file.
function (basis_export_footer CODE)
set (C "\n# Cleanup temporary variables.\n")
set (C "${C}set (_IMPORT_PREFIX)\n")
set (C "${C}\n# Commands beyond this point should not need to know the version.\n")
set (C "${C}set (CMAKE_IMPORT_FILE_VERSION)\n")
set (C "${C}cmake_policy (POP)\n")
set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## @brief Export all targets added by basis_add_* commands.
function (basis_export_targets)
# parse arguments
CMAKE_PARSE_ARGUMENTS (ARGN "" "FILE;CUSTOM_FILE" "" ${ARGN})
if (NOT ARGN_FILE)
message (FATAL_ERROR "basis_export_targets(): FILE option is required!")
endif ()
if (NOT ARGN_CUSTOM_FILE)
message (FATAL_ERROR "basis_export_targets(): CUSTOM_FILE option is required!")
endif ()
if (IS_ABSOLUTE ${ARGN_FILE})
message (FATAL_ERROR "basis_export_targets(): FILE option argument must be a relative path!")
endif ()
if (IS_ABSOLUTE ${ARGN_CUSTOM_FILE})
message (FATAL_ERROR "basis_export_targets(): CUSTOM_FILE option argument must be a relative path!")
endif ()
# --------------------------------------------------------------------------
# export non-custom targets
basis_get_project_property (EXPORT_TARGETS)
if (EXPORT_TARGETS)
if (BASIS_USE_TARGET_UIDS AND BASIS_USE_FULLY_QUALIFIED_UIDS)
set (NAMESPACE_OPT)
elseif (TOPLEVEL_PROJECT_NAMESPACE_CMAKE)
set (NAMESPACE_OPT NAMESPACE "${TOPLEVEL_PROJECT_NAMESPACE_CMAKE}.")
endif ()
export (
TARGETS ${EXPORT_TARGETS}
FILE "${PROJECT_BINARY_DIR}/${ARGN_FILE}"
${NAMESPACE_OPT}
)
basis_get_project_property (INSTALL_EXPORT_TARGETS)
if (INSTALL_EXPORT_TARGETS)
foreach (COMPONENT "${BASIS_RUNTIME_COMPONENT}" "${BASIS_LIBRARY_COMPONENT}")
install (
EXPORT "${PROJECT_NAME}"
DESTINATION "${INSTALL_CONFIG_DIR}"
FILE "${ARGN_FILE}"
COMPONENT "${COMPONENT}"
${NAMESPACE_OPT}
)
endforeach ()
endif ()
endif ()
# --------------------------------------------------------------------------
# export custom targets and/or test targets
basis_get_project_property (CUSTOM_EXPORT_TARGETS)
basis_get_project_property (TEST_EXPORT_TARGETS)
if (CUSTOM_EXPORT_TARGETS OR TEST_EXPORT_TARGETS)
# write exports for build tree
basis_export_header (CONTENT)
basis_export_import_targets (CONTENT ${CUSTOM_EXPORT_TARGETS} ${TEST_EXPORT_TARGETS})
basis_export_build_properties (CONTENT ${CUSTOM_EXPORT_TARGETS} ${TEST_EXPORT_TARGETS})
basis_export_footer (CONTENT)
file (WRITE "${PROJECT_BINARY_DIR}/${ARGN_CUSTOM_FILE}" "${CONTENT}")
unset (CONTENT)
# write exports for installation - excluding test targets
if (CUSTOM_EXPORT_TARGETS)
set (INSTALL_EXPORT_FILE "${PROJECT_BINARY_DIR}/CMakeFiles/Export/${INSTALL_CONFIG_DIR}/${ARGN_CUSTOM_FILE}")
basis_export_header (CONTENT)
basis_export_prefix (CONTENT)
basis_export_import_targets (CONTENT ${CUSTOM_EXPORT_TARGETS})
basis_export_install_properties (CONTENT ${CUSTOM_EXPORT_TARGETS})
basis_export_footer (CONTENT)
file (WRITE "${INSTALL_EXPORT_FILE}" "${CONTENT}")
unset (CONTENT)
install (
FILES "${INSTALL_EXPORT_FILE}"
DESTINATION "${INSTALL_CONFIG_DIR}"
)
endif ()
endif ()
endfunction ()
## @}
# end of Doxygen group