mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-30 01:44:37 +00:00
446 lines
13 KiB
Cheetah
446 lines
13 KiB
Cheetah
#? stdtmpl(subsChar='?') | standard
|
|
#proc generateNsisSetup(c: ConfigData): string =
|
|
# result = "; NSIS script generated by niminst\n" &
|
|
# "; To regenerate run ``niminst nsis`` or ``koch nsis``\n"
|
|
|
|
;--------------------------------
|
|
; Included headers
|
|
; Modern User Interface 2.0 Header
|
|
!include "MUI2.nsh"
|
|
|
|
; File Functions Header, used to get the current drive root.
|
|
!include "FileFunc.nsh"
|
|
|
|
;--------------------------------
|
|
; Global variables and defines
|
|
!define PRODUCT_NAME "?c.displayName"
|
|
!define PRODUCT_VERSION "?c.version"
|
|
!define PRODUCT_PUBLISHER "?c.authors"
|
|
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\?{c.name}.exe"
|
|
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
|
!define PRODUCT_UNINST_ROOT_KEY "HKCU"
|
|
!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"
|
|
|
|
|
|
;--------------------------------
|
|
; General Setup Information
|
|
|
|
; Name and output file
|
|
Name "?{c.name} ?{c.version}"
|
|
OutFile "?{c.name}_?{c.version}.exe"
|
|
|
|
; Default installation folder
|
|
; This is changed later (in .onInit) to the root directory, if possible.
|
|
InstallDir "$PROGRAMFILES?{when sizeof(int) == 8: "64" else: ""}\?{c.name}-?{c.version}\"
|
|
|
|
; Get installation folder from registry if available
|
|
InstallDirRegKey HKCU "Software\c.name\c.version" ""
|
|
|
|
; Request user level application privileges.
|
|
RequestExecutionLevel user
|
|
|
|
; Allow installation to the root drive directory.
|
|
AllowRootDirInstall false
|
|
|
|
; Maximum compression!
|
|
SetCompressor /SOLID /FINAL lzma
|
|
|
|
; Installer and Uninstaller Icons
|
|
; Icon "nim.ico"
|
|
; UninstallIcon "nim.ico"
|
|
|
|
; Set installation details to be shown by default
|
|
ShowInstDetails show
|
|
ShowUnInstDetails show
|
|
|
|
;--------------------------------
|
|
; Interface Settings
|
|
|
|
; Warn the user if aborting during installation/uninstallation
|
|
!define MUI_ABORTWARNING
|
|
!define MUI_UNABORTWARNING
|
|
|
|
; Don't show a description for sections
|
|
!define MUI_COMPONENTSPAGE_NODESC
|
|
|
|
;--------------------------------
|
|
; Pages
|
|
|
|
; Setup the installer pages
|
|
!insertmacro MUI_PAGE_WELCOME
|
|
!insertmacro MUI_PAGE_LICENSE "?{expandFilename(c.license)}"
|
|
!insertmacro MUI_PAGE_COMPONENTS
|
|
!insertmacro MUI_PAGE_DIRECTORY
|
|
|
|
; Setup the start menu entry page
|
|
var ICONS_GROUP
|
|
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "?{c.displayName}"
|
|
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
|
|
!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
|
|
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
|
|
!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
|
|
|
|
!insertmacro MUI_PAGE_INSTFILES
|
|
!insertmacro MUI_PAGE_FINISH
|
|
|
|
; Setup the uninstaller pages
|
|
!insertmacro MUI_UNPAGE_CONFIRM
|
|
!insertmacro MUI_UNPAGE_INSTFILES
|
|
|
|
;--------------------------------
|
|
;Languages
|
|
|
|
!insertmacro MUI_LANGUAGE "English"
|
|
|
|
;--------------------------------
|
|
;Installer Sections
|
|
|
|
; The core section. This is comprised of a base Nim installation,
|
|
; such as what would be retrieved via git, and an already bootstrapped
|
|
; Nim binary.
|
|
Section "Core Files" CoreSection
|
|
; This is a mandotory section
|
|
SectionIn RO
|
|
|
|
; Output files to the base installation directory
|
|
SetOutPath "$INSTDIR"
|
|
|
|
; Only overwrite newer files
|
|
SetOverwrite ifnewer
|
|
|
|
; Write all the files to the output directory.
|
|
#for i in low(FileCategory)..fcWindows:
|
|
# for f in items(c.cat[i]):
|
|
SetOutPath "$INSTDIR\?{splitFile(f).dir.toWin}"
|
|
File "?{expandFilename(f).toWin}"
|
|
# end for
|
|
#end for
|
|
|
|
; Write out the uninstaller
|
|
WriteUninstaller "$INSTDIR\uninstaller.exe"
|
|
SectionEnd
|
|
|
|
Section "-Add Registry Keys" RegistrySection
|
|
; Write application registry keys
|
|
WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninstaller.exe"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
|
; Reset the output path
|
|
SetOutPath "$INSTDIR"
|
|
SectionEnd
|
|
|
|
; Section for adding the shortcuts related to files and applications
|
|
Section "-Setup Shortcuts" ShortcutsSection
|
|
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
|
CreateDirectory "$SMPROGRAMS\$ICONS_GROUP"
|
|
|
|
#if c.app == appConsole:
|
|
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
|
|
CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
|
|
#else:
|
|
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
|
|
CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
|
|
#end if
|
|
|
|
; Write the shortcut to the uninstaller
|
|
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninstaller.exe"
|
|
!insertmacro MUI_STARTMENU_WRITE_END
|
|
SectionEnd
|
|
|
|
; Section for adding tools to the PATH variable
|
|
Section "Setup Path Environment" PathSection
|
|
Push "$INSTDIR\bin"
|
|
Call AddToPath
|
|
Push "$INSTDIR\dist\mingw"
|
|
Call AddToPath
|
|
Push "$INSTDIR\dist\mingw\bin"
|
|
Call AddToPath
|
|
Push "$PROFILE\.nimble\bin"
|
|
Call AddToPath
|
|
SectionEnd
|
|
|
|
; The downloadable sections. These sections are automatically generated by
|
|
; niminst and the template filters.
|
|
#var i = 0
|
|
#for download in c.downloads:
|
|
# inc i
|
|
# let d = download.split('|')
|
|
# if d.len != 5 and d.len != 6:
|
|
# quit("download string needs 5..6 parts: " & download)
|
|
# end if
|
|
# let sectionName = d[0]
|
|
# let dir = d[1]
|
|
# let zipName = d[2]
|
|
# let size = d[3]
|
|
# let url = d[4]
|
|
Section /o "?sectionName" ?{i}Section
|
|
; Add the section size to the total size.
|
|
AddSize ?size
|
|
|
|
; Download the file, and if successful, extract it to the given directory
|
|
; otherwise,
|
|
retry:
|
|
NSISdl::download "?url" "$TEMP\?zipName"
|
|
Pop $0
|
|
${If} $0 == "success"
|
|
ZipDLL::extractall "$TEMP\?zipName" "$INSTDIR\?dir"
|
|
Delete "$TEMP\?zipName"
|
|
${ElseIf} $0 == "cancel"
|
|
MessageBox MB_ICONQUESTION|MB_YESNO|MB_TOPMOST \
|
|
"Download of component '?sectionName' cancelled. Continue installation process??" \
|
|
IDYES ignore
|
|
abort
|
|
${Else}
|
|
MessageBox MB_ICONSTOP|MB_ABORTRETRYIGNORE|MB_TOPMOST "Error: $0" \
|
|
IDRETRY retry IDIGNORE ignore
|
|
abort
|
|
${EndIf}
|
|
|
|
; Shortcuts
|
|
# if d.len >= 6:
|
|
# let startMenuEntry = d[5]
|
|
# let e = splitFile(startMenuEntry).name.capitalizeAscii
|
|
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
|
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}"
|
|
!insertmacro MUI_STARTMENU_WRITE_END
|
|
# end if
|
|
|
|
ignore:
|
|
SectionEnd
|
|
#end
|
|
|
|
;--------------------------------
|
|
; Section Descriptions
|
|
; Series of strings describing each section
|
|
; LangString DESC_CoreSection ${LANG_ENGLISH} "Core Nim files"
|
|
|
|
; The macros to actually insert the descriptions into the sections.
|
|
; Each description above should have a corresponding MUI_DESCRIPTION_TEXT
|
|
; macro linking the section to the description.
|
|
; !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
|
; !insertmacro MUI_DESCRIPTION_TEXT ${CoreSection} $(DESC_CoreSection)
|
|
; !insertmacro MUI_FUNCTION_DESCRIPTION_END
|
|
|
|
|
|
;--------------------------------
|
|
; Uninstaller Sections
|
|
|
|
Section "Uninstall"
|
|
; Remove previously created shortcuts
|
|
!insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
|
|
Delete "$DESKTOP\?{c.displayName}.lnk"
|
|
|
|
; Remove installed application files
|
|
RMDir /r "$SMPROGRAMS\$ICONS_GROUP"
|
|
RMDir /r "$INSTDIR"
|
|
|
|
; Remove the previously created registry key
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
|
DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}"
|
|
SetAutoClose true
|
|
|
|
; Remove entries from the PATH environment variable
|
|
Push "$INSTDIR\bin"
|
|
Call un.RemoveFromPath
|
|
Push "$INSTDIR\dist\mingw"
|
|
Call un.RemoveFromPath
|
|
Push "$INSTDIR\dist\mingw\bin"
|
|
Call un.RemoveFromPath
|
|
Push "$PROFILE\.nimble\bin"
|
|
Call un.RemoveFromPath
|
|
SectionEnd
|
|
|
|
;--------------------------------
|
|
; Function hooks
|
|
|
|
Function .onInit
|
|
${GetRoot} "$EXEDIR" $R0
|
|
strCpy $INSTDIR "$R0\?{c.name}"
|
|
FunctionEnd
|
|
|
|
|
|
;--------------------------------------------------------------------
|
|
; Path functions
|
|
;
|
|
; Based on example from:
|
|
; http://nsis.sourceforge.net/Path_Manipulation
|
|
;
|
|
; Actually based on:
|
|
; https://www.smartmontools.org/browser/trunk/smartmontools/os_win32/installer.nsi#L636
|
|
|
|
|
|
!include "WinMessages.nsh"
|
|
|
|
; Registry Entry for environment (NT4,2000,XP)
|
|
; All users:
|
|
;!define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
|
; Current user only:
|
|
!define Environ 'HKCU "Environment"'
|
|
|
|
|
|
; AddToPath - Appends dir to PATH
|
|
; (does not work on Win9x/ME)
|
|
;
|
|
; Usage:
|
|
; Push "dir"
|
|
; Call AddToPath
|
|
|
|
Function AddToPath
|
|
Exch $0
|
|
Push $1
|
|
Push $2
|
|
Push $3
|
|
Push $4
|
|
|
|
; NSIS ReadRegStr returns empty string on string overflow
|
|
; Native calls are used here to check actual length of PATH
|
|
|
|
; $4 = RegOpenKey(HKEY_CURRENT_USER, "Environment", &$3)
|
|
System::Call "advapi32::RegOpenKey(i 0x80000001, t'Environment', *i.r3) i.r4"
|
|
IntCmp $4 0 0 done done
|
|
; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2))
|
|
; RegCloseKey($3)
|
|
System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
|
|
System::Call "advapi32::RegCloseKey(i $3)"
|
|
|
|
IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
|
|
DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}"
|
|
MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}"
|
|
Goto done
|
|
|
|
IntCmp $4 0 +5 ; $4 != NO_ERROR
|
|
IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
|
|
DetailPrint "AddToPath: unexpected error code $4"
|
|
Goto done
|
|
StrCpy $1 ""
|
|
|
|
; Check if already in PATH
|
|
Push "$1;"
|
|
Push "$0;"
|
|
Call StrStr
|
|
Pop $2
|
|
StrCmp $2 "" 0 done
|
|
Push "$1;"
|
|
Push "$0\;"
|
|
Call StrStr
|
|
Pop $2
|
|
StrCmp $2 "" 0 done
|
|
|
|
; Prevent NSIS string overflow
|
|
StrLen $2 $0
|
|
StrLen $3 $1
|
|
IntOp $2 $2 + $3
|
|
IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";")
|
|
IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0
|
|
DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}"
|
|
MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}."
|
|
Goto done
|
|
|
|
; Append dir to PATH
|
|
DetailPrint "Add to PATH: $0"
|
|
StrCpy $2 $1 1 -1
|
|
StrCmp $2 ";" 0 +2
|
|
StrCpy $1 $1 -1 ; remove trailing ';'
|
|
StrCmp $1 "" +2 ; no leading ';'
|
|
StrCpy $0 "$1;$0"
|
|
WriteRegExpandStr ${Environ} "PATH" $0
|
|
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
|
|
|
done:
|
|
Pop $4
|
|
Pop $3
|
|
Pop $2
|
|
Pop $1
|
|
Pop $0
|
|
FunctionEnd
|
|
|
|
|
|
; RemoveFromPath - Removes dir from PATH
|
|
;
|
|
; Usage:
|
|
; Push "dir"
|
|
; Call RemoveFromPath
|
|
|
|
Function un.RemoveFromPath
|
|
Exch $0
|
|
Push $1
|
|
Push $2
|
|
Push $3
|
|
Push $4
|
|
Push $5
|
|
Push $6
|
|
|
|
ReadRegStr $1 ${Environ} "PATH"
|
|
StrCpy $5 $1 1 -1
|
|
StrCmp $5 ";" +2
|
|
StrCpy $1 "$1;" ; ensure trailing ';'
|
|
Push $1
|
|
Push "$0;"
|
|
Call un.StrStr
|
|
Pop $2 ; pos of our dir
|
|
StrCmp $2 "" done
|
|
|
|
DetailPrint "Remove from PATH: $0"
|
|
StrLen $3 "$0;"
|
|
StrLen $4 $2
|
|
StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove
|
|
StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove
|
|
StrCpy $3 "$5$6"
|
|
StrCpy $5 $3 1 -1
|
|
StrCmp $5 ";" 0 +2
|
|
StrCpy $3 $3 -1 ; remove trailing ';'
|
|
WriteRegExpandStr ${Environ} "PATH" $3
|
|
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
|
|
|
done:
|
|
Pop $6
|
|
Pop $5
|
|
Pop $4
|
|
Pop $3
|
|
Pop $2
|
|
Pop $1
|
|
Pop $0
|
|
FunctionEnd
|
|
|
|
|
|
; StrStr - find substring in a string
|
|
;
|
|
; Usage:
|
|
; Push "this is some string"
|
|
; Push "some"
|
|
; Call StrStr
|
|
; Pop $0 ; "some string"
|
|
|
|
!macro StrStr un
|
|
Function ${un}StrStr
|
|
Exch $R1 ; $R1=substring, stack=[old$R1,string,...]
|
|
Exch ; stack=[string,old$R1,...]
|
|
Exch $R2 ; $R2=string, stack=[old$R2,old$R1,...]
|
|
Push $R3
|
|
Push $R4
|
|
Push $R5
|
|
StrLen $R3 $R1
|
|
StrCpy $R4 0
|
|
; $R1=substring, $R2=string, $R3=strlen(substring)
|
|
; $R4=count, $R5=tmp
|
|
loop:
|
|
StrCpy $R5 $R2 $R3 $R4
|
|
StrCmp $R5 $R1 done
|
|
StrCmp $R5 "" done
|
|
IntOp $R4 $R4 + 1
|
|
Goto loop
|
|
done:
|
|
StrCpy $R1 $R2 "" $R4
|
|
Pop $R5
|
|
Pop $R4
|
|
Pop $R3
|
|
Pop $R2
|
|
Exch $R1 ; $R1=old$R1, stack=[result,...]
|
|
FunctionEnd
|
|
!macroend
|
|
!insertmacro StrStr ""
|
|
!insertmacro StrStr "un."
|