summary refs log tree commit diff stats
path: root/tools/niminst/nsis.nimf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/niminst/nsis.nimf')
-rw-r--r--tools/niminst/nsis.nimf445
1 files changed, 445 insertions, 0 deletions
diff --git a/tools/niminst/nsis.nimf b/tools/niminst/nsis.nimf
new file mode 100644
index 000000000..f4eb1d0cd
--- /dev/null
+++ b/tools/niminst/nsis.nimf
@@ -0,0 +1,445 @@
+#? 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."