summaryrefslogtreecommitdiff
path: root/scripts/installer.nsi
blob: c9dd8773693f8d235a5b5ae122552c8178952228 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
; xmake.nsi
;
; This script is perhaps one of the simplest NSIs you can make. All of the
; optional settings are left to their default settings. The installer simply
; prompts the user asking them where to install, and drops a copy of xmake.nsi
; there.

;--------------------------------
; includes
!include "MUI2.nsh"
!include "WordFunc.nsh"
!include "WinMessages.nsh"
!include FileFunc.nsh
!include UAC.nsh

; xmake version Information
!ifndef MAJOR
  !error 'xmake major version is not defined!'
!endif
!ifndef MINOR
  !error 'xmake minor version is not defined!'
!endif
!ifndef ALTER
  !error 'xmake alter version is not defined!'
!endif
!ifndef BUILD
  !error 'xmake build version is not defined!'
!endif

!define VERSION ${MAJOR}.${MINOR}.${ALTER}
!define VERSION_FULL ${VERSION}+${BUILD}

!ifdef x64
  !define ARCH x64
!else
  !define ARCH x86
!endif

;--------------------------------

; The name of the installer
Name "XMake - v${VERSION}"

; The file to write
OutFile "xmake.exe"

; Use unicode
Unicode true

; Use best compressor
SetCompressor /FINAL /SOLID lzma
SetCompressorDictSize 64
SetDatablockOptimize ON

; The default installation directory
!ifdef x64
  !define PROGRAMFILES $PROGRAMFILES64
  !define HKLM HKLM64
  !define HKCU HKCU64
!else
  !define PROGRAMFILES $PROGRAMFILES
  !define HKLM HKLM
  !define HKCU HKCU
!endif

; Request application privileges for Windows Vista
RequestExecutionLevel user

; Set DPI Aware
ManifestDPIAware true

;--------------------------------
; Interface Settings

!define MUI_ABORTWARNING

;--------------------------------
; Icon
!define MUI_ICON "..\core\src\demo\xmake.ico"

;--------------------------------
; UAC helper

!macro Init thing
  uac_tryagain:
  !insertmacro UAC_RunElevated
  ${Switch} $0
  ${Case} 0
    ${IfThen} $1 = 1 ${|} Quit ${|} ;we are the outer process, the inner process has done its work, we are done
    ${IfThen} $3 <> 0 ${|} ${Break} ${|} ;we are admin, let the show go on
    ${If} $1 = 3 ;RunAs completed successfully, but with a non-admin user
      MessageBox mb_YesNo|mb_IconExclamation|mb_TopMost|mb_SetForeground "This ${thing} requires admin privileges, try again" /SD IDNO IDYES uac_tryagain IDNO 0
    ${EndIf}
    ;fall-through and die
  ${Case} 1223
    MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "This ${thing} requires admin privileges, aborting!"
    Quit
  ${Case} 1062
    MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Logon service not running, aborting!"
    Quit
  ${Default}
    MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate, error $0"
    Quit
  ${EndSwitch}

  ; The UAC plugin changes the error level even in the inner process, reset it.
  ; note fix install exit code 1223 to 0 with slient /S
  SetErrorLevel 0
  SetShellVarContext all
!macroend

;--------------------------------
; Install Pages

!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "..\LICENSE.md"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_LINK "Donate $$5"
!define MUI_FINISHPAGE_LINK_LOCATION "https://xmake.io/#/sponsor"
!insertmacro MUI_PAGE_FINISH

;--------------------------------
; Uninstall Pages

!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH

;--------------------------------
; Languages

!insertmacro MUI_LANGUAGE "English"

;--------------------------------
; Version Information


VIProductVersion                         ${VERSION}.0
VIFileVersion                            ${VERSION}.0
VIAddVersionKey /LANG=0 ProductName      XMake
VIAddVersionKey /LANG=0 Comments         "A cross-platform build utility based on Lua$\nwebsite: https://xmake.io"
VIAddVersionKey /LANG=0 CompanyName      "The TBOOX Open Source Group"
VIAddVersionKey /LANG=0 LegalCopyright   "Copyright (C) 2015-present Ruki Wang, tboox.org, xmake.io"
VIAddVersionKey /LANG=0 FileDescription  "XMake Installer - v${VERSION}"
VIAddVersionKey /LANG=0 OriginalFilename "xmake-${ARCH}.exe"
VIAddVersionKey /LANG=0 FileVersion      ${VERSION_FULL}
VIAddVersionKey /LANG=0 ProductVersion   ${VERSION_FULL}


