mirror of
				https://github.com/arsenetar/dupeguru.git
				synced 2025-09-11 17:58:17 +00:00 
			
		
		
		
	Adapt build/package scripts to single-edition
This commit is contained in:
		
							parent
							
								
									c865f84c16
								
							
						
					
					
						commit
						ad45a6e16e
					
				| @ -5,9 +5,6 @@ a system. It's written mostly in Python 3 and has the peculiarity of using | ||||
| [multiple GUI toolkits][cross-toolkit], all using the same core Python code. On OS X, the UI layer | ||||
| is written in Objective-C and uses Cocoa. On Linux, it's written in Python and uses Qt5. | ||||
| 
 | ||||
| dupeGuru comes in 3 editions (standard, music and picture) which are all buildable from this same | ||||
| source tree. You choose the edition you want to build in a `configure.py` flag. | ||||
| 
 | ||||
| # Current status: People wanted | ||||
| 
 | ||||
| dupeGuru has currently only one maintainer, me. This is a dangerous situation that needs to be | ||||
| @ -121,7 +118,6 @@ For OS X: | ||||
| 
 | ||||
| With your virtualenv activated, you can build and run dupeGuru with these commands: | ||||
| 
 | ||||
|     $ python configure.py | ||||
|     $ python build.py | ||||
|     $ python run.py | ||||
| 
 | ||||
|  | ||||
| @ -44,4 +44,4 @@ else | ||||
| fi | ||||
| 
 | ||||
| echo "Bootstrapping complete! You can now configure, build and run dupeGuru with:" | ||||
| echo ". env/bin/activate && python configure.py && python build.py && python run.py" | ||||
| echo ". env/bin/activate && python build.py && python run.py" | ||||
|  | ||||
							
								
								
									
										164
									
								
								build.py
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								build.py
									
									
									
									
									
								
							| @ -1,6 +1,4 @@ | ||||
| # Created By: Virgil Dupras | ||||
| # Created On: 2009-12-30 | ||||
| # Copyright 2015 Hardcoded Software (http://www.hardcoded.net) | ||||
| # Copyright 2016 Hardcoded Software (http://www.hardcoded.net) | ||||
| # | ||||
| # This software is licensed under the "GPLv3" License as described in the "LICENSE" file, | ||||
| # which should be included with this package. The terms are also available at | ||||
| @ -11,7 +9,6 @@ import os | ||||
| import os.path as op | ||||
| from optparse import OptionParser | ||||
| import shutil | ||||
| import json | ||||
| import importlib | ||||
| import compileall | ||||
| 
 | ||||
| @ -22,10 +19,10 @@ from hscommon.build import ( | ||||
|     add_to_pythonpath, print_and_do, copy_packages, filereplace, | ||||
|     get_module_version, move_all, copy_all, OSXAppStructure, | ||||
|     build_cocoalib_xibless, fix_qt_resource_file, build_cocoa_ext, copy_embeddable_python_dylib, | ||||
|     collect_stdlib_dependencies, copy | ||||
|     collect_stdlib_dependencies | ||||
| ) | ||||
| from hscommon import loc | ||||
| from hscommon.plat import ISOSX, ISLINUX | ||||
| from hscommon.plat import ISOSX | ||||
| from hscommon.util import ensure_folder, delete_files_with_pattern | ||||
| 
 | ||||
