kopia lustrzana https://github.com/espressif/esp-idf
486 wiersze
17 KiB
PHP
486 wiersze
17 KiB
PHP
{ Copyright 2019-2021 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;
|
|
GitRepoParam: String;
|
|
GitResetParam: String;
|
|
GitRecursiveParam: String;
|
|
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;
|
|
|
|
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 --progress -b ' + IDFDownloadVersion;
|
|
|
|
GitRecursiveParam := ExpandConstant('{param:GITRECURSIVE|yes}');
|
|
if (GitRecursiveParam = 'yes') then begin
|
|
CmdLine := CmdLine + ' --recursive ';
|
|
end;
|
|
|
|
if IDFTempPath <> '' then
|
|
CmdLine := CmdLine + ' --reference ' + IDFTempPath;
|
|
|
|
GitRepoParam := ExpandConstant('{param:GITREPO|https://github.com/espressif/esp-idf.git}');
|
|
|
|
CmdLine := CmdLine + ' ' + GitRepoParam +' ' + 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);
|
|
|
|
GitResetParam := ExpandConstant('{param:GITRESET|yes}');
|
|
if (GitResetParam = 'yes') then begin
|
|
GitRepoFixNewlines(IDFPath);
|
|
end else begin
|
|
Log('Git reset disabled by command line option /GITRESET=yes.');
|
|
end;
|
|
|
|
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;
|
|
|
|
{ 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;
|
|
|
|
{ Get short version from long version e.g. 3.7.9 -> 3.7 }
|
|
function GetShortVersion(VersionString:String):String;
|
|
var
|
|
VersionIndex: Integer;
|
|
MajorString: String;
|
|
MinorString: String;
|
|
DotIndex: Integer;
|
|
begin
|
|
{ Transform version vx.y or release/vx.y to x.y }
|
|
VersionIndex := pos('v', VersionString);
|
|
if (VersionIndex > 0) then begin
|
|
Delete(VersionString, 1, VersionIndex);
|
|
end;
|
|
|
|
{ Transform version x.y.z to x.y }
|
|
DotIndex := pos('.', VersionString);
|
|
if (DotIndex > 0) then begin
|
|
MajorString := Copy(VersionString, 1, DotIndex - 1);
|
|
Delete(VersionString, 1, DotIndex);
|
|
{ Trim trailing version numbers. }
|
|
DotIndex := pos('.', VersionString);
|
|
if (DotIndex > 0) then begin
|
|
MinorString := Copy(VersionString, 1, DotIndex - 1);
|
|
VersionString := MajorString + '.' + MinorString;
|
|
end else begin
|
|
VersionString := MajorString + '.' + VersionString;
|
|
end;
|
|
end;
|
|
|
|
Result := VersionString;
|
|
end;
|
|
|
|
{ Get IDF version string in combination with Python version. }
|
|
{ Result e.g.: idf4.1_py38 }
|
|
function GetIDFPythonEnvironmentVersion():String;
|
|
var
|
|
IDFVersionString: String;
|
|
begin
|
|
{ Transform main or master to x.y }
|
|
if (Pos('main', IDFDownloadVersion) > 0) or (Pos('master', IDFDownloadVersion) > 0) then begin
|
|
IDFVersionString := GetIDFVersionFromHeaderFile();
|
|
end else begin
|
|
IDFVersionString := GetShortVersion(IDFDownloadVersion);
|
|
end;
|
|
|
|
Result := 'idf' + IDFVersionString + '_py' + GetShortVersion(PythonVersion);
|
|
end;
|
|
|
|
procedure IDFToolsSetup();
|
|
var
|
|
CmdLine: String;
|
|
IDFPath: String;
|
|
IDFToolsPyPath: String;
|
|
IDFToolsPyCmd: String;
|
|
BundledIDFToolsPyPath: String;
|
|
JSONArg: String;
|
|
OfflineParameter: String;
|
|
PythonWheelsUrlParameter: 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');
|
|
|
|
OfflineParameter := ExpandConstant('{param:OFFLINE|no}');
|
|
if (OfflineParameter = 'yes') then begin
|
|
SetEnvironmentVariable('PIP_NO_INDEX', 'true');
|
|
Log('Offline installation selected. Setting environment variable PIP_NO_INDEX=1');
|
|
end else begin
|
|
PythonWheelsUrlParameter := ExpandConstant('{param:PYTHONWHEELSURL|https://dl.espressif.com/pypi}');
|
|
SetEnvironmentVariable('PIP_EXTRA_INDEX_URL', PythonWheelsUrlParameter);
|
|
Log('Adding extra Python wheels location. Setting environment variable PIP_EXTRA_INDEX_URL=' + PythonWheelsUrlParameter);
|
|
end;
|
|
|
|
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;
|
|
|
|
|
|
{ ------------------------------ Start menu shortcut ------------------------------ }
|
|
|
|
procedure CreateIDFCommandPromptShortcut(LnkString: String);
|
|
var
|
|
Destination: String;
|
|
Description: String;
|
|
PythonVirtualEnvPath: String;
|
|
Command: String;
|
|
begin
|
|
ForceDirectories(ExpandConstant(LnkString));
|
|
Destination := ExpandConstant(LnkString + '\{#IDFCmdExeShortcutFile}');
|
|
Description := '{#IDFCmdExeShortcutDescription}';
|
|
|
|
{ The links should contain reference to Python vitual env }
|
|
PythonVirtualEnvPath := ExpandConstant('{app}\python_env\') + GetIDFPythonEnvironmentVersion() + '_env\Scripts';
|
|
Log('Path to Python in virtual env: ' + PythonVirtualEnvPath);
|
|
|
|
{ Fallback in case of not existing environment. }
|
|
if (not FileExists(PythonVirtualEnvPath + '\python.exe')) then begin
|
|
PythonVirtualEnvPath := PythonPath;
|
|
Log('python.exe not found, reverting to:' + 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 shortcut: ' + Destination, mbError, MB_OK);
|
|
RaiseException('Failed to create the shortcut');
|
|
end;
|
|
end;
|
|
|
|
procedure CreateIDFPowershellShortcut(LnkString: String);
|
|
var
|
|
Destination: String;
|
|
Description: String;
|
|
Command: String;
|
|
GitPathWithForwardSlashes: String;
|
|
PythonPathWithForwardSlashes: String;
|
|
begin
|
|
ForceDirectories(ExpandConstant(LnkString));
|
|
Destination := ExpandConstant(LnkString + '\{#IDFPsShortcutFile}');
|
|
Description := '{#IDFPsShortcutDescription}';
|
|
GitPathWithForwardSlashes := GitPath;
|
|
PythonPathWithForwardSlashes := PythonPath;
|
|
StringChangeEx(GitPathWithForwardSlashes, '\', '/', True);
|
|
StringChangeEx(PythonPathWithForwardSlashes, '\', '/', True);
|
|
Command := ExpandConstant('-ExecutionPolicy Bypass -NoExit -File ""{app}\idf_cmd_init.ps1"" ') + '"' + GitPathWithForwardSlashes + '" "' + PythonPathWithForwardSlashes + '"'
|
|
Log('CreateShellLink Destination=' + Destination + ' Description=' + Description + ' Command=' + Command)
|
|
try
|
|
CreateShellLink(
|
|
Destination,
|
|
Description,
|
|
'powershell.exe',
|
|
Command,
|
|
GetIDFPath(''),
|
|
'', 0, SW_SHOWNORMAL);
|
|
except
|
|
MsgBox('Failed to create the 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;
|