;--------------------------------
; Reg paths

!define RegUninstall "Software\Microsoft\Windows\CurrentVersion\Uninstall\XMake"

;--------------------------------

Var NOADMIN

Function TrimQuote
	Exch $R1 ; Original string
	Push $R2

Loop:
	StrCpy $R2 "$R1" 1
	StrCmp "$R2" "'"   TrimLeft
	StrCmp "$R2" "$\"" TrimLeft
	StrCmp "$R2" "$\r" TrimLeft
	StrCmp "$R2" "$\n" TrimLeft
	StrCmp "$R2" "$\t" TrimLeft
	StrCmp "$R2" " "   TrimLeft
	GoTo Loop2
TrimLeft:
	StrCpy $R1 "$R1" "" 1
	Goto Loop

Loop2:
	StrCpy $R2 "$R1" 1 -1
	StrCmp "$R2" "'"   TrimRight
	StrCmp "$R2" "$\"" TrimRight
	StrCmp "$R2" "$\r" TrimRight
	StrCmp "$R2" "$\n" TrimRight
	StrCmp "$R2" "$\t" TrimRight
	StrCmp "$R2" " "   TrimRight
	GoTo Done
TrimRight:
	StrCpy $R1 "$R1" -1
	Goto Loop2

Done:
	Pop $R2
	Exch $R1
FunctionEnd

; Installer
Function .onInit
  ${GetOptions} $CMDLINE "/NOADMIN" $NOADMIN
  ${If} ${Errors}
    !insertmacro Init "installer"
    StrCpy $NOADMIN "false"
  ${Else}
    StrCpy $NOADMIN "true"
  ${EndIf}

  ; load from reg
  ${If} $InstDir == ""
    ${If} $NOADMIN == "false"
      ReadRegStr $R0 ${HKLM} ${RegUninstall} "InstallLocation"
    ${Else}
      ReadRegStr $R0 ${HKCU} ${RegUninstall} "InstallLocation"
    ${EndIf}
    ${If} $R0 != ""
      Push $R0
      Call TrimQuote
      Pop  $R0
      StrCpy $InstDir $R0
    ${EndIf}
  ${EndIf}
  ; use default
  ${If} $InstDir == ""
    StrCpy $InstDir ${PROGRAMFILES}\xmake
  ${EndIf}

FunctionEnd

Section "XMake (required)" InstallExeutable

  SectionIn RO

  ; Set output path to the installation directory.
  SetOutPath $InstDir

  ; Remove previous directories used
  ; https://github.com/xmake-io/xmake/issues/1888
  IfFileExists "$InstDir\xmake.exe" file_found file_not_found_or_end
  file_found:
    RMDir /r "$InstDir"
    goto file_not_found_or_end
  file_not_found_or_end:

  ; Put file there
  File /r /x ".DS_Store" /x "*.swp" "..\xmake\*.*"
  File "..\*.md"
  File "..\core\build\xmake.exe"
  File "..\scripts\xrepo.bat"
  File "..\scripts\xrepo.ps1"
  File /r /x ".DS_Store" "..\winenv"

  WriteUninstaller "uninstall.exe"

  !macro AddReg RootKey

    ; Write uac info
    WriteRegStr   ${RootKey} ${RegUninstall} "NoAdmin"               "$NOADMIN"

    ; Write the uninstall keys for Windows
    WriteRegStr   ${RootKey} ${RegUninstall} "DisplayName"           "XMake build utility (${ARCH})"
    WriteRegStr   ${RootKey} ${RegUninstall} "DisplayIcon"           '"$InstDir\xmake.exe"'
    WriteRegStr   ${RootKey} ${RegUninstall} "Comments"              "A cross-platform build utility based on Lua"
    WriteRegStr   ${RootKey} ${RegUninstall} "Publisher"             "The TBOOX Open Source Group"
    WriteRegStr   ${RootKey} ${RegUninstall} "UninstallString"       '"$InstDir\uninstall.exe"'
    WriteRegStr   ${RootKey} ${RegUninstall} "QuiteUninstallString"  '"$InstDir\uninstall.exe" /S'
    WriteRegStr   ${RootKey} ${RegUninstall} "InstallLocation"       $InstDir
    WriteRegStr   ${RootKey} ${RegUninstall} "HelpLink"              'https://xmake.io/'
    WriteRegStr   ${RootKey} ${RegUninstall} "URLInfoAbout"          'https://github.com/xmake-io/xmake'
    WriteRegStr   ${RootKey} ${RegUninstall} "URLUpdateInfo"         'https://github.com/xmake-io/xmake/releases'
    WriteRegDWORD ${RootKey} ${RegUninstall} "VersionMajor"          ${MAJOR}
    WriteRegDWORD ${RootKey} ${RegUninstall} "VersionMinor"          ${MINOR}
    WriteRegStr   ${RootKey} ${RegUninstall} "DisplayVersion"        ${VERSION_FULL}
    WriteRegDWORD ${RootKey} ${RegUninstall} "NoModify"              1
    WriteRegDWORD ${RootKey} ${RegUninstall} "NoRepair"              1

    ;write size to reg
    ${GetSize} "$InstDir" "/S=0K" $0 $1 $2
    IntFmt $0 "0x%08X" $0
    WriteRegDWORD ${RootKey} ${RegUninstall} "EstimatedSize" "$0"
  !macroend

  ${If} $NOADMIN == "false"
    !insertmacro AddReg ${HKLM}
  ${Else}
    !insertmacro AddReg ${HKCU}
  ${EndIf}

