/admin/mac/macdeploy.py

http://github.com/tomahawk-player/tomahawk · Python · 605 lines · 465 code · 80 blank · 60 comment · 74 complexity · f3e84be992c94cd07d0ebf8b9016c30e MD5 · raw file

  1. #!/usr/bin/python
  2. # This file is part of Tomahawk.
  3. # It was inspired in large part by the macdeploy script in Clementine.
  4. #
  5. # Clementine is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # Clementine is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with Clementine. If not, see <http://www.gnu.org/licenses/>.
  17. import os
  18. import re
  19. import subprocess
  20. import commands
  21. import sys
  22. import glob
  23. TARGET_NAME="tomahawk"
  24. FRAMEWORK_SEARCH_PATH=[
  25. '/Library/Frameworks',
  26. os.path.join(os.environ['HOME'], 'Library/Frameworks')
  27. ]
  28. LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/opt/vlc/lib', '/usr/local/Cellar/gettext/0.19.2/lib', '.']
  29. VLC_PLUGINS=[
  30. 'libattachment_plugin.dylib',
  31. #'libaccess_avio_plugin.dylib',
  32. #'libaccess_fake_plugin.dylib',
  33. 'libftp_plugin.dylib',
  34. 'libhttp_plugin.dylib',
  35. 'libhttplive_plugin.dylib',
  36. 'libimem_plugin.dylib',
  37. #'libaccess_mmap_plugin.dylib',
  38. 'libaccess_mms_plugin.dylib',
  39. 'libaccess_realrtsp_plugin.dylib',
  40. 'libtcp_plugin.dylib',
  41. 'libudp_plugin.dylib',
  42. 'libcdda_plugin.dylib',
  43. 'libfilesystem_plugin.dylib',
  44. 'libqtcapture_plugin.dylib',
  45. 'librtp_plugin.dylib',
  46. 'libzip_plugin.dylib',
  47. 'liba52tofloat32_plugin.dylib',
  48. 'liba52tospdif_plugin.dylib',
  49. 'libaudio_format_plugin.dylib',
  50. 'libaudiobargraph_a_plugin.dylib',
  51. 'libchorus_flanger_plugin.dylib',
  52. #'libconverter_fixed_plugin.dylib',
  53. 'libdolby_surround_decoder_plugin.dylib',
  54. 'libdtstofloat32_plugin.dylib',
  55. 'libdtstospdif_plugin.dylib',
  56. 'libequalizer_plugin.dylib',
  57. 'libheadphone_channel_mixer_plugin.dylib',
  58. 'libmono_plugin.dylib',
  59. 'libmpgatofixed32_plugin.dylib',
  60. 'libnormvol_plugin.dylib',
  61. 'libparam_eq_plugin.dylib',
  62. 'libscaletempo_plugin.dylib',
  63. 'libsimple_channel_mixer_plugin.dylib',
  64. 'libspatializer_plugin.dylib',
  65. 'libtrivial_channel_mixer_plugin.dylib',
  66. 'libugly_resampler_plugin.dylib',
  67. 'libfloat_mixer_plugin.dylib',
  68. #'libspdif_mixer_plugin.dylib',
  69. #'libtrivial_mixer_plugin.dylib',
  70. #'libaout_file_plugin.dylib',
  71. 'libauhal_plugin.dylib',
  72. 'liba52_plugin.dylib',
  73. 'libadpcm_plugin.dylib',
  74. 'libaes3_plugin.dylib',
  75. 'libaraw_plugin.dylib',
  76. 'libavcodec_plugin.dylib',
  77. 'libcc_plugin.dylib',
  78. 'libcdg_plugin.dylib',
  79. 'libdts_plugin.dylib',
  80. 'libfaad_plugin.dylib',
  81. #'libfake_plugin.dylib',
  82. 'libflac_plugin.dylib',
  83. #'libfluidsynth_plugin.dylib',
  84. #'libinvmem_plugin.dylib',
  85. 'liblpcm_plugin.dylib',
  86. 'libmpeg_audio_plugin.dylib',
  87. 'libpng_plugin.dylib',
  88. 'librawvideo_plugin.dylib',
  89. 'libspeex_plugin.dylib',
  90. 'libspudec_plugin.dylib',
  91. 'libtheora_plugin.dylib',
  92. 'libtwolame_plugin.dylib',
  93. 'libvorbis_plugin.dylib',
  94. #'libgestures_plugin.dylib',
  95. #'libhotkeys_plugin.dylib',
  96. #'libmotion_plugin.dylib',
  97. #'libnetsync_plugin.dylib',
  98. #'libsignals_plugin.dylib',
  99. 'libaiff_plugin.dylib',
  100. 'libasf_plugin.dylib',
  101. 'libau_plugin.dylib',
  102. #'libavformat_plugin.dylib',
  103. 'libavi_plugin.dylib',
  104. 'libdemux_cdg_plugin.dylib',
  105. 'libdemuxdump_plugin.dylib',
  106. 'libdiracsys_plugin.dylib',
  107. 'libes_plugin.dylib',
  108. 'libflacsys_plugin.dylib',
  109. 'liblive555_plugin.dylib',
  110. 'libmkv_plugin.dylib',
  111. 'libmod_plugin.dylib',
  112. 'libmp4_plugin.dylib',
  113. 'libmpc_plugin.dylib',
  114. 'libmpgv_plugin.dylib',
  115. 'libnsc_plugin.dylib',
  116. 'libnsv_plugin.dylib',
  117. 'libnuv_plugin.dylib',
  118. 'libogg_plugin.dylib',
  119. 'libplaylist_plugin.dylib',
  120. 'libps_plugin.dylib',
  121. 'libpva_plugin.dylib',
  122. 'librawaud_plugin.dylib',
  123. 'librawdv_plugin.dylib',
  124. 'librawvid_plugin.dylib',
  125. 'libreal_plugin.dylib',
  126. 'libsmf_plugin.dylib',
  127. 'libts_plugin.dylib',
  128. 'libtta_plugin.dylib',
  129. 'libty_plugin.dylib',
  130. 'libvc1_plugin.dylib',
  131. 'libvoc_plugin.dylib',
  132. 'libwav_plugin.dylib',
  133. 'libxa_plugin.dylib',
  134. 'libfolder_plugin.dylib',
  135. 'libtaglib_plugin.dylib',
  136. #'libaudioscrobbler_plugin.dylib',
  137. 'libdummy_plugin.dylib',
  138. 'libexport_plugin.dylib',
  139. #'libfreetype_plugin.dylib',
  140. #'libgnutls_plugin.dylib',
  141. 'liblogger_plugin.dylib',
  142. 'liblua_plugin.dylib',
  143. #'libosd_parser_plugin.dylib',
  144. #'libquartztext_plugin.dylib',
  145. #'libstats_plugin.dylib',
  146. 'libvod_rtsp_plugin.dylib',
  147. 'libxml_plugin.dylib',
  148. #'libxtag_plugin.dylib',
  149. 'libi420_rgb_mmx_plugin.dylib',
  150. 'libi420_yuy2_mmx_plugin.dylib',
  151. 'libi422_yuy2_mmx_plugin.dylib',
  152. #'libmemcpymmx_plugin.dylib',
  153. #'libmemcpymmxext_plugin.dylib',
  154. 'libmux_asf_plugin.dylib',
  155. 'libmux_avi_plugin.dylib',
  156. 'libmux_dummy_plugin.dylib',
  157. 'libmux_mp4_plugin.dylib',
  158. 'libmux_mpjpeg_plugin.dylib',
  159. 'libmux_ogg_plugin.dylib',
  160. 'libmux_ps_plugin.dylib',
  161. 'libmux_ts_plugin.dylib',
  162. 'libmux_wav_plugin.dylib',
  163. 'libpacketizer_copy_plugin.dylib',
  164. 'libpacketizer_dirac_plugin.dylib',
  165. 'libpacketizer_flac_plugin.dylib',
  166. 'libpacketizer_h264_plugin.dylib',
  167. 'libpacketizer_mlp_plugin.dylib',
  168. 'libpacketizer_mpeg4audio_plugin.dylib',
  169. 'libpacketizer_mpeg4video_plugin.dylib',
  170. 'libpacketizer_mpegvideo_plugin.dylib',
  171. 'libpacketizer_vc1_plugin.dylib',
  172. 'libi420_rgb_sse2_plugin.dylib',
  173. 'libi420_yuy2_sse2_plugin.dylib',
  174. 'libi422_yuy2_sse2_plugin.dylib',
  175. 'libdecomp_plugin.dylib',
  176. #'libstream_filter_rar_plugin.dylib',
  177. 'librecord_plugin.dylib',
  178. #'libvisual_plugin.dylib',
  179. 'libsecuretransport_plugin.dylib'
  180. ]
  181. VLC_SEARCH_PATH=[
  182. '/usr/local/opt/vlc/lib/vlc/plugins/',
  183. ]
  184. QT_PLUGINS = [
  185. # 'crypto/libqca-ossl.dylib',
  186. 'platforms/libqcocoa.dylib',
  187. 'sqldrivers/libqsqlite.dylib',
  188. 'imageformats/libqgif.dylib',
  189. 'imageformats/libqico.dylib',
  190. 'imageformats/libqjpeg.dylib',
  191. 'imageformats/libqsvg.dylib',
  192. 'imageformats/libqmng.dylib',
  193. ]
  194. SNORE_PLUGINS = [
  195. 'libsnore_backend_growl.so',
  196. 'libsnore_backend_osxnotificationcenter.so',
  197. ]
  198. TOMAHAWK_PLUGINS = [
  199. 'lib%s_account_xmpp.dylib' % TARGET_NAME,
  200. 'lib%s_account_google.so' % TARGET_NAME,
  201. 'lib%s_account_zeroconf.so' % TARGET_NAME,
  202. 'lib%s_account_hatchet.so' % TARGET_NAME,
  203. 'lib%s_infoplugin_adium.so' % TARGET_NAME,
  204. 'lib%s_infoplugin_charts.so' % TARGET_NAME,
  205. # 'lib%s_infoplugin_discogs.so' % TARGET_NAME,
  206. 'lib%s_infoplugin_echonest.so' % TARGET_NAME,
  207. 'lib%s_infoplugin_hypem.so' % TARGET_NAME,
  208. # 'lib%s_infoplugin_musicbrainz.so' % TARGET_NAME,
  209. 'lib%s_infoplugin_musixmatch.so' % TARGET_NAME,
  210. 'lib%s_infoplugin_newreleases.so' % TARGET_NAME,
  211. # 'lib%s_infoplugin_rovi.so' % TARGET_NAME,
  212. 'lib%s_infoplugin_snorenotify.so' % TARGET_NAME,
  213. 'lib%s_infoplugin_spotify.so' % TARGET_NAME,
  214. 'lib%s_viewpage_dashboard.so' % TARGET_NAME,
  215. # 'lib%s_viewpage_networkactivity.so' % TARGET_NAME,
  216. 'lib%s_viewpage_charts.so' % TARGET_NAME,
  217. 'lib%s_viewpage_newreleases.so' % TARGET_NAME,
  218. 'lib%s_viewpage_whatsnew_0_8.so' % TARGET_NAME,
  219. ]
  220. QT_PLUGINS_SEARCH_PATH=[
  221. '/usr/local/opt/qt5/plugins',
  222. ]
  223. SNORE_PLUGINS_SEARCH_PATH=[
  224. '/usr/local/opt/snorenotify/lib/plugins/libsnore-qt5',
  225. ]
  226. class Error(Exception):
  227. pass
  228. class CouldNotFindQtPluginErrorFindFrameworkError(Error):
  229. pass
  230. class InstallNameToolError(Error):
  231. pass
  232. class CouldNotFindFrameworkError(Error):
  233. pass
  234. class CouldNotFindQtPluginError(Error):
  235. pass
  236. class CouldNotFindSnorePluginError(Error):
  237. pass
  238. class CouldNotFindVLCPluginError(Error):
  239. pass
  240. class CouldNotFindScriptPluginError(Error):
  241. pass
  242. if len(sys.argv) < 2:
  243. print 'Usage: %s <bundle.app>' % sys.argv[0]
  244. bundle_dir = sys.argv[1]
  245. bundle_name = os.path.basename(bundle_dir).split('.')[0]
  246. commands = []
  247. framework_paths = []
  248. binary_dir = os.path.join(bundle_dir, 'Contents', 'MacOS')
  249. frameworks_dir = os.path.join(bundle_dir, 'Contents', 'Frameworks')
  250. commands.append(['mkdir', '-p', frameworks_dir])
  251. vlcplugins_dir = os.path.join(frameworks_dir, 'vlc', 'plugins')
  252. commands.append(['mkdir', '-p', vlcplugins_dir])
  253. snoreplugins_dir = os.path.join(binary_dir, 'libsnore')
  254. commands.append(['mkdir', '-p', snoreplugins_dir])
  255. resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources')
  256. commands.append(['mkdir', '-p', resources_dir])
  257. plugins_dir = os.path.join(bundle_dir, 'Contents', 'qt-plugins')
  258. binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name)
  259. fixed_libraries = []
  260. fixed_frameworks = []
  261. def GetBrokenLibraries(binary):
  262. #print "Checking libs for binary: %s" % binary
  263. output = subprocess.Popen(['otool', '-L', binary], stdout=subprocess.PIPE).communicate()[0]
  264. broken_libs = {
  265. 'frameworks': [],
  266. 'libs': []}
  267. for line in [x.split(' ')[0].lstrip() for x in output.split('\n')[1:]]:
  268. #print "Checking line: %s" % line
  269. if not line: # skip empty lines
  270. continue
  271. if os.path.basename(binary) == os.path.basename(line):
  272. #print "mnope %s-%s" % (os.path.basename(binary), os.path.basename(line))
  273. continue
  274. if re.match(r'^\s*/System/', line):
  275. continue # System framework
  276. elif re.match(r'^\s*/usr/lib/', line):
  277. #print "unix style system lib"
  278. continue # unix style system library
  279. elif re.match(r'Breakpad', line):
  280. continue # Manually added by cmake.
  281. elif re.match(r'^\s*@executable_path', line) or re.match(r'^\s*@loader_path', line) and not re.match(r'^\s*@loader_path/../lib', line):
  282. # Potentially already fixed library
  283. if '.framework' in line:
  284. relative_path = os.path.join(*line.split('/')[3:])
  285. if not os.path.exists(os.path.join(frameworks_dir, relative_path)):
  286. broken_libs['frameworks'].append(relative_path)
  287. else:
  288. relative_path = os.path.join(*line.split('/')[1:])
  289. #print "RELPATH %s %s" % (relative_path, os.path.join(binary_dir, relative_path))
  290. if not os.path.exists(os.path.join(binary_dir, relative_path)):
  291. broken_libs['libs'].append(relative_path)
  292. elif re.search(r'\w+\.framework', line):
  293. broken_libs['frameworks'].append(line)
  294. else:
  295. broken_libs['libs'].append(line)
  296. return broken_libs
  297. def FindFramework(path):
  298. for search_path in FRAMEWORK_SEARCH_PATH:
  299. abs_path = os.path.join(search_path, path)
  300. if os.path.exists(abs_path):
  301. return abs_path
  302. # replace rpath with /Library/Frameworks for Sparkle
  303. abs_path = path.replace("@rpath/", "/Library/Frameworks/")
  304. if os.path.exists(abs_path):
  305. return abs_path
  306. raise CouldNotFindFrameworkError(path)
  307. def FindLibrary(path):
  308. if os.path.exists(path):
  309. return path
  310. for search_path in LIBRARY_SEARCH_PATH:
  311. abs_path = os.path.join(search_path, path)
  312. if os.path.exists(abs_path):
  313. return abs_path
  314. else: # try harder---look for lib name in library folders
  315. newpath = os.path.join(search_path,os.path.basename(path))
  316. if os.path.exists(newpath):
  317. return newpath
  318. return ""
  319. #raise CouldNotFindFrameworkError(path)
  320. def FixAllLibraries(broken_libs):
  321. for framework in broken_libs['frameworks']:
  322. FixFramework(framework)
  323. for lib in broken_libs['libs']:
  324. FixLibrary(lib)
  325. def FixFramework(path):
  326. if path in fixed_libraries:
  327. return
  328. else:
  329. fixed_libraries.append(path)
  330. abs_path = FindFramework(path)
  331. broken_libs = GetBrokenLibraries(abs_path)
  332. FixAllLibraries(broken_libs)
  333. new_path = CopyFramework(abs_path)
  334. id = os.sep.join(new_path.split(os.sep)[3:])
  335. FixFrameworkId(new_path, id)
  336. for framework in broken_libs['frameworks']:
  337. FixFrameworkInstallPath(framework, new_path)
  338. for library in broken_libs['libs']:
  339. FixLibraryInstallPath(library, new_path)
  340. def FixLibrary(path):
  341. if path in fixed_libraries or FindSystemLibrary(os.path.basename(path)) is not None:
  342. return
  343. else:
  344. fixed_libraries.append(path)
  345. abs_path = FindLibrary(path)
  346. if abs_path == "":
  347. print "Could not resolve %s, not fixing!" % path
  348. return
  349. broken_libs = GetBrokenLibraries(abs_path)
  350. FixAllLibraries(broken_libs)
  351. new_path = CopyLibrary(abs_path)
  352. FixLibraryId(new_path)
  353. for framework in broken_libs['frameworks']:
  354. FixFrameworkInstallPath(framework, new_path)
  355. for library in broken_libs['libs']:
  356. FixLibraryInstallPath(library, new_path)
  357. def FixVLCPlugin(abs_path):
  358. broken_libs = GetBrokenLibraries(abs_path)
  359. FixAllLibraries(broken_libs)
  360. #print "Copying plugin....%s %s %s" % (plugins_dir, subdir, os.path.join(abs_path.split('/')[-2:]))
  361. new_path = os.path.join(vlcplugins_dir, os.path.basename(abs_path))
  362. args = ['mkdir', '-p', os.path.dirname(new_path)]
  363. commands.append(args)
  364. args = ['ditto', '--arch=i386', '--arch=x86_64', abs_path, new_path]
  365. commands.append(args)
  366. args = ['chmod', 'u+w', new_path]
  367. commands.append(args)
  368. for framework in broken_libs['frameworks']:
  369. FixFrameworkInstallPath(framework, new_path)
  370. for library in broken_libs['libs']:
  371. FixLibraryInstallPath(library, new_path)
  372. def FixPlugin(abs_path, subdir):
  373. broken_libs = GetBrokenLibraries(abs_path)
  374. FixAllLibraries(broken_libs)
  375. new_path = CopyPlugin(abs_path, subdir)
  376. for framework in broken_libs['frameworks']:
  377. FixFrameworkInstallPath(framework, new_path)
  378. for library in broken_libs['libs']:
  379. FixLibraryInstallPath(library, new_path)
  380. def FixBinary(path):
  381. broken_libs = GetBrokenLibraries(path)
  382. FixAllLibraries(broken_libs)
  383. for framework in broken_libs['frameworks']:
  384. FixFrameworkInstallPath(framework, path)
  385. for library in broken_libs['libs']:
  386. FixLibraryInstallPath(library, path)
  387. def CopyLibrary(path):
  388. new_path = os.path.join(frameworks_dir, os.path.basename(path))
  389. args = ['ditto', '--arch=i386', '--arch=x86_64', path, new_path]
  390. commands.append(args)
  391. args = ['chmod', 'u+w', new_path]
  392. commands.append(args)
  393. return new_path
  394. def CopyPlugin(path, subdir):
  395. new_path = os.path.join(plugins_dir, subdir, os.path.basename(path))
  396. args = ['mkdir', '-p', os.path.dirname(new_path)]
  397. commands.append(args)
  398. args = ['ditto', '--arch=i386', '--arch=x86_64', path, new_path]
  399. commands.append(args)
  400. args = ['chmod', 'u+w', new_path]
  401. commands.append(args)
  402. return new_path
  403. def CopyFramework(path):
  404. parts = path.split(os.sep)
  405. for i, part in enumerate(parts):
  406. if re.match(r'\w+\.framework', part):
  407. full_path = os.path.join(frameworks_dir, *parts[i:-1])
  408. framework_name = part.split(".framework")[0]
  409. break
  410. if full_path in framework_paths:
  411. return os.path.join(full_path, parts[-1])
  412. framework_paths.append(full_path)
  413. args = ['mkdir', '-p', full_path]
  414. commands.append(args)
  415. args = ['ditto', '--arch=i386', '--arch=x86_64', path, full_path]
  416. commands.append(args)
  417. args = ['chmod', 'u+w', os.path.join(full_path, parts[-1])]
  418. commands.append(args)
  419. menu_nib = os.path.join(os.path.split(path)[0], 'Resources', 'qt_menu.nib')
  420. if os.path.exists(menu_nib):
  421. args = ['cp', '-rf', menu_nib, resources_dir]
  422. commands.append(args)
  423. # Fix framework structure for signing
  424. path_base_dir = os.path.join(os.path.split(path)[0], '..', '..')
  425. path_versions_dir = os.path.join(path_base_dir, 'Versions')
  426. if not os.path.exists(os.path.join(full_path, 'Versions', 'Current')):
  427. framework_base_dir = os.path.join(full_path, '..', '..')
  428. framework_versions_dir = os.path.join(framework_base_dir, 'Versions')
  429. versionParts = glob.glob(path_versions_dir+'/*')[0].split(os.sep)
  430. args = ['ln', '-s', versionParts[-1], framework_versions_dir+'/Current']
  431. commands.append(args)
  432. args = ['ln', '-s', 'Versions/Current/'+framework_name, framework_base_dir+'/'+framework_name]
  433. commands.append(args)
  434. args = ['ln', '-s', 'Versions/Current/Resources', framework_base_dir+'/Resources']
  435. commands.append(args)
  436. # Copy Contents/Info.plist to Resources/Info.plist if Resources/Info.plist does not exist
  437. # If Contents/Info.plist doesn't exist either, error out. If we actually see this, we can copy QtCore's Info.plist
  438. info_plist_in_resources = os.path.join(os.path.split(path)[0], '..', '..', 'Resources', 'Info.plist')
  439. if os.path.exists(info_plist_in_resources):
  440. info_plist_in_contents = os.path.join(os.path.split(path)[0], '..', '..', 'Resources', 'Info.plist')
  441. framework_resources_dir = os.path.join(framework_versions_dir, versionParts[-1], 'Resources')
  442. args = ['mkdir', '-p', framework_resources_dir]
  443. commands.append(args)
  444. if os.path.exists(info_plist_in_contents):
  445. args = ['cp', '-rf', info_plist_in_contents, framework_resources_dir]
  446. commands.append(args)
  447. args = ['chmod', '+rw', os.path.join(framework_resources_dir, 'Info.plist')]
  448. commands.append(args)
  449. else:
  450. print "%s: Framework does not contain an Info.plist file in Resources/ folder." % (path)
  451. sys.exit(-1)
  452. return os.path.join(full_path, parts[-1])
  453. def FixId(path, library_name):
  454. id = '@executable_path/../Frameworks/%s' % library_name
  455. args = ['install_name_tool', '-id', id, path]
  456. commands.append(args)
  457. def FixLibraryId(path):
  458. library_name = os.path.basename(path)
  459. FixId(path, library_name)
  460. def FixFrameworkId(path, id):
  461. FixId(path, id)
  462. def FixInstallPath(library_path, library, new_path):
  463. args = ['install_name_tool', '-change', library_path, new_path, library]
  464. commands.append(args)
  465. def FindSystemLibrary(library_name):
  466. for path in ['/lib', '/usr/lib']:
  467. full_path = os.path.join(path, library_name)
  468. if os.path.exists(full_path):
  469. return full_path
  470. return None
  471. def FixLibraryInstallPath(library_path, library):
  472. system_library = FindSystemLibrary(os.path.basename(library_path))
  473. if system_library is None:
  474. new_path = '@executable_path/../Frameworks/%s' % os.path.basename(library_path)
  475. FixInstallPath(library_path, library, new_path)
  476. else:
  477. FixInstallPath(library_path, library, system_library)
  478. def FixFrameworkInstallPath(library_path, library):
  479. parts = library_path.split(os.sep)
  480. for i, part in enumerate(parts):
  481. if re.match(r'\w+\.framework', part):
  482. full_path = os.path.join(*parts[i:])
  483. break
  484. new_path = '@executable_path/../Frameworks/%s' % full_path
  485. FixInstallPath(library_path, library, new_path)
  486. def FindQtPlugin(name):
  487. for path in QT_PLUGINS_SEARCH_PATH:
  488. if os.path.exists(path):
  489. if os.path.exists(os.path.join(path, name)):
  490. return os.path.join(path, name)
  491. raise CouldNotFindQtPluginError(name)
  492. def FindSnorePlugin(name):
  493. for path in SNORE_PLUGINS_SEARCH_PATH:
  494. if os.path.exists(path):
  495. if os.path.exists(os.path.join(path, name)):
  496. return os.path.join(path, name)
  497. raise CouldNotFindSnorePluginError(name)
  498. def FindVLCPlugin(name):
  499. for path in VLC_SEARCH_PATH:
  500. if os.path.exists(path):
  501. if os.path.exists(os.path.join(path, name)):
  502. return os.path.join(path, name)
  503. raise CouldNotFindVLCPluginError(name)
  504. FixBinary(binary)
  505. for plugin in VLC_PLUGINS:
  506. FixVLCPlugin(FindVLCPlugin(plugin))
  507. for plugin in TOMAHAWK_PLUGINS:
  508. FixPlugin(plugin, '../MacOS')
  509. for plugin in SNORE_PLUGINS:
  510. FixPlugin(FindSnorePlugin(plugin), '../lib/plugins/libsnore-qt5')
  511. try:
  512. FixPlugin('%s_crash_reporter' % TARGET_NAME, '../MacOS')
  513. except:
  514. print 'Failed to find %s_crash_reporter' % TARGET_NAME
  515. for plugin in QT_PLUGINS:
  516. FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
  517. if len(sys.argv) <= 2:
  518. print 'Would run %d commands:' % len(commands)
  519. for command in commands:
  520. print ' '.join(command)
  521. print 'OK?'
  522. raw_input()
  523. for command in commands:
  524. p = subprocess.Popen(command)
  525. os.waitpid(p.pid, 0)