Subversion Repositories Scribus

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
12446 pierre 1
#
2
# Somehow "backport" CMakeIngestOSXBundleLibraries.cmake
3
# rename in ScribusIngestOSXBundleLibraries.cmake to not conflict if already present
4
#
5
# Only for the Mac build.
6
#
7
# Depends on OS tools:
8
#   otool
9
#   install_name_tool
10
#
11
# This script ingests libraries and frameworks into an existing .app bundle and
12
# then uses install_name_tool to fixup the references to the newly embedded
13
# libraries so that they all refer to each other via "@executable_path."
14
#
15
# The main intent (and simplifying assumption used for developing the script)
16
# is to have a single executable .app bundle that becomes "self-contained" by
17
# copying all non-system libs that it depends on into itself. The further
18
# assumption is that all such dependencies are simple .dylib shared library
19
# files or Mac Framework libraries.
20
#
21
# This script can be used as part of the build via ADD_CUSTOM_COMMAND, or used
22
# only during make install via INSTALL SCRIPT.
23
#
24
IF(NOT DEFINED input_file)
25
  MESSAGE(FATAL_ERROR "
26
${CMAKE_CURRENT_LIST_FILE}(${CMAKE_CURRENT_LIST_LINE}): error: Variable input_file is not defined.
27
 
28
Use a command line like this to use this script:
29
  cmake \"-Dinput_file=filename\" \"-Dextra_libs=/path/to/lib1;/path/to/lib2\" \"-Dlib_path=/path/to/unqualified/libs\" -P \"${CMAKE_CURRENT_LIST_FILE}\"
30
 
31
'input_file' should be the main executable inside a Mac bundle directory structure.
32
For example, use 'bin/paraview.app/Contents/MacOS/paraview' from a ParaView binary dir.
33
 
34
'extra_libs' should be a semi-colon separated list of full path names to extra libraries
35
to copy into the bundle that cannot be derived from otool -L output. For example, you may
36
also want to fixup dynamically loaded plugins from your build tree and copy them into the
37
bundle.
38
 
39
'lib_path' should be the path where to find libraries referenced without a path name in
40
otool -L output.
41
 
42
")
43
ENDIF(NOT DEFINED input_file)
44
 
45
SET(eol_char "E")
46
 
47
IF(APPLE)
48
  SET(dep_tool "otool")
49
  SET(dep_cmd_args "-L")
50
  SET(dep_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$")
51
ENDIF(APPLE)
52
 
53
 
54
MESSAGE("")
55
MESSAGE("# Script \"${CMAKE_CURRENT_LIST_FILE}\" running...")
56
MESSAGE("")
57
MESSAGE("input_file: '${input_file}'")
58
MESSAGE("extra_libs: '${extra_libs}'")
59
MESSAGE("lib_path: '${lib_path}'")
60
MESSAGE("")
61
 
62
GET_FILENAME_COMPONENT(input_file_full "${input_file}" ABSOLUTE)
63
MESSAGE("input_file_full: '${input_file_full}'")
64
 
65
GET_FILENAME_COMPONENT(bundle "${input_file_full}/../../.." ABSOLUTE)
66
MESSAGE("bundle: '${bundle}'")
67
 
68
 
69
FIND_PROGRAM(dep_cmd ${dep_tool})
70
 
71
 
72
MACRO(APPEND_UNIQUE au_list_var au_value)
73
  SET(${au_list_var} ${${au_list_var}} "${au_value}")
74
ENDMACRO(APPEND_UNIQUE)
75
 
76
 
77
MACRO(GATHER_DEPENDENTS gd_target gd_dependents_var)
78
  EXECUTE_PROCESS(
79
    COMMAND ${dep_cmd} ${dep_cmd_args} ${gd_target}
80
    OUTPUT_VARIABLE dep_tool_ov
81
    )
82
 
83
  STRING(REGEX REPLACE ";" "\\\\;" dep_candidates "${dep_tool_ov}")
84
  STRING(REGEX REPLACE "\n" "${eol_char};" dep_candidates "${dep_candidates}")
85
 
86
  SET(${gd_dependents_var} "")
87
 
88
  FOREACH(candidate ${dep_candidates})
89
  IF("${candidate}" MATCHES "${dep_regex}")
90
    STRING(REGEX REPLACE "${dep_regex}" "\\1" raw_item "${candidate}")
91
    STRING(REGEX REPLACE "${dep_regex}" "\\2" raw_compat_version "${candidate}")
92
    STRING(REGEX REPLACE "${dep_regex}" "\\3" raw_current_version "${candidate}")
93
 
94
    SET(item "${raw_item}")
95
 
96
    STRING(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}")
97
    STRING(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}")
98
    STRING(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}")
99
 
100
    STRING(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}")
101
    STRING(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}")
102
    STRING(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}")
103
 
104
#MESSAGE("${raw_item} - compat ${raw_compat_version} - current ${raw_current_version}")
105
    APPEND_UNIQUE("${gd_dependents_var}" "${item}")
106
  ELSE("${candidate}" MATCHES "${dep_regex}")
107
    IF("${candidate}" STREQUAL "${gd_target}:${eol_char}")
108
#MESSAGE("info: ignoring target name...")
109
    ELSE("${candidate}" STREQUAL "${gd_target}:${eol_char}")
110
      MESSAGE("error: candidate='${candidate}'")
111
    ENDIF("${candidate}" STREQUAL "${gd_target}:${eol_char}")
112
  ENDIF("${candidate}" MATCHES "${dep_regex}")
113
  ENDFOREACH(candidate)
114
ENDMACRO(GATHER_DEPENDENTS)
115
 
116
 
117
MESSAGE("Gathering dependent libraries for '${input_file_full}'...")
118
GATHER_DEPENDENTS("${input_file_full}" deps)
119
MESSAGE("")
120
 
121
 
122
# Order lexicographically:
123
#
124
LIST(SORT deps)
125
 
126
 
127
# Split into separate lists, "system" "embedded" and "nonsystem" libraries.
128
# System libs are assumed to be available on all target runtime Macs and do not
129
# need to be copied/fixed-up by this script. Embedded libraries are assumed to
130
# be in the bundle and fixed-up already. Only non-system, non-embedded libs
131
# need copying and fixing up...
132
#
133
SET(system_deps "")
134
SET(embedded_deps "")
135
SET(nonsystem_deps "")
136
 
137
FOREACH(d ${deps})
138
  SET(d_is_embedded_lib 0)
139
  SET(d_is_system_lib 0)
140
 
141
  IF("${d}" MATCHES "^(/System/Library|/usr/lib)")
142
    SET(d_is_system_lib 1)
143
  ELSE("${d}" MATCHES "^(/System/Library|/usr/lib)")
144
    IF("${d}" MATCHES "^@executable_path")
145
      SET(d_is_embedded_lib 1)
146
    ENDIF("${d}" MATCHES "^@executable_path")
147
  ENDIF("${d}" MATCHES "^(/System/Library|/usr/lib)")
148
 
149
  IF(d_is_system_lib)
150
    SET(system_deps ${system_deps} "${d}")
151
  ELSE(d_is_system_lib)
152
    IF(d_is_embedded_lib)
153
      SET(embedded_deps ${embedded_deps} "${d}")
154
    ELSE(d_is_embedded_lib)
155
      SET(nonsystem_deps ${nonsystem_deps} "${d}")
156
    ENDIF(d_is_embedded_lib)
157
  ENDIF(d_is_system_lib)
158
ENDFOREACH(d)
159
 
160
MESSAGE("")
161
MESSAGE("system_deps:")
162
FOREACH(d ${system_deps})
163
  MESSAGE("${d}")
164
ENDFOREACH(d ${system_deps})
165
 
166
MESSAGE("")
167
MESSAGE("embedded_deps:")
168
FOREACH(d ${embedded_deps})
169
  MESSAGE("${d}")
170
ENDFOREACH(d ${embedded_deps})
171
 
172
MESSAGE("")
173
MESSAGE("nonsystem_deps:")
174
FOREACH(d ${nonsystem_deps})
175
  MESSAGE("${d}")
176
ENDFOREACH(d ${nonsystem_deps})
177
 
178
MESSAGE("")
179
 
180
 
181
MACRO(COPY_LIBRARY_INTO_BUNDLE clib_bundle clib_libsrc clib_dstlibs clib_fixups)
182
#
183
# If the source library is a framework, copy just the shared lib bit of the framework
184
# into the bundle under "${clib_bundle}/Contents/Frameworks" - if it is just a dylib
185
# copy it into the same directory with the main bundle executable under
186
# "${clib_bundle}/Contents/MacOS"
187
#
188
  IF("${clib_libsrc}" MATCHES ".framework/.*/.*/.*")
189
    SET(fw_src "/Library/Frameworks/${clib_libsrc}")
190
    GET_FILENAME_COMPONENT(fw_srcdir "${fw_src}/../../.." ABSOLUTE)
191
    GET_FILENAME_COMPONENT(fwdirname "${fw_srcdir}" NAME)
192
    STRING(REGEX REPLACE "^(.*)\\.framework$" "\\1" fwname "${fwdirname}")
193
    STRING(REGEX REPLACE "^.*/${fwname}\\.framework/(.*)$" "\\1" fwlibname "${clib_libsrc}")
194
    SET(fw_dstdir "${clib_bundle}/Contents/Frameworks/${fwdirname}")
195
 
196
#    MESSAGE("")
197
#    MESSAGE("fwdirname: '${fwdirname}'")
198
#    MESSAGE("fwname: '${fwname}'")
199
#    MESSAGE("fwlibname: '${fwlibname}'")
200
#    MESSAGE("fw_src: '${fw_src}'")
201
#    MESSAGE("fw_srcdir: '${fw_srcdir}'")
202
#    MESSAGE("fw_dstdir: '${fw_dstdir}'")
203
#    MESSAGE("new_name: '@executable_path/../Frameworks/${fwdirname}/${fwlibname}'")
204
#    MESSAGE("")
205
 
206
    MESSAGE("Copying ${fw_srcdir} into bundle...")
207
 
208
# This command copies the *entire* framework recursively:
209
#
210
#    EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_directory
211
#      "${fw_srcdir}" "${fw_dstdir}"
212
#    )
213
 
214
# This command copies just the main shared lib of the framework:
215
# (This technique will not work for frameworks that have necessary
216
# resource or auxiliary files...)
217
#
218
    EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy
219
      "${fw_src}" "${fw_dstdir}/${fwlibname}"
220
    )
221
 
222
    EXECUTE_PROCESS(COMMAND install_name_tool
223
      -id "@executable_path/../Frameworks/${fwdirname}/${fwlibname}"
224
      "${clib_bundle}/Contents/Frameworks/${fwdirname}/${fwlibname}"
225
    )
226
    SET(${clib_dstlibs} ${${clib_dstlibs}}
227
      "${clib_bundle}/Contents/Frameworks/${fwdirname}/${fwlibname}"
228
    )
229
    SET(${clib_fixups} ${${clib_fixups}}
230
      "-change"
231
      "${clib_libsrc}"
232
      "@executable_path/../Frameworks/${fwdirname}/${fwlibname}"
233
    )
234
  ELSE("${clib_libsrc}" MATCHES ".framework/.*/.*/.*")
235
    IF("${clib_libsrc}" MATCHES "/")
236
      SET(clib_libsrcfull "${clib_libsrc}")
237
    ELSE("${clib_libsrc}" MATCHES "/")
238
      SET(clib_libsrcfull "${lib_path}/${clib_libsrc}")
239
      IF(NOT EXISTS "${clib_libsrcfull}")
240
        MESSAGE(FATAL_ERROR "error: '${clib_libsrcfull}' does not exist...")
241
      ENDIF(NOT EXISTS "${clib_libsrcfull}")
242
    ENDIF("${clib_libsrc}" MATCHES "/")
243
 
244
    GET_FILENAME_COMPONENT(dylib_src "${clib_libsrcfull}" ABSOLUTE)
245
    GET_FILENAME_COMPONENT(dylib_name "${dylib_src}" NAME)
246
    SET(dylib_dst "${clib_bundle}/Contents/MacOS/${dylib_name}")
247
 
248
#    MESSAGE("dylib_src: ${dylib_src}")
249
#    MESSAGE("dylib_dst: ${dylib_dst}")
250
#    MESSAGE("new_name: '@executable_path/${dylib_name}'")
251
 
252
    MESSAGE("Copying ${dylib_src} into bundle...")
253
    EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy
254
      "${dylib_src}" "${dylib_dst}")
