forked from sagemath/sage-windows-cygwin
-
Notifications
You must be signed in to change notification settings - Fork 2
/
SageMath.iss
352 lines (294 loc) · 13.1 KB
/
SageMath.iss
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
#define MyAppName "SageMath"
#ifndef SageVersion
#error SageVersion must be defined--pass /DSageVersion=<version> to InnoSetup with the correct version
#endif
#ifndef InstallerVersion
#error InstallerVersion must be defined--pass /DInstallerVersion=<version> to InnoSetup with the correct version
#endif
#ifndef SageArch
#define SageArch "x86_64"
#endif
#if SageArch == "x86_64"
#define MyArchitecturesAllowed "x64"
#else
#define MyArchitecturesAllowed "x86 x64"
#endif
#ifndef SageTestInstaller
#define SageTestInstaller "0"
#endif
#if SageTestInstaller == "1"
#define SageExcludes "\opt\*,\home\*"
#else
#define SageExcludes "\home\*"
#endif
#define MyAppVersion SageVersion
#define MyAppPublisher "SageMath"
#define MyAppURL "http://www.sagemath.org/"
#define MyAppContact "http://www.sagemath.org/"
#define SageGroupName MyAppName + " " + MyAppVersion
#ifndef Compression
#define Compression "lzma2"
#endif
#ifndef EnvsDir
#define EnvsDir "envs"
#endif
#ifndef OutputDir
#define OutputDir "dist"
#endif
#ifndef DiskSpanning
#if Compression == "none"
#define DiskSpanning="yes"
#else
#define DiskSpanning="no"
#endif
#endif
#define Source EnvsDir + "\runtime-" + SageVersion + "-" + SageArch
#define Runtime "{app}\runtime"
#define Bin Runtime + "\bin"
#define SageRoot "\opt\sagemath-" + MyAppVersion
#define SageRootWin Runtime + SageRoot
#define SageRootPosix "/opt/sagemath-" + MyAppVersion
#define SageDoc SageRoot + "\local\share\doc\sage\html"
[Setup]
AppCopyright={#MyAppPublisher}
AppId={#MyAppName}-{#MyAppVersion}
AppContact={#MyAppContact}
AppComments={#MyAppURL}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
ArchitecturesAllowed={#MyArchitecturesAllowed}
ArchitecturesInstallIn64BitMode=x64
DefaultDirName={pf}\{#SageGroupName}
DefaultGroupName={#SageGroupName}
DisableProgramGroupPage=yes
DisableWelcomePage=no
DiskSpanning={#DiskSpanning}
OutputDir={#OutputDir}
OutputBaseFilename={#MyAppName}-{#MyAppVersion}-Installer-v{#InstallerVersion}
OutputManifestFile=SageMath-Manifest.txt
PrivilegesRequired=lowest
Compression={#Compression}
SolidCompression=yes
WizardImageFile=resources\sage-banner.bmp
WizardSmallImageFile=resources\sage-sticker.bmp
WizardImageStretch=yes
UninstallDisplayIcon={app}\unins000.exe
SetupIconFile=resources\sage-floppy-disk.ico
ChangesEnvironment=true
SetupLogging=yes
LicenseFile="{#Source}\opt\sagemath-{#SageVersion}\COPYING.txt"
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Types]
Name: "full"; Description: "Full installation"
Name: "custom"; Description: "Custom installation"; Flags: iscustom
[Components]
Name: "sage"; Description: "SageMath Core"; Types: full custom; Flags: fixed
Name: "sagedoc"; Description: "SageMath HTML Documentation"; Types: full
[Tasks]
Name: startmenu; Description: "Create &start menu icons"; GroupDescription: "Additional icons"
Name: desktop; Description: "Create &desktop icons"; GroupDescription: "Additional icons"
[Files]
Source: "dot_sage\*"; DestDir: "{#SageRootWin}\dot_sage"; Flags: recursesubdirs ignoreversion; Components: sage
Source: "{#Source}\*"; DestDir: "{#Runtime}"; Excludes: "{#SageExcludes},{#SageDoc}"; Flags: recursesubdirs ignoreversion; Components: sage
Source: "{#Source}{#SageDoc}\*"; DestDir: "{#Runtime}{#SageDoc}"; Flags: recursesubdirs ignoreversion solidbreak; Components: sagedoc
Source: "resources\sagemath.ico"; DestDir: "{app}"; Flags: ignoreversion; AfterInstall: PostInstall; Components: sage
; InnoSetup will not create empty directories found when including files
; recursively in the [Files] section, so any directories that must exist
; (but start out empty) in the cygwin distribution must be created
;
; /etc/fstab.d is where user-specific mount tables go--this is used in
; sage for windows by /etc/sagerc to set up the /dot_sage mount point for
; each user's DOT_SAGE directory, since the actual path name might contain
; spaces and other special characters not handled well by some software that
; uses DOT_SAGE
;
; /dev/shm and /dev/mqueue are used by the system for POSIX semaphores, shared
; memory, and message queues and must be created world-writeable
[Dirs]
Name: "{#Runtime}\etc\fstab.d"; Permissions: users-modify
Name: "{#Runtime}\dev\shm"; Permissions: users-modify
Name: "{#Runtime}\dev\mqueue"; Permissions: users-modify
Name: "{#Runtime}\home\sage"; Permissions: users-modify
[UninstallDelete]
Type: filesandordirs; Name: "{app}"
#define RunSage "/bin/bash --login -c '" + SageRootPosix + "/sage'"
#define RunSageName "SageMath " + SageVersion
#define RunSageTitle "SageMath " + SageVersion + " Console"
#define RunSageDoc "The SageMath console interface"
#define RunSageSh "/bin/bash --login -c '" + SageRootPosix + "/sage -sh'"
#define RunSageShName "SageMath " + SageVersion + " Shell"
#define RunSageShTitle RunSageShName
#define RunSageShDoc "Command prompt in the SageMath shell environment"
#define RunSageNb "/bin/bash --login -c '" + SageRootPosix + "/sage --notebook jupyter'"
#define RunSageNbName "SageMath " + SageVersion + " Notebook"
#define RunSageNbTitle "SageMath " + SageVersion + " Notebook Server"
#define RunSageNbDoc "Start SageMath notebook server"
[Icons]
Name: "{app}\{#RunSageName}"; Filename: "{#Bin}\mintty.exe"; Parameters: "-t '{#RunSageTitle}' -i sagemath.ico {#RunSage}"; WorkingDir: "{app}"; Comment: "{#RunSageDoc}"; IconFilename: "{app}\sagemath.ico"
Name: "{group}\{#RunSageName}"; Filename: "{#Bin}\mintty.exe"; Parameters: "-t '{#RunSageTitle}' -i sagemath.ico {#RunSage}"; WorkingDir: "{app}"; Comment: "{#RunSageDoc}"; IconFilename: "{app}\sagemath.ico"; Tasks: startmenu
Name: "{code:GetDesktopPath}\{#RunSageName}"; Filename: "{#Bin}\mintty.exe"; Parameters: "-t '{#RunSageTitle}' -i sagemath.ico {#RunSage}"; WorkingDir: "{app}"; Comment: "{#RunSageDoc}"; IconFilename: "{app}\sagemath.ico"; Tasks: desktop
Name: "{app}\{#RunSageShName}"; Filename: "{#Bin}\mintty.exe"; Parameters: "-t '{#RunSageShTitle}' -i sagemath.ico {#RunSageSh}"; WorkingDir: "{app}"; Comment: "{#RunSageShDoc}"; IconFilename: "{app}\sagemath.ico"
Name: "{group}\{#RunSageShName}"; Filename: "{#Bin}\mintty.exe"; Parameters: "-t '{#RunSageShTitle}' -i sagemath.ico {#RunSageSh}"; WorkingDir: "{app}"; Comment: "{#RunSageShDoc}"; IconFilename: "{app}\sagemath.ico"; Tasks: startmenu
Name: "{code:GetDesktopPath}\{#RunSageShName}"; Filename: "{#Bin}\mintty.exe"; Parameters: "-t '{#RunSageShTitle}' -i sagemath.ico {#RunSageSh}"; WorkingDir: "{app}"; Comment: "{#RunSageShDoc}"; IconFilename: "{app}\sagemath.ico"; Tasks: desktop
Name: "{app}\{#RunSageNbName}"; Filename: "{#Bin}\mintty.exe"; Parameters: "-t '{#RunSageNbTitle}' -i sagemath.ico {#RunSageNb}"; WorkingDir: "{app}"; Comment: "{#RunSageNbDoc}"; IconFilename: "{app}\sagemath.ico"
Name: "{group}\{#RunSageNbName}"; Filename: "{#Bin}\mintty.exe"; Parameters: "-t '{#RunSageNbTitle}' -i sagemath.ico {#RunSageNb}"; WorkingDir: "{app}"; Comment: "{#RunSageNbDoc}"; IconFilename: "{app}\sagemath.ico"; Tasks: startmenu
Name: "{code:GetDesktopPath}\{#RunSageNbName}"; Filename: "{#Bin}\mintty.exe"; Parameters: "-t '{#RunSageNbTitle}' -i sagemath.ico {#RunSageNb}"; WorkingDir: "{app}"; Comment: "{#RunSageNbDoc}"; IconFilename: "{app}\sagemath.ico"; Tasks: desktop
[Code]
var
UserInstall: Boolean;
UserHomeDir: String;
InstallModeSelectPageID: Integer;
UserHomeDirSelectPageID: Integer;
// This function is used above in the [Icons] section to get the correct
// installation path for desktop icons depending on what installation mode
// was selected
function GetDesktopPath(Param: String): String;
begin
if UserInstall then
begin
Result := ExpandConstant('{userdesktop}');
end
else begin
Result := ExpandConstant('{commondesktop}');
end;
end;
// ******************* Custom Install Wizard Pages ***************************
function ProcessInstallModeSelectPage(Page: TWizardPage): Boolean;
begin
if TInputOptionWizardPage(Page).CheckListBox.Checked[0] then
begin
WizardForm.DirEdit.Text := ExpandConstant('{localappdata}\{#SageGroupName}');
UserInstall := True;
end
else begin
WizardForm.DirEdit.Text := ExpandConstant('{pf}\{#SageGroupName}');
UserInstall := False;
end;
Result := True;
end;
procedure CreateInstallModeSelectPage();
var
Page: TInputOptionWizardPage;
begin
Page := CreateInputOptionPage(wpUserInfo, 'Install Mode Select',
'Install either for a single user or for all users on the system (requires Administrator privileges).', '', True, False);
InstallModeSelectPageID := Page.ID;
Page.Add('Install just for the current user');
Page.Add('Install for all users (installer must be run with Administrator privileges)');
UserInstall := Boolean(
StrToInt(
GetPreviousData('UserInstall', IntToStr(Integer(not IsAdminLoggedOn())))));
with Page do
begin
CheckListBox.Checked[0] := UserInstall;
CheckListBox.Checked[1] := (not UserInstall);
CheckListBox.ItemEnabled[1] := IsAdminLoggedOn();
OnNextButtonClick := @ProcessInstallModeSelectPage;
end;
end;
function ProcessUserHomeDirSelectPage(Page: TWizardPage): Boolean;
begin
UserHomeDir := TInputDirWizardPage(Page).Values[0];
Result := True;
end;
procedure CreateUserHomeDirSelectPage();
var
Page: TInputDirWizardPage;
begin
Page := CreateInputDirPage(InstallModeSelectPageID, 'Select Sage home directory',
'Select the default directory that Sage will start in', '', False, '');
Page.Add('Sage will start with this folder as your working directory by default; you can also change this after installation using the sage-sethome command:');
UserHomeDirSelectPageID := Page.ID;
with Page do
begin
Values[0] := ExpandConstant('{%USERPROFILE}');
OnNextButtonClick := @ProcessUserHomeDirSelectPage;
end;
end;
procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
SetPreviousData(PreviousDataKey, 'UserInstall', IntToStr(Integer(UserInstall)));
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
Result := False;
if (PageID = UserHomeDirSelectPageID) and (not UserInstall) then
Result := True;
end;
procedure InitializeWizard();
begin
UserInstall := not IsAdminLoggedOn();
CreateInstallModeSelectPage();
CreateUserHomeDirSelectPage();
end;
// Symlinks from the Cygwin runtime are stored in the .lnk file format
// which is one of the different ways of storing symlinks supported by Cygwin;
// for this to work they must have the READ ONLY attribute set on them.
// When the files are compressed by InnoSetup they lose this attribute, so
// we must have a list of files that are supposed to by symlinks, which is
// created by the Makefile as <runtime-env>/etc/symlinks.lst and included in
// the installer. This procedure loops over all the files in this list and
// applies the READ ONLY attribute to them so they can once again be recognized
// by Cygwin as symlinks.
procedure FixupSymlinks();
var
n: Integer;
i: Integer;
resultCode: Integer;
filenames: TArrayOfString;
filenam: String;
begin
LoadStringsFromFile(ExpandConstant('{#Runtime}\etc\symlinks.lst'), filenames);
n := GetArrayLength(filenames);
WizardForm.ProgressGauge.Min := 0;
WizardForm.ProgressGauge.Max := n - 1;
WizardForm.ProgressGauge.Position := 0;
WizardForm.StatusLabel.Caption := 'Fixing up symlinks...';
for i := 0 to n - 1 do
begin
filenam := filenames[i] + '.lnk';
WizardForm.FilenameLabel.Caption := Copy(filenam, 2, Length(filenam));
WizardForm.ProgressGauge.Position := i;
Exec(ExpandConstant('{sys}\attrib.exe'), '+R ' + filenam,
ExpandConstant('{#Runtime}'), SW_HIDE, ewNoWait, resultCode);
end;
end;
// In principle we should be able to run the sage-sethome script with the
// just-installed bash.exe, but this seems to encounter insurmountable
// problems with quoting or I'm not sure what else, so we essentially
// reimplement that script here to write the appropriate /etc/fstab.d file.
procedure SetHome();
var
resultCode: Integer;
userHome: String;
fstabdFile: String;
fstabLine: String;
fstabLines: TArrayOfString;
begin
fstabdFile := ExpandConstant('{#Runtime}\etc\fstab.d\') + GetUserNameString();
userHome := Copy(UserHomeDir, 1, Length(UserHomeDir));
StringChangeEx(userHome, ' ', '\040', True)
fstabLine := userHome + ' /home/sage ntfs binary,posix=1,user,acl 0 0';
SetArrayLength(fstabLines, 2);
fstabLines[0] := fstabLine;
fstabLines[1] := 'none /tmp usertemp binary,posix=0 0 0';
SaveStringsToUTF8File(fstabdFile, fstabLines, False);
// The above nevertheless writes the file with a bunch of stupid
// ideosyncracies (most notably, a useless UTF-8 BOM) which confuse
// Cygwin; we run this final cleanup script to fix everything, ugh.
Exec(ExpandConstant('{#Bin}\dash.exe'),
'/usr/local/bin/_sage-complete-install.sh',
ExpandConstant('{#Runtime}'),
SW_HIDE, ewNoWait, resultCode);
end;
procedure PostInstall();
begin
FixupSymlinks();
if UserInstall then
SetHome();
end;