diff --git a/installers/build-cli-win.py b/installers/build-cli-win.py new file mode 100644 index 000000000..be186b594 --- /dev/null +++ b/installers/build-cli-win.py @@ -0,0 +1,88 @@ +# +# This is a script for easily building the wownero cli installer in an automated build. Note +# that it is also possible to build the installer by dropping the .nsi file on the NSIS GUI, +# but that this will not work, as the script requires some defines, parsed from the wownero +# version file, to be passed on the command line. +# + +import sys +sys.dont_write_bytecode = True + +import os +import os.path +import subprocess + +# +# Grab the dir of this .py +# +basedir = os.path.dirname(os.path.abspath(__file__)) + +# +# Try to find version.cpp.in. +# +version_file = os.path.join('..', 'src', 'version.cpp.in') +if not os.path.isfile(version_file): + print('Version file not found: %s' % version_file) + sys.exit(-1) + +# +# Try to parse version.cpp.in. +# +version_string = None +release_name = None +with open(version_file, 'r') as fp: + version_prefix = '#define DEF_MONERO_VERSION "' + release_prefix = '#define DEF_MONERO_RELEASE_NAME "' + for line in fp: + if line.startswith(version_prefix): + version_string = line.replace(version_prefix, '')[:-2] + elif line.startswith(release_prefix): + release_name = line.replace(release_prefix, '')[:-2] + +if not version_string: + print('Failed to parse version from: %s' % version_file) + sys.exit(-1) + +if not release_name: + print('Failed to parse release name from: %s' % version_file) + sys.exit(-1) + +# +# Check that we got an expected version format. +# +version_parts = version_string.split('.') +if len(version_parts) != 4: + print('Invalid version string: %s' % version_string) + sys.exit(-1) + +# +# Try to find makensis. +# +makensis = 'makensis.exe' +if not os.path.isfile(makensis): + for dir in os.environ['PATH'].split(';'): + test = os.path.join(dir, makensis) + if os.path.isfile(test): + makensis = test + break + +if not os.path.isfile(makensis): + print('Failed to find makensis.exe') + sys.exit(-1) + +# +# Build & run makensis command line. +# +cmd = '"%s"' % makensis +cmd += ' /V4' +cmd += ' /DVERSION_MAJOR=%s' % version_parts[0] +cmd += ' /DVERSION_MINOR=%s' % version_parts[1] +cmd += ' /DVERSION_BUILD=%s' % version_parts[2] +cmd += ' /DVERSION_REVISION=%s' % version_parts[3] +cmd += ' /DRELEASE_NAME="%s"' % release_name +cmd += ' "%s"' % os.path.join(basedir, 'cli-win', 'installer.nsi') + +print("Calling makensis: %s" % cmd) + +subprocess.call(cmd) + diff --git a/installers/cli-win/app.ico b/installers/cli-win/app.ico new file mode 100644 index 000000000..3004f190a Binary files /dev/null and b/installers/cli-win/app.ico differ diff --git a/installers/cli-win/header.bmp b/installers/cli-win/header.bmp new file mode 100644 index 000000000..c27a11941 Binary files /dev/null and b/installers/cli-win/header.bmp differ diff --git a/installers/cli-win/installer.nsi b/installers/cli-win/installer.nsi new file mode 100644 index 000000000..289270a68 --- /dev/null +++ b/installers/cli-win/installer.nsi @@ -0,0 +1,262 @@ +;----------------------------------------------------------------------------------------- +; File: Wownero CLI NSIS installer +; Author: 0x000090 +; Date: 1 Dec 2018 +; License: WTFPL +;----------------------------------------------------------------------------------------- +; +; DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE +; Version 2, December 2004 +; +; Copyright (C) 2018 Wownero Inc., a Monero Enterprise Alliance partner company +; +; DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE +; TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +; +; 0. You just DO WHAT THE FUCK YOU WANT TO. +; +;----------------------------------------------------------------------------------------- +!include 'MUI2.nsh' +!include 'TextFunc.nsh' +!include 'WordFunc.nsh' +!include 'Sections.nsh' + +;----------------------------------------------------------------------------------------- +!ifndef VERSION_MAJOR + !warning 'VERSION_MAJOR not defined!' + Quit +!endif + +!ifndef VERSION_MINOR + !warning 'VERSION_MINOR not defined!' + Quit +!endif + +!ifndef VERSION_BUILD + !warning 'VERSION_BUILD not defined!' + Quit +!endif + +!ifndef VERSION_REVISION + !warning 'VERSION_REVISION not defined!' + Quit +!endif + +!ifndef RELEASE_NAME + !warning 'RELEASE_NAME not defined!' + Quit +!endif + +!define VERSION_SHORT '${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}' +!define VERSION_LONG '${VERSION_SHORT}.${VERSION_REVISION}' + +;----------------------------------------------------------------------------------------- +!define PROJECT_NAME 'Wownero' +!define PRODUCT_NAME 'Wownero CLI' +!define COMPANY_NAME 'Wownero Inc.' +!define EXE_BASENAME 'wownero' +!define HELP_URL 'http://wownero.org/#community' +!define ABOUT_URL 'http://wownero.org/#about' +!define SOURCE_DIR '..\..\build\release\bin' +!define TARGET_DIR '..\..\build\installers' +!define TARGET_PATH '${TARGET_DIR}\Wownero-CLI-${VERSION_LONG}-win.exe' +!define INSTALL_SUBDIR 'cli' +!define INSTALL_SIZE 181000 +!define UNINSTALLER_NAME 'uninstall.exe' +!define REG_BASE 'Software\Microsoft\Windows\CurrentVersion\Uninstall' +!define REG_KEY '${REG_BASE}\{E114584F-4E1B-4B2D-8B1C-69A188025E98}' +!define /date CURRENT_YEAR '%Y' + +;----------------------------------------------------------------------------------------- +!system 'if not exist "${TARGET_DIR}" md "${TARGET_DIR}"' + +;----------------------------------------------------------------------------------------- +Name '${PRODUCT_NAME}' +OutFile '${TARGET_PATH}' +BrandingText '${PRODUCT_NAME} ${VERSION_LONG} "${RELEASE_NAME}"' +CRCCheck force +RequestExecutionLevel admin +InstallDir "$PROGRAMFILES64\${PROJECT_NAME}\${INSTALL_SUBDIR}" +ShowInstDetails show +ShowUninstDetails show + +;----------------------------------------------------------------------------------------- +VIAddVersionKey 'CompanyName' '${COMPANY_NAME}' +VIAddVersionKey 'ProductName' '${PRODUCT_NAME}' +VIAddVersionKey 'FileDescription' '${PRODUCT_NAME}' +VIAddVersionKey 'LegalCopyright' 'Copyright (c) ${CURRENT_YEAR}, ${COMPANY_NAME}' +VIAddVersionKey 'FileVersion' '${VERSION_SHORT}' +VIProductVersion '${VERSION_LONG}' + +;----------------------------------------------------------------------------------------- +!define MUI_ABORTWARNING +!define MUI_UNABORTWARNING + +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_UNFINISHPAGE_NOAUTOCLOSE + +!define MUI_ICON "app.ico" +!define MUI_UNICON "app.ico" + +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_RIGHT +!define MUI_HEADERIMAGE_BITMAP "header.bmp" +!define MUI_HEADERIMAGE_UNBITMAP "header.bmp" +!define MUI_HEADERIMAGE_BITMAP_NOSTRETCH +!define MUI_HEADERIMAGE_UNBITMAP_NOSTRETCH + +!define MUI_WELCOMEFINISHPAGE_BITMAP "welcome.bmp" +!define MUI_UNWELCOMEFINISHPAGE_BITMAP "welcome.bmp" +!define MUI_WELCOMEFINISHPAGE_BITMAP_NOSTRETCH +!define MUI_UNWELCOMEFINISHPAGE_UNBITMAP_NOSTRETCH + +;----------------------------------------------------------------------------------------- +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_UNPAGE_WELCOME +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +;----------------------------------------------------------------------------------------- +!insertmacro MUI_LANGUAGE "English" + +;----------------------------------------------------------------------------------------- +Function VerifyUserIsAdmin + UserInfo::GetAccountType + Pop $0 + ${If} $0 != "admin" + MessageBox MB_ICONSTOP "Admin permissions required, please use right-click > Run as Administrator." + SetErrorLevel 740 ; ERROR_ELEVATION_REQUIRED + Quit + ${EndIf} +FunctionEnd + +Function .onInit + Call VerifyUserIsAdmin +FunctionEnd + +Function un.onInit +FunctionEnd + +;----------------------------------------------------------------------------------------- +!macro RemoveFile file + Push $0 + ${TrimNewLines} '${file}' $0 + SetDetailsPrint both + ${If} ${FileExists} '$0' + DetailPrint 'Deleting file $0' + SetDetailsPrint textonly + Delete "$0" + ${Else} + DetailPrint 'File not found: $0' + ${Endif} + SetDetailsPrint lastused + Pop $0 +!macroend + +!macro RemoveDir dir + Push $0 + ${TrimNewLines} '${dir}' $0 + SetDetailsPrint both + ${If} ${FileExists} '$0' + DetailPrint 'Deleting directory $0' + SetDetailsPrint textonly + RmDir /r "$0" + ${Else} + DetailPrint 'Directory not found: $0' + ${Endif} + SetDetailsPrint lastused + Pop $0 +!macroend + +;----------------------------------------------------------------------------------------- +Function WriteFiles + DetailPrint 'Installing application files...' + SetDetailsPrint both + SetOutPath '$INSTDIR' + File 'app.ico' + + ; + ; Add here whatever else you want to be included: + ; + File '${SOURCE_DIR}\${EXE_BASENAME}d.exe' + File '${SOURCE_DIR}\${EXE_BASENAME}-wallet-cli.exe' + File '${SOURCE_DIR}\${EXE_BASENAME}-wallet-rpc.exe' + File '${SOURCE_DIR}\${EXE_BASENAME}-gen-trusted-multisig.exe' + + ; + ; NOTE: you can also add all files in a dir, like this: + ; + ;File /r '${SOURCE_DIR}\*.*' + + SetDetailsPrint lastused + DetailPrint 'Writing uninstaller...' + WriteUninstaller '$INSTDIR\${UNINSTALLER_NAME}' +FunctionEnd + +Function un.WriteFiles + DetailPrint 'Removing application files...' + !insertmacro RemoveDir '$INSTDIR' +FunctionEnd + +;----------------------------------------------------------------------------------------- +Function WriteShortcuts + DetailPrint 'Creating Desktop shortcuts...' + CreateShortCut '$DESKTOP\${PRODUCT_NAME} Wallet.lnk' '$INSTDIR\${EXE_BASENAME}-wallet-cli.exe' '' '$INSTDIR\app.ico' + CreateShortCut '$DESKTOP\${PRODUCT_NAME} Daemon.lnk' '$INSTDIR\${EXE_BASENAME}d.exe' '' '$INSTDIR\app.ico' + DetailPrint 'Creating Start Menu shortcuts...' + CreateDirectory '$SMPROGRAMS\${COMPANY_NAME}\${PRODUCT_NAME}' + CreateShortCut '$SMPROGRAMS\${COMPANY_NAME}\${PRODUCT_NAME}\${PRODUCT_NAME} Wallet.lnk' '$INSTDIR\${EXE_BASENAME}-wallet-cli.exe' '' '$INSTDIR\app.ico' + CreateShortCut '$SMPROGRAMS\${COMPANY_NAME}\${PRODUCT_NAME}\${PRODUCT_NAME} Daemon.lnk' '$INSTDIR\${EXE_BASENAME}d.exe' '' '$INSTDIR\app.ico' + CreateShortCut '$SMPROGRAMS\${COMPANY_NAME}\${PRODUCT_NAME}\Uninstall ${PRODUCT_NAME}.lnk' '$INSTDIR\${UNINSTALLER_NAME}' '' '$INSTDIR\app.ico' +FunctionEnd + +Function un.WriteShortcuts + DetailPrint 'Removing Desktop shortcuts...' + !insertmacro RemoveFile '$DESKTOP\${PRODUCT_NAME} Daemon.lnk' + !insertmacro RemoveFile '$DESKTOP\${PRODUCT_NAME} Wallet.lnk' + DetailPrint 'Removing Start Menu shortcuts...' + !insertmacro RemoveDir '$SMPROGRAMS\${COMPANY_NAME}\${PRODUCT_NAME}' +FunctionEnd + +;----------------------------------------------------------------------------------------- +Function WriteUninstaller + DetailPrint 'Registering ${PRODUCT_NAME} ${VERSION_SHORT}' + WriteRegDWORD HKLM '${REG_KEY}' 'VersionMajor' ${VERSION_MAJOR} + WriteRegDWORD HKLM '${REG_KEY}' 'VersionMinor' ${VERSION_MINOR} + WriteRegDWORD HKLM '${REG_KEY}' 'EstimatedSize' ${INSTALL_SIZE} + WriteRegDWORD HKLM '${REG_KEY}' 'NoModify' 1 + WriteRegDWORD HKLM '${REG_KEY}' 'NoRepair' 1 + WriteRegStr HKLM '${REG_KEY}' 'Contact' '${COMPANY_NAME}' + WriteRegStr HKLM '${REG_KEY}' 'Publisher' '${COMPANY_NAME}' + WriteRegStr HKLM '${REG_KEY}' 'HelpLink' '${HELP_URL}' + WriteRegStr HKLM '${REG_KEY}' 'URLInfoAbout' '${ABOUT_URL}' + WriteRegStr HKLM '${REG_KEY}' 'DisplayVersion' '${VERSION_SHORT}' + WriteRegStr HKLM '${REG_KEY}' 'Comments' '${PRODUCT_NAME}' + WriteRegStr HKLM '${REG_KEY}' 'DisplayName' '${PRODUCT_NAME} ${VERSION_SHORT}' + WriteRegStr HKLM '${REG_KEY}' 'InstallLocation' '"$INSTDIR"' + WriteRegStr HKLM '${REG_KEY}' 'DisplayIcon' '"$INSTDIR\app.ico"' + WriteRegStr HKLM '${REG_KEY}' 'UninstallString' '"$INSTDIR\${UNINSTALLER_NAME}"' + WriteRegStr HKLM '${REG_KEY}' 'QuietUninstallString' '"$INSTDIR\${UNINSTALLER_NAME}" /S' +FunctionEnd + +Function un.WriteUninstaller + DetailPrint 'Unregistering ${PRODUCT_NAME} ${VERSION_SHORT}...' + DeleteRegKey HKLM '${REG_KEY}' +FunctionEnd + +;----------------------------------------------------------------------------------------- +Section "${PRODUCT_NAME} ${VERSION_SHORT}" + Call WriteFiles + Call WriteShortcuts + Call WriteUninstaller +SectionEnd + +;----------------------------------------------------------------------------------------- +Section "Uninstall" + Call un.WriteFiles + Call un.WriteShortcuts + Call un.WriteUninstaller +SectionEnd + diff --git a/installers/cli-win/welcome.bmp b/installers/cli-win/welcome.bmp new file mode 100644 index 000000000..f690cc96d Binary files /dev/null and b/installers/cli-win/welcome.bmp differ diff --git a/installers/readme.txt b/installers/readme.txt new file mode 100644 index 000000000..a22a088c6 --- /dev/null +++ b/installers/readme.txt @@ -0,0 +1,31 @@ +Installer notes + +So, at this point I just have one installer, for the cli, on windows. What do you need +to know .. + +1. It uses NSIS, and expects to find makensis.exe on your PATH. + +2. It expects built products to be found at: + + wownero/build/release/bin + +3. It currently includes the daemon, wallet, rpc, and gen-trusted-multisig. I note that + releases on the wownero github have had different files (static libs, pthreads dll) + than I end up with in my /bin dir when I build, so you may or may not need to change + which files you include. At any rate, it is easy to do, in the WriteFiles function + in installer.nsi. + +4. Provided everything is ok, it should be as simple as executing build-cli-win.py; built + installer, versioned according to src/version.cpp.in, will be depostied here: + + wownero/build/installers/Wownero-CLI--win.exe + +5. The installer includes an uninstaller, shortcuts on desktop & start menu, and it + registers itself with windows, so it shows up as expected in programs & features. + +6. I have tried to keep the installer script pretty generic, so it can be reused later, + for gui, or whatever. It installs to a /Wownero/cli subdirectory, so + that other applications can eventually be installed alongside. NOTE: if you copy the + installer.nsi file to use for another project, you will need to make a new GUID for + it, and put it in the REG_KEY define. +