255
    EXECUTE_PROCESS(COMMAND install_name_tool
256
      -id "@executable_path/${dylib_name}"
257
      "${dylib_dst}"
258
    )
259
    SET(${clib_dstlibs} ${${clib_dstlibs}}
260
      "${dylib_dst}"
261
    )
262
    SET(${clib_fixups} ${${clib_fixups}}
263
      "-change"
264
      "${clib_libsrc}"
265
      "@executable_path/${dylib_name}"
266
    )
267
  ENDIF("${clib_libsrc}" MATCHES ".framework/.*/.*/.*")
268
ENDMACRO(COPY_LIBRARY_INTO_BUNDLE)
269
 
270
 
271
# Copy dependent "nonsystem" libraries into the bundle:
272
#
273
MESSAGE("Copying dependent libraries into bundle...")
274
SET(srclibs ${nonsystem_deps} ${extra_libs})
275
SET(dstlibs "")
276
SET(fixups "")
277
FOREACH(d ${srclibs})
278
  COPY_LIBRARY_INTO_BUNDLE("${bundle}" "${d}" dstlibs fixups)
279
ENDFOREACH(d)
280
 
281
MESSAGE("")
282
MESSAGE("dstlibs='${dstlibs}'")
283
MESSAGE("")
284
MESSAGE("fixups='${fixups}'")
285
MESSAGE("")
286
 
