-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFixupDependencies.cmake
229 lines (225 loc) · 13.5 KB
/
FixupDependencies.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
# fixup_dependencies.cmake
#
# Mark J. Olah ([email protected] DOT edu)
# Copyright 2014-2017
# Licensed under the Apache License, Version 2.0
# https://www.apache.org/licenses/LICENSE-2.0
# See: LICENSE file
#
# This tool automatically works to find and copy necessary dependencies to the build or install tree to allow packaging of
# cross-compiled packages together with their necessary dependencies. This function works for both the build and install trees.
# Correctly handles dependency resolution for Linux and Win64 cross-build Tartgets. On linux the dependency resolution algorithm is
# aware RPATH and RUNPATH variables and their respective implications for library search order.
#
# Respects the following CMake variables:
# * CMAKE_SYSROOT
# * CMAKE_FIND_ROOT_PATH
# * CMAKE_STAGING_PREFIX
# * OPT_FIXUP_DEPENDENCIES_VERBOSE - On=Verbose output if
# * OPT_FIXUP_DEPENDENCIES_SILENT - On=Errors and warnings only
#
# Options:
# COPY_GCC_LIBS - [UNIX only] [default: off] Copy libraries provided by GCC [i.e. libgcc_s libstdc++, etc.]. This implies
# Setting RPATH for targets to the COPU_DESTINATION. This is only possibly useful if deploying to
# systems with and older GCC than was used to build them.
# COPY_GLIBC_LIBS - [UNIX only] [DANGEROUS} [default: off] Copy libraries provided glibc [i.e. libc, ld-linux-x86_64 etc.].
# Also copy in Glibc libraries. WARNING. This is almost certainly going to cause problems as
# the version of libc and ld-linux-x86_64 must match exactly. For now this is disabled.
#
# LINK_INSTALLED_LIBS - [default: off] [WIN32 only] [deprecated: does not seem to be viable option] instead of copying into current directory make a symlink if dep us under in the install_prefix
#
# Single argument keywords:
# COPY_DESTINATION - [optional] [default: 'lib'] Relative path from the install_prefix in which to copy dependencies.
# PARENT_LIB - [optional] [default: False] The library that will load this library possibly via dlopen. We can use the RPATH or RUNPATH from this
# ELF file to correctly find libraries that will be provided on the system path.
# For fixing up matlab MEx files, this should be ${MATLAB_ROOT}/bin/${MATLAB_ARCH}/MATLAB or equivalent.
# FIXUP_INSTALL_SCRIPT_TEMPLATE - [optional] [default: FixupInstallTargetDependencies.cmake look for script in ../Templates or ./Templates]
# FIXUP_BUILD_SCRIPT_TEMPLATE - [optional] [default: FixupBuildTargetDependencies.cmake look for script in ../Templates or ./Templates]
# EXPORT_BUILD_TREE - [default: off] Fixup the libraries for the build-tree export
# EXPORT_INSTALL_TREE - [default: on] Fixup the libraries for the install-tree export
# Multi-argument keywords:
# TARGETS - List of targets to copy dependencies for. These targets should share all of the other keyword properties.
# If multiple targets require different options to fixup_dependencies, then multiple independent calls should be made.
# TARGET_DESTINATIONS - [suggested but optional] [default try to find_file in install prefix]. List of relative paths
# to look for the installed target under the install prefix. This is the same value as given to DESTINATION keyword of install(TARGETS).
# PROVIDED_LIB_DIRS - Absolute paths to directories containing libraries that will be provided by the system or parent program for dynamic imports.
# Libraries found in these directories will not be copied as they are assumed provided.
# PROVIDED_LIBS - Names (with of without extensions) of provided libraries that should not be copied.
# SEARCH_LIB_DIRS - Additional directories to search for libraries. These libraries will be copied into COPY_DESTINATION
# SEARCH_LIB_DIR_SUFFIXES - Additional suffixes to check for
#
#
set(_fixup_dependencies_install_PATH ${CMAKE_CURRENT_LIST_DIR})
function(fixup_dependencies)
cmake_parse_arguments(FIXUP "COPY_GCC_LIBS;COPY_GLIBC_LIBS;LINK_INSTALLED_LIBS"
"COPY_DESTINATION;PARENT_LIB;INSTALL_SCRIPT_TEMPLATE;BUILD_SCRIPT_TEMPLATE;EXPORT_BUILD_TREE;EXPORT_INSTALL_TREE"
"TARGETS;TARGET_DESTINATIONS;PROVIDED_LIB_DIRS;PROVIDED_LIBS;SEARCH_LIB_DIRS;SEARCH_LIB_DIR_SUFFIXES" ${ARGN})
if(NOT OPT_FIXUP_DEPENDENCIES_SILENT)
set(msg_hdr "[fixup_dependencies:configure-phase]:")
endif()
if(UNIX AND NOT FIXUP_COPY_DESTINATION)
set(FIXUP_COPY_DESTINATION "lib") #Must be relative to INSTALL_PREFIX
endif()
if(NOT FIXUP_TARGET_DESTINATIONS)
set(FIXUP_TARGET_DESTINATIONS) #Signal to use find_file in FixupTarget script
endif()
if(NOT FIXUP_INSTALL_SCRIPT_TEMPLATE)
find_file(FIXUP_INSTALL_SCRIPT_TEMPLATE_PATH FixupInstallTargetDependenciesScript.cmake.in
PATHS ${_fixup_dependencies_install_PATH}/Templates ${_fixup_dependencies_install_PATH}/../Templates
NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
mark_as_advanced(FIXUP_INSTALL_SCRIPT_TEMPLATE_PATH)
if(NOT FIXUP_INSTALL_SCRIPT_TEMPLATE_PATH)
message(FATAL_ERROR "${msg_hdr} Cannot find FixupInstallTargetDependenciesScript.cmake.in")
endif()
set(FIXUP_INSTALL_SCRIPT_TEMPLATE ${FIXUP_INSTALL_SCRIPT_TEMPLATE_PATH})
endif()
if(NOT DEFINED FIXUP_EXPORT_BUILD_TREE)
set(FIXUP_EXPORT_BUILD_TREE Off)
endif()
if(NOT DEFINED FIXUP_EXPORT_INSTALL_TREE)
set(FIXUP_EXPORT_INSTALL_TREE On)
endif()
if(FIXUP_EXPORT_BUILD_TREE AND NOT FIXUP_BUILD_SCRIPT_TEMPLATE)
find_file(FIXUP_BUILD_SCRIPT_TEMPLATE_PATH FixupBuildTargetDependenciesScript.cmake.in
PATHS ${_fixup_dependencies_install_PATH}/Templates ${_fixup_dependencies_install_PATH}/../Templates
NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
mark_as_advanced(FIXUP_BUILD_SCRIPT_TEMPLATE_PATH)
if(NOT FIXUP_BUILD_SCRIPT_TEMPLATE_PATH)
message(FATAL_ERROR "${msg_hdr} Cannot find FixupBuildTargetDependenciesScript.cmake.in")
endif()
set(FIXUP_BUILD_SCRIPT_TEMPLATE ${FIXUP_BUILD_SCRIPT_TEMPLATE_PATH})
endif()
if(NOT FIXUP_COPY_SYSTEM_LIBS AND OPT_INSTALL_SYSTEM_DEPENDENCIES)
set(FIXUP_COPY_SYSTEM_LIBS True)
endif()
#Normal variables WIN32 UNIX, etc. are not respected in install scrtipts
#(apparently due to toolchain file not being used at install time?)
if(WIN32)
set(FIXUP_TARGET_OS WIN32)
elseif(UNIX AND NOT APPLE)
set(FIXUP_TARGET_OS UNIX)
else()
set(FIXUP_TARGET_OS OSX)
endif()
if(FIXUP_PROVIDED_LIBS)
set(_provided)
foreach(_lib IN LISTS FIXUP_PROVIDED_LIBS)
get_filename_component(_name ${_lib} NAME_WE)
list(APPEND _provided ${_name})
endforeach()
set(FIXUP_PROVIDED_LIBS ${_provided})
if(WIN32)
string(TOLOWER "${PROVIDED_LIBS}" PROVIDED_LIBS) #Case insensitive-match on windows
endif()
endif()
#Append system libraries to FIXUP_PROVIDED_LIBS
set(FIXUP_GCC_PROVIDED_LIBS libstdc++ libgfortran libgcc_s libatomic libgomp libquadmath libmpx libmpxwrappers)
if(UNIX AND NOT APPLE)
#libc and ld-linux-x86-64 loader must match versions exactly with system loader since
#the loader location is hard-coded as an absolute path, it cannot be made relocatable without using system
#loader which implied also using system libc.
if(NOT FIXUP_COPY_GCC_LIBS)
list(APPEND FIXUP_PROVIDED_LIBS ${FIXUP_GCC_PROVIDED_LIBS}) #gcc libs
endif()
if(NOT FIXUP_COPY_GLIBC_LIBS)
list(APPEND FIXUP_PROVIDED_LIBS libdl libpthread libcrypt librt libm) #glibc libs
endif()
list(APPEND FIXUP_PROVIDED_LIBS libc ld-linux-x86-64) #loader
elseif(WIN32)
list(APPEND FIXUP_PROVIDED_LIBS kernel32 user32 msvcrt advapi32 ws2_32 msvcp120 msvcr120 msvcp120 dbghelp oleaut32 ole32 psapi powrprof)
endif()
#FIXUP_DEFAULT_LIBRARY_SEARCH_SUFFIXS - generally matches the CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES
set(FIXUP_DEFAULT_LIBRARY_SEARCH_SUFFIXS)
if(UNIX AND NOT APPLE)
set(_suffixs ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) #dirs of libraries provided by host system
foreach(sdir IN LISTS _suffixs)
if(sdir MATCHES "^/(.*)")
list(APPEND FIXUP_DEFAULT_LIBRARY_SEARCH_SUFFIXS ${CMAKE_MATCH_1})
else()
list(APPEND FIXUP_DEFAULT_LIBRARY_SEARCH_SUFFIXS ${sdir})
endif()
endforeach()
unset(_suffixs)
list(APPEND FIXUP_DEFAULT_LIBRARY_SEARCH_SUFFIXS lib lib64)
elseif(WIN32)
set(_suffixs ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) #dirs of libraries provided by host system
foreach(_suffix IN LISTS _suffixs)
if(IS_ABSOLUTE ${_suffix})
get_filename_component(_suffix ${_suffix} REALPATH)
set(_found)
foreach(pre IN ITEMS ${CMAKE_FIND_ROOT_PATH})
get_filename_component(pre ${pre} REALPATH)
if(_suffix MATCHES "^${pre}/(.*)")
list(APPEND FIXUP_DEFAULT_LIBRARY_SEARCH_SUFFIXS ${CMAKE_MATCH_1})
set(_found True)
break()
endif()
endforeach()
if(NOT _found AND ${_suffix} MATCHES "^/(.*)")
list(APPEND FIXUP_DEFAULT_LIBRARY_SEARCH_SUFFIXS ${CMAKE_MATCH_1})
endif()
unset(_found)
else()
list(APPEND FIXUP_DEFAULT_LIBRARY_SEARCH_SUFFIXS ${_suffix})
endif()
endforeach()
unset(_suffixs)
list(APPEND FIXUP_DEFAULT_LIBRARY_SEARCH_SUFFIXS bin usr/bin lib usr/lib)
endif()
set(FIXUP_SCRIPT_OUTPUT_DIR ${CMAKE_BINARY_DIR}/FixupDependencies) #Directory where fixup-scripts will be written.
foreach(FIXUP_TARGET IN LISTS FIXUP_TARGETS)
if(NOT TARGET ${FIXUP_TARGET})
message(FATAL_ERROR "${msg_hdr} Got invalid target: ${FIXUP_TARGET}")
endif()
get_target_property(FIXUP_TARGET_TYPE ${FIXUP_TARGET} TYPE)
if(NOT (${FIXUP_TARGET_TYPE} MATCHES SHARED_LIBRARY OR ${FIXUP_TARGET_TYPE} MATCHES EXECUTABLE) )
message(STATUS "${msg_hdr} Skipping non-shared target: ${FIXUP_TARGET}")
else()
if(FIXUP_EXPORT_INSTALL_TREE)
set(FIXUP_INSTALL_SCRIPT ${FIXUP_SCRIPT_OUTPUT_DIR}/Fixup-Install-${FIXUP_TARGET}.cmake)
set(FIXUP_INSTALL_SCRIPT_GEN_TMP ${FIXUP_SCRIPT_OUTPUT_DIR}/gen.tmp/Fixup-Install-${FIXUP_TARGET}.cmake.gen) #temporary file to use for immediate generation
configure_file(${FIXUP_INSTALL_SCRIPT_TEMPLATE} ${FIXUP_INSTALL_SCRIPT_GEN_TMP} @ONLY)
file(GENERATE OUTPUT ${FIXUP_INSTALL_SCRIPT} INPUT ${FIXUP_INSTALL_SCRIPT_GEN_TMP})
install(SCRIPT ${FIXUP_INSTALL_SCRIPT})
get_target_property(script ${FIXUP_TARGET} FIXUP_INSTALL_SCRIPT)
if(NOT OPT_FIXUP_DEPENDENCIES_SILENT)
if(script)
message(STATUS "${msg_hdr} Re-generated install-tree dependency fixup script for target: ${FIXUP_TARGET}")
else()
message(STATUS "${msg_hdr} Generated install-tree dependency fixup script for target: ${FIXUP_TARGET}")
endif()
endif()
set_target_properties(${FIXUP_TARGET} PROPERTIES FIXUP_INSTALL_SCRIPT ${FIXUP_INSTALL_SCRIPT}) #Mark as fixup-ready.
endif()
if(FIXUP_EXPORT_BUILD_TREE)
get_target_property(_libs ${FIXUP_TARGET} LINK_LIBRARIES)
if(NOT _libs)
set(_libs)
endif()
set(FIXUP_BUILD_TARGET_LINK_DIRECTORIES)
foreach(_lib IN LISTS _libs)
if(TARGET ${_lib})
get_target_property(_type ${_lib} TYPE)
if(_type STREQUAL SHARED_LIBRARY OR _type STREQUAL EXECUTABLE)
list(APPEND FIXUP_BUILD_TARGET_LINK_DIRECTORIES "$<TARGET_FILE_DIR:${_lib}>")
endif()
elseif(IS_ABSOLUTE ${_lib})
list(APPEND FIXUP_BUILD_TARGET_LINK_DIRECTORIES ${_lib})
endif()
endforeach()
set(FIXUP_BUILD_SCRIPT ${FIXUP_SCRIPT_OUTPUT_DIR}/Fixup-Build-${FIXUP_TARGET}.cmake)
set(FIXUP_BUILD_SCRIPT_GEN_TMP ${FIXUP_SCRIPT_OUTPUT_DIR}/gen.tmp/Fixup-Build-${FIXUP_TARGET}.cmake.gen) #temporary file to use for immediate generation
if(UNIX AND NOT APPLE AND FIXUP_COPY_GCC_LIBS AND FIXUP_EXPORT_BUILD_TREE)
list(APPEND FIXUP_PROVIDED_LIBS ${FIXUP_GCC_PROVIDED_LIBS}) #Prevent fixing-up gcc libs in build tree. Risking breaking gcc and other tools.
endif()
configure_file(${FIXUP_BUILD_SCRIPT_TEMPLATE} ${FIXUP_BUILD_SCRIPT_GEN_TMP} @ONLY)
file(GENERATE OUTPUT ${FIXUP_BUILD_SCRIPT} INPUT ${FIXUP_BUILD_SCRIPT_GEN_TMP})
set(_build_target "FixupDependencies-${FIXUP_TARGET}")
add_custom_command(TARGET ${FIXUP_TARGET} POST_BUILD COMMAND cmake ARGS -P ${FIXUP_BUILD_SCRIPT} COMMENT "FIXUP Build tree dependencies of target: ${FIXUP_TARGET}")
if(NOT OPT_FIXUP_DEPENDENCIES_SILENT)
message(STATUS "${msg_hdr} Generated build-tree dependency fixup script for target: ${FIXUP_TARGET}")
endif()
endif()
endif()
endforeach()
endfunction()