SectionEnd

Section "Enable Long Path" LongPath
  ${If} $NOADMIN == "false"
    ; Enable long path
    WriteRegDWORD ${HKLM} "SYSTEM\CurrentControlSet\Control\FileSystem" "LongPathsEnabled" 1
  ${EndIf}
SectionEnd

Section "Add to PATH" InstallPath

  ${If} $NOADMIN == "false"
    ; Remove the installation path from the $PATH environment variable first
    ReadRegStr $R0 ${HKLM} "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path"
    ${WordReplace} $R0 ";$InstDir" "" "+" $R1

    ; Write the installation path into the $PATH environment variable
    WriteRegExpandStr ${HKLM} "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path" "$R1;$InstDir"
  ${Else}
    ; Remove the installation path from the $PATH environment variable first
    ReadRegStr $R0 ${HKCU} "Environment" "Path"
    ${WordReplace} $R0 ";$InstDir" "" "+" $R1

    ; Write the installation path into the $PATH environment variable
    WriteRegExpandStr ${HKCU} "Environment" "Path" "$R1;$InstDir"
  ${EndIf}
  
  ; make sure windows knows about the change
   SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000

SectionEnd

;--------------------------------
; Descriptions

; Language strings
LangString DESC_InstallExeutable ${LANG_ENGLISH} "A cross-platform build utility based on Lua"
LangString DESC_InstallPath ${LANG_ENGLISH} "Add xmake to PATH"
LangString DESC_LongPath ${LANG_ENGLISH} "Increases the maximum path length limit, up to 32,767 characters (before 256). This can be useful if a project has many recursive subfolders to make sure that the project is compiled without errors. A reboot might be required because some processes may have started before the new value was set"

; Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${InstallExeutable} $(DESC_InstallExeutable)
!insertmacro MUI_DESCRIPTION_TEXT ${InstallPath} $(DESC_InstallPath)
!insertmacro MUI_DESCRIPTION_TEXT ${LongPath} $(DESC_LongPath)
!insertmacro MUI_FUNCTION_DESCRIPTION_END

;--------------------------------

; Uninstaller

Function un.onInit
  ; check if we need uac
  ReadRegStr $NOADMIN ${HKLM} ${RegUninstall} "NoAdmin"
  IfErrors 0 +2
  ReadRegStr $NOADMIN ${HKCU} ${RegUninstall} "NoAdmin"

  ${IfNot} $NOADMIN == "true"
    !insertmacro Init "uninstaller"
  ${EndIf}

FunctionEnd

Section "Uninstall"

  ; Remove directories used
  RMDir /r "$InstDir"

  ; Clean reg
  ${If} $NOADMIN == "false"
    DeleteRegKey ${HKLM} ${RegUninstall}
    ; Remove the installation path from the $PATH environment variable
    ReadRegStr $R0 ${HKLM} "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path"
    ${WordReplace} $R0 ";$InstDir" "" "+" $R1
    WriteRegExpandStr ${HKLM} "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path" "$R1"
  ${Else}
    DeleteRegKey ${HKCU} ${RegUninstall}
    ; Remove the installation path from the $PATH environment variable
    ReadRegStr $R0 ${HKCU} "Environment" "Path"
    ${WordReplace} $R0 ";$InstDir" "" "+" $R1
    WriteRegExpandStr ${HKCU} "Environment" "Path" "$R1"
  ${EndIf}

SectionEnd