287
 
288
# Fixup references to copied libraries in the main bundle executable and in the
289
# copied libraries themselves:
290
#
291
IF(NOT "${fixups}" STREQUAL "")
292
  MESSAGE("Fixing up references...")
293
  FOREACH(d ${dstlibs} "${input_file_full}")
294
    MESSAGE("fixing up references in: '${d}'")
295
    EXECUTE_PROCESS(COMMAND install_name_tool ${fixups} "${d}")
296
  ENDFOREACH(d)
297
  MESSAGE("")
298
ENDIF(NOT "${fixups}" STREQUAL "")
299
 
300
 
301
# List all references to eyeball them and make sure they look right:
302
#
303
MESSAGE("Listing references...")
304
FOREACH(d ${dstlibs} "${input_file_full}")
305
  EXECUTE_PROCESS(COMMAND otool -L "${d}")
306
  MESSAGE("")
307
ENDFOREACH(d)
308
MESSAGE("")
309
 
310
 
311
# Output file:
312
#
313
GET_FILENAME_COMPONENT(script_name "${CMAKE_CURRENT_LIST_FILE}" NAME)
314
FILE(WRITE "${input_file_full}_${script_name}" "# Script \"${CMAKE_CURRENT_LIST_FILE}\" completed.\n")
315
MESSAGE("")
316
MESSAGE("# Script \"${CMAKE_CURRENT_LIST_FILE}\" completed.")
317
MESSAGE("")
318