forked from qt-creator/qt-creator
		
	Change-Id: Ia966c154e0827ce7dc0c4d0a3a45d234f82d0e90 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
		
			
				
	
	
		
			275 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			275 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python
 | |
| ################################################################################
 | |
| # Copyright (c) 2011 Nokia Corporation
 | |
| # All rights reserved.
 | |
| #
 | |
| # Redistribution and use in source and binary forms, with or without
 | |
| # modification, are permitted provided that the following conditions are met:
 | |
| #
 | |
| #   * Redistributions of source code must retain the above copyright notice,
 | |
| #     this list of conditions and the following disclaimer.
 | |
| #   * Redistributions in binary form must reproduce the above copyright notice,
 | |
| #     this list of conditions and the following disclaimer in the documentation
 | |
| #     and/or other materials provided with the distribution.
 | |
| #   * Neither the name of Nokia Corporation, nor the names of its contributors
 | |
| #     may be used to endorse or promote products derived from this software
 | |
| #     without specific prior written permission.
 | |
| #
 | |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | |
| # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 | |
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | |
| # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| ################################################################################
 | |
| 
 | |
| import os
 | |
| import sys
 | |
| import getopt
 | |
| import subprocess
 | |
| import re
 | |
| import string
 | |
| import shutil
 | |
| from glob import glob
 | |
| 
 | |
| ignoreErrors = False
 | |
| is_debug_build = False
 | |
| 
 | |
| def usage():
 | |
|     print "Usage: %s <creator_install_dir> [qmake_path]" %  os.path.basename(sys.argv[0])
 | |
| 
 | |
| def which(program):
 | |
|     def is_exe(fpath):
 | |
|         return os.path.exists(fpath) and os.access(fpath, os.X_OK)
 | |
| 
 | |
|     fpath, fname = os.path.split(program)
 | |
|     if fpath:
 | |
|         if is_exe(program):
 | |
|             return program
 | |
|         if sys.platform.startswith('win'):
 | |
|             if is_exe(program + ".exe"):
 | |
|                 return program  + ".exe"
 | |
|     else:
 | |
|         for path in os.environ["PATH"].split(os.pathsep):
 | |
|             exe_file = os.path.join(path, program)
 | |
|             if is_exe(exe_file):
 | |
|                 return exe_file
 | |
|             if sys.platform.startswith('win'):
 | |
|                 if is_exe(exe_file + ".exe"):
 | |
|                     return exe_file  + ".exe"
 | |
| 
 | |
|     return None
 | |
| 
 | |
| def check_debug(fpath):
 | |
|     # bootstrap exception
 | |
|     if fpath.endswith('QtCore4d.dll'):
 | |
|         return True
 | |
|     output = subprocess.check_output(['dumpbin', '/imports', fpath])
 | |
|     return output.find('QtCored4.dll') != -1
 | |
| 
 | |
| def check_debug_build(install_dir):
 | |
|     return check_debug(os.path.join(install_dir, 'bin', 'qtcreator.exe'))
 | |
| 
 | |
| def op_failed(details = None):
 | |
|     if details != None:
 | |
|         print details
 | |
|     if ignoreErrors == False:
 | |
|         print("Error: operation failed!")
 | |
|         sys.exit(2)
 | |
|     else:
 | |
|         print("Error: operation failed, but proceeding gracefully.")
 | |
| 
 | |
| def fix_rpaths_helper(chrpath_bin, install_dir, dirpath, filenames):
 | |
|     # patch file
 | |
|     for filename in filenames:
 | |
|         fpath = os.path.join(dirpath, filename)
 | |
|         relpath = os.path.relpath(install_dir+'/lib/qtcreator', dirpath)
 | |
|         command = [chrpath_bin, '-r', '$ORIGIN/'+relpath, fpath]
 | |
|         print fpath, ':', command
 | |
|         try:
 | |
|             subprocess.check_call(command)
 | |
|         except:
 | |
|             op_failed()
 | |
| 
 | |
| def check_unix_binary_exec_helper(dirpath, filename):
 | |
|     """ Whether a file is really a binary executable and not a script (unix only)"""
 | |
|     fpath = os.path.join(dirpath, filename)
 | |
|     if os.path.exists(fpath) and os.access(fpath, os.X_OK):
 | |
|         with open(fpath) as f:
 | |
|             return f.read(2) != "#!"
 | |
| 
 | |
| def check_unix_library_helper(dirpath, filename):
 | |
|     """ Whether a file is really a library and not a symlink (unix only)"""
 | |
