# Created By: Virgil Dupras # Created On: 2009-12-30 # Copyright 2011 Hardcoded Software (http://www.hardcoded.net) # # This software is licensed under the "BSD" License as described in the "LICENSE" file, # which should be included with this package. The terms are also available at # http://www.hardcoded.net/licenses/bsd_license import sys import os import os.path as op from optparse import OptionParser import shutil import json from setuptools import setup, Extension from hscommon import sphinxgen from hscommon.build import (add_to_pythonpath, print_and_do, copy_packages, filereplace, get_module_version, build_all_cocoa_locs, move_all, copy_sysconfig_files_for_embed, copy_all) from hscommon import loc def parse_args(): usage = "usage: %prog [options]" parser = OptionParser(usage=usage) parser.add_option('--clean', action='store_true', dest='clean', help="Clean build folder before building") parser.add_option('--doc', action='store_true', dest='doc', help="Build only the help file") parser.add_option('--loc', action='store_true', dest='loc', help="Build only localization") parser.add_option('--updatepot', action='store_true', dest='updatepot', help="Generate .pot files from source code.") parser.add_option('--mergepot', action='store_true', dest='mergepot', help="Update all .po files based on .pot files.") (options, args) = parser.parse_args() return options def build_cocoa(edition, dev): build_cocoa_proxy_module() build_cocoa_bridging_interfaces() print("Building dg_cocoa.plugin") specific_packages = { 'se': ['core_se'], 'me': ['core_me'], 'pe': ['core_pe'], }[edition] tocopy = ['core', 'hscommon', 'cocoa/inter', 'cocoalib/cocoa'] + specific_packages copy_packages(tocopy, 'build', create_links=dev) cocoa_project_path = 'cocoa/{0}'.format(edition) shutil.copy(op.join(cocoa_project_path, 'dg_cocoa.py'), 'build') from pluginbuilder import copy_embeddable_python_dylib, get_python_header_folder, collect_dependencies copy_embeddable_python_dylib('build') if not op.exists('build/PythonHeaders'): os.symlink(get_python_header_folder(), 'build/PythonHeaders') if not op.exists('build/py'): os.mkdir('build/py') sys.path.insert(0, 'build') collect_dependencies('build/dg_cocoa.py', 'build/py', excludes=['PyQt4']) # Views are not referenced by python code, so they're not found by the collector. copy_all('build/inter/*.so', 'build/py/inter') del sys.path[0] copy_sysconfig_files_for_embed('build/py') os.chdir(cocoa_project_path) print('Generating Info.plist') app_version = get_module_version('core_{}'.format(edition)) filereplace('InfoTemplate.plist', 'Info.plist', version=app_version) print("Building the XCode project") args = ['-project dupeguru.xcodeproj'] if dev: args.append('-configuration dev') else: args.append('-configuration release') args = ' '.join(args) os.system('xcodebuild {0}'.format(args)) os.chdir('../..') print("Creating the run.py file") app_path = { 'se': 'cocoa/se/dupeGuru.app', 'me': 'cocoa/me/dupeGuru\\ ME.app', 'pe': 'cocoa/pe/dupeGuru\\ PE.app', }[edition] tmpl = open('run_template_cocoa.py', 'rt').read() run_contents = tmpl.replace('{{app_path}}', app_path) open('run.py', 'wt').write(run_contents) def build_qt(edition, dev): print("Building Qt stuff") print_and_do("pyrcc4 -py3 {0} > {1}".format(op.join('qt', 'base', 'dg.qrc'), op.join('qt', 'base', 'dg_rc.py'))) print("Creating the run.py file") tmpl = open('run_template_qt.py', 'rt').read() run_contents = tmpl.replace('{{edition}}', edition) open('run.py', 'wt').write(run_contents) def build_help(edition): 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)) tixurl = "https://hardcoded.lighthouseapp.com/projects/31699-dupeguru/tickets/{0}" 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} sphinxgen.gen(help_basepath, help_destpath, changelog_path, tixurl, confrepl) def build_localizations(ui, edition): print("Building localizations") loc.compile_all_po('locale') loc.compile_all_po(op.join('hscommon', 'locale')) loc.merge_locale_dir(op.join('hscommon', 'locale'), 'locale') if op.exists(op.join('build', 'locale')): shutil.rmtree(op.join('build', 'locale')) shutil.copytree('locale', op.join('build', 'locale'), ignore=shutil.ignore_patterns('*.po', '*.pot')) if ui == 'cocoa': print("Creating lproj folders based on .po files") for lang in loc.get_langs('locale'): if lang == 'en': continue pofile = op.join('locale', lang, 'LC_MESSAGES', 'ui.po') for edition_folder in ['base', 'se', 'me', 'pe']: enlproj = op.join('cocoa', edition_folder, 'en.lproj') dest_lproj = op.join('cocoa', edition_folder, lang + '.lproj') loc.po2allxibstrings(pofile, enlproj, dest_lproj) if edition_folder == 'base': loc.po2strings(pofile, op.join(enlproj, 'Localizable.strings'), op.join(dest_lproj, 'Localizable.strings')) pofile = op.join('cocoalib', 'locale', lang, 'LC_MESSAGES', 'cocoalib.po') loc.po2allxibstrings(pofile, op.join('cocoalib', 'en.lproj'), op.join('cocoalib', lang + '.lproj')) build_all_cocoa_locs('cocoalib') build_all_cocoa_locs(op.join('cocoa', 'base')) build_all_cocoa_locs(op.join('cocoa', edition)) elif ui == 'qt': loc.compile_all_po(op.join('qtlib', 'locale')) loc.merge_locale_dir(op.join('qtlib', 'locale'), 'locale') def build_updatepot(): print("Building .pot files from source files") print("Building core.pot") all_cores = ['core', 'core_se', 'core_me', 'core_pe'] loc.generate_pot(all_cores, op.join('locale', 'core.pot'), ['tr']) print("Building columns.pot") loc.generate_pot(all_cores, op.join('locale', 'columns.pot'), ['coltr']) print("Building ui.pot") ui_packages = ['qt', op.join('cocoa', 'inter')] loc.generate_pot(ui_packages, op.join('locale', 'ui.pot'), ['tr']) print("Building hscommon.pot") loc.generate_pot(['hscommon'], op.join('hscommon', 'locale', 'hscommon.pot'), ['tr']) print("Building qtlib.pot") loc.generate_pot(['qtlib'], op.join('qtlib', 'locale', 'qtlib.pot'), ['tr']) print("Enhancing ui.pot with Cocoa's strings files") loc.allstrings2pot(op.join('cocoa', 'base', 'en.lproj'), op.join('locale', 'ui.pot'), excludes={'core', 'message', 'columns'}) loc.allstrings2pot(op.join('cocoa', 'se', 'en.lproj'), op.join('locale', 'ui.pot')) loc.allstrings2pot(op.join('cocoa', 'me', 'en.lproj'), op.join('locale', 'ui.pot')) loc.allstrings2pot(op.join('cocoa', 'pe', 'en.lproj'), op.join('locale', 'ui.pot')) def build_mergepot(): print("Updating .po files using .pot files") loc.merge_pots_into_pos('locale') loc.merge_pots_into_pos(op.join('hscommon', 'locale')) def build_cocoa_proxy_module(): print("Building Cocoa Proxy") import objp.p2o objp.p2o.generate_python_proxy_code('cocoalib/cocoa/CocoaProxy.h', 'build/CocoaProxy.m') exts = [ Extension("CocoaProxy", ['cocoalib/cocoa/CocoaProxy.m', 'build/CocoaProxy.m', 'build/ObjP.m'], extra_link_args=["-framework", "CoreFoundation", "-framework", "Foundation", "-framework", "AppKit"]), ] setup( script_args = ['build_ext', '--inplace'], ext_modules = exts, ) move_all('CocoaProxy*', 'cocoalib/cocoa') def build_cocoa_bridging_interfaces(): print("Building Cocoa Bridging Interfaces") import objp.o2p import objp.p2o add_to_pythonpath('cocoa') add_to_pythonpath('cocoalib') from cocoa.inter import (PyGUIObject, GUIObjectView, PyColumns, ColumnsView, PyOutline, OutlineView, PySelectableList, SelectableListView, PyTable, TableView, PyFairware) from inter.details_panel import PyDetailsPanel, DetailsPanelView from inter.directory_outline import PyDirectoryOutline, DirectoryOutlineView from inter.extra_fairware_reminder import PyExtraFairwareReminder, ExtraFairwareReminderView from inter.prioritize_dialog import PyPrioritizeDialog, PrioritizeDialogView from inter.prioritize_list import PyPrioritizeList, PrioritizeListView from inter.problem_dialog import PyProblemDialog from inter.result_table import PyResultTable, ResultTableView from inter.stats_label import PyStatsLabel, StatsLabelView from inter.app import PyDupeGuruBase, DupeGuruView from inter.app_se import PyDupeGuru allclasses = [PyGUIObject, PyColumns, PyOutline, PySelectableList, PyTable, PyFairware, PyDetailsPanel, PyDirectoryOutline, PyExtraFairwareReminder, PyPrioritizeDialog, PyPrioritizeList, PyProblemDialog, PyResultTable, PyStatsLabel, PyDupeGuruBase, PyDupeGuru] for class_ in allclasses: objp.o2p.generate_objc_code(class_, 'cocoa/autogen', inherit=True) allclasses = [GUIObjectView, ColumnsView, OutlineView, SelectableListView, TableView, DetailsPanelView, DirectoryOutlineView, ExtraFairwareReminderView, PrioritizeDialogView, PrioritizeListView, ResultTableView, StatsLabelView, DupeGuruView] for class_ in allclasses: clsspec = objp.o2p.spec_from_python_class(class_) clsname = class_.__name__ extmodule_path = op.join('build', clsname + '.m') objp.p2o.generate_python_proxy_code_from_clsspec(clsspec, extmodule_path) exts = [ Extension(clsname, [extmodule_path, 'build/ObjP.m'], extra_link_args=["-framework", "Foundation"]), ] setup( script_args = ['build_ext', '--inplace'], ext_modules = exts, ) move_all('*.so', 'cocoa/inter') def build_pe_modules(ui): print("Building PE Modules") exts = [ Extension("_block", [op.join('core_pe', 'modules', 'block.c'), op.join('core_pe', 'modules', 'common.c')]), Extension("_cache", [op.join('core_pe', 'modules', 'cache.c'), op.join('core_pe', 'modules', 'common.c')]), ] if ui == 'qt': exts.append(Extension("_block_qt", [op.join('qt', 'pe', 'modules', 'block.c')])) elif ui == 'cocoa': exts.append(Extension( "_block_osx", [op.join('core_pe', 'modules', 'block_osx.m'), op.join('core_pe', 'modules', 'common.c')], extra_link_args=[ "-framework", "CoreFoundation", "-framework", "Foundation", "-framework", "ApplicationServices",] )) setup( script_args = ['build_ext', '--inplace'], ext_modules = exts, ) move_all('_block_qt*', op.join('qt', 'pe')) move_all('_block*', 'core_pe') move_all('_cache*', 'core_pe') def build_normal(edition, ui, dev): print("Building dupeGuru {0} with UI {1}".format(edition.upper(), ui)) add_to_pythonpath('.') build_help(edition) build_localizations(ui, edition) print("Building dupeGuru") if edition == 'pe': build_pe_modules(ui) if ui == 'cocoa': build_cocoa(edition, dev) elif ui == 'qt': build_qt(edition, dev) def main(): options = parse_args() conf = json.load(open('conf.json')) edition = conf['edition'] ui = conf['ui'] dev = conf['dev'] if dev: print("Building in Dev mode") if options.clean: if op.exists('build'): shutil.rmtree('build') if not op.exists('build'): os.mkdir('build') if options.doc: build_help(edition) elif options.loc: build_localizations(ui, edition) elif options.updatepot: build_updatepot() elif options.mergepot: build_mergepot() else: build_normal(edition, ui, dev) if __name__ == '__main__': main()