| def parse_args(): | ||||
| @ -39,6 +36,14 @@ def parse_args(): | ||||
|         '--doc', action='store_true', dest='doc', | ||||
|         help="Build only the help file" | ||||
|     ) | ||||
|     parser.add_option( | ||||
|         '--ui', dest='ui', | ||||
|         help="Type of UI to build. 'qt' or 'cocoa'. Default is determined by your system." | ||||
|     ) | ||||
|     parser.add_option( | ||||
|         '--dev', action='store_true', dest='dev', default=False, | ||||
|         help="If this flag is set, will configure for dev builds." | ||||
|     ) | ||||
|     parser.add_option( | ||||
|         '--loc', action='store_true', dest='loc', | ||||
|         help="Build only localization" | ||||
| @ -70,15 +75,11 @@ def parse_args(): | ||||
|     (options, args) = parser.parse_args() | ||||
|     return options | ||||
| 
 | ||||
| def cocoa_app(edition): | ||||
|     app_path = { | ||||
|         'se': 'build/dupeGuru.app', | ||||
|         'me': 'build/dupeGuru ME.app', | ||||
|         'pe': 'build/dupeGuru PE.app', | ||||
|     }[edition] | ||||
| def cocoa_app(): | ||||
|     app_path = 'build/dupeGuru.app' | ||||
|     return OSXAppStructure(app_path) | ||||
| 
 | ||||
| def build_xibless(edition, dest='cocoa/autogen'): | ||||
| def build_xibless(dest='cocoa/autogen'): | ||||
|     import xibless | ||||
|     ensure_folder(dest) | ||||
|     FNPAIRS = [ | ||||
| @ -94,35 +95,36 @@ def build_xibless(edition, dest='cocoa/autogen'): | ||||
|     for srcname, dstname in FNPAIRS: | ||||
|         xibless.generate( | ||||
|             op.join('cocoa', 'base', 'ui', srcname), op.join(dest, dstname), | ||||
|             localizationTable='Localizable', args={'edition': edition} | ||||
|         ) | ||||
|     if edition == 'pe': | ||||
|         xibless.generate( | ||||
|             'cocoa/pe/ui/details_panel.py', op.join(dest, 'DetailsPanel_UI'), | ||||
|             localizationTable='Localizable' | ||||
|         ) | ||||
|     else: | ||||
|         xibless.generate( | ||||
|             'cocoa/base/ui/details_panel.py', op.join(dest, 'DetailsPanel_UI'), | ||||
|             localizationTable='Localizable' | ||||
|         ) | ||||
|     # XXX This is broken | ||||
|     assert False | ||||
|     #  if edition == 'pe': | ||||
|     #      xibless.generate( | ||||
|     #          'cocoa/pe/ui/details_panel.py', op.join(dest, 'DetailsPanel_UI'), | ||||
|     #          localizationTable='Localizable' | ||||
|     #      ) | ||||
|     #  else: | ||||
|     #      xibless.generate( | ||||
|     #          'cocoa/base/ui/details_panel.py', op.join(dest, 'DetailsPanel_UI'), | ||||
|     #          localizationTable='Localizable' | ||||
|     #      ) | ||||
| 
 | ||||
| def build_cocoa(edition, dev): | ||||
| def build_cocoa(dev): | ||||
|     print("Creating OS X app structure") | ||||
|     ed = lambda s: s.format(edition) | ||||
|     app = cocoa_app(edition) | ||||
|     app_version = get_module_version(ed('core_{}')) | ||||
|     cocoa_project_path = ed('cocoa/{}') | ||||
|     app = cocoa_app() | ||||
|     app_version = get_module_version('core_se') | ||||
|     cocoa_project_path = 'cocoa/se' | ||||
|     filereplace(op.join(cocoa_project_path, 'InfoTemplate.plist'), op.join('build', 'Info.plist'), version=app_version) | ||||
|     app.create(op.join('build', 'Info.plist')) | ||||
|     print("Building localizations") | ||||
|     build_localizations('cocoa', edition) | ||||
|     build_localizations('cocoa') | ||||
|     print("Building xibless UIs") | ||||
|     build_cocoalib_xibless() | ||||
|     build_xibless(edition) | ||||
|     build_xibless() | ||||
|     print("Building Python extensions") | ||||
|     build_cocoa_proxy_module() | ||||
|     build_cocoa_bridging_interfaces(edition) | ||||
|     build_cocoa_bridging_interfaces() | ||||
|     print("Building the cocoa layer") | ||||
|     copy_embeddable_python_dylib('build') | ||||
|     pydep_folder = op.join(app.resources, 'py') | ||||
| @ -130,21 +132,15 @@ def build_cocoa(edition, dev): | ||||
|         os.mkdir(pydep_folder) | ||||
|     shutil.copy(op.join(cocoa_project_path, 'dg_cocoa.py'), 'build') | ||||
|     appscript_pkgs = ['appscript', 'aem', 'mactypes', 'osax'] | ||||
|     specific_packages = { | ||||
|         'se': ['core_se'], | ||||
|         'me': ['core_me'] + appscript_pkgs + ['hsaudiotag'], | ||||
|         'pe': ['core_pe'] + appscript_pkgs, | ||||
|     }[edition] | ||||
|     tocopy = [ | ||||
|         'core', 'hscommon', 'cocoa/inter', 'cocoalib/cocoa', 'objp', 'send2trash' | ||||
|     ] + specific_packages | ||||
|         'core', 'core_se', 'core_me', 'core_pe', 'hscommon', 'cocoa/inter', 'cocoalib/cocoa', | ||||
|         'objp', 'send2trash', 'hsaudiotag', | ||||
|     ] + appscript_pkgs | ||||
|     copy_packages(tocopy, pydep_folder, create_links=dev) | ||||
|     sys.path.insert(0, 'build') | ||||
|     extra_deps = None | ||||
|     if edition == 'pe': | ||||
|         # ModuleFinder can't seem to correctly detect the multiprocessing dependency, so we have | ||||
|         # to manually specify it. | ||||
|         extra_deps = ['multiprocessing'] | ||||
|     # ModuleFinder can't seem to correctly detect the multiprocessing dependency, so we have | ||||
|     # to manually specify it. | ||||
|     extra_deps = ['multiprocessing'] | ||||
|     collect_stdlib_dependencies('build/dg_cocoa.py', pydep_folder, extra_deps=extra_deps) | ||||
|     del sys.path[0] | ||||
|     # Views are not referenced by python code, so they're not found by the collector. | ||||
| @ -157,12 +153,12 @@ def build_cocoa(edition, dev): | ||||
|         delete_files_with_pattern(pydep_folder, '__pycache__') | ||||
|     print("Compiling with WAF") | ||||
|     os.chdir('cocoa') | ||||
|     print_and_do('{0} waf configure --edition {1} && {0} waf'.format(sys.executable, edition)) | ||||
|     print_and_do('{0} waf configure && {0} waf'.format(sys.executable)) | ||||
|     os.chdir('..') | ||||
|     app.copy_executable('cocoa/build/dupeGuru') | ||||
|     build_help(edition) | ||||
|     build_help() | ||||
|     print("Copying resources and frameworks") | ||||
|     image_path = ed('cocoa/{}/dupeguru.icns') | ||||
|     image_path = 'cocoa/se/dupeguru.icns' | ||||
|     resources = [image_path, 'cocoa/base/dsa_pub.pem', 'build/dg_cocoa.py', 'build/help'] | ||||
|     app.copy_resources(*resources, use_symlinks=dev) | ||||
|     app.copy_frameworks('build/Python', 'cocoalib/Sparkle.framework') | ||||
| @ -171,26 +167,26 @@ def build_cocoa(edition, dev): | ||||
|     run_contents = tmpl.replace('{{app_path}}', app.dest) | ||||
|     open('run.py', 'wt').write(run_contents) | ||||
| 
 | ||||
| def build_qt(edition, dev, conf): | ||||
| def build_qt(dev): | ||||
|     print("Building localizations") | ||||
|     build_localizations('qt', edition) | ||||
|     build_localizations('qt') | ||||
|     print("Building Qt stuff") | ||||
|     print_and_do("pyrcc5 {0} > {1}".format(op.join('qt', 'base', 'dg.qrc'), op.join('qt', 'base', 'dg_rc.py'))) | ||||
|     fix_qt_resource_file(op.join('qt', 'base', 'dg_rc.py')) | ||||
|     build_help(edition) | ||||
|     build_help() | ||||
|     print("Creating the run.py file") | ||||
|     filereplace(op.join('qt', 'run_template.py'), 'run.py', edition=edition) | ||||
|     shutil.copy(op.join('qt', 'run_template.py'), 'run.py') | ||||
| 
 | ||||
| def build_help(edition): | ||||
| def build_help(): | ||||
|     print("Generating Help") | ||||
|     current_path = op.abspath('.') | ||||
|     help_basepath = op.join(current_path, 'help', 'en') | ||||
|     help_destpath = op.join(current_path, 'build', 'help'.format(edition)) | ||||
|     changelog_path = op.join(current_path, 'help', 'changelog_{}'.format(edition)) | ||||
|     help_destpath = op.join(current_path, 'build', 'help') | ||||
|     changelog_path = op.join(current_path, 'help', 'changelog_se') | ||||
|     tixurl = "https://github.com/hsoft/dupeguru/issues/{}" | ||||
|     appname = {'se': 'dupeGuru', 'me': 'dupeGuru Music Edition', 'pe': 'dupeGuru Picture Edition'}[edition] | ||||
|     homepage = 'http://www.hardcoded.net/dupeguru{}/'.format('_' + edition if edition != 'se' else '') | ||||
|     confrepl = {'edition': edition, 'appname': appname, 'homepage': homepage, 'language': 'en'} | ||||
|     appname = 'dupeGuru' | ||||
|     homepage = 'https://www.hardcoded.net/dupeguru/' | ||||
|     confrepl = {'appname': appname, 'homepage': homepage, 'language': 'en'} | ||||
|     changelogtmpl = op.join(current_path, 'help', 'changelog.tmpl') | ||||
|     conftmpl = op.join(current_path, 'help', 'conf.tmpl') | ||||
|     sphinxgen.gen(help_basepath, help_destpath, changelog_path, tixurl, confrepl, conftmpl, changelogtmpl) | ||||
| @ -199,10 +195,10 @@ def build_qt_localizations(): | ||||
|     loc.compile_all_po(op.join('qtlib', 'locale')) | ||||
|     loc.merge_locale_dir(op.join('qtlib', 'locale'), 'locale') | ||||
| 
 | ||||
| def build_localizations(ui, edition): | ||||
| def build_localizations(ui): | ||||
|     loc.compile_all_po('locale') | ||||
|     if ui == 'cocoa': | ||||
|         app = cocoa_app(edition) | ||||
|         app = cocoa_app() | ||||
|         loc.build_cocoa_localizations(app, en_stringsfile=op.join('cocoa', 'base', 'en.lproj', 'Localizable.strings')) | ||||
|         locale_dest = op.join(app.resources, 'locale') | ||||
|     elif ui == 'qt': | ||||
| @ -211,25 +207,13 @@ def build_localizations(ui, edition): | ||||
|     if op.exists(locale_dest): | ||||
|         shutil.rmtree(locale_dest) | ||||
|     shutil.copytree('locale', locale_dest, ignore=shutil.ignore_patterns('*.po', '*.pot')) | ||||
|     if ui == 'qt' and not ISLINUX: | ||||
|         print("Copying qt_*.qm files into the 'locale' folder") | ||||
|         from PyQt5.QtCore import QLibraryInfo | ||||
|         trfolder = QLibraryInfo.location(QLibraryInfo.TranslationsPath) | ||||
|         for lang in loc.get_langs('locale'): | ||||
|             qmname = 'qt_%s.qm' % lang | ||||
|             src = op.join(trfolder, qmname) | ||||
|             if op.exists(src): | ||||
|                 copy(src, op.join('build', 'locale', qmname)) | ||||
| 
 | ||||
| def build_updatepot(): | ||||
|     if ISOSX: | ||||
|         print("Updating Cocoa strings file.") | ||||
|         # We need to have strings from *all* editions in here, so we'll call xibless for all editions | ||||
|         # in dummy subfolders. | ||||
|         build_cocoalib_xibless('cocoalib/autogen') | ||||
|         loc.generate_cocoa_strings_from_code('cocoalib', 'cocoalib/en.lproj') | ||||
|         for edition in ('se', 'me', 'pe'): | ||||
|             build_xibless(edition, op.join('cocoa', 'autogen', edition)) | ||||
|         build_xibless('se', op.join('cocoa', 'autogen', 'se')) | ||||
|         loc.generate_cocoa_strings_from_code('cocoa', 'cocoa/base/en.lproj') | ||||
|     print("Building .pot files from source files") | ||||
|     print("Building core.pot") | ||||
| @ -280,7 +264,7 @@ def build_cocoa_proxy_module(): | ||||
|         ['cocoalib', 'cocoa/autogen'] | ||||
|     ) | ||||
| 
 | ||||