|     fpath = os.path.join(dirpath, filename)
 | |
|     return filename.find('.so') != -1 and not os.path.islink(fpath)
 | |
| 
 | |
| def fix_rpaths(chrpath_bin, install_dir):
 | |
|     print "fixing rpaths..."
 | |
|     for dirpath, dirnames, filenames in os.walk(os.path.join(install_dir, 'bin')):
 | |
|         #TODO remove library_helper once all libs moved out of bin/ on linux
 | |
|         filenames = [filename for filename in filenames if check_unix_binary_exec_helper(dirpath, filename) or check_unix_library_helper(dirpath, filename)]
 | |
|         fix_rpaths_helper(chrpath_bin, install_dir, dirpath, filenames)
 | |
|     for dirpath, dirnames, filenames in os.walk(os.path.join(install_dir, 'lib')):
 | |
|         filenames = [filename for filename in filenames if check_unix_library_helper(dirpath, filename)]
 | |
|         fix_rpaths_helper(chrpath_bin, install_dir, dirpath, filenames)
 | |
| 
 | |
| def ignore_pattern_helper(filename):
 | |
|     ignore_patterns = ['.lib', '.pdb', '.exp', '.ilk', '.dll']
 | |
|     for ip in ignore_patterns:
 | |
|         if filename.endswith(ip):
 | |
|             return False
 | |
|     return True
 | |
| 
 | |
| def copy_ignore_patterns_helper(dir, filenames):
 | |
|     if not sys.platform.startswith('win'):
 | |
|         return filenames
 | |
| 
 | |
|     useful =  filter(ignore_pattern_helper, filenames)
 | |
|     if is_debug_build:
 | |
|         dlls = filter(lambda filename: filename.endswith('.dll') and check_debug(os.path.join(dir, filename)), filenames)
 | |
|     else:
 | |
|         dlls = filter(lambda filename:  filename.endswith('.dll') and not check_debug(os.path.join(dir, filename)), filenames)
 | |
| 
 | |
|     filenames = useful + dlls
 | |
|     return filenames
 | |
| 
 | |
| def copy_qt_libs(install_dir, qt_libs_dir, qt_plugin_dir, qt_import_dir, plugins, imports):
 | |
|     print "copying Qt libraries..."
 | |
| 
 | |
|     if sys.platform.startswith('win'):
 | |
|         libraries = glob(os.path.join(qt_libs_dir, '*.dll'))
 | |
|     else:
 | |
|         libraries = glob(os.path.join(qt_libs_dir, '*.so.*'))
 | |
| 
 | |
|     if sys.platform.startswith('win'):
 | |
|         dest = os.path.join(install_dir, 'bin')
 | |
|     else:
 | |
|         dest = os.path.join(install_dir, 'lib', 'qtcreator')
 | |
| 
 | |
|     if sys.platform.startswith('win'):
 | |
|         if is_debug_build:
 | |
|             libraries = filter(lambda library: check_debug(library), libraries)
 | |
|         else:
 | |
|             libraries = filter(lambda library: not check_debug(library), libraries)
 | |
| 
 | |
|     for library in libraries:
 | |
|         print library, '->', dest
 | |
|         if os.path.islink(library):
 | |
|             linkto = os.readlink(library)
 | |
|             try:
 | |
|                 os.symlink(linkto, os.path.join(dest, os.path.basename(library)))
 | |
|             except:
 | |
|                 op_failed("Link already exists!")
 | |
|         else:
 | |
|             shutil.copy(library, dest)
 | |
| 
 | |
|     copy_ignore_func = None
 | |
|     if sys.platform.startswith('win'):
 | |
|         copy_ignore_func = copy_ignore_patterns_helper
 | |
| 
 | |
|     print "Copying plugins:", plugins
 | |
|     for plugin in plugins:
 | |
|         target = os.path.join(install_dir, 'bin', plugin)
 | |
|         if (os.path.exists(target)):
 | |
|             shutil.rmtree(target)
 | |
|         shutil.copytree(os.path.join(qt_plugin_dir, plugin), target, ignore=copy_ignore_func, symlinks=True)
 | |
| 
 | |
|     print "Copying plugins:", imports
 | |
|     for qtimport in imports:
 | |
|         target = os.path.join(install_dir, 'bin', qtimport)
 | |
|         if (os.path.exists(target)):
 | |
|             shutil.rmtree(target)
 | |
|         shutil.copytree(os.path.join(qt_import_dir, qtimport), target, ignore=copy_ignore_func, symlinks=True)
 | |
| 
 | |
