forked from godotengine/godot
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add files to create a Windows editor installer using Inno Setup
This partially addresses godotengine/godot-proposals#1432. To fully address the proposal above, official Windows installers will have to be compiled and distributed.
- Loading branch information
Showing
4 changed files
with
301 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Ignore both the Godot executable and generated installers. | ||
*.exe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Windows installer | ||
|
||
`godot.iss` is an [Inno Setup](https://jrsoftware.org/isinfo.php) installer file | ||
that can be used to build a Windows installer. The generated installer is able | ||
to run without Administrator privileges and can optionally add Godot to the | ||
user's `PATH` environment variable. | ||
|
||
To use Inno Setup on Linux, use [innoextract](https://constexpr.org/innoextract/) | ||
to extract the Inno Setup installer then run `ISCC.exe` using | ||
[WINE](https://www.winehq.org/). | ||
|
||
## Building | ||
|
||
- Place a Godot editor executable in this folder and rename it to `godot.exe`. | ||
- Run the Inno Setup Compiler (part of the Inno Setup suite) on the `godot.iss` file. | ||
|
||
If everything succeeds, an installer will be generated in this folder. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#define MyAppName "Godot Engine" | ||
#define MyAppVersion "4.0.dev" | ||
#define MyAppPublisher "Godot Engine contributors" | ||
#define MyAppURL "https://godotengine.org/" | ||
#define MyAppExeName "godot.exe" | ||
|
||
[Setup] | ||
AppId={{60D07AAA-400E-40F5-B073-A796C34D9D78} | ||
AppName={#MyAppName} | ||
AppVersion={#MyAppVersion} | ||
; Don't add "version {version}" to the installed app name in the Add/Remove Programs | ||
; dialog as it's redundant with the Version field in that same dialog. | ||
AppVerName={#MyAppName} | ||
AppPublisher={#MyAppPublisher} | ||
AppPublisherURL={#MyAppURL} | ||
AppSupportURL={#MyAppURL} | ||
AppUpdatesURL={#MyAppURL} | ||
AppComments=Godot Engine editor | ||
ChangesEnvironment=yes | ||
DefaultDirName={localappdata}\Godot | ||
DefaultGroupName=Godot Engine | ||
AllowNoIcons=yes | ||
UninstallDisplayIcon={app}\{#MyAppExeName} | ||
#ifdef App32Bit | ||
OutputBaseFilename=godot-setup-x86 | ||
#else | ||
OutputBaseFilename=godot-setup-x86_64 | ||
ArchitecturesAllowed=x64 | ||
ArchitecturesInstallIn64BitMode=x64 | ||
#endif | ||
Compression=lzma | ||
SolidCompression=yes | ||
PrivilegesRequired=lowest | ||
|
||
[Languages] | ||
Name: "english"; MessagesFile: "compiler:Default.isl" | ||
|
||
[Tasks] | ||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked | ||
Name: "modifypath"; Description: "Add Godot to PATH environment variable" | ||
|
||
[Files] | ||
Source: "{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion | ||
|
||
[Icons] | ||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" | ||
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon | ||
|
||
[Run] | ||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent | ||
|
||
[Code] | ||
const | ||
ModPathName = 'modifypath'; | ||
ModPathType = 'user'; | ||
function ModPathDir(): TArrayOfString; | ||
begin | ||
setArrayLength(Result, 1) | ||
Result[0] := ExpandConstant('{app}'); | ||
end; | ||
#include "modpath.pas" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
// ---------------------------------------------------------------------------- | ||
// | ||
// Inno Setup Ver: 5.4.2 | ||
// Script Version: 1.4.2 | ||
// Author: Jared Breland <jbreland@legroom.net> | ||
// Homepage: http://www.legroom.net/software | ||
// License: GNU Lesser General Public License (LGPL), version 3 | ||
// http://www.gnu.org/licenses/lgpl.html | ||
// | ||
// Script Function: | ||
// Allow modification of environmental path directly from Inno Setup installers | ||
// | ||
// Instructions: | ||
// Copy modpath.iss to the same directory as your setup script | ||
// | ||
// Add this statement to your [Setup] section | ||
// ChangesEnvironment=true | ||
// | ||
// Add this statement to your [Tasks] section | ||
// You can change the Description or Flags | ||
// You can change the Name, but it must match the ModPathName setting below | ||
// Name: modifypath; Description: &Add application directory to your environmental path; Flags: unchecked | ||
// | ||
// Add the following to the end of your [Code] section | ||
// ModPathName defines the name of the task defined above | ||
// ModPathType defines whether the 'user' or 'system' path will be modified; | ||
// this will default to user if anything other than system is set | ||
// setArrayLength must specify the total number of dirs to be added | ||
// Result[0] contains first directory, Result[1] contains second, etc. | ||
// const | ||
// ModPathName = 'modifypath'; | ||
// ModPathType = 'user'; | ||
// | ||
// function ModPathDir(): TArrayOfString; | ||
// begin | ||
// setArrayLength(Result, 1); | ||
// Result[0] := ExpandConstant('{app}'); | ||
// end; | ||
// #include "modpath.iss" | ||
// ---------------------------------------------------------------------------- | ||
|
||
procedure ModPath(); | ||
var | ||
oldpath: String; | ||
newpath: String; | ||
updatepath: Boolean; | ||
pathArr: TArrayOfString; | ||
aExecFile: String; | ||
aExecArr: TArrayOfString; | ||
i, d: Integer; | ||
pathdir: TArrayOfString; | ||
regroot: Integer; | ||
regpath: String; | ||
|
||
begin | ||
// Get constants from main script and adjust behavior accordingly | ||
// ModPathType MUST be 'system' or 'user'; force 'user' if invalid | ||
if ModPathType = 'system' then begin | ||
regroot := HKEY_LOCAL_MACHINE; | ||
regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; | ||
end else begin | ||
regroot := HKEY_CURRENT_USER; | ||
regpath := 'Environment'; | ||
end; | ||
|
||
// Get array of new directories and act on each individually | ||
pathdir := ModPathDir(); | ||
for d := 0 to GetArrayLength(pathdir)-1 do begin | ||
updatepath := true; | ||
|
||
// Modify WinNT path | ||
if UsingWinNT() = true then begin | ||
|
||
// Get current path, split into an array | ||
RegQueryStringValue(regroot, regpath, 'Path', oldpath); | ||
oldpath := oldpath + ';'; | ||
i := 0; | ||
|
||
while (Pos(';', oldpath) > 0) do begin | ||
SetArrayLength(pathArr, i+1); | ||
pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1); | ||
oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath)); | ||
i := i + 1; | ||
|
||
// Check if current directory matches app dir | ||
if pathdir[d] = pathArr[i-1] then begin | ||
// if uninstalling, remove dir from path | ||
if IsUninstaller() = true then begin | ||
continue; | ||
// if installing, flag that dir already exists in path | ||
end else begin | ||
updatepath := false; | ||
end; | ||
end; | ||
|
||
// Add current directory to new path | ||
if i = 1 then begin | ||
newpath := pathArr[i-1]; | ||
end else begin | ||
newpath := newpath + ';' + pathArr[i-1]; | ||
end; | ||
end; | ||
|
||
// Append app dir to path if not already included | ||
if (IsUninstaller() = false) AND (updatepath = true) then | ||
newpath := newpath + ';' + pathdir[d]; | ||
|
||
// Write new path | ||
RegWriteStringValue(regroot, regpath, 'Path', newpath); | ||
|
||
// Modify Win9x path | ||
end else begin | ||
|
||
// Convert to shortened dirname | ||
pathdir[d] := GetShortName(pathdir[d]); | ||
|
||
// If autoexec.bat exists, check if app dir already exists in path | ||
aExecFile := 'C:\AUTOEXEC.BAT'; | ||
if FileExists(aExecFile) then begin | ||
LoadStringsFromFile(aExecFile, aExecArr); | ||
for i := 0 to GetArrayLength(aExecArr)-1 do begin | ||
if IsUninstaller() = false then begin | ||
// If app dir already exists while installing, skip add | ||
if (Pos(pathdir[d], aExecArr[i]) > 0) then | ||
updatepath := false; | ||
break; | ||
end else begin | ||
// If app dir exists and = what we originally set, then delete at uninstall | ||
if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then | ||
aExecArr[i] := ''; | ||
end; | ||
end; | ||
end; | ||
|
||
// If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path | ||
if (IsUninstaller() = false) AND (updatepath = true) then begin | ||
SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True); | ||
|
||
// If uninstalling, write the full autoexec out | ||
end else begin | ||
SaveStringsToFile(aExecFile, aExecArr, False); | ||
end; | ||
end; | ||
end; | ||
end; | ||
|
||
// Split a string into an array using passed delimeter | ||
procedure MPExplode(var Dest: TArrayOfString; Text: String; Separator: String); | ||
var | ||
i: Integer; | ||
begin | ||
i := 0; | ||
repeat | ||
SetArrayLength(Dest, i+1); | ||
if Pos(Separator,Text) > 0 then begin | ||
Dest[i] := Copy(Text, 1, Pos(Separator, Text)-1); | ||
Text := Copy(Text, Pos(Separator,Text) + Length(Separator), Length(Text)); | ||
i := i + 1; | ||
end else begin | ||
Dest[i] := Text; | ||
Text := ''; | ||
end; | ||
until Length(Text)=0; | ||
end; | ||
|
||
|
||
procedure CurStepChanged(CurStep: TSetupStep); | ||
var | ||
taskname: String; | ||
begin | ||
taskname := ModPathName; | ||
if CurStep = ssPostInstall then | ||
if IsTaskSelected(taskname) then | ||
ModPath(); | ||
end; | ||
|
||
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); | ||
var | ||
aSelectedTasks: TArrayOfString; | ||
i: Integer; | ||
taskname: String; | ||
regpath: String; | ||
regstring: String; | ||
appid: String; | ||
begin | ||
// only run during actual uninstall | ||
if CurUninstallStep = usUninstall then begin | ||
// get list of selected tasks saved in registry at install time | ||
appid := '{#emit SetupSetting("AppId")}'; | ||
if appid = '' then appid := '{#emit SetupSetting("AppName")}'; | ||
regpath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\'+appid+'_is1'); | ||
RegQueryStringValue(HKLM, regpath, 'Inno Setup: Selected Tasks', regstring); | ||
if regstring = '' then RegQueryStringValue(HKCU, regpath, 'Inno Setup: Selected Tasks', regstring); | ||
|
||
// check each task; if matches modpath taskname, trigger patch removal | ||
if regstring <> '' then begin | ||
taskname := ModPathName; | ||
MPExplode(aSelectedTasks, regstring, ','); | ||
if GetArrayLength(aSelectedTasks) > 0 then begin | ||
for i := 0 to GetArrayLength(aSelectedTasks)-1 do begin | ||
if comparetext(aSelectedTasks[i], taskname) = 0 then | ||
ModPath(); | ||
end; | ||
end; | ||
end; | ||
end; | ||
end; | ||
|
||
function NeedRestart(): Boolean; | ||
var | ||
taskname: String; | ||
begin | ||
taskname := ModPathName; | ||
if IsTaskSelected(taskname) and not UsingWinNT() then begin | ||
Result := True; | ||
end else begin | ||
Result := False; | ||
end; | ||
end; |