PageRenderTime 147ms CodeModel.GetById 40ms app.highlight 75ms RepoModel.GetById 26ms app.codeStats 0ms

/admin/mac/macdeploy.py

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