| def copy_translations(install_dir, qt_tr_dir, tr_catalogs):
 | |
|     langs=[]
 | |
|     tr_dir = os.path.join(install_dir, 'share', 'qtcreator', 'translations')
 | |
|     p = re.compile(r'_(.*).qm')
 | |
|     for dirpath, dirnames, filenames in os.walk(tr_dir):
 | |
|         for filename in filenames:
 | |
|             if filename.endswith('.qm') and string.find(filename, 'qtcreator_') != -1:
 | |
|                 lang = p.findall(filename)
 | |
|                 if lang != '':
 | |
|                     langs += lang
 | |
| 
 | |
|     print "copying translations..."
 | |
|     for lang in langs:
 | |
|         for catalog in tr_catalogs:
 | |
|             copy_file = "%s_%s.qm" % (catalog, lang)
 | |
|             copy_src = os.path.join(qt_tr_dir, copy_file)
 | |
|             copy_dst = os.path.join(tr_dir, copy_file)
 | |
|             print copy_src, '->', copy_dst
 | |
|             shutil.copy(copy_src, copy_dst)
 | |
| 
 | |
| def readQmakeVar(qmake_bin, var):
 | |
|     pipe = os.popen(' '.join([qmake_bin, '-query', var]))
 | |
|     return pipe.read().rstrip('\n')
 | |
| 
 | |
| def main():
 | |
|     generateMode = False
 | |
|     try:
 | |
|         opts, args = getopt.gnu_getopt(sys.argv[1:], 'hi', ['help', 'ignore-errors'])
 | |
|     except:
 | |
|         print str(err)
 | |
|         usage()
 | |
|         sys.exit(2)
 | |
|     for o, a in opts:
 | |
|         if o in ('-h', '--help'):
 | |
|             usage()
 | |
|             sys.exit(0)
 | |
|         if o in ('-i', '--ignore-errors'):
 | |
|             global ignoreErrors
 | |
|             ignoreErrors = True
 | |
|             print "Note: Ignoring all errors"
 | |
| 
 | |
|     if len(args) < 1:
 | |
|             usage()
 | |
|             sys.exit(2)
 | |
| 
 | |
|     install_dir=args[0]
 | |
| 
 | |
|     qmake_bin = 'qmake'
 | |
|     if len(args) > 1:
 | |
|         qmake_bin = args[1]
 | |
|     qmake_bin = which(qmake_bin)
 | |
| 
 | |
|     if qmake_bin == None:
 | |
|             print "Cannot find required binary 'qmake'."
 | |
|             sys.exit(2)
 | |
| 
 | |
|     if not sys.platform.startswith('win'):
 | |
|         chrpath_bin = which('chrpath')
 | |
|         if chrpath_bin == None:
 | |
|             print "Cannot find required binary 'chrpath'."
 | |
|             sys.exit(2)
 | |
| 
 | |
|     QT_INSTALL_LIBS = readQmakeVar(qmake_bin, 'QT_INSTALL_LIBS')
 | |
|     QT_INSTALL_PLUGINS = readQmakeVar(qmake_bin, 'QT_INSTALL_PLUGINS')
 | |
|     QT_INSTALL_IMPORTS = readQmakeVar(qmake_bin, 'QT_INSTALL_IMPORTS')
 | |
|     QT_INSTALL_TRANSLATIONS = readQmakeVar(qmake_bin, 'QT_INSTALL_TRANSLATIONS')
 | |
| 
 | |
|     plugins = ['accessible', 'designer', 'iconengines', 'imageformats', 'sqldrivers']
 | |
|     imports = ['Qt', 'QtWebKit']
 | |
|     tr_catalogs = ['assistant', 'designer', 'qt', 'qt_help']
 | |
| 
 | |
|     if sys.platform.startswith('win'):
 | |
|         global is_debug_build
 | |
|         is_debug_build = check_debug_build(install_dir)
 | |
| 
 | |
|     copy_qt_libs(install_dir, QT_INSTALL_LIBS, QT_INSTALL_PLUGINS, QT_INSTALL_IMPORTS, plugins, imports)
 | |
|     copy_translations(install_dir, QT_INSTALL_TRANSLATIONS, tr_catalogs)
 | |
| 
 | |
|     if not sys.platform.startswith('win'):
 | |
|         fix_rpaths(chrpath_bin ,install_dir)
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     if sys.platform == 'darwin':
 | |
|         print "Mac OS is not supported by this script, please use macqtdeploy!"
 | |
|         sys.exit(2)
 | |
|     else:
 | |
|         main()
 |