| def build_cocoa_bridging_interfaces(edition): | ||||
| def build_cocoa_bridging_interfaces(): | ||||
|     print("Building Cocoa Bridging Interfaces") | ||||
|     import objp.o2p | ||||
|     import objp.p2o | ||||
| @ -301,7 +285,7 @@ def build_cocoa_bridging_interfaces(edition): | ||||
|     from inter.result_table import PyResultTable, ResultTableView | ||||
|     from inter.stats_label import PyStatsLabel, StatsLabelView | ||||
|     from inter.app import PyDupeGuruBase, DupeGuruView | ||||
|     appmod = importlib.import_module('inter.app_{}'.format(edition)) | ||||
|     appmod = importlib.import_module('inter.app_se') | ||||
|     allclasses = [ | ||||
|         PyGUIObject, PyColumns, PyOutline, PySelectableList, PyTable, PyBaseApp, | ||||
|         PyDetailsPanel, PyDirectoryOutline, PyPrioritizeDialog, PyPrioritizeList, PyProblemDialog, | ||||
| @ -345,24 +329,22 @@ def build_pe_modules(ui): | ||||
|     move_all('_block*', 'core_pe') | ||||
|     move_all('_cache*', 'core_pe') | ||||
| 
 | ||||
| def build_normal(edition, ui, dev, conf): | ||||
|     print("Building dupeGuru {0} with UI {1}".format(edition.upper(), ui)) | ||||
| def build_normal(ui, dev): | ||||
|     print("Building dupeGuru with UI {}".format(ui)) | ||||
|     add_to_pythonpath('.') | ||||
|     print("Building dupeGuru") | ||||
|     if edition == 'pe': | ||||
|         build_pe_modules(ui) | ||||
|     build_pe_modules(ui) | ||||
|     if ui == 'cocoa': | ||||
|         build_cocoa(edition, dev) | ||||
|         build_cocoa(dev) | ||||
|     elif ui == 'qt': | ||||
|         build_qt(edition, dev, conf) | ||||
|         build_qt(dev) | ||||
| 
 | ||||
| def main(): | ||||
|     options = parse_args() | ||||
|     conf = json.load(open('conf.json')) | ||||
|     edition = conf['edition'] | ||||
|     ui = conf['ui'] | ||||
|     dev = conf['dev'] | ||||
|     if dev: | ||||
|     ui = options.ui | ||||
|     if ui not in ('cocoa', 'qt'): | ||||
|         ui = 'cocoa' if ISOSX else 'qt' | ||||
|     if options.dev: | ||||
|         print("Building in Dev mode") | ||||
|     if options.clean: | ||||
|         for path in ['build', op.join('cocoa', 'build'), op.join('cocoa', 'autogen')]: | ||||
| @ -371,9 +353,9 @@ def main(): | ||||
|     if not op.exists('build'): | ||||
|         os.mkdir('build') | ||||
|     if options.doc: | ||||
|         build_help(edition) | ||||
|         build_help() | ||||
|     elif options.loc: | ||||
|         build_localizations(ui, edition) | ||||
|         build_localizations(ui) | ||||
|     elif options.updatepot: | ||||
|         build_updatepot() | ||||
|     elif options.mergepot: | ||||
| @ -382,17 +364,17 @@ def main(): | ||||
|         build_normpo() | ||||
|     elif options.cocoa_ext: | ||||
|         build_cocoa_proxy_module() | ||||
|         build_cocoa_bridging_interfaces(edition) | ||||
|         build_cocoa_bridging_interfaces() | ||||
|     elif options.cocoa_compile: | ||||
|         os.chdir('cocoa') | ||||
|         print_and_do('{0} waf configure --edition {1} && {0} waf'.format(sys.executable, edition)) | ||||
|         print_and_do('{0} waf configure && {0} waf'.format(sys.executable)) | ||||
|         os.chdir('..') | ||||
|         cocoa_app(edition).copy_executable('cocoa/build/dupeGuru') | ||||
|         cocoa_app().copy_executable('cocoa/build/dupeGuru') | ||||
|     elif options.xibless: | ||||
|         build_cocoalib_xibless() | ||||
|         build_xibless(edition) | ||||
|         build_xibless() | ||||
|     else: | ||||
|         build_normal(edition, ui, dev, conf) | ||||
|         build_normal(ui, options.dev) | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
|  | ||||
							
								
								
									
										45
									
								
								configure.py
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								configure.py
									
									
									
									
									
								
							| @ -1,45 +0,0 @@ | ||||
| # Created By: Virgil Dupras | ||||
| # Created On: 2009-12-30 | ||||
| # Copyright 2015 Hardcoded Software (http://www.hardcoded.net) | ||||
| # | ||||
| # This software is licensed under the "GPLv3" License as described in the "LICENSE" file, | ||||
| # which should be included with this package. The terms are also available at | ||||
| # http://www.gnu.org/licenses/gpl-3.0.html | ||||
| 
 | ||||
| from optparse import OptionParser | ||||
| import json | ||||
| 
 | ||||
| from hscommon.plat import ISOSX | ||||
| 
 | ||||
| def main(options): | ||||
|     if options.edition not in {'se', 'me', 'pe'}: | ||||
|         options.edition = 'se' | ||||
|     if options.ui not in {'cocoa', 'qt'}: | ||||
|         options.ui = 'cocoa' if ISOSX else 'qt' | ||||
|     build_type = 'Dev' if options.dev else 'Release' | ||||
|     print("Configuring dupeGuru {0} for UI {1} ({2})".format(options.edition.upper(), options.ui, build_type)) | ||||
|     conf = { | ||||
|         'edition': options.edition, | ||||
|         'ui': options.ui, | ||||
|         'dev': options.dev, | ||||
|     } | ||||
|     json.dump(conf, open('conf.json', 'w')) | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     usage = "usage: %prog [options]" | ||||
|     parser = OptionParser(usage=usage) | ||||
|     parser.add_option( | ||||
|         '--edition', dest='edition', | ||||
|         help="dupeGuru edition to build (se, me or pe). Default is se." | ||||
|     ) | ||||
|     parser.add_option( | ||||
|         '--ui', dest='ui', | ||||
|         help="Type of UI to build. 'qt' or 'cocoa'. Default is determined by your system." | ||||
|     ) | ||||
|     parser.add_option( | ||||
|         '--dev', action='store_true', dest='dev', default=False, | ||||
|         help="If this flag is set, will configure for dev builds." | ||||
|     ) | ||||
|     (options, args) = parser.parse_args() | ||||
|     main(options) | ||||
| 
 | ||||
							
								
								
									
										190
									
								
								package.py
									
									
									
									
									
								
							
							
						
						
									
										190
									
								
								package.py
									
									
									
									
									
								
							| @ -1,6 +1,4 @@ | ||||
| # Created By: Virgil Dupras | ||||
| # Created On: 2009-12-30 | ||||
| # Copyright 2015 Hardcoded Software (http://www.hardcoded.net) | ||||
| # Copyright 2016 Hardcoded Software (http://www.hardcoded.net) | ||||
| # | ||||
| # This software is licensed under the "GPLv3" License as described in the "LICENSE" file, | ||||
| # which should be included with this package. The terms are also available at | ||||
| @ -13,13 +11,12 @@ import shutil | ||||
| import json | ||||
| from argparse import ArgumentParser | ||||
| import platform | ||||
| import glob | ||||
| 
 | ||||
| from hscommon.plat import ISWINDOWS, ISLINUX | ||||
| from hscommon.plat import ISOSX | ||||
| from hscommon.build import ( | ||||
|     add_to_pythonpath, print_and_do, copy_packages, build_debian_changelog, | ||||
|     copy_qt_plugins, get_module_version, filereplace, copy, setup_package_argparser, | ||||
|     package_cocoa_app_in_dmg, copy_all, find_in_path | ||||
|     print_and_do, copy_packages, build_debian_changelog, | ||||
|     get_module_version, filereplace, copy, setup_package_argparser, | ||||
|     package_cocoa_app_in_dmg, copy_all | ||||
| ) | ||||
| 
 | ||||
| def parse_args(): | ||||
| @ -27,90 +24,10 @@ def parse_args(): | ||||
|     setup_package_argparser(parser) | ||||
|     return parser.parse_args() | ||||
| 
 | ||||
| def package_cocoa(edition, args): | ||||
|     app_path = { | ||||
|         'se': 'build/dupeGuru.app', | ||||
|         'me': 'build/dupeGuru ME.app', | ||||
|         'pe': 'build/dupeGuru PE.app', | ||||
|     }[edition] | ||||
| def package_cocoa(args): | ||||
|     app_path = 'build/dupeGuru.app' | ||||
|     package_cocoa_app_in_dmg(app_path, '.', args) | ||||
| 
 | ||||
| def package_windows(edition, dev): | ||||
|     if not ISWINDOWS: | ||||
|         print("Qt packaging only works under Windows.") | ||||
|         return | ||||
|     from cx_Freeze import setup, Executable | ||||
|     from PyQt5.QtCore import QLibraryInfo | ||||
|     add_to_pythonpath('.') | ||||
|     app_version = get_module_version('core_{}'.format(edition)) | ||||
|     distdir = 'dist' | ||||
| 
 | ||||
|     if op.exists(distdir): | ||||
|         shutil.rmtree(distdir) | ||||
| 
 | ||||
|     if not dev: | ||||
|         # Copy qt plugins | ||||
|         plugin_dest = distdir | ||||
|         plugin_names = ['accessible', 'codecs', 'iconengines', 'imageformats'] | ||||
|         copy_qt_plugins(plugin_names, plugin_dest) | ||||
| 
 | ||||
|     # Since v4.2.3, cx_freeze started to falsely include tkinter in the package. We exclude it | ||||
|     # explicitly because of that. | ||||
|     options = { | ||||
|         'build_exe': { | ||||
|             'includes': 'atexit', | ||||
|             'excludes': ['tkinter'], | ||||
|             'bin_excludes': ['icudt51', 'icuin51.dll', 'icuuc51.dll'], | ||||
|             'icon': 'images\\dg{0}_logo.ico'.format(edition), | ||||
|             'include_msvcr': True, | ||||
|         }, | ||||
|         'install_exe': { | ||||
|             'install_dir': 'dist', | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     executables = [ | ||||
|         Executable( | ||||
|             'run.py', | ||||
|             base='Win32GUI', | ||||
|             targetDir=distdir, | ||||
|             targetName={'se': 'dupeGuru', 'me': 'dupeGuru ME', 'pe': 'dupeGuru PE'}[edition] + '.exe', | ||||
|         ) | ||||
|     ] | ||||
| 
 | ||||
|     setup( | ||||
|         script_args=['install'], | ||||
|         options=options, | ||||
|         executables=executables | ||||
|     ) | ||||
| 
 | ||||
|     print("Removing useless files") | ||||
|     # Debug info that cx_freeze brings in. | ||||
|     for fn in glob.glob(op.join(distdir, '*', '*.pdb')): | ||||
|         os.remove(fn) | ||||
|     print("Copying forgotten DLLs") | ||||
|     qtlibpath = QLibraryInfo.location(QLibraryInfo.LibrariesPath) | ||||
|     shutil.copy(op.join(qtlibpath, 'libEGL.dll'), distdir) | ||||
|     shutil.copy(find_in_path('msvcp110.dll'), distdir) | ||||
|     print("Copying the rest") | ||||
|     help_path = op.join('build', 'help') | ||||
|     print("Copying {} to dist\\help".format(help_path)) | ||||
|     shutil.copytree(help_path, op.join(distdir, 'help')) | ||||
|     locale_path = op.join('build', 'locale') | ||||
|     print("Copying {} to dist\\locale".format(locale_path)) | ||||
|     shutil.copytree(locale_path, op.join(distdir, 'locale')) | ||||
| 
 | ||||
|     # AdvancedInstaller.com has to be in your PATH | ||||
|     # this is so we don'a have to re-commit installer.aip at every version change | ||||
|     installer_file = 'installer.aip' | ||||
|     installer_path = op.join('qt', edition, installer_file) | ||||
|     shutil.copy(installer_path, 'installer_tmp.aip') | ||||
|     print_and_do('AdvancedInstaller.com /edit installer_tmp.aip /SetVersion %s' % app_version) | ||||
|     print_and_do('AdvancedInstaller.com /build installer_tmp.aip -force') | ||||
|     os.remove('installer_tmp.aip') | ||||
|     if op.exists('installer_tmp.back.aip'): | ||||
|         os.remove('installer_tmp.back.aip') | ||||
| 
 | ||||
| def copy_files_to_package(destpath, packages, with_so): | ||||
|     # when with_so is true, we keep .so files in the package, and otherwise, we don't. We need this | ||||
|     # flag because when building debian src pkg, we *don't* want .so files (they're compiled later) | ||||
| @ -126,71 +43,70 @@ def copy_files_to_package(destpath, packages, with_so): | ||||
|     shutil.copytree(op.join('build', 'locale'), op.join(destpath, 'locale')) | ||||
|     compileall.compile_dir(destpath) | ||||
| 
 | ||||
| def package_debian_distribution(edition, distribution): | ||||
|     app_version = get_module_version('core_{}'.format(edition)) | ||||
| def package_debian_distribution(distribution): | ||||
|     app_version = get_module_version('core_se') | ||||
|     version = '{}~{}'.format(app_version, distribution) | ||||
|     ed = lambda s: s.format(edition) | ||||
|     destpath = op.join('build', 'dupeguru-{0}-{1}'.format(edition, version)) | ||||
|     destpath = op.join('build', 'dupeguru-{}'.format(version)) | ||||
|     srcpath = op.join(destpath, 'src') | ||||
|     packages = ['hscommon', 'core', ed('core_{0}'), 'qtlib', 'qt', 'send2trash'] | ||||
|     if edition == 'me': | ||||
|         packages.append('hsaudiotag') | ||||
|     packages = [ | ||||
|         'hscommon', 'core', 'core_se', 'core_me', 'core_pe', 'qtlib', 'qt', 'send2trash', | ||||
|         'hsaudiotag' | ||||
|     ] | ||||
|     copy_files_to_package(srcpath, packages, with_so=False) | ||||
|     if edition == 'pe': | ||||
|         os.mkdir(op.join(destpath, 'modules')) | ||||
|         copy_all(op.join('core_pe', 'modules', '*.*'), op.join(destpath, 'modules')) | ||||
|         copy(op.join('qt', 'pe', 'modules', 'block.c'), op.join(destpath, 'modules', 'block_qt.c')) | ||||
|         copy(op.join('pkg', 'debian', 'build_pe_modules.py'), op.join(destpath, 'build_pe_modules.py')) | ||||
|     os.mkdir(op.join(destpath, 'modules')) | ||||
|     copy_all(op.join('core_pe', 'modules', '*.*'), op.join(destpath, 'modules')) | ||||
|     copy(op.join('qt', 'pe', 'modules', 'block.c'), op.join(destpath, 'modules', 'block_qt.c')) | ||||
|     copy(op.join('pkg', 'debian', 'build_pe_modules.py'), op.join(destpath, 'build_pe_modules.py')) | ||||
|     debdest = op.join(destpath, 'debian') | ||||
|     debskel = op.join('pkg', 'debian') | ||||
|     os.makedirs(debdest) | ||||
|     debopts = json.load(open(op.join(debskel, ed('{}.json')))) | ||||
|     debopts = json.load(open(op.join(debskel, 'se.json'))) | ||||
|     for fn in ['compat', 'copyright', 'dirs', 'rules']: | ||||
|         copy(op.join(debskel, fn), op.join(debdest, fn)) | ||||
|     filereplace(op.join(debskel, 'control'), op.join(debdest, 'control'), **debopts) | ||||
|     filereplace(op.join(debskel, 'Makefile'), op.join(destpath, 'Makefile'), **debopts) | ||||
|     filereplace(op.join(debskel, 'dupeguru.desktop'), op.join(debdest, ed('dupeguru_{}.desktop')), **debopts) | ||||
|     changelogpath = op.join('help', ed('changelog_{}')) | ||||
|     filereplace(op.join(debskel, 'dupeguru.desktop'), op.join(debdest, 'dupeguru.desktop'), **debopts) | ||||
|     changelogpath = op.join('help', 'changelog_se') | ||||
|     changelog_dest = op.join(debdest, 'changelog') | ||||
|     project_name = debopts['pkgname'] | ||||
|     from_version = {'se': '2.9.2', 'me': '5.7.2', 'pe': '1.8.5'}[edition] | ||||
|     from_version = '2.9.2' | ||||
|     build_debian_changelog( | ||||
|         changelogpath, changelog_dest, project_name, from_version=from_version, | ||||
|         distribution=distribution | ||||
|     ) | ||||
|     shutil.copy(op.join('images', ed('dg{0}_logo_128.png')), srcpath) | ||||
|     shutil.copy(op.join('images', 'dgse_logo_128.png'), srcpath) | ||||
|     os.chdir(destpath) | ||||
|     cmd = "dpkg-buildpackage -S" | ||||
|     os.system(cmd) | ||||
|     os.chdir('../..') | ||||
| 
 | ||||
| def package_debian(edition): | ||||
| def package_debian(): | ||||
|     print("Packaging for Ubuntu") | ||||
|     for distribution in ['trusty', 'utopic']: | ||||
|         package_debian_distribution(edition, distribution) | ||||
|         package_debian_distribution(distribution) | ||||
| 
 | ||||
| def package_arch(edition): | ||||
| def package_arch(): | ||||
|     # For now, package_arch() will only copy the source files into build/. It copies less packages | ||||
|     # than package_debian because there are more python packages available in Arch (so we don't | ||||
|     # need to include them). | ||||
|     print("Packaging for Arch") | ||||
|     ed = lambda s: s.format(edition) | ||||
|     srcpath = op.join('build', ed('dupeguru-{}-arch')) | ||||
|     packages = ['hscommon', 'core', ed('core_{0}'), 'qtlib', 'qt', 'send2trash'] | ||||
|     if edition == 'me': | ||||
|         packages.append('hsaudiotag') | ||||
|     srcpath = op.join('build', 'dupeguru-arch') | ||||
|     packages = [ | ||||
|         'hscommon', 'core', 'core_se', 'core_me', 'core_pe', 'qtlib', 'qt', 'send2trash', | ||||
|         'hsaudiotag', | ||||
|     ] | ||||
|     copy_files_to_package(srcpath, packages, with_so=True) | ||||
|     shutil.copy(op.join('images', ed('dg{}_logo_128.png')), srcpath) | ||||
|     debopts = json.load(open(op.join('pkg', 'arch', ed('{}.json')))) | ||||
|     filereplace(op.join('pkg', 'arch', 'dupeguru.desktop'), op.join(srcpath, ed('dupeguru-{}.desktop')), **debopts) | ||||
|     shutil.copy(op.join('images', 'dgse_logo_128.png'), srcpath) | ||||
|     debopts = json.load(open(op.join('pkg', 'arch', 'se.json'))) | ||||
|     filereplace(op.join('pkg', 'arch', 'dupeguru.desktop'), op.join(srcpath, 'dupeguru.desktop'), **debopts) | ||||
| 
 | ||||
| def package_source_tgz(edition): | ||||
| def package_source_tgz(): | ||||
|     if not op.exists('deps'): | ||||
|         print("Downloading PyPI dependencies") | ||||
|         print_and_do('./download_deps.sh') | ||||
|     print("Creating git archive") | ||||
|     app_version = get_module_version('core_{}'.format(edition)) | ||||
|     name = 'dupeguru-{}-src-{}.tar'.format(edition, app_version) | ||||
|     app_version = get_module_version('core_se') | ||||
|     name = 'dupeguru-src-{}.tar'.format(app_version) | ||||
|     dest = op.join('build', name) | ||||
|     print_and_do('git archive -o {} HEAD'.format(dest)) | ||||
|     print("Adding dependencies and wrapping up") | ||||
| @ -199,31 +115,23 @@ def package_source_tgz(edition): | ||||
| 
 | ||||
| def main(): | ||||
|     args = parse_args() | ||||
|     conf = json.load(open('conf.json')) | ||||
|     edition = conf['edition'] | ||||
|     ui = conf['ui'] | ||||
|     dev = conf['dev'] | ||||
|     ui = 'cocoa' if ISOSX else 'qt' | ||||
|     if args.src_pkg: | ||||
|         print("Creating source package for dupeGuru {}".format(edition.upper())) | ||||
|         package_source_tgz(edition) | ||||
|         print("Creating source package for dupeGuru") | ||||
|         package_source_tgz() | ||||
|         return | ||||
|     print("Packaging dupeGuru {0} with UI {1}".format(edition.upper(), ui)) | ||||
|     print("Packaging dupeGuru with UI {}".format(ui)) | ||||
|     if ui == 'cocoa': | ||||
|         package_cocoa(edition, args) | ||||
|         package_cocoa(args) | ||||
|     elif ui == 'qt': | ||||
|         if ISWINDOWS: | ||||
|             package_windows(edition, dev) | ||||
|         elif ISLINUX: | ||||
|             if not args.arch_pkg: | ||||
|                 distname, _, _ = platform.dist() | ||||
|             else: | ||||
|                 distname = 'arch' | ||||
|             if distname == 'arch': | ||||
|                 package_arch(edition) | ||||
|             else: | ||||
|                 package_debian(edition) | ||||
|         if not args.arch_pkg: | ||||
|             distname, _, _ = platform.dist() | ||||
|         else: | ||||
|             print("Qt packaging only works under Windows or Linux.") | ||||
|             distname = 'arch' | ||||
|         if distname == 'arch': | ||||
|             package_arch() | ||||
|         else: | ||||
|             package_debian() | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| #!/usr/bin/python3 | ||||
| # Copyright 2015 Hardcoded Software (http://www.hardcoded.net) | ||||
| #  | ||||
| # This software is licensed under the "GPLv3" License as described in the "LICENSE" file,  | ||||
| # which should be included with this package. The terms are also available at  | ||||
| # | ||||
| # This software is licensed under the "GPLv3" License as described in the "LICENSE" file, | ||||
| # which should be included with this package. The terms are also available at | ||||
| # http://www.gnu.org/licenses/gpl-3.0.html | ||||
| 
 | ||||
| import sys | ||||
| @ -13,16 +13,12 @@ from PyQt5.QtCore import QCoreApplication, QSettings | ||||
| from PyQt5.QtGui import QIcon, QPixmap | ||||
| from PyQt5.QtWidgets import QApplication | ||||
| 
 | ||||
| from hscommon.plat import ISWINDOWS | ||||
| from hscommon.trans import install_gettext_trans_under_qt | ||||
| from qtlib.error_report_dialog import install_excepthook | ||||
| from qtlib.util import setupQtLogging | ||||
| from qt.base import dg_rc | ||||
| from qt.base.platform import BASE_PATH | ||||
| from core_{edition} import __version__, __appname__ | ||||
| 
 | ||||
| if ISWINDOWS: | ||||
|     import qt.base.cxfreeze_fix | ||||
| from core_se import __version__, __appname__ | ||||
| 
 | ||||
| def main(): | ||||
|     app = QApplication(sys.argv) | ||||
| @ -36,7 +32,7 @@ def main(): | ||||
|     install_gettext_trans_under_qt(locale_folder, lang) | ||||
|     # Many strings are translated at import time, so this is why we only import after the translator | ||||
|     # has been installed | ||||
|     from qt.{edition}.app import DupeGuru | ||||
|     from qt.se.app import DupeGuru | ||||
|     app.setWindowIcon(QIcon(QPixmap(":/{0}".format(DupeGuru.LOGO_NAME)))) | ||||
|     dgapp = DupeGuru() | ||||
|     install_excepthook('https://github.com/hsoft/dupeguru/issues') | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user