""" Use with: python3 setup.py build_exe --no-compress -O1 """ import sys import os import site import subprocess import tempfile import atexit import shutil import zipfile import cx_Freeze sys.path.insert(0, "dist") import gramps from gramps.version import VERSION_TUPLE try: from gramps.version import VERSION_QUALIFIER except: VERSION_QUALIFIER = "" UPX_ALT_PATH = r"UPX" # import logging # logging.basicConfig(level=logging.DEBUG) VQ = { "-alpha1": 10, "-alpha2": 11, "-alpha3": 12, "-beta1": 21, "-beta2": 22, "-beta3": 23, "-rc1": 22, "": 0, } VERSION = ".".join(map(str, VERSION_TUPLE)) + "." + str(VQ.get(VERSION_QUALIFIER, 99)) COPYRIGHT = "Copyright 2020, Gramps developers. GNU General Public License" # Prepare a temporay directory TEMP_DIR = tempfile.TemporaryDirectory() atexit.register(TEMP_DIR.cleanup) BASE_DIR = os.path.split(sys.prefix)[1] SETUP_DIR = os.path.dirname(os.path.realpath(__file__)) SETUP_FILES = [ "setup.py", "gramps.ico", "grampsc.ico", "grampsd.ico", "grampsaioc.py", "grampsaiocd.py", "grampsaiow.py", ] if "32" in BASE_DIR: SETUP_FILES.append("".join(("grampsaio", "32", ".nsi"))) else: SETUP_FILES.append("".join(("grampsaio", "64", ".nsi"))) INCLUDE_DLL_PATH = os.path.join(sys.exec_prefix, "bin") INCLUDE_FILES = [] INCLUDES = ["gi", "cgi", "colorsys", "site"] PACKAGES = [ "gi", "cairo", "xml", "bsddb3", "lxml", "PIL", "json", "csv", "sqlite3", "cProfile", "networkx", "psycopg2", "requests", "logging", "html", "compileall", "graphviz", "pydotplus", "pygraphviz", "pydot", ] EXCLUDES = [ "tkinter", "PyQt5", "PyQt5.QtCore", "PyQt5.QtGui", "pyside" "PyQt5.QtWidgets", "sip", "lib2to3", "PIL.ImageQt", "pip", "distlib", ] REPLACE_PATHS = [ ("*", "AIO/"), ( site.getsitepackages()[0] + "cx_freeze-5.0-py3.6-mingw.egg/cx_Freeze", "cx_Freeze/", ), ] MISSING_DLL = [ "libgtk-3-0.dll", "libgtkspell3-3-0.dll", "libgexiv2-2.dll", "libgoocanvas-3.0-9.dll", "libosmgpsmap-1.0-1.dll", "gswin32c.exe", "dot.exe", "libgvplugin_core-6.dll", "libgvplugin_dot_layout-6.dll", "libgvplugin_gd-6.dll", "libgvplugin_pango-6.dll", "libgvplugin_rsvg-6.dll", "glib-compile-schemas.exe", "gdk-pixbuf-query-loaders.exe", "gtk-update-icon-cache-3.0.exe", "fc-cache.exe", "fc-match.exe", "gspawn-win64-helper-console.exe", "gspawn-win64-helper.exe", "libgeocode-glib-0.dll", ] BIN_EXCLUDES = ["Qt5Core.dll", "gdiplus.dll", "gdiplus"] from os.path import dirname, basename import lib2to3 lib23_path = dirname(lib2to3.__file__) INCLUDE_FILES.append((lib23_path, "lib/lib2to3")) import pip libpip_path = dirname(pip.__file__) INCLUDE_FILES.append((libpip_path, "lib/pip")) import distlib libdistlib_path = dirname(distlib.__file__) INCLUDE_FILES.append((libdistlib_path, "lib/distlib")) os.makedirs(os.path.join(BASE_DIR, "var/cache/fontconfig"), exist_ok=True) for file in SETUP_FILES: INCLUDE_FILES.append((os.path.join(SETUP_DIR, file), os.path.join("src", file))) for dll in MISSING_DLL: INCLUDE_FILES.append( (os.path.join(INCLUDE_DLL_PATH, dll), os.path.join("lib", dll)) ) MISSING_LIBS = [ "lib/enchant-2", "lib/gdk-pixbuf-2.0", "lib/girepository-1.0", "share/enchant", "share/glib-2.0/schemas", "share/xml/iso-codes", "etc/gtk-3.0", "etc/ssl/certs", "etc/ssl/cert.pem", "etc/fonts", "lib/gio", "share/icons/gnome", "share/icons/hicolor", "share/icons/gramps.png", "share/icons/Adwaita/icon-theme.cache", "share/icons/Adwaita/index.theme", "share/hunspell", ] ADWAITA = [ "8x8", "16x16", "22x22", "24x24", "32x32", "48x48", "64x64", "96x96", "cursors", ] for adw in ADWAITA: INCLUDE_FILES.append( ( os.path.join(sys.prefix, "share/icons/Adwaita", adw), os.path.join("share/icons/Adwaita", adw), ) ) for lib in MISSING_LIBS: INCLUDE_FILES.append((os.path.join(sys.prefix, lib), lib)) INCLUDE_FILES.append("dist/gramps") INCLUDE_FILES.append( ("dist/gramps-" + ".".join(map(str, VERSION_TUPLE)) + ".data/data/share", "share") ) EXECUTABLES = [ cx_Freeze.Executable( "grampsaioc.py", base="Console", target_name="gramps.exe", icon="gramps.ico", copyright=COPYRIGHT, ), cx_Freeze.Executable( "grampsaiow.py", base="Win32GUI", target_name="grampsw.exe", icon="gramps.ico", copyright=COPYRIGHT, ), cx_Freeze.Executable( "grampsaiocd.py", base="Console", target_name="grampsd.exe", icon="grampsd.ico", copyright=COPYRIGHT, ), ] BUILD_EXE_OPTIONS = { "packages": PACKAGES, "includes": INCLUDES, "excludes": EXCLUDES, "include_files": INCLUDE_FILES, "bin_includes": MISSING_DLL, "zip_include_packages": "*", # ZIP_INCLUDE_PACKAGES, "zip_exclude_packages": EXCLUDES, "bin_excludes": BIN_EXCLUDES, "replace_paths": REPLACE_PATHS, "build_exe": BASE_DIR, } BDIST_MSI_OPTIONS = { # uuid.uuid5(uuid.NAMESPACE_DNS, 'GrampsAIO64-5-trunk') "upgrade_code": "{fbccc04b-7b2e-56d3-8bb7-94d5f68de822}", # uuid.uuid5(uuid.NAMESPACE_DNS, 'v5.0.0-alpha1-476-g473d3aa') "product_code": "{48304362-2945-5a10-ad60-241f233be4d2}", "add_to_path": False, #'initial_target_dir': r'[ProgramFilesFolder]\%s\%s' % # (company_name, product_name), } cx_Freeze.setup( name="GrampsAIO32" if "32" in BASE_DIR else "GrampsAIO64", options={"build_exe": BUILD_EXE_OPTIONS, "bdist_msi": BDIST_MSI_OPTIONS}, version=VERSION, description="Gramps Genealogy software", long_description=VERSION_QUALIFIER, executables=EXECUTABLES, ) ZIN = zipfile.ZipFile(os.path.join(BASE_DIR, "lib/library.zip"), "r") ZOUT = zipfile.ZipFile(os.path.join(BASE_DIR, "lib/pythonx.zip"), "w") for item in ZIN.infolist(): if not os.path.dirname(item.filename).startswith("gramps"): # if '/test' in item.filename or 'test/' in item.filename: # print("Zip Excluded:", item.filename) # else: print("Zip Included:", item.filename) buffer = ZIN.read(item.filename) ZOUT.writestr(item, buffer) ZOUT.close() ZIN.close() shutil.move( os.path.join(BASE_DIR, "lib/pythonx.zip"), os.path.join(BASE_DIR, "lib/library.zip") ) if os.path.isfile(UPX_ALT_PATH): UPX = UPX_ALT_PATH else: WHICH = "where" if os.name == "nt" else "which" try: subprocess.check_call([WHICH, "UPX"]) except subprocess.CalledProcessError: UPX = None else: UPX = "upx" if UPX is not None: ARGS = [UPX, "-7", "--no-progress"] ARGS.extend( os.path.join(BASE_DIR, filename) for filename in os.listdir(BASE_DIR) if filename == "name" or os.path.splitext(filename)[1].lower() in (".exe", ".dll", ".pyd", ".so") and os.path.splitext(filename)[0].lower() not in ("libgcc_s_dw2-1", "gramps", "grampsw", "grampsd", "libwinpthread-1") ) subprocess.call(ARGS) else: print("\nUPX not found")