def package_source_tgz(): print("Creating git archive") app_version = get_module_version('core') name = 'dupeguru-src-{}.tar'.format(app_version) dest = op.join('build', name) print_and_do('git archive -o {} HEAD'.format(dest)) print_and_do('gzip {}'.format(dest))
def package_debian_distribution(edition, distribution): app_version = get_module_version('core_{}'.format(edition)) version = '{}~{}'.format(app_version, distribution) ed = lambda s: s.format(edition) destpath = op.join('build', 'dupeguru-{0}-{1}'.format(edition, version)) srcpath = op.join(destpath, 'src') packages = ['hscommon', 'core', ed('core_{0}'), 'qtlib', 'qt', 'send2trash', 'jobprogress'] if edition == 'me': packages.append('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('debian', 'build_pe_modules.py'), op.join(destpath, 'build_pe_modules.py')) debdest = op.join(destpath, 'debian') os.makedirs(debdest) debopts = json.load(open(op.join('debian', ed('{}.json')))) for fn in ['compat', 'copyright', 'dirs', 'rules']: copy(op.join('debian', fn), op.join(debdest, fn)) filereplace(op.join('debian', 'control'), op.join(debdest, 'control'), **debopts) filereplace(op.join('debian', 'Makefile'), op.join(destpath, 'Makefile'), **debopts) filereplace(op.join('debian', 'dupeguru.desktop'), op.join(debdest, ed('dupeguru_{}.desktop')), **debopts) changelogpath = op.join('help', ed('changelog_{}')) 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] 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) os.chdir(destpath) cmd = "dpkg-buildpackage -S" os.system(cmd) os.chdir('../..')
def package_debian_distribution(distribution): app_version = get_module_version('core') version = '{}~{}'.format(app_version, distribution) destpath = op.join('build', 'dupeguru-{}'.format(version)) srcpath = op.join(destpath, 'src') packages = [ 'hscommon', 'core', 'qtlib', 'qt', 'send2trash', 'hsaudiotag' ] copy_files_to_package(srcpath, packages, with_so=False) 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, 'dupeguru.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, 'dupeguru.desktop'), **debopts) changelogpath = op.join('help', 'changelog') changelog_dest = op.join(debdest, 'changelog') project_name = debopts['pkgname'] from_version = '2.9.2' build_debian_changelog( changelogpath, changelog_dest, project_name, from_version=from_version, distribution=distribution ) shutil.copy(op.join('images', 'dgse_logo_128.png'), srcpath) os.chdir(destpath) cmd = "dpkg-buildpackage -S" os.system(cmd) os.chdir('../..')
def build_cocoa(dev): sparkle_framework_path = op.join('cocoa', 'Sparkle', 'build', 'Release', 'Sparkle.framework') if not op.exists(sparkle_framework_path): print("Building Sparkle") os.chdir(op.join('cocoa', 'Sparkle')) print_and_do('make build') os.chdir(op.join('..', '..')) print("Creating OS X app structure") app = cocoa_app() app_version = get_module_version('core') cocoa_project_path = 'cocoa' 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') print("Building xibless UIs") build_cocoalib_xibless() build_xibless() print("Building Python extensions") build_cocoa_proxy_module() build_cocoa_bridging_interfaces() print("Building the cocoa layer") copy_embeddable_python_dylib('build') pydep_folder = op.join(app.resources, 'py') if not op.exists(pydep_folder): os.mkdir(pydep_folder) shutil.copy(op.join(cocoa_project_path, 'dg_cocoa.py'), 'build') tocopy = [ 'core', 'hscommon', 'cocoa/inter', 'cocoalib/cocoa', 'objp', 'send2trash', 'hsaudiotag', ] copy_packages(tocopy, pydep_folder, create_links=dev) sys.path.insert(0, 'build') # 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. copy_all('build/inter/*.so', op.join(pydep_folder, 'inter')) if not dev: # Important: Don't ever run delete_files_with_pattern('*.py') on dev builds because you'll # be deleting all py files in symlinked folders. compileall.compile_dir(pydep_folder, force=True, legacy=True) delete_files_with_pattern(pydep_folder, '*.py') delete_files_with_pattern(pydep_folder, '__pycache__') print("Compiling with WAF") os.chdir('cocoa') print_and_do('{0} waf configure && {0} waf'.format(sys.executable)) os.chdir('..') app.copy_executable('cocoa/build/dupeGuru') build_help() print("Copying resources and frameworks") image_path = 'cocoa/dupeguru.icns' resources = [image_path, 'cocoa/dsa_pub.pem', 'build/dg_cocoa.py', 'build/help'] app.copy_resources(*resources, use_symlinks=dev) app.copy_frameworks('build/Python', sparkle_framework_path) print("Creating the run.py file") tmpl = open('cocoa/run_template.py', 'rt').read() run_contents = tmpl.replace('{{app_path}}', app.dest) open('run.py', 'wt').write(run_contents)
def package_source_txz(): print("Creating git archive") app_version = get_module_version("core") name = "dupeguru-src-{}.tar".format(app_version) base_path = os.getcwd() build_path = op.join(base_path, "build") dest = op.join(build_path, name) print_and_do("git archive -o {} HEAD".format(dest)) print_and_do("xz {}".format(dest))
def package_windows(dev): from cx_Freeze import Freezer, Executable app_version = get_module_version('core') if op.exists('dist'): shutil.rmtree('dist') is64bit = platform.architecture()[0] == '64bit' exe = Executable( targetName = 'PdfMasher.exe', script = 'run.py', base = 'Win32GUI', icon = 'images\\main_icon.ico', ) freezer = Freezer( [exe], # Since v4.2.3, cx_freeze started to falsely include tkinter in the package. We exclude it explicitly because of that. excludes = ['tkinter'], ) freezer.Freeze() # Now we have to copy pdfminder's cmap to our root dist dir (We'll set CMAP_PATH env at runtime) import pdfminer.cmap cmap_src = op.dirname(pdfminer.cmap.__file__) cmap_dest = op.join('dist', 'cmap') shutil.copytree(cmap_src, cmap_dest) if not dev: # Copy qt plugins plugin_dest = op.join('dist', 'qt4_plugins') plugin_names = ['accessible', 'codecs', 'iconengines', 'imageformats'] copy_qt_plugins(plugin_names, plugin_dest) # Compress with UPX if not is64bit: # UPX doesn't work on 64 bit libs = [name for name in os.listdir('dist') if op.splitext(name)[1] in ('.pyd', '.dll', '.exe')] for lib in libs: print_and_do("upx --best \"dist\\{0}\"".format(lib)) help_path = 'build\\help' print("Copying {0} to dist\\help".format(help_path)) shutil.copytree(help_path, 'dist\\help') if is64bit: # In 64bit mode, we don't install the VC redist as a prerequisite. We just bundle the # appropriate dlls. shutil.copy(find_in_path('msvcr100.dll'), 'dist') shutil.copy(find_in_path('msvcp100.dll'), 'dist') if not dev: # 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 = 'qt\\installer64.aip' if is64bit else 'qt\\installer.aip' shutil.copy(installer_file, 'installer_tmp.aip') print_and_do('AdvancedInstaller.com /edit installer_tmp.aip /SetVersion {}'.format(app_version)) print_and_do('AdvancedInstaller.com /build installer_tmp.aip -force') os.remove('installer_tmp.aip')
def package_windows(): app_version = get_module_version("core") arch = platform.architecture()[0] # Information to pass to pyinstaller and NSIS match = re.search("[0-9]+.[0-9]+.[0-9]+", app_version) version_array = match.group(0).split(".") match = re.search("[0-9]+", arch) bits = match.group(0) if bits == "64": arch = "x64" else: arch = "x86" # include locale files if they are built otherwise exit as it will break # the localization if not check_loc_doc(): print("Exiting...") return # create version information file from template try: version_template = open("win_version_info.temp", "r") version_info = version_template.read() version_template.close() version_info_file = open("win_version_info.txt", "w") version_info_file.write( version_info.format(version_array[0], version_array[1], version_array[2], bits)) version_info_file.close() except Exception: print("Error creating version info file, exiting...") return # run pyinstaller from here: import PyInstaller.__main__ # UCRT dlls are included if the system has the windows kit installed PyInstaller.__main__.run([ "--name=dupeguru-win{0}".format(bits), "--windowed", "--noconfirm", "--icon=images/dgse_logo.ico", "--add-data={0};locale".format(LOCALE_DIR), "--add-data={0};help".format(HELP_DIR), "--version-file=win_version_info.txt", "--paths=C:\\Program Files (x86)\\Windows Kits\\10\\Redist\\ucrt\\DLLs\\{0}" .format(arch), ENTRY_SCRIPT, ]) # remove version info file os.remove("win_version_info.txt") # Call NSIS (TODO update to not use hardcoded path) cmd = ( '"C:\\Program Files (x86)\\NSIS\\Bin\\makensis.exe" ' "/DVERSIONMAJOR={0} /DVERSIONMINOR={1} /DVERSIONPATCH={2} /DBITS={3} setup.nsi" ) print_and_do( cmd.format(version_array[0], version_array[1], version_array[2], bits))
def package_source_tgz(edition): 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) dest = op.join('build', name) print_and_do('git archive -o {} HEAD'.format(dest)) print("Adding dependencies and wrapping up") print_and_do('tar -rf {} deps'.format(dest)) print_and_do('gzip {}'.format(dest))
def package_windows(edition, dev): if not ISWINDOWS: print("Qt packaging only works under Windows.") return add_to_pythonpath('.') app_version = get_module_version('core_{}'.format(edition)) distdir = 'dist' if op.exists(distdir): shutil.rmtree(distdir) is64bit = platform.architecture()[0] == '64bit' # Since v4.2.3, cx_freeze started to falsely include tkinter in the package. We exclude it explicitly because of that. cmd = 'cxfreeze --base-name Win32GUI --target-dir "{0}" --target-name "{1}.exe" --icon {2} --exclude-modules tkinter run.py' target_name = {'se': 'dupeGuru', 'me': 'dupeGuru ME', 'pe': 'dupeGuru PE'}[edition] icon_path = 'images\\dg{0}_logo.ico'.format(edition) print_and_do(cmd.format(distdir, target_name, icon_path)) if not dev: # Copy qt plugins plugin_dest = op.join(distdir, 'qt4_plugins') plugin_names = ['accessible', 'codecs', 'iconengines', 'imageformats'] copy_qt_plugins(plugin_names, plugin_dest) # Compress with UPX if not is64bit: # UPX doesn't work on 64 bit libs = [name for name in os.listdir(distdir) if op.splitext(name)[1] in ('.pyd', '.dll', '.exe')] for lib in libs: print_and_do("upx --best \"{0}\"".format(op.join(distdir, lib))) 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')) if is64bit: # In 64bit mode, we don't install the VC redist as a prerequisite. We just bundle the # appropriate dlls. shutil.copy(find_in_path('msvcr100.dll'), distdir) shutil.copy(find_in_path('msvcp100.dll'), distdir) # 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 = 'installer64.aip' if is64bit else '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 build_cocoa(dev): app = OSXAppStructure('build/PdfMasher.app') print('Generating Info.plist') app_version = get_module_version('core') filereplace('cocoa/InfoTemplate.plist', 'cocoa/Info.plist', version=app_version) app.create('cocoa/Info.plist') print("Building the cocoa layer") build_cocoalib_xibless() build_xibless() pydep_folder = op.join(app.resources, 'py') if not op.exists(pydep_folder): os.mkdir(pydep_folder) build_cocoa_proxy_module() build_cocoa_bridging_interfaces() copy_embeddable_python_dylib('build') tocopy = [ 'core', 'ebooks', 'hscommon', 'cocoa/inter', 'cocoalib/cocoa', 'jobprogress', 'objp', 'cssutils', 'cssselect', 'pdfminer', 'lxml', 'ply', 'markdown', 'encutils' ] copy_packages(tocopy, pydep_folder, create_links=dev) copy('cocoa/pyplugin.py', 'build/pyplugin.py') sys.path.insert(0, 'build') collect_stdlib_dependencies('build/pyplugin.py', pydep_folder) del sys.path[0] # Views are not referenced by python code, so they're not found by the collector. copy_all('build/inter/*.so', op.join(pydep_folder, 'inter')) copy_sysconfig_files_for_embed(pydep_folder) if not dev: # Important: Don't ever run delete_files_with_pattern('*.py') on dev builds because you'll # be deleting all py files in symlinked folders. compileall.compile_dir(pydep_folder, force=True, legacy=True) delete_files_with_pattern(pydep_folder, '*.py') delete_files_with_pattern(pydep_folder, '__pycache__') os.chdir('cocoa') print("Compiling with WAF") os.system('{0} waf configure && {0} waf'.format(sys.executable)) os.chdir('..') print("Creating the .app folder") app.copy_executable('cocoa/build/PdfMasher') resources = [ 'images/main_icon.icns', 'cocoa/dsa_pub.pem', 'build/pyplugin.py', 'build/help' ] app.copy_resources(*resources, use_symlinks=dev) app.copy_frameworks('build/Python', 'cocoalib/Sparkle.framework') print("Creating the run.py file") copy('cocoa/runtemplate.py', 'run.py')
def build_cocoa(dev): build_localizations() build_cocoa_proxy_module() build_cocoa_bridging_interfaces() app_version = get_module_version('core') cocoa_project_path = 'cocoa' filereplace(op.join(cocoa_project_path, 'InfoTemplate.plist'), op.join('build', 'Info.plist'), version=app_version) copy_embeddable_python_dylib('build') if not op.exists('build/PythonHeaders'): os.symlink(op.dirname(sysconfig.get_config_h_filename()), 'build/PythonHeaders') build_help() pydep_folder = op.join('build', 'py') if not op.exists(pydep_folder): os.mkdir(pydep_folder) shutil.copy(op.join(cocoa_project_path, 'dg_cocoa.py'), 'build') tocopy = [ 'dupeguru/core', 'dupeguru/hscommon', 'cocoa/inter', 'cocoalib/cocoa', 'objp', 'send2trash', 'hsaudiotag', ] copy_packages(tocopy, pydep_folder, create_links=dev) sys.path.insert(0, 'build') # 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. copy_all('build/inter/*.so', op.join(pydep_folder, 'inter')) if not dev: # Important: Don't ever run delete_files_with_pattern('*.py') on dev builds because you'll # be deleting all py files in symlinked folders. compileall.compile_dir(pydep_folder, force=True, legacy=True) delete_files_with_pattern(pydep_folder, '*.py') delete_files_with_pattern(pydep_folder, '__pycache__') print_and_do('xcodebuild')
def package_debian_distribution(distribution): app_version = get_module_version('core') version = '{}~{}'.format(app_version, distribution) destpath = op.join('build', 'pdfmasher-{}'.format(version)) srcpath = op.join(destpath, 'src') copy_cource_files(srcpath, ['qt', 'ebooks', 'hscommon', 'core', 'qtlib', 'pdfminer', 'ply', 'jobprogress', 'markdown', 'cssutils', 'cssselect', 'encutils']) shutil.copytree('debian', op.join(destpath, 'debian')) move(op.join(destpath, 'debian', 'Makefile'), op.join(destpath, 'Makefile')) build_debian_changelog(op.join('help', 'changelog'), op.join(destpath, 'debian', 'changelog'), 'pdfmasher', from_version='0.1.0', distribution=distribution) shutil.copytree(op.join('build', 'help'), op.join(srcpath, 'help')) os.chdir(destpath) cmd = "dpkg-buildpackage -S" os.system(cmd) os.chdir('../..')
def package_debian_distribution(edition, distribution): app_version = get_module_version('core_{}'.format(edition)) version = '{}~{}'.format(app_version, distribution) ed = lambda s: s.format(edition) destpath = op.join('build', 'dupeguru-{0}-{1}'.format(edition, version)) srcpath = op.join(destpath, 'src') packages = [ 'hscommon', 'core', ed('core_{0}'), 'qtlib', 'qt', 'send2trash' ] if edition == 'me': packages.append('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')) debdest = op.join(destpath, 'debian') debskel = op.join('pkg', 'debian') os.makedirs(debdest) debopts = json.load(open(op.join(debskel, ed('{}.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_{}')) 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] 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) os.chdir(destpath) cmd = "dpkg-buildpackage -S" os.system(cmd) os.chdir('../..')
def package_debian_distribution(distribution): app_version = get_module_version("core") version = "{}~{}".format(app_version, distribution) destpath = op.join("build", "dupeguru-{}".format(version)) srcpath = op.join(destpath, "src") packages = ["hscommon", "core", "qtlib", "qt", "send2trash", "hsaudiotag"] copy_files_to_package(srcpath, packages, with_so=False) 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, "dupeguru.json"))) for fn in ["compat", "copyright", "dirs", "rules", "source"]: 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, "dupeguru.desktop"), **debopts) changelogpath = op.join("help", "changelog") changelog_dest = op.join(debdest, "changelog") project_name = debopts["pkgname"] from_version = "2.9.2" build_debian_changelog( changelogpath, changelog_dest, project_name, from_version=from_version, distribution=distribution, ) shutil.copy(op.join("images", "dgse_logo_128.png"), srcpath) os.chdir(destpath) cmd = "dpkg-buildpackage -F -us -uc" os.system(cmd) os.chdir("../..")
def package_source_tgz(): print("Creating git archive") app_version = get_module_version('core') name = 'dupeguru-src-{}.tar'.format(app_version) base_path = os.getcwd() build_path = op.join(base_path, 'build') dest = op.join(build_path, name) print_and_do('git archive -o {} HEAD'.format(dest)) # Now, we need to include submodules SUBMODULES = ['hscommon', 'qtlib'] for submodule in SUBMODULES: print("Adding submodule {} to archive".format(submodule)) os.chdir(submodule) archive_path = op.join(build_path, '{}.tar'.format(submodule)) print_and_do('git archive -o {} --prefix {}/ HEAD'.format(archive_path, submodule)) os.chdir(base_path) print_and_do('tar -A {} -f {}'.format(archive_path, dest)) print_and_do('gzip {}'.format(dest))
def package_windows(): app_version = get_module_version('core') arch = platform.architecture()[0] # Information to pass to pyinstaller and NSIS match = re.search('[0-9]+.[0-9]+.[0-9]+', app_version) version_array = match.group(0).split('.') match = re.search('[0-9]+', arch) bits = match.group(0) # include locale files if they are built otherwise exit as it will break # the localization if not op.exists('build/locale'): print("Locale files not built, exiting...") return # include help files if they are built otherwise exit as they should be included? if not op.exists('build/help'): print("Help files not built, exiting...") return # create version information file from template try: version_template = open("win_version_info.temp", "r") version_info = version_template.read() version_template.close() version_info_file = open("win_version_info.txt", "w") version_info_file.write( version_info.format(version_array[0], version_array[1], version_array[2], bits)) version_info_file.close() except Exception: print("Error creating version info file, exiting...") return # run pyinstaller via command line print_and_do( 'pyinstaller -w --name=dupeguru-win{0} --icon=images/dgse_logo.ico ' '--add-data "build/locale;locale" --add-data "build/help;help" ' '--version-file win_version_info.txt run.py'.format(bits)) # remove version info file os.remove('win_version_info.txt') # Call NSIS (TODO update to not use hardcoded path) cmd = ( '"C:\\Program Files (x86)\\NSIS\\Bin\\makensis.exe" ' '/DVERSIONMAJOR={0} /DVERSIONMINOR={1} /DVERSIONPATCH={2} /DBITS={3} setup.nsi' ) print_and_do( cmd.format(version_array[0], version_array[1], version_array[2], bits))
def package_source_tgz(): print("Creating git archive") app_version = get_module_version('core') name = 'dupeguru-src-{}.tar'.format(app_version) base_path = os.getcwd() build_path = op.join(base_path, 'build') dest = op.join(build_path, name) print_and_do('git archive -o {} HEAD'.format(dest)) # Now, we need to include submodules SUBMODULES = ['hscommon', 'qtlib', 'cocoalib'] for submodule in SUBMODULES: print("Adding submodule {} to archive".format(submodule)) os.chdir(submodule) archive_path = op.join(build_path, '{}.tar'.format(submodule)) print_and_do('git archive -o {} --prefix {}/ HEAD'.format( archive_path, submodule)) os.chdir(base_path) print_and_do('tar -A {} -f {}'.format(archive_path, dest)) print_and_do('gzip {}'.format(dest))
def build_cocoa(dev): app = OSXAppStructure('build/PdfMasher.app') print('Generating Info.plist') app_version = get_module_version('core') filereplace('cocoa/InfoTemplate.plist', 'cocoa/Info.plist', version=app_version) app.create('cocoa/Info.plist') print("Building the cocoa layer") build_cocoalib_xibless() build_xibless() pydep_folder = op.join(app.resources, 'py') if not op.exists(pydep_folder): os.mkdir(pydep_folder) build_cocoa_proxy_module() build_cocoa_bridging_interfaces() copy_embeddable_python_dylib('build') tocopy = ['core', 'ebooks', 'hscommon', 'cocoa/inter', 'cocoalib/cocoa', 'jobprogress', 'objp', 'cssutils', 'cssselect', 'pdfminer', 'lxml', 'ply', 'markdown', 'encutils'] copy_packages(tocopy, pydep_folder, create_links=dev) copy('cocoa/pyplugin.py', 'build/pyplugin.py') sys.path.insert(0, 'build') collect_stdlib_dependencies('build/pyplugin.py', pydep_folder) del sys.path[0] # Views are not referenced by python code, so they're not found by the collector. copy_all('build/inter/*.so', op.join(pydep_folder, 'inter')) copy_sysconfig_files_for_embed(pydep_folder) if not dev: # Important: Don't ever run delete_files_with_pattern('*.py') on dev builds because you'll # be deleting all py files in symlinked folders. compileall.compile_dir(pydep_folder, force=True, legacy=True) delete_files_with_pattern(pydep_folder, '*.py') delete_files_with_pattern(pydep_folder, '__pycache__') os.chdir('cocoa') print("Compiling with WAF") os.system('{0} waf configure && {0} waf'.format(sys.executable)) os.chdir('..') print("Creating the .app folder") app.copy_executable('cocoa/build/PdfMasher') resources = ['images/main_icon.icns', 'cocoa/dsa_pub.pem', 'build/pyplugin.py', 'build/help'] app.copy_resources(*resources, use_symlinks=dev) app.copy_frameworks('build/Python', 'cocoalib/Sparkle.framework') print("Creating the run.py file") copy('cocoa/runtemplate.py', 'run.py')
def package_debian_distribution(distribution): app_version = get_module_version('core') version = '{}~{}'.format(app_version, distribution) destpath = op.join('build', 'dupeguru-{}'.format(version)) srcpath = op.join(destpath, 'src') packages = ['hscommon', 'core', 'qtlib', 'qt', 'send2trash', 'hsaudiotag'] copy_files_to_package(srcpath, packages, with_so=False) 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, 'dupeguru.json'))) for fn in ['compat', 'copyright', 'dirs', 'rules', 'source']: 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, 'dupeguru.desktop'), **debopts) changelogpath = op.join('help', 'changelog') changelog_dest = op.join(debdest, 'changelog') project_name = debopts['pkgname'] from_version = '2.9.2' build_debian_changelog(changelogpath, changelog_dest, project_name, from_version=from_version, distribution=distribution) shutil.copy(op.join('images', 'dgse_logo_128.png'), srcpath) os.chdir(destpath) cmd = "dpkg-buildpackage -S -us -uc" os.system(cmd) os.chdir('../..')
def package_debian_distribution(distribution): app_version = get_module_version('core') version = '{}~{}'.format(app_version, distribution) destpath = op.join('build', 'pdfmasher-{}'.format(version)) srcpath = op.join(destpath, 'src') copy_cource_files(srcpath, [ 'qt', 'ebooks', 'hscommon', 'core', 'qtlib', 'pdfminer', 'ply', 'jobprogress', 'markdown', 'cssutils', 'cssselect', 'encutils' ]) shutil.copytree('debian', op.join(destpath, 'debian')) move(op.join(destpath, 'debian', 'Makefile'), op.join(destpath, 'Makefile')) build_debian_changelog(op.join('help', 'changelog'), op.join(destpath, 'debian', 'changelog'), 'pdfmasher', from_version='0.1.0', distribution=distribution) shutil.copytree(op.join('build', 'help'), op.join(srcpath, 'help')) os.chdir(destpath) cmd = "dpkg-buildpackage -S" os.system(cmd) os.chdir('../..')
def package_windows(): app_version = get_module_version('core') arch = platform.architecture()[0] # Information to pass to pyinstaller and NSIS match = re.search('[0-9]+.[0-9]+.[0-9]+', app_version) version_array = match.group(0).split('.') match = re.search('[0-9]+', arch) bits = match.group(0) # include locale files if they are built otherwise exit as it will break # the localization if not op.exists('build/locale'): print("Locale files not built, exiting...") return # include help files if they are built otherwise exit as they should be included? if not op.exists('build/help'): print("Help files not built, exiting...") return # create version information file from template try: version_template = open("win_version_info.temp", "r") version_info = version_template.read() version_template.close() version_info_file = open("win_version_info.txt", "w") version_info_file.write(version_info.format(version_array[0], version_array[1], version_array[2], bits)) version_info_file.close() except Exception: print("Error creating version info file, exiting...") return # run pyinstaller via command line print_and_do('pyinstaller -w --name=dupeguru-win{0} --icon=images/dgse_logo.ico ' '--add-data "build/locale;locale" --add-data "build/help;help" ' '--version-file win_version_info.txt run.py'.format(bits)) # remove version info file os.remove('win_version_info.txt') # Call NSIS (TODO update to not use hardcoded path) cmd = ('"C:\\Program Files (x86)\\NSIS\\Bin\\makensis.exe" ' '/DVERSIONMAJOR={0} /DVERSIONMINOR={1} /DVERSIONPATCH={2} /DBITS={3} setup.nsi') print_and_do(cmd.format(version_array[0], version_array[1], version_array[2], bits))
def build_cocoa(edition, 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/{}') 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) print("Building xibless UIs") build_cocoalib_xibless() build_xibless(edition) print("Building Python extensions") build_cocoa_proxy_module() build_cocoa_bridging_interfaces(edition) print("Building the cocoa layer") copy_embeddable_python_dylib('build') pydep_folder = op.join(app.resources, 'py') if not op.exists(pydep_folder): 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 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'] 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. copy_all('build/inter/*.so', op.join(pydep_folder, 'inter')) if not dev: # Important: Don't ever run delete_files_with_pattern('*.py') on dev builds because you'll # be deleting all py files in symlinked folders. compileall.compile_dir(pydep_folder, force=True, legacy=True) delete_files_with_pattern(pydep_folder, '*.py') delete_files_with_pattern(pydep_folder, '__pycache__') print("Compiling with WAF") os.chdir('cocoa') print_and_do(cocoa_compile_command(edition)) os.chdir('..') app.copy_executable('cocoa/build/dupeGuru') build_help(edition) print("Copying resources and frameworks") image_path = ed('cocoa/{}/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') print("Creating the run.py file") tmpl = open('cocoa/run_template.py', 'rt').read() run_contents = tmpl.replace('{{app_path}}', app.dest) open('run.py', 'wt').write(run_contents)
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 package_source_tgz(edition): app_version = get_module_version('core_{}'.format(edition)) name = 'dupeguru-{}-src-{}.tar.gz'.format(edition, app_version) dest = op.join('build', name) print_and_do('git archive -o {} HEAD'.format(dest))
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 package_windows(): from cx_Freeze import setup, Executable app_version = get_module_version('core') arch = platform.architecture()[0] buildpath = op.join('build', 'dupeguru-win{}'.format(arch)) # remove existing build directory if op.exists(buildpath): shutil.rmtree(buildpath) include_files = [] # include locale files if they are built otherwise exit as it will break # the localization if op.exists('build/locale'): include_files.append(('build/locale', 'locale')) else: print("Locale files not built, exiting...") return # include help files if they are built otherwise exit as they should be included? if op.exists('build/help'): include_files.append(('build/help', 'help')) else: print("Help files not built, exiting...") return # options for cx_Freeze # if zip_include packages is not used, the cx_Freeze packager will include # the whole PyQT5 directory options = { 'build_exe': { 'build_exe': buildpath, 'excludes': [], 'includes': ['atexit'], 'include_files': include_files, 'include_msvcr': True, 'zip_include_packages': ['*'], 'zip_exclude_packages': [] }, } # executables to build, uses se edition icon executables = [ Executable(script='run.py', base='Win32GUI', targetName='dupeguru.exe', icon='images/dgse_logo.ico', copyright='Copyright (C) 2017 Hardcoded Software') ] # call cx_freeze setup(name='dupeguru', version=app_version, description='Tool to find duplicate files on your computer.', options=options, executables=executables, script_args=['build']) # Information to pass to NSIS version_array = app_version.split('.') match = re.search('[0-9]+', arch) bits = match.group(0) # Call NSIS (TODO update to not use hardcoded path) cmd = ( '"C:\\Program Files (x86)\\NSIS\\Bin\\makensis.exe" ' '/DVERSIONMAJOR={0} /DVERSIONMINOR={1} /DVERSIONPATCH={2} /DBITS={3} setup.nsi' ) print_and_do( cmd.format(version_array[0], version_array[1], version_array[2], bits))
def package_windows(): from cx_Freeze import setup, Executable app_version = get_module_version('core') arch = platform.architecture()[0] buildpath = op.join('build', 'dupeguru-win{}'.format(arch)) # remove existing build directory if op.exists(buildpath): shutil.rmtree(buildpath) include_files = [] # include locale files if they are built otherwise exit as it will break # the localization if op.exists('build/locale'): include_files.append(('build/locale', 'locale')) else: print("Locale files not built, exiting...") return # include help files if they are built otherwise exit as they should be included? if op.exists('build/help'): include_files.append(('build/help', 'help')) else: print("Help files not built, exiting...") return # options for cx_Freeze # if zip_include packages is not used, the cx_Freeze packager will include # the whole PyQT5 directory options = { 'build_exe': { 'build_exe': buildpath, 'excludes': [], 'includes': ['atexit', 'dbm.dumb'], 'include_files': include_files, 'include_msvcr': True, 'zip_include_packages': ['*'], 'zip_exclude_packages': [] }, } # executables to build, uses se edition icon executables = [ Executable( script='run.py', base='Win32GUI', targetName='dupeguru.exe', icon='images/dgse_logo.ico', copyright='Copyright (C) 2017 Hardcoded Software' ) ] # call cx_freeze setup( name='dupeguru', version=app_version, description='Tool to find duplicate files on your computer.', options=options, executables=executables, script_args=['build'] ) # Information to pass to NSIS version_array = app_version.split('.') match = re.search('[0-9]+', arch) bits = match.group(0) # Call NSIS (TODO update to not use hardcoded path) cmd = ('"C:\\Program Files (x86)\\NSIS\\Bin\\makensis.exe" ' '/DVERSIONMAJOR={0} /DVERSIONMINOR={1} /DVERSIONPATCH={2} /DBITS={3} setup.nsi') print_and_do(cmd.format(version_array[0], version_array[1], version_array[2], bits))
def build_cocoa(edition, 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/{}') 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) print("Building xibless UIs") build_cocoalib_xibless() build_xibless(edition) print("Building Python extensions") build_cocoa_proxy_module() build_cocoa_bridging_interfaces(edition) print("Building the cocoa layer") copy_embeddable_python_dylib('build') pydep_folder = op.join(app.resources, 'py') if not op.exists(pydep_folder): 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', 'jobprogress', 'objp', 'send2trash'] + specific_packages 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'] 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. copy_all('build/inter/*.so', op.join(pydep_folder, 'inter')) copy_sysconfig_files_for_embed(pydep_folder) if not dev: # Important: Don't ever run delete_files_with_pattern('*.py') on dev builds because you'll # be deleting all py files in symlinked folders. compileall.compile_dir(pydep_folder, force=True, legacy=True) delete_files_with_pattern(pydep_folder, '*.py') delete_files_with_pattern(pydep_folder, '__pycache__') print("Compiling with WAF") os.chdir('cocoa') print_and_do(cocoa_compile_command(edition)) os.chdir('..') app.copy_executable('cocoa/build/dupeGuru') print("Copying resources and frameworks") image_path = ed('cocoa/{}/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') print("Creating the run.py file") tmpl = open('cocoa/run_template.py', 'rt').read() run_contents = tmpl.replace('{{app_path}}', app.dest) open('run.py', 'wt').write(run_contents)