diff --git a/.gitignore b/.gitignore index 439b333d..5e7c7043 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ cocoa/autogen /help/*/changelog.rst *.pyd -*.exe \ No newline at end of file +*.exe +*.spec \ No newline at end of file diff --git a/package.py b/package.py index 9561bcc5..51de369c 100644 --- a/package.py +++ b/package.py @@ -114,64 +114,38 @@ def package_source_tgz(): print_and_do('gzip {}'.format(dest)) 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 + # Information to pass to pyinstaller and NSIS version_array = app_version.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') diff --git a/requirements-windows.txt b/requirements-windows.txt index a433328e..fe6a53af 100644 --- a/requirements-windows.txt +++ b/requirements-windows.txt @@ -1,3 +1,3 @@ PyQt5 >=5.4,<6.0 -cx-Freeze>=5.1.1 -pypiwin32>=200 \ No newline at end of file +pypiwin32>=200 +pyinstaller>=3.4,<4.0 \ No newline at end of file diff --git a/setup.nsi b/setup.nsi index 289b7ebd..9c1fbdc5 100644 --- a/setup.nsi +++ b/setup.nsi @@ -34,7 +34,7 @@ SetCompressor /SOLID lzma !endif !ifndef SOURCEPATH !echo "SOURCEPATH is NOT defined" - !define SOURCEPATH "build" + !define SOURCEPATH "dist" !endif !ifndef VERSIONMAJOR | VERSIONMINOR | VERSIONPATCH | BITS | SOURCEPATH !error "Command line Defines missing use /DDEFINE=VALUE to define before script" @@ -161,12 +161,12 @@ Section "!Application" AppSec SetOutPath "$INSTDIR" ; set from result of installer pages ; Files to install - File /r "${SOURCEPATH}\${APPNAME}-win${BITS}bit\*" + File /r "${SOURCEPATH}\${APPNAME}-win${BITS}\*" ; Create Start Menu Items !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateDirectory "$SMPROGRAMS\$StartMenuFolder" - CreateShortcut "$SMPROGRAMS\$StartMenuFolder\${APPNAME}.lnk" "$INSTDIR\${APPNAME}.exe" + CreateShortcut "$SMPROGRAMS\$StartMenuFolder\${APPNAME}.lnk" "$INSTDIR\${APPNAME}-win${BITS}.exe" CreateShortcut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe" !insertmacro MUI_STARTMENU_WRITE_END @@ -223,15 +223,16 @@ Section "Uninstall" RMDir /r "$SMPROGRAMS\$StartMenuFolder" ; Remove Files & Folders in Install Folder + RMDir /r "$INSTDIR\core" RMDir /r "$INSTDIR\help" - RMDir /r "$INSTDIR\imageformats" - RMDir /r "$INSTDIR\lib" + RMDir /r "$INSTDIR\PyQt5" + RMDir /r "$INSTDIR\qt" RMDir /r "$INSTDIR\locale" - RMDir /r "$INSTDIR\platforms" - Delete "$INSTDIR\dupeguru.exe" - Delete "$INSTDIR\python36.dll" - Delete "$INSTDIR\sqlite3.dll" - Delete "$INSTDIR\Uninstall.exe" + Delete "$INSTDIR\*.exe" + Delete "$INSTDIR\*.dll" + Delete "$INSTDIR\*.pyd" + Delete "$INSTDIR\*.zip" + Delete "$INSTDIR\*.manifest" ; Remove Install Folder if empty RMDir "$INSTDIR" diff --git a/win_version_info.temp b/win_version_info.temp new file mode 100644 index 00000000..7a3ee4ec --- /dev/null +++ b/win_version_info.temp @@ -0,0 +1,43 @@ +# UTF-8 +# +# For more details about fixed file info 'ffi' see: +# http://msdn.microsoft.com/en-us/library/ms646997.aspx +VSVersionInfo( + ffi=FixedFileInfo( + # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) + # Set not needed items to zero 0. + filevers=({0}, {1}, {2}, 0), + prodvers=({0}, {1}, {2}, 0), + # Contains a bitmask that specifies the valid bits 'flags'r + mask=0x3f, + # Contains a bitmask that specifies the Boolean attributes of the file. + flags=0x0, + # The operating system for which this file was designed. + # 0x4 - NT and there is no need to change it. + OS=0x40004, + # The general type of file. + # 0x1 - the file is an application. + fileType=0x1, + # The function of the file. + # 0x0 - the function is not defined for this fileType + subtype=0x0, + # Creation date and time stamp. + date=(0, 0) + ), + kids=[ + StringFileInfo( + [ + StringTable( + u'040904B0', + [StringStruct(u'CompanyName', u'Hardcoded Software'), + StringStruct(u'FileDescription', u'dupeGuru is a tool to find duplicate files on your computer.'), + StringStruct(u'FileVersion', u'{0}.{1}.{2}.0'), + StringStruct(u'InternalName', u'dupeGuru'), + StringStruct(u'LegalCopyright', u'© Hardcoded Software'), + StringStruct(u'OriginalFilename', u'dupeguru-win{3}.exe'), + StringStruct(u'ProductName', u'dupeGuru'), + StringStruct(u'ProductVersion', u'{0}.{1}.{2}.0')]) + ]), + VarFileInfo([VarStruct(u'Translation', [1033, 1200])]) + ] +)