esp-idf/tools/windows/tool_setup/idf_setup.iss.inc
Ivan Grokhotkov 46cfc436ad Merge branch 'feature/idf_tools_github_mirror' into 'master'
Add GitHub mirror option for IDF tools installs

Closes IDF-2028

See merge request espressif/esp-idf!10616
2020-12-14 15:58:51 +08:00

408 lines
14 KiB
PHP

{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD
SPDX-License-Identifier: Apache-2.0 }
{ ------------------------------ Downloading ESP-IDF ------------------------------ }
var
IDFZIPFileVersion, IDFZIPFileName: String;
function GetIDFPath(Unused: String): String;
begin
if IDFUseExisting then
Result := IDFExistingPath
else
Result := IDFDownloadPath;
end;
function GetIDFZIPFileVersion(Version: String): String;
var
ReleaseVerPart: String;
i: Integer;
Found: Boolean;
begin
if WildCardMatch(Version, 'v*') or WildCardMatch(Version, 'v*-rc*') then
Result := Version
else if Version = 'master' then
Result := ''
else if WildCardMatch(Version, 'release/v*') then
begin
ReleaseVerPart := Version;
Log('ReleaseVerPart=' + ReleaseVerPart)
Delete(ReleaseVerPart, 1, Length('release/'));
Log('ReleaseVerPart=' + ReleaseVerPart)
Found := False;
for i := 0 to GetArrayLength(IDFDownloadAvailableVersions) - 1 do
begin
if Pos(ReleaseVerPart, IDFDownloadAvailableVersions[i]) = 1 then
begin
Result := IDFDownloadAvailableVersions[i];
Found := True;
break;
end;
end;
if not Found then
Result := '';
end;
Log('GetIDFZIPFileVersion(' + Version + ')=' + Result);
end;
procedure IDFAddDownload();
var
Url, MirrorUrl: String;
begin
IDFZIPFileVersion := GetIDFZIPFileVersion(IDFDownloadVersion);
if IDFZIPFileVersion <> '' then
begin
Url := 'https://github.com/espressif/esp-idf/releases/download/' + IDFZIPFileVersion + '/esp-idf-' + IDFZIPFileVersion + '.zip';
MirrorUrl := 'https://dl.espressif.com/github_assets/espressif/esp-idf/releases/download/' + IDFZIPFileVersion + '/esp-idf-' + IDFZIPFileVersion + '.zip';
IDFZIPFileName := ExpandConstant('{app}\releases\esp-idf-' + IDFZIPFileVersion + '.zip')
if not FileExists(IDFZIPFileName) then
begin
ForceDirectories(ExpandConstant('{app}\releases'))
Log('Adding download: ' + Url + ', mirror: ' + MirrorUrl + ', destination: ' + IDFZIPFileName);
idpAddFile(Url, IDFZIPFileName);
idpAddMirror(Url, MirrorUrl);
end else begin
Log(IDFZIPFileName + ' already exists')
end;
end;
end;
procedure RemoveAlternatesFile(Path: String);
begin
Log('Removing ' + Path);
DeleteFile(Path);
end;
{
Replacement of the '--dissociate' flag of 'git clone', to support older versions of Git.
'--reference' is supported for submodules since git 2.12, but '--dissociate' only from 2.18.
}
procedure GitRepoDissociate(Path: String);
var
CmdLine: String;
begin
CmdLine := GitExecutablePath + ' -C ' + Path + ' repack -d -a'
DoCmdlineInstall('Finishing ESP-IDF installation', 'Re-packing the repository', CmdLine);
CmdLine := GitExecutablePath + ' -C ' + Path + ' submodule foreach git repack -d -a'
DoCmdlineInstall('Finishing ESP-IDF installation', 'Re-packing the submodules', CmdLine);
FindFileRecursive(Path + '\.git', 'alternates', @RemoveAlternatesFile);
end;
{
Run git config fileMode is repairing problem when git repo was zipped on Linux and extracted on Windows.
The repo and submodules are marked as dirty which confuses users that fresh installation already contains changes.
More information: https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-config.html
}
procedure GitRepoFixFileMode(Path: String);
var
CmdLine: String;
begin
CmdLine := GitExecutablePath + ' -C ' + Path + ' config --local core.fileMode false';
Log('Setting core.fileMode on repository: ' + CmdLine);
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating fileMode', CmdLine);
Log('Setting core.fileMode on repository for submodules: ' + CmdLine);
CmdLine := GitExecutablePath + ' -C ' + Path + ' submodule foreach --recursive git config --local core.fileMode false';
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating fileMode in submodules', CmdLine);
end;
{ Run git reset --hard in the repo and in the submodules, to fix the newlines. }
procedure GitRepoFixNewlines(Path: String);
var
CmdLine: String;
begin
CmdLine := GitExecutablePath + ' -C ' + Path + ' reset --hard';
Log('Resetting the repository: ' + CmdLine);
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating newlines', CmdLine);
Log('Resetting the submodules: ' + CmdLine);
CmdLine := GitExecutablePath + ' -C ' + Path + ' submodule foreach git reset --hard';
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating newlines in submodules', CmdLine);
end;
{
There are 3 possible ways how an ESP-IDF copy can be obtained:
- Download the .zip archive with submodules included, extract to destination directory,
then do 'git reset --hard' and 'git submodule foreach git reset --hard' to correct for
possibly different newlines. This is done for release versions.
- Do a git clone of the Github repository into the destination directory.
This is done for the master branch.
- Download the .zip archive of a "close enough" release version, extract into a temporary
directory. Then do a git clone of the Github repository, using the temporary directory
as a '--reference'. This is done for other versions (such as release branches).
}
procedure IDFDownload();
var
CmdLine: String;
IDFTempPath: String;
IDFPath: String;
NeedToClone: Boolean;
begin
IDFPath := IDFDownloadPath;
{ If there is a release archive to download, IDFZIPFileName and IDFZIPFileVersion will be set.
See GetIDFZIPFileVersion function.
}
if IDFZIPFileName <> '' then
begin
if IDFZIPFileVersion <> IDFDownloadVersion then
begin
{ The version of .zip file downloaded is not the same as the version the user has requested.
Will use 'git clone --reference' to obtain the correct version, using the contents
of the .zip file as reference.
}
NeedToClone := True;
end;
ExtractTemporaryFile('7za.exe')
CmdLine := ExpandConstant('{tmp}\7za.exe x -o' + ExpandConstant('{tmp}') + ' -r -aoa "' + IDFZIPFileName + '"');
IDFTempPath := ExpandConstant('{tmp}\esp-idf-') + IDFZIPFileVersion;
Log('Extracting ESP-IDF reference repository: ' + CmdLine);
Log('Reference repository path: ' + IDFTempPath);
DoCmdlineInstall('Extracting ESP-IDF', 'Setting up reference repository', CmdLine);
end else begin
{ IDFZIPFileName is not set, meaning that we will rely on 'git clone'. }
NeedToClone := True;
Log('Not .zip release archive. Will do full clone.');
end;
if NeedToClone then
begin
CmdLine := GitExecutablePath + ' clone --recursive --progress -b ' + IDFDownloadVersion;
if IDFTempPath <> '' then
CmdLine := CmdLine + ' --reference ' + IDFTempPath;
CmdLine := CmdLine + ' https://github.com/espressif/esp-idf.git ' + IDFPath;
Log('Cloning IDF: ' + CmdLine);
DoCmdlineInstall('Downloading ESP-IDF', 'Using git to clone ESP-IDF repository', CmdLine);
if IDFTempPath <> '' then
GitRepoDissociate(IDFPath);
end else begin
Log('Copying ' + IDFTempPath + ' to ' + IDFPath);
if DirExists(IDFPath) then
begin
if not DirIsEmpty(IDFPath) then
begin
MsgBox('Destination directory exists and is not empty: ' + IDFPath, mbError, MB_OK);
RaiseException('Failed to copy ESP-IDF')
end;
end;
{ If cmd.exe command argument starts with a quote, the first and last quote chars in the command
will be removed by cmd.exe.
Keys explanation: /s+/e includes all subdirectories, /i assumes that destination is a directory,
/h copies hidden files, /q disables file name logging (making copying faster!)
}
CmdLine := ExpandConstant('cmd.exe /c ""xcopy" /s /e /i /h /q "' + IDFTempPath + '" "' + IDFPath + '""');
DoCmdlineInstall('Extracting ESP-IDF', 'Copying ESP-IDF into the destination directory', CmdLine);
GitRepoFixFileMode(IDFPath);
GitRepoFixNewlines(IDFPath);
DelTree(IDFTempPath, True, True, True);
end;
end;
{ ------------------------------ IDF Tools setup, Python environment setup ------------------------------ }
function UseBundledIDFToolsPy(Version: String) : Boolean;
begin
Result := False;
{ Use bundled copy of idf_tools.py, as the copy shipped with these IDF versions can not work due to
the --no-site-packages bug.
}
if (Version = 'v4.0') or (Version = 'v3.3.1') then
begin
Log('UseBundledIDFToolsPy: version=' + Version + ', using bundled idf_tools.py');
Result := True;
end;
end;
procedure IDFToolsSetup();
var
CmdLine: String;
IDFPath: String;
IDFToolsPyPath: String;
IDFToolsPyCmd: String;
BundledIDFToolsPyPath: String;
JSONArg: String;
begin
IDFPath := GetIDFPath('');
IDFToolsPyPath := IDFPath + '\tools\idf_tools.py';
BundledIDFToolsPyPath := ExpandConstant('{app}\idf_tools_fallback.py');
JSONArg := '';
if FileExists(IDFToolsPyPath) then
begin
Log('idf_tools.py exists in IDF directory');
if UseBundledIDFToolsPy(IDFDownloadVersion) then
begin
Log('Using the bundled idf_tools.py copy');
IDFToolsPyCmd := BundledIDFToolsPyPath;
end else begin
IDFToolsPyCmd := IDFToolsPyPath;
end;
end else begin
Log('idf_tools.py does not exist in IDF directory, using a fallback version');
IDFToolsPyCmd := BundledIDFToolsPyPath;
JSONArg := ExpandConstant('--tools "{app}\tools_fallback.json"');
end;
{ IDFPath not quoted, as it can not contain spaces }
IDFToolsPyCmd := PythonExecutablePath + ' "' + IDFToolsPyCmd + '" --idf-path ' + IDFPath + JSONArg;
SetEnvironmentVariable('PYTHONUNBUFFERED', '1')
Log('idf_tools.py command: ' + IDFToolsPyCmd);
CmdLine := IDFToolsPyCmd + ' install';
Log('Installing tools:' + CmdLine);
DoCmdlineInstall('Installing ESP-IDF tools', '', CmdLine);
CmdLine := IDFToolsPyCmd + ' install-python-env';
Log('Installing Python environment:' + CmdLine);
DoCmdlineInstall('Installing Python environment', '', CmdLine);
end;
{ Find Major and Minor version in esp_idf_version.h file. }
function GetIDFVersionFromHeaderFile():String;
var
HeaderFileName: String;
HeaderLines: TArrayOfString;
LineIndex: Integer;
LineCount: Longint;
Line: String;
MajorVersion: String;
MinorVersion: String;
begin
HeaderFileName := GetIDFPath('') + '\components\esp_common\include\esp_idf_version.h';
if (not FileExists(HeaderFileName)) then begin
Result := '';
Exit;
end;
LoadStringsFromFile(HeaderFileName, HeaderLines);
LineCount := GetArrayLength(HeaderLines);
for LineIndex := 0 to LineCount - 1 do begin
Line := HeaderLines[LineIndex];
if (pos('define ESP_IDF_VERSION_MAJOR', Line) > 0) then begin
Delete(Line, 1, 29);
MajorVersion := Trim(Line);
end else if (pos('define ESP_IDF_VERSION_MINOR', Line) > 0) then begin
Delete(Line, 1, 29);
MinorVersion := Trim(Line);
Result := MajorVersion + '.' + MinorVersion;
Exit;
end
end;
end;
{ ------------------------------ Start menu shortcut ------------------------------ }
procedure CreateIDFCommandPromptShortcut(LnkString: String);
var
Destination: String;
Description: String;
VersionIndex: Integer;
MajorString: String;
MinorString: String;
DotIndex: Integer;
IDFVersionString: String;
PythonVirtualEnvPath: String;
Command: String;
begin
ForceDirectories(ExpandConstant(LnkString));
Destination := ExpandConstant(LnkString + '\{#IDFCmdExeShortcutFile}');
Description := '{#IDFCmdExeShortcutDescription}';
IDFVersionString := IDFDownloadVersion;
{ Transform version vx.y or release/vx.y to x.y }
VersionIndex := pos('v', IDFVersionString);
if (VersionIndex > 0) then begin
Delete(IDFVersionString, 1, VersionIndex);
end;
{ Transform version x.y.z to x.y }
DotIndex := pos('.', IDFVersionString);
if (DotIndex > 0) then begin
MajorString := Copy(IDFVersionString, 1, DotIndex - 1);
Delete(IDFVersionString, 1, DotIndex);
{ Trim trailing version numbers. }
DotIndex := pos('.', IDFVersionString);
if (DotIndex > 0) then begin
MinorString := Copy(IDFVersionString, 1, DotIndex - 1);
IDFVersionString := MajorString + '.' + MinorString;
end else begin
IDFVersionString := MajorString + '.' + IDFVersionString;
end;
end;
{ Transform master to x.y }
if (IDFVersionString = 'master') then begin
IDFVersionString := GetIDFVersionFromHeaderFile();
end;
{ The links should contain reference to Python vitual env }
PythonVirtualEnvPath := ExpandConstant('{app}\python_env\idf') + IDFVersionString + '_py' + PythonVersion + '_env\Scripts';
{ Fallback in case of not existing environment. }
if (not FileExists(PythonVirtualEnvPath + '\python.exe')) then begin
PythonVirtualEnvPath := PythonPath;
end;
{ If cmd.exe command argument starts with a quote, the first and last quote chars in the command
will be removed by cmd.exe; each argument needs to be surrounded by quotes as well. }
Command := ExpandConstant('/k ""{app}\idf_cmd_init.bat" "') + PythonVirtualEnvPath + '" "' + GitPath + '""';
Log('CreateShellLink Destination=' + Destination + ' Description=' + Description + ' Command=' + Command)
try
CreateShellLink(
Destination,
Description,
'cmd.exe',
Command,
GetIDFPath(''),
'', 0, SW_SHOWNORMAL);
except
MsgBox('Failed to create the Start menu shortcut: ' + Destination, mbError, MB_OK);
RaiseException('Failed to create the shortcut');
end;
end;
{ ------------------------------ WD exclusion registration ------------------------------ }
procedure RegisterIDFToolsExecutablesInWD();
var
CmdLine: String;
begin
CmdLine := ExpandConstant('powershell -ExecutionPolicy ByPass -File "{app}\dist\tools_WD_excl.ps1" -AddExclPath "{app}\*.exe"');
Log('Registering IDF Tools executables in Windows Defender: ' + CmdLine);
DoCmdlineInstall('Finishing ESP-IDF installation', 'Registering IDF Tools executables in Windows Defender', CmdLine);
end;
<event('CurPageChanged')>
procedure CheckWinDefenderAvailable(CurPageID: Integer);
var
x: Integer;
begin
if CurPageID = wpSelectTasks then
begin
{ WD registration checkbox is identified by 'Windows Defender' substring anywhere in its caption.
Please, keep this in mind when making changes }
for x:=0 to (WizardForm.TasksList.Items.Count-1) do
begin
if Pos('Windows Defender', WizardForm.TasksList.ItemCaption[x]) > 0 then
begin
WizardForm.TasksList.ItemEnabled[x] := isWindowsDefenderEnabled;
WizardForm.TasksList.Checked[x] := isWindowsDefenderEnabled;
break;
end;
end;
end;
end;