tools: IDF Windows installer offline mode support

This commit is contained in:
Juraj Michalek
2020-08-28 12:33:48 +02:00
committed by Juraj Michálek
parent 67ba80f2ec
commit 70e06a46ba
29 changed files with 830 additions and 241 deletions

View File

@@ -389,7 +389,7 @@ build_installer:
extends: .test-on-windows extends: .test-on-windows
# using a different stage here to be able to use artifacts from build_cmdlinerunner job # using a different stage here to be able to use artifacts from build_cmdlinerunner job
stage: host_test stage: host_test
image: $CI_DOCKER_REGISTRY/wine-innosetup:1 image: $CI_DOCKER_REGISTRY/wine-innosetup:2
dependencies: # set dependencies to null to avoid missing artifacts issue dependencies: # set dependencies to null to avoid missing artifacts issue
needs: needs:
- build_cmdlinerunner - build_cmdlinerunner

View File

@@ -183,6 +183,9 @@ test_idf_tools:
- export PATH=$(p=$(echo $PATH | tr ":" "\n" | grep -v "/root/.espressif/tools\|/opt/espressif" | tr "\n" ":"); echo ${p%:}) - export PATH=$(p=$(echo $PATH | tr ":" "\n" | grep -v "/root/.espressif/tools\|/opt/espressif" | tr "\n" ":"); echo ${p%:})
- cd ${IDF_PATH}/tools/test_idf_tools - cd ${IDF_PATH}/tools/test_idf_tools
- ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_idf_tools.py - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_idf_tools.py
# Test for create virtualenv. It must be invoked from Python, not from virtualenv.
- cd ${IDF_PATH}/tools
- python3 ./idf_tools.py install-python-env
test_esp_err_to_name_on_host: test_esp_err_to_name_on_host:
extends: .host_test_template extends: .host_test_template

View File

@@ -6,7 +6,9 @@ Command-line parameters
Windows Installer `esp-idf-tools-setup` provides the following command-line parameters: Windows Installer `esp-idf-tools-setup` provides the following command-line parameters:
* ``/GITRECURSIVE=[yes|no]`` - Clone recursively all git repository submodules. Default: yes`` * ``/CONFIG=[PATH]`` - Path to ``ini`` configuration file to override default configuration of the installer. Default: ``config.ini``.
* ``/GITCLEAN=[yes|no]`` - Perform git clean and remove untracked directories in Offline mode installation. Default: yes.
* ``/GITRECURSIVE=[yes|no]`` - Clone recursively all git repository submodules. Default: yes
* ``/GITREPO=[URL|PATH]`` - URL of repository to clone ESP-IDF. Default: https://github.com/espressif/esp-idf.git * ``/GITREPO=[URL|PATH]`` - URL of repository to clone ESP-IDF. Default: https://github.com/espressif/esp-idf.git
* ``/GITRESET=[yes|no]`` - Enable/Disable git reset of repository during installation. Default: yes. * ``/GITRESET=[yes|no]`` - Enable/Disable git reset of repository during installation. Default: yes.
* ``/HELP`` - Display command line options provided by Inno Setup installer. * ``/HELP`` - Display command line options provided by Inno Setup installer.
@@ -16,6 +18,7 @@ Windows Installer `esp-idf-tools-setup` provides the following command-line para
* ``/LOG=[PATH]`` - Store installation log file in specific directory. Default: empty. * ``/LOG=[PATH]`` - Store installation log file in specific directory. Default: empty.
* ``/OFFLINE=[yes|no]`` - Execute installation of Python packages by PIP in offline mode. The same result can be achieved by setting the environment variable PIP_NO_INDEX. Default: no. * ``/OFFLINE=[yes|no]`` - Execute installation of Python packages by PIP in offline mode. The same result can be achieved by setting the environment variable PIP_NO_INDEX. Default: no.
* ``/USEEMBEDDEDPYTHON=[yes|no]`` - Use Embedded Python version for the installation. Set to ``no`` to allow Python selection screen in the installer. Default: yes. * ``/USEEMBEDDEDPYTHON=[yes|no]`` - Use Embedded Python version for the installation. Set to ``no`` to allow Python selection screen in the installer. Default: yes.
* ``/PYTHONNOUSERSITE=[yes|no]`` - Set PYTHONNOUSERSITE variable before launching any Python command to avoid loading Python packages from AppData\Roaming. Default: yes.
* ``/PYTHONWHEELSURL=[URL]`` - Specify URLs to PyPi repositories for resolving binary Python Wheel dependencies. The same result can be achieved by setting the environment variable PIP_EXTRA_INDEX_URL. Default: https://dl.espressif.com/pypi * ``/PYTHONWHEELSURL=[URL]`` - Specify URLs to PyPi repositories for resolving binary Python Wheel dependencies. The same result can be achieved by setting the environment variable PIP_EXTRA_INDEX_URL. Default: https://dl.espressif.com/pypi
* ``/SKIPSYSTEMCHECK=[yes|no]`` - Skip System Check page. Default: no. * ``/SKIPSYSTEMCHECK=[yes|no]`` - Skip System Check page. Default: no.
* ``/VERYSILENT /SUPPRESSMSGBOXES /SP- /NOCANCEL`` - Perform silent installation. * ``/VERYSILENT /SUPPRESSMSGBOXES /SP- /NOCANCEL`` - Perform silent installation.

View File

@@ -32,12 +32,7 @@ For this Getting Started we're going to use the Command Prompt, but after ESP-ID
ESP-IDF Tools Installer ESP-IDF Tools Installer
======================= =======================
The easiest way to install ESP-IDF's prerequisites is to download one of ESP-IDF Tools Installers from this URL: The easiest way to install ESP-IDF's prerequisites is to download one of ESP-IDF Tools Installers from this URL: https://dl.espressif.com/dl/esp-idf/?idf=4.4
- Online Installer (30 MB): https://dl.espressif.com/dl/esp-idf-tools-setup-online-2.5.exe
- Offline Installer - includes ESP-IDF v4.2, v4.1.1 (810 MB): https://dl.espressif.com/dl/esp-idf-tools-setup-offline-2.5.exe
.. IMPORTANT: Next time this link is updated, please go to get-started/index.rst and rewrite the section under "Alternative File Downloads ... Windows". Then delete this comment.
What is the usecase for Online and Offline Installer What is the usecase for Online and Offline Installer
---------------------------------------------------- ----------------------------------------------------

View File

@@ -32,12 +32,7 @@ ESP-IDF 需要安装一些必备工具,才能围绕 {IDF_TARGET_NAME} 构建
ESP-IDF 工具安装器 ESP-IDF 工具安装器
======================= =======================
安装 ESP-IDF 必备工具最简易的方式是下载 ESP-IDF 工具安装器,请选择下列地址之一: 安装 ESP-IDF 必备工具最简易的方式是从 https://dl.espressif.com/dl/esp-idf/?idf=4.4 中下载 ESP-IDF 工具安装器
- 在线安装30 MBhttps://dl.espressif.com/dl/esp-idf-tools-setup-online-2.5.exe
- 离线安装(包括 ESP-IDF v4.2、v4.1.1810 MBhttps://dl.espressif.com/dl/esp-idf-tools-setup-offline-2.5.exe
.. 重要:下次更新此链接时,请重新写文件 get-started/index.rst 中“其它文件下载方式”这一章节,然后将此条注意事项删除。
在线安装与离线安装的区别 在线安装与离线安装的区别
----------------------------------------- -----------------------------------------

View File

@@ -651,12 +651,12 @@
"version_regex": "Python ([0-9.]+)", "version_regex": "Python ([0-9.]+)",
"versions": [ "versions": [
{ {
"name": "3.9.1", "name": "3.8.7",
"status": "recommended", "status": "recommended",
"win64": { "win64": {
"sha256": "d5a0e625dd5b2bc6872de90292d71009c17e2396e3d1575d886a94d0dfb00c87", "sha256": "5fdf20350e71570642377fc58e61138f407cf286a87f11416829d94c4d9f2019",
"size": 20362758, "size": 20086226,
"url": "https://dl.espressif.com/dl/idf-python/idf-python-3.9.1-embed-win64.zip" "url": "https://dl.espressif.com/dl/idf-python/idf-python-3.8.7-embed-win64.zip"
} }
} }
] ]
@@ -680,17 +680,17 @@
"version_cmd": [ "version_cmd": [
"cmd", "cmd",
"/c", "/c",
"echo idf4.3_py3.9_2021-01-07" "echo 3.8-2020-01-21"
], ],
"version_regex": "(idf4.3_py3.9_2021-01-07)", "version_regex": "(3.8-2020-01-21)",
"versions": [ "versions": [
{ {
"name": "idf4.3_py3.9_2021-01-07", "name": "3.8-2020-01-21",
"status": "recommended", "status": "recommended",
"win64": { "win64": {
"sha256": "2a33dbaa106aec9c5098b1af46f04c69923be947291c19855ff355b9707314b6", "sha256": "0c2f40b615ce7a3d70c6690b44ef550c7c9fe4a480a92dfeb151ba4952e0212b",
"size": 8316997, "size": 9107660,
"url": "https://dl.espressif.com/dl/idf-python-wheels/idf-python-wheels-idf4.3_py3.9_2021-01-07-win64.zip" "url": "https://dl.espressif.com/dl/idf-python-wheels/idf-python-wheels-3.8-2020-01-21-win64.zip"
} }
} }
] ]

View File

@@ -4,3 +4,5 @@ dist
unzip unzip
keys keys
idf_versions.txt idf_versions.txt
releases
tools

View File

@@ -38,3 +38,10 @@ SystemCheckFixesFailed=Failed application of Fixes. Please refer to the Full log
SystemCheckNotCompleteConsent=System check is not complete. Do you want to proceed by skipping checks? SystemCheckNotCompleteConsent=System check is not complete. Do you want to proceed by skipping checks?
SystemCheckRootCertificates=Checking certificates SystemCheckRootCertificates=Checking certificates
SystemCheckRootCertificateWarning=Unable to load data from server dl.espressif.com. SystemCheckRootCertificateWarning=Unable to load data from server dl.espressif.com.
CreateShortcutStartMenu=Start Menu
CreateShortcutDesktop=Desktop
CreateShortcutPowerShell=PowerShell - Create shortcut for the ESP-IDF Tools:
CreateShortcutCMD=CMD - Create shortcut for the ESP-IDF Tools:
OptimizationTitle=Optimization:
OptimizationWindowsDefender=Register the ESP-IDF Tools executables as Windows Defender exclusions. The registration might improve compilation speed. The registration of exclusions requires elevation of privileges.
OptimizationDownloadMirror=Use Espressif download server instead of downloading tool packages from GitHub.

View File

@@ -32,7 +32,60 @@ This uses `wine-innosetup` Docker image and `build_installer.sh` script. This is
docker run --rm -v $IDF_PATH:/idf -w /idf/tools/windows/tool_setup -it $CI_DOCKER_REGISTRY/wine-innosetup:1 /bin/bash build_installer.sh docker run --rm -v $IDF_PATH:/idf -w /idf/tools/windows/tool_setup -it $CI_DOCKER_REGISTRY/wine-innosetup:1 /bin/bash build_installer.sh
``` ```
### Manually, step by step ### Windows development env with WSL2 and Windows Docker Containers
The best approach to quickly develop and test all aspects of the build process is to use Windows with WSL2.
Requirements:
* WSL2 and Ubuntu distribution via Microsoft Store
* Install Windows Terminal - https://github.com/microsoft/terminal
* Install Docker and switch container runner to Windows
* Install Visual Studio Code - install plugin for Inno Setup and Docker
* Install Inno Setup - `choco install innnosetup`
#### The first build of the installer
This step is bootstrapping the whole process. Open Windows Terminal, click + sign and select Ubuntu.
```
cd tools/windows/tools_setup/
./build_installer.sh online
```
The setup will download the necessary dependencies and it will build the installer.
#### Build of offline version of the installer
The offline version is built by setting /DOFFLINE=yes to ISCC on the command-line. To speed up build, it's possible to redirect stdout of ISCC to the file.
```
./build_installer.sh offline >out.txt
```
To speed up development build it's possible to disable compression which is set by default to lzma.
```
./build_installer.sh offline none >out.txt
```
#### Development work in idf_tool_setup.iss
Open Inno Setup and open file idf_tool_setup.iss. This is the main file of the installer
Press CTRL+F9 to rebuild the whole installer. Inno Setup detects changes only in the main file. If you change anything in include files, you need to explicitly press CTRL+F9 to build and Run.
Press F9 to run the installer.
Additional parameters to speed up development could be passed via Run - Parameters
#### Development work in iss.inc files
The majority of code is store in iss.inc files. The best way to develop it is to open a whole esp-idf directory in Visual Studio Code.
To configure syntax highlight for inc files, open Settings CTRL+, search for `Associations`. In section TextEditor - Files find `File: Associations`. Click `Add Item`, set `item` to `*.inc`, set `value` to `innnosetup`.
#### Manually, step by step
* Build cmdlinerunner DLL. * Build cmdlinerunner DLL.
- On Linux/Mac, install mingw-w64 toolchain (`i686-w64-mingw32-gcc`). Then build the DLL using CMake: - On Linux/Mac, install mingw-w64 toolchain (`i686-w64-mingw32-gcc`). Then build the DLL using CMake:
@@ -53,15 +106,7 @@ docker run --rm -v $IDF_PATH:/idf -w /idf/tools/windows/tool_setup -it $CI_DOCKE
* Build the installer using Inno Setup Compiler: `ISCC.exe idf_tools_setup.iss`. * Build the installer using Inno Setup Compiler: `ISCC.exe idf_tools_setup.iss`.
## Signing the installer ### Testing of the installer
* Obtain the signing key (e.g `key.pem`) and the certificate chain (e.g. `certchain.pem`). Set the environment variables to point to these files:
- `export KEYFILE=key.pem`
- `export CERTCHAIN=certchain.pem`
* Run `sign_installer.sh` script. This will ask for the `key.pem` password, and produce the signed installer in the Output directory. If you plan to run the script multiple times, you may also set `KEYPASSWORD` environment variable to the `key.pem` password, to avoid the prompt.
## Development and testing of the installer
Development and testing of the installer can be simplified by using command line parameters which can be passed to the installer. Development and testing of the installer can be simplified by using command line parameters which can be passed to the installer.
@@ -85,9 +130,9 @@ Documentation of parameters is available in api-guides/tools/idf-windows-install
### Testing installation in Docker with Windows containers ### Testing installation in Docker with Windows containers
The testing script is stored in docker-compose.yml. The test perform full silent installation and executes build of get-started example. The testing script is stored in docker-compose.yml. The test performs full silent installation and executes the build of get-started example.
Commands for testing multiple versions: Commands for testing of `online` and `offline` installer with support for cache of dist and releases:
``` ```
$env:IDF_VERSION="v4.1"; docker-compose.exe run idf-setup-test $env:IDF_VERSION="v4.1"; docker-compose.exe run idf-setup-test
@@ -100,7 +145,41 @@ $env:IDF_VERSION="release/v3.3"; docker-compose.exe run idf-setup-test
$env:IDF_VERSION="master"; docker-compose.exe run idf-setup-test $env:IDF_VERSION="master"; docker-compose.exe run idf-setup-test
``` ```
Command for testing `offline` type of installer which contains everything but kitchen sink.:
```
$env:IDF_VERSION="v4.2"; docker-compose.exe run idf-setup-offline-test
$env:IDF_VERSION="release/v4.2"; docker-compose.exe run idf-setup-offline-test
```
The installation log is not displayed immediately on the screen. It's stored in the file and it's displayed when the installation finishes. The glitch of Inno Setup is that in case of failed installation it won't terminate and it keeps hanging. The installation log is not displayed immediately on the screen. It's stored in the file and it's displayed when the installation finishes. The glitch of Inno Setup is that in case of failed installation it won't terminate and it keeps hanging.
Recommendation: Use Visual Studio Code with Docker plugin to work with container. Recommendation: Use Visual Studio Code with Docker plugin to work with container.
The log file is then accessible under Docker - Containers - Container - Files - Temp - install.txt - right click - Open. The log file is then accessible under Docker - Containers - Container - Files - Temp - install.txt - right click - Open.
### Testing multiple installations at once
Docker compose contains definition of multiple scenarios. The test can be launched by command:
```
$env:IDF_VERSION="v4.2"; docker-compose up --force-recreate
```
Note: `--force-recreate` is necessary otherwise the container will be just resumed from previous state.
### Testing the installation in Hyper-V
Docker does not support the test of installation with GUI and enabled Windows Defender. These tests can be executed in Hyper-V available on Windows. Launch `Hyper-V Manager`, create VM, and connect to it.
Use the following command to copy the installer to Hyper-V machine with the name "win10":
```
Copy-VMFile "win10" -SourcePath C:\projects\esp-idf\tools\windows\tool_setup\Output\esp-idf-tools-setup-unsigned.exe -DestinationPath "C:\Users\Tester\Desktop\esp-idf-tools-setup-unsigned.exe" -CreateFullPath -FileSource Host -Force
```
## Signing the installer
* Obtain the signing key (e.g `key.pem`) and the certificate chain (e.g. `certchain.pem`). Set the environment variables to point to these files:
- `export KEYFILE=key.pem`
- `export CERTCHAIN=certchain.pem`
* Run `sign_installer.sh` script. This will ask for the `key.pem` password and produce the signed installer in the Output directory. If you plan to run the script multiple times, you may also set `KEYPASSWORD` environment variable to the `key.pem` password, to avoid the prompt.

View File

@@ -4,12 +4,21 @@ param (
[string]$IdfVersion = "v4.1" [string]$IdfVersion = "v4.1"
) )
$Installer "Configuration:"
$IdfPath "* Installer = $Installer"
$IdfVersion "* IdfPath = $IdfPath"
"* IdfVersion = $IdfVersion"
$ProcessName = (Get-Item $Installer).Basename
"Waiting for process: $ProcessName"
# Set PYTHONHOME and PYTHONPATH to some directory which is not on the system to test process of creating venv
# The Installer and IDF shell wrappers contains clearing of variables
$env:PYTHONPATH="C:\Hvannadalshnúkur"
$env:PYTHONHOME="C:\Hvannadalshnúkur"
mkdir C:\Temp mkdir C:\Temp
C:\Output\esp-idf-tools-setup-unsigned.exe /VERYSILENT /LOG=C:\Temp\install.txt /SUPPRESSMSGBOXES /SP- /NOCANCEL /NORESTART /IDFVERSION=${IdfVersion} &$Installer /VERYSILENT /LOG=C:\Temp\install.txt /SUPPRESSMSGBOXES /SP- /NOCANCEL /NORESTART /IDFVERSION=${IdfVersion}
$InstallerProcess = Get-Process esp-idf-tools-setup-unsigned $InstallerProcess = Get-Process $ProcessName
Wait-Process -Id $InstallerProcess.id Wait-Process -Id $InstallerProcess.id
Get-Content C:\Temp\install.txt Get-Content -Tail 80 C:\Temp\install.txt

View File

@@ -1,28 +0,0 @@
param (
[string]$PythonPath = "C:\Python38\",
[string]$IdfPath = "C:\Users\ContainerAdministrator\Desktop\esp-idf"
)
$env:PATH+=";${PythonPath}"
Set-Location "${IdfPath}"
#.\export.ps1
$env:PYTHONPATH="C:\Users\ContainerAdministrator\Desktop\esp-idf\tools\"
# Append build script and launch via link
#Add-Content -Path ${IdfPath}\export.bat -Value ${BuildCommands}
# timeout is necessary to fix the problem when installer is writing some final files
# it seems that installer exits, but locks were not released yet
Start-Sleep -s 5
$WSShell = New-Object -comObject WScript.Shell
$Shortcut = $WSShell.CreateShortcut('C:\Users\ContainerAdministrator\Desktop\ESP-IDF Command Prompt (cmd.exe).lnk')
$Arguments = $Shortcut.Arguments -replace "/k ", "/c '"
$Command = $Shortcut.TargetPath + ' ' + $Arguments -replace '""', '"'
$Command += " && cd examples\get-started\blink\ && idf.py build'"
Invoke-Expression -Command $Command
#powershell.exe
#C:\Windows\system32\cmd.exe /c '"C:\Users\ContainerAdministrator\.espressif\idf_cmd_init.bat" "C:\Users\ContainerAdministrator\.espressif\python_env\idf4.1_py3.7_env\Scripts" "C:\Program Files\Git\cmd\" && cd examples\get-started\blink\ && idf.py build'
#cmd /c "ping -n 4 127.0.0.1 && .\export.bat && cd examples\get-started\blink\ && idf.py build"
#cmd /c "ping -n 4 127.0.0.1 && .\export.bat && cd examples\get-started\blink\ && idf.py build"
#cmd /c "timeout 4 && C:\Users\ContainerAdministrator\.espressif\idf_cmd_init.bat 'C:\' && cd examples\get-started\blink\ && idf.py build"
#& "C:\Users\ContainerAdministrator\Desktop\esp-idf\Run ESP-IDF Command Prompt (cmd.exe).lnk"

View File

@@ -0,0 +1,19 @@
param (
[string]$PythonPath = "C:\Python38\",
[string]$IdfPath = "C:\Users\ContainerAdministrator\Desktop\esp-idf"
)
$env:PATH+=";${PythonPath}"
Set-Location "${IdfPath}"
$env:PYTHONPATH="C:\Users\ContainerAdministrator\Desktop\esp-idf\tools\"
# Timeout is necessary to fix the problem when installer is writing some final files
# it seems that installer exits, but locks were not released yet
Start-Sleep -s 5
$WSShell = New-Object -comObject WScript.Shell
$Shortcut = $WSShell.CreateShortcut('C:\Users\ContainerAdministrator\Desktop\ESP-IDF Command Prompt (cmd.exe).lnk')
$Arguments = $Shortcut.Arguments -replace "/k ", "/c '"
$Command = $Shortcut.TargetPath + ' ' + $Arguments -replace '""', '"'
$Command += " && cd examples\get-started\blink\ && idf.py build'"
Invoke-Expression -Command $Command

View File

@@ -0,0 +1,31 @@
param (
[string]$PythonPath = "C:\Python38\",
[string]$IdfPath = "C:\Users\ContainerAdministrator\Desktop\esp-idf"
)
$env:PATH+=";${PythonPath}"
Set-Location "${IdfPath}"
$env:PYTHONPATH="C:\Users\ContainerAdministrator\Desktop\esp-idf\tools\"
# Timeout is necessary to fix the problem when installer is writing some final files
# it seems that installer exits, but locks were not released yet
Start-Sleep -s 5
$WSShell = New-Object -comObject WScript.Shell
$Shortcut = $WSShell.CreateShortcut('C:\Users\ContainerAdministrator\Desktop\ESP-IDF PowerShell.lnk')
$Command = '. ' + $Shortcut.Arguments -replace '""', '"'
$Command = $Command -replace " -ExecutionPolicy Bypass -NoExit -File", ""
$Command
Invoke-Expression -Command $Command
cd examples\get-started\blink\
idf.py build
# Check whether the repository is clean
$GitChanges=(git status -s).Lenght
if ($GitChanges -gt 0) {
"* Warning! Git repository dirty."
$GitChanges
} else {
"Git repository clean."
}

View File

@@ -7,23 +7,166 @@
# - Downloads 7z and idf_versions.txt # - Downloads 7z and idf_versions.txt
# - Runs ISCC under wine to compile the installer itself # - Runs ISCC under wine to compile the installer itself
set -x
set -e set -e
set -u set -u
INSTALLER_TYPE="${1-full}" INSTALLER_TYPE="${1-online}"
COMPRESSION="${2-lzma}"
# Default values for IDF installer passed in 'offline' version of build
IDF_GIT_VERSION="2.30.0.2"
IDF_GIT_VERSION_DIR="v2.30.0.windows.2"
IDF_PYTHON_VERSION="3.8.7"
IDF_PYTHON_WHEELS_VERSION="3.8-2021-01-21"
echo "Selected installer type: $INSTALLER_TYPE" echo "Selected installer type: $INSTALLER_TYPE"
echo "Available installer types: full, netinst" echo "Selected compresion: $COMPRESSION"
echo "Available installer types: online, offline, precached, draft"
echo "Available compressions: lzma, none"
PACKAGES="all" # Configuration options passed to ISCC compiler
if [[ "$INSTALLER_TYPE" == "netinst" ]]; then # OFFLINE [yes|no] - set installer to offline mode, nothing will be retrieved from
PACKAGES="idf-python" # internet during installation
ISCC_PARAMS=""
function prepare_offline_branches()
{
BUNDLE_DIR="releases/esp-idf-bundle"
if [[ ! -d "$BUNDLE_DIR" ]]; then
echo "Performing full clone."
git clone --shallow-since=2020-01-01 --jobs 8 --recursive https://github.com/espressif/esp-idf.git "$BUNDLE_DIR"
# Fix repo mode
git -C "$BUNDLE_DIR" config --local core.fileMode false
git -C "$BUNDLE_DIR" submodule foreach --recursive git config --local core.fileMode false
# Allow deleting directories by git clean --force
# Required when switching between versions which does not have a module present in current branch
git -C "$BUNDLE_DIR" config --local clean.requireForce false
git -C "$BUNDLE_DIR" reset --hard
git -C "$BUNDLE_DIR" submodule foreach git reset --hard
else
git -C "$BUNDLE_DIR" fetch
fi
VERSIONS="idf_versions.txt"
tac "$VERSIONS" | while read BRANCH; do
pushd "$BUNDLE_DIR"
if [[ -z "$BRANCH" ]]; then
continue
fi
echo "processing branch: ($BRANCH)"
git fetch origin tag "$BRANCH"
git checkout "$BRANCH"
# Pull changes only for branches, tags does not support pull
#https://stackoverflow.com/questions/1593188/how-to-programmatically-determine-whether-the-git-checkout-is-a-tag-and-if-so-w
git describe --exact-match HEAD || git pull
git submodule update --init --recursive
# Clean up left over submodule directories after switching to other branch
git clean --force -d
# Some modules are very persistent like cmok and needs 2nd round of cleaning
git clean --force -d
git reset --hard
git submodule foreach git reset --hard
if [[ $(git status -s | wc -l ) -ne 0 ]]; then
echo "git status not empty. Repository is dirty. Aborting."
git status
exit 1
fi
$IDF_PATH/tools/idf_tools.py --tools-json tools/tools.json --non-interactive download --platform Windows-x86_64 all
popd
done
# Remove symlinks which are not supported on Windws, unfortunatelly -c core.symlinks=false does not work
find "$BUNDLE_DIR" -type l -print -delete;
}
function install_idf_package()
{
TOOL_URL="$1"
TOOL_FILE="$2"
TOOL_VERSION="$3"
if [[ ! -f "${TOOL_FILE}" ]]; then
wget --no-verbose -O "${TOOL_FILE}" "${TOOL_URL}"
fi
if [[ ! -d "${TOOL_VERSION}" ]]; then
mkdir -p "${TOOL_VERSION}"
unzip -q "${TOOL_FILE}" -d "${TOOL_VERSION}"
fi
}
function install_idf_python()
{
install_idf_package \
"https://dl.espressif.com/dl/idf-python/idf-python-$IDF_PYTHON_VERSION-embed-win64.zip" \
"${IDF_TOOLS_PATH}/idf-python-${IDF_PYTHON_VERSION}-embed-win64.zip" \
"tools/idf-python/${IDF_PYTHON_VERSION}"
}
function install_idf_python_wheels()
{
install_idf_package \
"https://dl.espressif.com/dl/idf-python-wheels/idf-python-wheels-$IDF_PYTHON_WHEELS_VERSION-win64.zip" \
"${IDF_TOOLS_PATH}/idf-python-wheels-${IDF_PYTHON_WHEELS_VERSION}-win64.zip" \
"tools/idf-python-wheels/${IDF_PYTHON_WHEELS_VERSION}"
}
function install_idf_git()
{
IDF_FILE="Git-${IDF_GIT_VERSION}-64-bit.exe"
if [[ -f "${IDF_FILE}" ]]; then
return
fi
mkdir -p "${IDF_TOOLS_PATH}/dist/"
wget -nc --no-verbose -O "${IDF_TOOLS_PATH}/dist/${IDF_FILE}" "https://github.com/git-for-windows/git/releases/download/${IDF_GIT_VERSION_DIR}/${IDF_FILE}" || echo "exists"
if [[ `file -b "${IDF_TOOLS_PATH}/dist/${IDF_FILE}"` != "PE32 executable (GUI) Intel 80386, for MS Windows" ]]; then
echo "Git installer is not valid Windows Executable"
exit 1
fi
}
function download_idf_versions()
{
echo "Downloading idf_versions.txt..."
wget --no-verbose -O idf_versions.txt https://dl.espressif.com/dl/esp-idf/idf_versions.txt
}
function build_with_wine()
{
xvfb-run-wine /opt/wine/drive_c/Program\ Files\ \(x86\)/Inno\ Setup\ 6/ISCC.exe $ISCC_PARAMS idf_tool_setup.iss
}
# Check for ISCC on Windows WSL2
iscc_path=$(which ISCC.exe) || echo "ISCC.exe not found. If running in WSL2, install ISCC by following command: choco install innosetup"
if [[ -z "$iscc_path" ]]; then
echo "Searching for iscc"
iscc_path=$(which iscc)
if [[ -z "$iscc_path" ]]; then
echo "Inno setup compiler (iscc) not found. Are you running wine-innosetup Docker image?"
exit 1
fi
fi fi
iscc_path=$(which iscc) if [ ! -d "unzip" ]; then
if [[ -z "$iscc_path" ]]; then echo "Downloading 7z..."
echo "Inno setup compiler (iscc) not found. Are you running wine-innosetup Docker image?" mkdir -p unzip
exit 1 pushd unzip
wget --no-verbose -O 7z1900-extra.7z https://www.7-zip.org/a/7z1900-extra.7z
7zr e -y 7z1900-extra.7z
popd
fi fi
if [[ -z "${IDF_PATH:-}" ]]; then if [[ -z "${IDF_PATH:-}" ]]; then
@@ -31,24 +174,61 @@ if [[ -z "${IDF_PATH:-}" ]]; then
echo "Assuming IDF_PATH: ${IDF_PATH}" echo "Assuming IDF_PATH: ${IDF_PATH}"
fi fi
echo "Downloading IDF Tools..." export IDF_TOOLS_PATH="${PWD}/idf_tools_tmp_${INSTALLER_TYPE}"
mkdir -p idf_tools_tmp mkdir -p "${IDF_TOOLS_PATH}"
export IDF_TOOLS_PATH=$PWD/idf_tools_tmp echo "Using IDF_TOOLS_PATH specific for installer type: ${IDF_TOOLS_PATH}"
$IDF_PATH/tools/idf_tools.py --non-interactive download --platform Windows-x86_64 $PACKAGES
$IDF_PATH/tools/idf_tools.py --tools-json tools_fallback.json --non-interactive download --platform Windows-x86_64 all # Clean up production dist, data will be transferred from helper dist specific for installer type
if [[ -d "dist" ]]; then
rm -rf dist
fi
mkdir -p dist mkdir -p dist
cp idf_tools_tmp/dist/* dist/
echo "Downloading 7z..." if [[ "$INSTALLER_TYPE" == "precached" ]]; then
mkdir -p unzip ISCC_PARAMS="/DOFFLINE=no /DCOMPRESSION=$COMPRESSION /DSOLIDCOMPRESSION=no /DPYTHONWHEELSVERSION= /DGITVERSION=${IDF_GIT_VERSION} /DGITVERSIONDIR=${IDF_GIT_VERSION_DIR}"
pushd unzip download_idf_versions
wget --no-verbose -O 7z1900-extra.7z https://www.7-zip.org/a/7z1900-extra.7z $IDF_PATH/tools/idf_tools.py --non-interactive download --platform Windows-x86_64 all
7zr e -y 7z1900-extra.7z $IDF_PATH/tools/idf_tools.py --tools-json tools_fallback.json --non-interactive download --platform Windows-x86_64 all
popd cp $IDF_TOOLS_PATH/dist/* dist/
elif [[ "$INSTALLER_TYPE" == "online" ]]; then
ISCC_PARAMS="/DOFFLINE=no /DCOMPRESSION=$COMPRESSION /DSOLIDCOMPRESSION=no /DPYTHONWHEELSVERSION= /DGITVERSION=${IDF_GIT_VERSION} /DGITVERSIONDIR=${IDF_GIT_VERSION_DIR}"
download_idf_versions
install_idf_python
rm -rf tools/idf-python-wheels
elif [[ "$INSTALLER_TYPE" == "offline" ]]; then
# Turn off also solid compression - it causes delay in start time of installer.
ISCC_PARAMS="/DOFFLINE=yes /DCOMPRESSION=$COMPRESSION /DSOLIDCOMPRESSION=no /DPYTHONWHEELSVERSION=$IDF_PYTHON_WHEELS_VERSION /DGITVERSION=${IDF_GIT_VERSION} /DGITVERSIONDIR=${IDF_GIT_VERSION_DIR}"
echo "Downloading idf_versions.txt..." install_idf_git
wget --no-verbose -O idf_versions.txt https://dl.espressif.com/dl/esp-idf/idf_versions.txt install_idf_python
install_idf_python_wheels
cp idf_versions_offline.txt idf_versions.txt
prepare_offline_branches
cp $IDF_TOOLS_PATH/dist/* dist/
elif [[ "$INSTALLER_TYPE" == "draft" ]]; then
ISCC_PARAMS="/DOFFLINE=yes /DCOMPRESSION=$COMPRESSION /DSOLIDCOMPRESSION=no /DPYTHONWHEELSVERSION=$IDF_PYTHON_WHEELS_VERSION /DGITVERSION=${IDF_GIT_VERSION} /DGITVERSIONDIR=${IDF_GIT_VERSION_DIR}"
else
echo "Uknown type of installer: $INSTALLER_TYPE"
exit 1
fi
# Check for cmdlinerunner
if [[ ! -f "cmdlinerunner/build/cmdlinerunner.dll" ]]; then
echo "cmdlinerunner not found, downloading"
wget --no-verbose -O $IDF_TOOLS_PATH/idf-cmdlinerunner-1.0.zip https://dl.espressif.com/dl/idf-cmdlinerunner/idf-cmdlinerunner-1.0.zip
mkdir -p cmdlinerunner/build
unzip -q $IDF_TOOLS_PATH/idf-cmdlinerunner-1.0.zip -d cmdlinerunner/build/
rm $IDF_TOOLS_PATH/idf-cmdlinerunner-1.0.zip
fi
echo "Running ISCC..." echo "Running ISCC..."
# https://jrsoftware.org/ishelp/index.php?topic=compilercmdline # https://jrsoftware.org/ishelp/index.php?topic=compilercmdline
iscc idf_tool_setup.iss echo "iscc $ISCC_PARAMS idf_tool_setup.iss"
# Check whether we should run wine in case of docker image
which xvfb-run-wine && \
build_with_wine ||
iscc $ISCC_PARAMS idf_tool_setup.iss
mv "Output/esp-idf-tools-setup-unsigned.exe" "Output/esp-idf-tools-setup-${INSTALLER_TYPE}-unsigned.exe"

View File

@@ -0,0 +1,18 @@
[DEFAULT]
GITRECURSIVE=yes
GITRESET=yes
GITREPO=https://github.com/espressif/esp-idf.git
; In case of password protected keychain you can use ssh-agent
; Make sure that the 'Open SSH Agent' service is not Disabled in services list.
; Add kyes: ssh-add
; Tell git which ssh command to use, otherwise it might still prompt you for password
; [Environment]::SetEnvironmentVariable("GIT_SSH", "$((Get-Command ssh).Source)", [System.EnvironmentVariableTarget]::User)
; Start new process/terminal to load env variable
; Note: OpenSSH is part of Windows 1803 - https://poshsecurity.com/blog/using-the-openssh-client-included-in-windows-10-1809-as-your-gits-ssh-client
IDFDIR=
IDFVERSION=
IDFVERSIONSURL=https://dl.espressif.com/dl/esp-idf/idf_versions.txt
OFFLINE=yes
PYTHONWHEELSURL=https://dl.espressif.com/pypi
SKIPSYSTEMCHECK=no
USEEMBEDDEDPYTHON=yes

View File

@@ -0,0 +1,73 @@
{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD
SPDX-License-Identifier: Apache-2.0 }
{ ------------------------------ Load configuration of the installer ------------------------------ }
var
ConfigurationFile: String;
GitRepository: String;
IsGitRecursive: Boolean;
IsGitResetAllowed: Boolean;
IsGitCleanAllowed: Boolean;
IsPythonNoUserSite: Boolean;
IsOfflineMode: Boolean;
IDFDirectory: String;
IDFVersion: String;
IDFVersionUrl: String;
PythonWheelsUrl: String;
PythonWheelsVersion: String;
SkipSystemCheck: Boolean;
UseEmbeddedPython: Boolean;
function GetConfigurationString(Key: String; Default: String):String;
var Value: String;
begin
Value := GetIniString('DEFAULT', Key, Default, ConfigurationFile);
Value := ExpandConstant('{param:' + Key + '|' + Value + '}');
Log('Configuration /' + Key + '=' + Value);
Result := Value;
end;
function GetConfigurationBoolean(Key: String; DefaultString: String):Boolean;
begin
Result := (GetConfigurationString(Key, DefaultString) = 'yes');
end;
{ Initialize configuration of the installer. }
{ Default configuration is encoded in installer. }
{ The configuration can be changed by configuration.ini file. }
{ The configuration can be changed by command line options which have highest priority. }
<event('InitializeWizard')>
procedure InitializeConfiguration();
begin
ConfigurationFile := ExpandConstant('{param:CONFIG|}');
if (ConfigurationFile <> '') then begin
if (not FileExists(ConfigurationFile)) then begin
Log('Configuration file does not exist, using default values.');
end;
end;
Log('Configuration /CONFIG=' + ConfigurationFile);
IsGitCleanAllowed := GetConfigurationBoolean('GITCLEAN', 'yes');
IsGitRecursive := GetConfigurationBoolean('GITRECURSIVE', 'yes');
IsGitResetAllowed := GetConfigurationBoolean('GITRESET', 'yes');
GitRepository := GetConfigurationString('GITREPO', 'https://github.com/espressif/esp-idf.git');
IDFDirectory := GetConfigurationString('IDFDIR', '');
IDFVersion := GetConfigurationString('IDFVERSION', '');
IDFVersionUrl := GetConfigurationString('IDFVERSIONSURL', 'https://dl.espressif.com/dl/esp-idf/idf_versions.txt');
IsOfflineMode := GetConfigurationBoolean('OFFLINE', '{#OFFLINE}');
IsPythonNoUserSite := GetConfigurationBoolean('PYTHONNOUSERSITE', 'yes');
PythonWheelsUrl := GetConfigurationString('PYTHONWHEELSURL', 'https://dl.espressif.com/pypi');
PythonWheelsVersion := GetConfigurationString('PYTHONWHEELSVERSION', '{#PYTHONWHEELSVERSION}');
SkipSystemCheck := GetConfigurationBoolean('SKIPSYSTEMCHECK', 'no');
UseEmbeddedPython := GetConfigurationBoolean('USEEMBEDDEDPYTHON', 'yes');
end;
{ Required to display option for installation configuration. }
function IsOnlineMode():Boolean;
begin
Result := not IsOfflineMode;
end;

View File

@@ -3,9 +3,39 @@ version: "3"
# This docker-compose is for testing the installation process. # This docker-compose is for testing the installation process.
# In starts the installation and executes also build of get-started example. # In starts the installation and executes also build of get-started example.
services: services:
idf-setup-test: idf-setup-online-test:
image: mcr.microsoft.com/windows/servercore:1809 image: mcr.microsoft.com/windows/servercore:1809
command: powershell -c "C:/Scripts/Prepare-Cache.ps1 -IdfVersion ${IDF_VERSION}; C:/Scripts/Install-Idf.ps1 -Installer 'c:/Output/esp-idf-tools-setup-unsigned.exe' -IdfVersion ${IDF_VERSION}; C:/Scripts/Test-Idf.ps1; powershell ;exit $$LASTEXITCODE" command: powershell -c "C:/Scripts/Install-Idf.ps1 -Installer 'c:/Output/esp-idf-tools-setup-online-unsigned.exe' -IdfVersion ${IDF_VERSION}; C:/Scripts/Test-IdfCmd.ps1; C:/Scripts/Test-IdfPowerShell.ps1;; powershell ;exit $$LASTEXITCODE"
tmpfs:
- C:\Users\ContainerAdministrator\.espressif
volumes:
- type: bind
source: C:\projects\esp-idf\tools\windows\tool_setup\Output
target: C:\Output
read_only: true
- type: bind
source: C:\projects\esp-idf\tools\windows\tool_setup\Scripts
target: C:\Scripts
read_only: true
idf-setup-offline-test:
image: mcr.microsoft.com/windows/servercore:1809
command: powershell -c "C:/Scripts/Install-Idf.ps1 -Installer 'c:/Output/esp-idf-tools-setup-offline-unsigned.exe' -IdfVersion ${IDF_VERSION}; C:/Scripts/Test-IdfCmd.ps1; C:/Scripts/Test-IdfPowerShell.ps1; powershell ;exit $$LASTEXITCODE"
tmpfs:
- C:\Users\ContainerAdministrator\.espressif
volumes:
- type: bind
source: C:\projects\esp-idf\tools\windows\tool_setup\Output
target: C:\Output
read_only: true
- type: bind
source: C:\projects\esp-idf\tools\windows\tool_setup\Scripts
target: C:\Scripts
read_only: true
idf-setup-precached-test:
image: mcr.microsoft.com/windows/servercore:1809
command: powershell -c "C:/Scripts/Prepare-Cache.ps1 -IdfVersion ${IDF_VERSION}; C:/Scripts/Install-Idf.ps1 -Installer 'c:/Output/esp-idf-tools-setup-online-unsigned.exe' -IdfVersion ${IDF_VERSION}; C:/Scripts/Test-IdfCmd.ps1; C:/Scripts/Test-IdfPowerShell.ps1; powershell ;exit $$LASTEXITCODE"
tmpfs: tmpfs:
- C:\Users\ContainerAdministrator\.espressif - C:\Users\ContainerAdministrator\.espressif
volumes: volumes:

View File

@@ -31,6 +31,18 @@ if not "%PYTHONPATH%"=="" (
set PYTHONPATH= set PYTHONPATH=
) )
:: Clear PYTHONHOME as it may contain path to other Python versions which can cause crash of Python using virtualenv
if not "%PYTHONHOME%"=="" (
echo Clearing PYTHONHOME, was set to %PYTHONHOME%
set PYTHONHOME=
)
:: Set PYTHONNOUSERSITE to avoid loading of Python packages from AppData\Roaming profile
if "%PYTHONNOUSERSITE%"=="" (
echo Setting PYTHONNOUSERSITE, was not set
set PYTHONNOUSERSITE=True
)
:: Add Python and Git paths to PATH :: Add Python and Git paths to PATH
set "PATH=%IDF_PYTHON_DIR%;%IDF_GIT_DIR%;%PATH%" set "PATH=%IDF_PYTHON_DIR%;%IDF_GIT_DIR%;%PATH%"
echo Using Python in %IDF_PYTHON_DIR% echo Using Python in %IDF_PYTHON_DIR%

View File

@@ -17,6 +17,24 @@ if (-not $isEspIdfRoot) {
Write-Output "This script must be invoked from ESP-IDF directory." Write-Output "This script must be invoked from ESP-IDF directory."
} }
# Clear PYTHONPATH as it may contain libraries of other Python versions
if ($null -ne $env:PYTHONPATH) {
"Clearing PYTHONPATH, was set to $env:PYTHONPATH"
$env:PYTHONPATH=$null
}
# Clear PYTHONHOME as it may contain path to other Python versions which can cause crash of Python using virtualenv
if ($null -ne $env:PYTHONHOME) {
"Clearing PYTHONHOME, was set to $env:PYTHONHOME"
$env:PYTHONHOME=$null
}
# Set PYTHONNOUSERSITE to avoid loading of Python packages from AppData\Roaming profile
if ($null -eq $env:PYTHONNOUSERSITE) {
"Setting PYTHONNOUSERSITE, was not set"
$env:PYTHONNOUSERSITE="True"
}
# Strip quotes # Strip quotes
$IdfGitDir = $IdfGitDir.Trim("`"") $IdfGitDir = $IdfGitDir.Trim("`"")
$IdfPythonDir = $IdfPythonDir.Trim("`"") $IdfPythonDir = $IdfPythonDir.Trim("`"")

View File

@@ -13,6 +13,11 @@ var
BaseName: String; BaseName: String;
RepeatIndex: Integer; RepeatIndex: Integer;
begin begin
if (IDFDirectory <> '') then begin
Result := IDFDirectory
Exit;
end;
{ Start with Desktop\esp-idf name and if it already exists, { Start with Desktop\esp-idf name and if it already exists,
keep trying with Desktop\esp-idf-N for N=2 and above. } keep trying with Desktop\esp-idf-N for N=2 and above. }
BaseName := ExpandConstant('{userdesktop}\esp-idf'); BaseName := ExpandConstant('{userdesktop}\esp-idf');
@@ -41,19 +46,22 @@ begin
Result := ''; Result := '';
end; end;
procedure ExtractIDFVersionList();
begin
ExtractTemporaryFile('idf_versions.txt');
end;
procedure DownloadIDFVersionsList(); procedure DownloadIDFVersionsList();
var var
Url: String;
VersionFile: String; VersionFile: String;
begin begin
Url := ExpandConstant('{param:IDFVERSIONSURL|https://dl.espressif.com/dl/esp-idf/idf_versions.txt}')
VersionFile := ExpandConstant('{tmp}\idf_versions.txt'); VersionFile := ExpandConstant('{tmp}\idf_versions.txt');
if idpDownloadFile(Url, VersionFile) then if idpDownloadFile(IDFVersionUrl, VersionFile) then
begin begin
Log('Downloaded ' + Url + ' to ' + VersionFile); Log('Downloaded ' + IDFVersionUrl + ' to ' + VersionFile);
end else begin end else begin
Log('Download of ' + Url + ' failed, using a fallback versions list'); Log('Download of ' + IDFVersionUrl + ' failed, using a fallback versions list');
ExtractTemporaryFile('idf_versions.txt'); ExtractIDFVersionList();
end; end;
end; end;
@@ -62,14 +70,18 @@ var
Page: TInputOptionWizardPage; Page: TInputOptionWizardPage;
VersionFile: String; VersionFile: String;
i: Integer; i: Integer;
SuggestedIDFDirectory: String;
begin begin
Page := TInputOptionWizardPage(Sender); Page := TInputOptionWizardPage(Sender);
Log('OnIDFDownloadPagePrepare'); Log('OnIDFDownloadPagePrepare');
if Page.CheckListBox.Items.Count > 0 then if Page.CheckListBox.Items.Count > 0 then
exit; exit;
DownloadIDFVersionsList(); if (IsOfflineMode) then begin
Log('Offline Mode: using embedded idf_versions.txt')
ExtractIDFVersionList();
end else begin
DownloadIDFVersionsList();
end;
VersionFile := ExpandConstant('{tmp}\idf_versions.txt'); VersionFile := ExpandConstant('{tmp}\idf_versions.txt');
if not LoadStringsFromFile(VersionFile, IDFDownloadAvailableVersions) then if not LoadStringsFromFile(VersionFile, IDFDownloadAvailableVersions) then
@@ -87,8 +99,7 @@ begin
end; end;
Page.SelectedValueIndex := 0; Page.SelectedValueIndex := 0;
SuggestedIDFDirectory := ExpandConstant('{param:IDFDIR|' + GetSuggestedIDFDirectory() + '}'); ChoicePageSetInputText(Page, GetSuggestedIDFDirectory());
ChoicePageSetInputText(Page, SuggestedIDFDirectory);
end; end;
{ Validation of PATH for IDF releases which does not support special characters. } { Validation of PATH for IDF releases which does not support special characters. }
@@ -143,15 +154,15 @@ begin
IDFDownloadPath := IDFPath; IDFDownloadPath := IDFPath;
{ Use parameter /IDFVE=x to override selection in the box. } { Use parameter /IDFVERSION=x to override selection in the box. }
IDFDownloadVersion := ExpandConstant('{param:IDFVERSION|}'); IDFDownloadVersion := IDFVersion;
if (IDFDownloadVersion = '') then begin if (IDFDownloadVersion = '') then begin
IDFDownloadVersion := IDFDownloadAvailableVersions[Page.SelectedValueIndex]; IDFDownloadVersion := IDFDownloadAvailableVersions[Page.SelectedValueIndex];
end; end;
{ Following ZIP versions of IDF does not support installation on path with special characters. } { Following ZIP versions of IDF does not support installation on path with special characters. }
{ Issue: https://github.com/espressif/esp-idf/issues/5996 } { Issue: https://github.com/espressif/esp-idf/issues/5996 }
if ((IDFDownloadVersion = 'v4.1') or (IDFDownloadVersion = 'v4.0.2') or if ((IDFDownloadVersion = 'v4.2') or (IDFDownloadVersion = 'v4.0.2') or
(IDFDownloadVersion = 'v3.3.4')) then begin (IDFDownloadVersion = 'v3.3.4')) then begin
if (not IsDirNameValid(IDFPath)) then begin if (not IsDirNameValid(IDFPath)) then begin
MsgBox('The installation of selected version of IDF is not supported on path with special characters.' + #13#10 MsgBox('The installation of selected version of IDF is not supported on path with special characters.' + #13#10
@@ -175,10 +186,10 @@ procedure CreateIDFDownloadPage();
begin begin
IDFDownloadPage := ChoicePageCreate( IDFDownloadPage := ChoicePageCreate(
IDFPage.ID, IDFPage.ID,
'Download ESP-IDF', 'Please choose ESP-IDF version to download', 'Version of ESP-IDF', 'Please choose ESP-IDF version to install',
'For more information about ESP-IDF versions, see' + #13#10 + 'For more information about ESP-IDF versions, see' + #13#10 +
'https://docs.espressif.com/projects/esp-idf/en/latest/versions.html', 'https://docs.espressif.com/projects/esp-idf/en/latest/versions.html',
'Choose a directory to download ESP-IDF to', 'Choose a directory to install ESP-IDF to',
True, True,
@OnIDFDownloadPagePrepare, @OnIDFDownloadPagePrepare,
@OnIDFDownloadSelectionChange, @OnIDFDownloadSelectionChange,

View File

@@ -103,6 +103,16 @@ begin
end; end;
end; end;
<event('ShouldSkipPage')>
function ShouldSkipIDFPage(PageID: Integer): Boolean;
begin
{ The page does not make sense in offline mode }
if (PageID = IDFPage.ID) and IsOfflineMode then begin
Result := True;
end;
end;
<event('InitializeWizard')> <event('InitializeWizard')>
procedure CreateIDFPage(); procedure CreateIDFPage();
begin begin

View File

@@ -51,19 +51,24 @@ var
Url, MirrorUrl: String; Url, MirrorUrl: String;
begin begin
IDFZIPFileVersion := GetIDFZIPFileVersion(IDFDownloadVersion); IDFZIPFileVersion := GetIDFZIPFileVersion(IDFDownloadVersion);
Log('IDFZIPFileVersion: ' + IDFZIPFileVersion);
if IDFZIPFileVersion <> '' then if IDFZIPFileVersion <> '' then
begin begin
Url := 'https://github.com/espressif/esp-idf/releases/download/' + IDFZIPFileVersion + '/esp-idf-' + IDFZIPFileVersion + '.zip'; 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'; 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') IDFZIPFileName := ExpandConstant('{app}\releases\esp-idf-' + IDFZIPFileVersion + '.zip');
if not FileExists(IDFZIPFileName) then if not FileExists(IDFZIPFileName) then
begin begin
Log('IDFZIPFileName: ' + IDFZIPFileName + ' exists');
ForceDirectories(ExpandConstant('{app}\releases')) ForceDirectories(ExpandConstant('{app}\releases'))
Log('Adding download: ' + Url + ', mirror: ' + MirrorUrl + ', destination: ' + IDFZIPFileName); Log('Adding download: ' + Url + ', mirror: ' + MirrorUrl + ', destination: ' + IDFZIPFileName);
idpAddFile(Url, IDFZIPFileName); idpAddFile(Url, IDFZIPFileName);
idpAddMirror(Url, MirrorUrl); idpAddMirror(Url, MirrorUrl);
end else begin end else begin
Log(IDFZIPFileName + ' already exists') Log('IDFZIPFileName: ' + IDFZIPFileName + ' does not exist');
end; end;
end; end;
end; end;
@@ -90,6 +95,19 @@ begin
FindFileRecursive(Path + '\.git', 'alternates', @RemoveAlternatesFile); FindFileRecursive(Path + '\.git', 'alternates', @RemoveAlternatesFile);
end; end;
{
Initialize submodules - required to call when switching branches in existing repo.
E.g. created by offline installer
}
procedure GitUpdateSubmodules(Path: String);
var
CmdLine: String;
begin
CmdLine := GitExecutablePath + ' -C ' + Path + ' submodule update --init --recursive';
Log('Updating submodules: ' + CmdLine);
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating submodules', CmdLine);
end;
{ {
Run git config fileMode is repairing problem when git repo was zipped on Linux and extracted on Windows. 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. The repo and submodules are marked as dirty which confuses users that fresh installation already contains changes.
@@ -109,10 +127,15 @@ begin
end; end;
{ Run git reset --hard in the repo and in the submodules, to fix the newlines. } { Run git reset --hard in the repo and in the submodules, to fix the newlines. }
procedure GitRepoFixNewlines(Path: String); procedure GitResetHard(Path: String);
var var
CmdLine: String; CmdLine: String;
begin begin
if (not IsGitResetAllowed) then begin
Log('Git reset disabled by command line option /GITRESET=no.');
Exit;
end;
CmdLine := GitExecutablePath + ' -C ' + Path + ' reset --hard'; CmdLine := GitExecutablePath + ' -C ' + Path + ' reset --hard';
Log('Resetting the repository: ' + CmdLine); Log('Resetting the repository: ' + CmdLine);
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating newlines', CmdLine); DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating newlines', CmdLine);
@@ -122,6 +145,39 @@ begin
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating newlines in submodules', CmdLine); DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating newlines in submodules', CmdLine);
end; end;
{ Run git clean - clean leftovers after switching between tags }
{ The repo should be created with: git config --local clean.requireForce false}
procedure GitCleanForceDirectory(Path: String);
var
CmdLine: String;
begin
if (not IsGitCleanAllowed) then begin
Log('Git clean disabled by command line option /GITCLEAN=no.');
Exit;
end;
CmdLine := GitExecutablePath + ' -C ' + Path + ' clean --force -d';
Log('Resetting the repository: ' + CmdLine);
DoCmdlineInstall('Finishing ESP-IDF installation', 'Cleaning untracked directories', CmdLine);
end;
{
Switch to different branch. Used in offline installation.
}
procedure GitSwitchBranch(Path: String; BranchName: String);
var
CmdLine: String;
begin
CmdLine := GitExecutablePath + ' -C ' + Path + ' checkout ' + BranchName;
Log('Updating submodules: ' + CmdLine);
DoCmdlineInstall('Switching branch', 'Switching to branch', CmdLine);
GitUpdateSubmodules(Path);
GitResetHard(Path);
GitCleanForceDirectory(Path);
end;
{ {
There are 3 possible ways how an ESP-IDF copy can be obtained: There are 3 possible ways how an ESP-IDF copy can be obtained:
- Download the .zip archive with submodules included, extract to destination directory, - Download the .zip archive with submodules included, extract to destination directory,
@@ -134,15 +190,25 @@ end;
as a '--reference'. This is done for other versions (such as release branches). as a '--reference'. This is done for other versions (such as release branches).
} }
procedure IDFDownload(); procedure IDFOfflineInstall();
var
IDFTempPath: String;
IDFPath: String;
begin
IDFPath := IDFDownloadPath;
IDFTempPath := ExpandConstant('{app}\releases\esp-idf-bundle');
Log('IDFTempPath - location of bundle: ' + IDFTempPath);
GitSwitchBranch(IDFPath, IDFDownloadVersion);
end;
procedure IDFDownloadInstall();
var var
CmdLine: String; CmdLine: String;
IDFTempPath: String; IDFTempPath: String;
IDFPath: String; IDFPath: String;
NeedToClone: Boolean; NeedToClone: Boolean;
GitRepoParam: String;
GitResetParam: String;
GitRecursiveParam: String;
begin begin
IDFPath := IDFDownloadPath; IDFPath := IDFDownloadPath;
{ If there is a release archive to download, IDFZIPFileName and IDFZIPFileVersion will be set. { If there is a release archive to download, IDFZIPFileName and IDFZIPFileVersion will be set.
@@ -175,17 +241,14 @@ begin
begin begin
CmdLine := GitExecutablePath + ' clone --progress -b ' + IDFDownloadVersion; CmdLine := GitExecutablePath + ' clone --progress -b ' + IDFDownloadVersion;
GitRecursiveParam := ExpandConstant('{param:GITRECURSIVE|yes}'); if (IsGitRecursive) then begin
if (GitRecursiveParam = 'yes') then begin
CmdLine := CmdLine + ' --recursive '; CmdLine := CmdLine + ' --recursive ';
end; end;
if IDFTempPath <> '' then if IDFTempPath <> '' then
CmdLine := CmdLine + ' --reference ' + IDFTempPath; CmdLine := CmdLine + ' --reference ' + IDFTempPath;
GitRepoParam := ExpandConstant('{param:GITREPO|https://github.com/espressif/esp-idf.git}'); CmdLine := CmdLine + ' ' + GitRepository +' ' + IDFPath;
CmdLine := CmdLine + ' ' + GitRepoParam +' ' + IDFPath;
Log('Cloning IDF: ' + CmdLine); Log('Cloning IDF: ' + CmdLine);
DoCmdlineInstall('Downloading ESP-IDF', 'Using git to clone ESP-IDF repository', CmdLine); DoCmdlineInstall('Downloading ESP-IDF', 'Using git to clone ESP-IDF repository', CmdLine);
@@ -193,6 +256,7 @@ begin
GitRepoDissociate(IDFPath); GitRepoDissociate(IDFPath);
end else begin end else begin
Log('Copying ' + IDFTempPath + ' to ' + IDFPath); Log('Copying ' + IDFTempPath + ' to ' + IDFPath);
if DirExists(IDFPath) then if DirExists(IDFPath) then
begin begin
@@ -202,21 +266,18 @@ begin
RaiseException('Failed to copy ESP-IDF') RaiseException('Failed to copy ESP-IDF')
end; end;
end; end;
{ If cmd.exe command argument starts with a quote, the first and last quote chars in the command { If cmd.exe command argument starts with a quote, the first and last quote chars in the command
will be removed by cmd.exe. will be removed by cmd.exe.
Keys explanation: /s+/e includes all subdirectories, /i assumes that destination is a directory, 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!) /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 + '""'); 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); DoCmdlineInstall('Extracting ESP-IDF', 'Copying ESP-IDF into the destination directory', CmdLine);
GitRepoFixFileMode(IDFPath);
GitResetParam := ExpandConstant('{param:GITRESET|yes}'); GitRepoFixFileMode(IDFPath);
if (GitResetParam = 'yes') then begin GitResetHard(IDFPath);
GitRepoFixNewlines(IDFPath);
end else begin
Log('Git reset disabled by command line option /GITRESET=yes.');
end;
DelTree(IDFTempPath, True, True, True); DelTree(IDFTempPath, True, True, True);
end; end;
@@ -318,6 +379,22 @@ begin
Result := 'idf' + IDFVersionString + '_py' + GetShortVersion(PythonVersion); Result := 'idf' + IDFVersionString + '_py' + GetShortVersion(PythonVersion);
end; end;
function GetPythonVirtualEnvPath(): String;
var
PythonVirtualEnvPath: String;
begin
{ 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;
Result := PythonVirtualEnvPath;
end;
procedure IDFToolsSetup(); procedure IDFToolsSetup();
var var
CmdLine: String; CmdLine: String;
@@ -326,8 +403,7 @@ var
IDFToolsPyCmd: String; IDFToolsPyCmd: String;
BundledIDFToolsPyPath: String; BundledIDFToolsPyPath: String;
JSONArg: String; JSONArg: String;
OfflineParameter: String; PythonVirtualEnvPath: String;
PythonWheelsUrlParameter: String;
begin begin
IDFPath := GetIDFPath(''); IDFPath := GetIDFPath('');
IDFToolsPyPath := IDFPath + '\tools\idf_tools.py'; IDFToolsPyPath := IDFPath + '\tools\idf_tools.py';
@@ -355,54 +431,54 @@ begin
SetEnvironmentVariable('PYTHONUNBUFFERED', '1'); SetEnvironmentVariable('PYTHONUNBUFFERED', '1');
OfflineParameter := ExpandConstant('{param:OFFLINE|no}'); if (IsOfflineMode) then begin
if (OfflineParameter = 'yes') then begin
SetEnvironmentVariable('PIP_NO_INDEX', 'true'); SetEnvironmentVariable('PIP_NO_INDEX', 'true');
Log('Offline installation selected. Setting environment variable PIP_NO_INDEX=1'); Log('Offline installation selected. Setting environment variable PIP_NO_INDEX=1');
SetEnvironmentVariable('PIP_FIND_LINKS', ExpandConstant('{app}\tools\idf-python-wheels\' + PythonWheelsVersion));
end else begin end else begin
PythonWheelsUrlParameter := ExpandConstant('{param:PYTHONWHEELSURL|https://dl.espressif.com/pypi}'); SetEnvironmentVariable('PIP_EXTRA_INDEX_URL', PythonWheelsUrl);
SetEnvironmentVariable('PIP_EXTRA_INDEX_URL', PythonWheelsUrlParameter); Log('Adding extra Python wheels location. Setting environment variable PIP_EXTRA_INDEX_URL=' + PythonWheelsUrl);
Log('Adding extra Python wheels location. Setting environment variable PIP_EXTRA_INDEX_URL=' + PythonWheelsUrlParameter);
end; end;
Log('idf_tools.py command: ' + IDFToolsPyCmd); Log('idf_tools.py command: ' + IDFToolsPyCmd);
CmdLine := IDFToolsPyCmd + ' install'; CmdLine := IDFToolsPyCmd + ' install';
Log('Installing tools:' + CmdLine); Log('Installing tools:' + CmdLine);
DoCmdlineInstall('Installing ESP-IDF tools', '', CmdLine); DoCmdlineInstall('Installing ESP-IDF tools', '', CmdLine);
CmdLine := IDFToolsPyCmd + ' install-python-env'; CmdLine := PythonExecutablePath + ' -m virtualenv --version';
Log('Checking Python virtualenv support:' + CmdLine)
DoCmdlineInstall('Checking Python virtualenv support', '', CmdLine);
PythonVirtualEnvPath := ExpandConstant('{app}\python_env\') + GetIDFPythonEnvironmentVersion() + '_env';
CmdLine := PythonExecutablePath + ' -m virtualenv "' + PythonVirtualEnvPath + '" -p ' + '"' + PythonExecutablePath + '"';
if (DirExists(PythonVirtualEnvPath)) then begin
Log('ESP-IDF Python Virtual environment exists, refreshing the environment: ' + CmdLine);
end else begin
Log('ESP-IDF Python Virtual environment does not exist, creating the environment: ' + CmdLine);
end;
DoCmdlineInstall('Creating Python environment', '', CmdLine);
CmdLine := IDFToolsPyCmd + ' install-python-env';
Log('Installing Python environment:' + CmdLine); Log('Installing Python environment:' + CmdLine);
DoCmdlineInstall('Installing Python environment', '', CmdLine); DoCmdlineInstall('Installing Python environment', '', CmdLine);
end; end;
{ ------------------------------ Start menu shortcut ------------------------------ } { ------------------------------ Start menu shortcut ------------------------------ }
procedure CreateIDFCommandPromptShortcut(LnkString: String); procedure CreateIDFCommandPromptShortcut(LnkString: String);
var var
Destination: String; Destination: String;
Description: String; Description: String;
PythonVirtualEnvPath: String;
Command: String; Command: String;
begin begin
ForceDirectories(ExpandConstant(LnkString)); ForceDirectories(ExpandConstant(LnkString));
Destination := ExpandConstant(LnkString + '\{#IDFCmdExeShortcutFile}'); Destination := ExpandConstant(LnkString + '\{#IDFCmdExeShortcutFile}');
Description := '{#IDFCmdExeShortcutDescription}'; 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 { 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. } 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 + '""'; Command := ExpandConstant('/k ""{app}\idf_cmd_init.bat" "') + GetPythonVirtualEnvPath() + '" "' + GitPath + '""';
Log('CreateShellLink Destination=' + Destination + ' Description=' + Description + ' Command=' + Command) Log('CreateShellLink Destination=' + Destination + ' Description=' + Description + ' Command=' + Command)
try try
CreateShellLink( CreateShellLink(
@@ -430,7 +506,8 @@ begin
Destination := ExpandConstant(LnkString + '\{#IDFPsShortcutFile}'); Destination := ExpandConstant(LnkString + '\{#IDFPsShortcutFile}');
Description := '{#IDFPsShortcutDescription}'; Description := '{#IDFPsShortcutDescription}';
GitPathWithForwardSlashes := GitPath; GitPathWithForwardSlashes := GitPath;
PythonPathWithForwardSlashes := PythonPath;
PythonPathWithForwardSlashes := GetPythonVirtualEnvPath();
StringChangeEx(GitPathWithForwardSlashes, '\', '/', True); StringChangeEx(GitPathWithForwardSlashes, '\', '/', True);
StringChangeEx(PythonPathWithForwardSlashes, '\', '/', True); StringChangeEx(PythonPathWithForwardSlashes, '\', '/', True);
Command := ExpandConstant('-ExecutionPolicy Bypass -NoExit -File ""{app}\idf_cmd_init.ps1"" ') + '"' + GitPathWithForwardSlashes + '" "' + PythonPathWithForwardSlashes + '"' Command := ExpandConstant('-ExecutionPolicy Bypass -NoExit -File ""{app}\idf_cmd_init.ps1"" ') + '"' + GitPathWithForwardSlashes + '" "' + PythonPathWithForwardSlashes + '"'
@@ -448,38 +525,3 @@ begin
RaiseException('Failed to create the shortcut'); RaiseException('Failed to create the shortcut');
end; end;
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;

View File

@@ -5,26 +5,55 @@
#include <idp.iss> #include <idp.iss>
#define MyAppName "ESP-IDF Tools" #define MyAppName "ESP-IDF Tools"
#define MyAppVersion "2.4" #define MyAppVersion "2.5"
#define MyAppPublisher "Espressif Systems (Shanghai) Co. Ltd." #define MyAppPublisher "Espressif Systems (Shanghai) Co. Ltd."
#define MyAppURL "https://github.com/espressif/esp-idf" #define MyAppURL "https://github.com/espressif/esp-idf"
#define PythonVersion "3.9.1" #ifndef PYTHONVERSION
#define PythonInstallerName "idf-python-3.9.1-embed-win64.zip" #define PYTHONVERSION "3.8.7"
#define PythonInstallerDownloadURL "https://dl.espressif.com/dl/idf-python/idf-python-3.9.1-embed-win64.zip" #endif
#define PythonInstallerName "idf-python-" + PYTHONVERSION + "-embed-win64.zip"
#define PythonInstallerDownloadURL "https://dl.espressif.com/dl/idf-python/idf-python-" + PYTHONVERSION + "-embed-win64.zip"
#define GitVersion "2.28.0" #ifndef GITVERSION
#define GitInstallerName "Git-2.28.0-64-bit.exe" #define GITVERSION "2.30.0.2"
#define GitInstallerDownloadURL "https://github.com/git-for-windows/git/releases/download/v2.28.0.windows.1/Git-2.28.0-64-bit.exe" #endif
; The URL where git is stored is not equal to it's version. Minor build has prefixes with windows
#ifndef GITVERSIONDIR
#define GITVERSIONDIR "v2.30.0.windows.2"
#endif
#define GitInstallerName "Git-" + GITVERSION + "-64-bit.exe"
#define GitInstallerDownloadURL "https://github.com/git-for-windows/git/releases/download/" + GITVERSIONDIR + "/Git-" + GITVERSION + "-64-bit.exe"
#define IDFVersionsURL "https://dl.espressif.com/dl/esp-idf/idf_versions.txt" #define IDFVersionsURL "https://dl.espressif.com/dl/esp-idf/idf_versions.txt"
#define IDFCmdExeShortcutDescription "Open ESP-IDF Command Prompt (cmd.exe) Environment" #define IDFCmdExeShortcutDescription "Open ESP-IDF Command Prompt (cmd.exe) Environment"
#define IDFCmdExeShortcutFile "ESP-IDF CMD.lnk" #define IDFCmdExeShortcutFile "ESP-IDF Command Prompt (cmd.exe).lnk"
#define IDFPsShortcutDescription "Open ESP-IDF PowerShell Environment" #define IDFPsShortcutDescription "Open ESP-IDF PowerShell Environment"
#define IDFPsShortcutFile "ESP-IDF PowerShell.lnk" #define IDFPsShortcutFile "ESP-IDF PowerShell.lnk"
; List of default values
; Default values can be set by command-line option when startig installer
; or it can be stored in .INI file which can be passed to installer by /CONFIG=[PATH].
; Code for evaluating configuration is in the file configuration.inc.iss.
#ifndef COMPRESSION
#define COMPRESSION = 'lzma';
#endif
; In case of large installer set it to 'no' to avoid problem delay during starting installer
; In case of 1 GB installer it could be 30+ seconds just to start installer.
#ifndef SOLIDCOMPRESSION
#define SOLIDCOMPRESSION = 'yes';
#endif
; Offline installation specific options
#ifndef OFFLINE
#define OFFLINE = 'no';
#endif
#ifndef PYTHONWHEELSVERSION
#define PYTHONWHEELSVERSION = '3.8-2021-01-21'
#endif
[Setup] [Setup]
; NOTE: The value of AppId uniquely identifies this application. ; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications. ; Do not use the same AppId value in installers for other applications.
@@ -43,8 +72,8 @@ DirExistsWarning=no
DefaultGroupName=ESP-IDF DefaultGroupName=ESP-IDF
DisableProgramGroupPage=yes DisableProgramGroupPage=yes
OutputBaseFilename=esp-idf-tools-setup-unsigned OutputBaseFilename=esp-idf-tools-setup-unsigned
Compression=lzma Compression={#COMPRESSION}
SolidCompression=yes SolidCompression={#SOLIDCOMPRESSION}
ArchitecturesAllowed=x64 ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64 ArchitecturesInstallIn64BitMode=x64
LicenseFile=license.txt LicenseFile=license.txt
@@ -53,6 +82,12 @@ SetupLogging=yes
ChangesEnvironment=yes ChangesEnvironment=yes
WizardStyle=modern WizardStyle=modern
; https://jrsoftware.org/ishelp/index.php?topic=setup_touchdate
; Default values are set to 'no' which might result in files that are installed on the machine
; in the 'future'. This creates a problem for Ninja/CMake which may end up in a neverending loop.
; Setting this flag to 'yes' should avoid the problem.
TimeStampsInUTC=yes
[Languages] [Languages]
Name: "english"; MessagesFile: "compiler:Default.isl,Languages/idf_tool_en-US.islu" Name: "english"; MessagesFile: "compiler:Default.isl,Languages/idf_tool_en-US.islu"
@@ -60,6 +95,7 @@ Name: "english"; MessagesFile: "compiler:Default.isl,Languages/idf_tool_en-US.is
Name: "{app}\dist" Name: "{app}\dist"
[Files] [Files]
Source: "configuration.ini"; Flags: dontcopy noencryption
Source: "cmdlinerunner\build\cmdlinerunner.dll"; Flags: dontcopy Source: "cmdlinerunner\build\cmdlinerunner.dll"; Flags: dontcopy
Source: "unzip\7za.exe"; Flags: dontcopy Source: "unzip\7za.exe"; Flags: dontcopy
Source: "idf_versions.txt"; Flags: dontcopy Source: "idf_versions.txt"; Flags: dontcopy
@@ -68,7 +104,13 @@ Source: "..\..\idf_tools.py"; DestDir: "{app}"; DestName: "idf_tools_fallback.py
Source: "tools_fallback.json"; DestDir: "{app}"; DestName: "tools_fallback.json" Source: "tools_fallback.json"; DestDir: "{app}"; DestName: "tools_fallback.json"
Source: "idf_cmd_init.bat"; DestDir: "{app}" Source: "idf_cmd_init.bat"; DestDir: "{app}"
Source: "idf_cmd_init.ps1"; DestDir: "{app}" Source: "idf_cmd_init.ps1"; DestDir: "{app}"
Source: "dist\*"; DestDir: "{app}\dist" Source: "dist\*"; DestDir: "{app}\dist"; Flags: skipifsourcedoesntexist;
; esp-idf-bundle - bundle only in case it exists, it's used only in offline installer
Source: "releases\esp-idf-bundle\*"; DestDir: "{code:GetIDFPath}"; Flags: recursesubdirs skipifsourcedoesntexist;
Source: "tools\idf-python\*"; DestDir: "{app}\tools\idf-python\"; Flags: recursesubdirs;
Source: "tools\idf-python-wheels\*"; DestDir: "{app}\tools\idf-python-wheels\"; Flags: recursesubdirs skipifsourcedoesntexist;
; Helper Python files for sanity check of Python environment - used by system_check_page ; Helper Python files for sanity check of Python environment - used by system_check_page
Source: "system_check\system_check_download.py"; Flags: dontcopy Source: "system_check\system_check_download.py"; Flags: dontcopy
Source: "system_check\system_check_subprocess.py"; Flags: dontcopy Source: "system_check\system_check_subprocess.py"; Flags: dontcopy
@@ -88,19 +130,22 @@ Type: files; Name: "{autodesktop}\{#IDFCmdExeShortcutFile}"
Type: files; Name: "{autodesktop}\{#IDFPsShortcutFile}" Type: files; Name: "{autodesktop}\{#IDFPsShortcutFile}"
[Tasks] [Tasks]
Name: CreateLnkStartCmd; Description: "Create Start Menu shortcut for the ESP-IDF Tools Command Prompt Environment"; Name: CreateLinkStartPowerShell; GroupDescription: "{cm:CreateShortcutPowerShell}"; Description: "{cm:CreateShortcutStartMenu}";
Name: CreateLnkStartPs; Description: "Create Start Menu shortcut for the ESP-IDF Tools Powershell Environment"; Name: CreateLinkDeskPowerShell; GroupDescription: "{cm:CreateShortcutPowerShell}"; Description: "{cm:CreateShortcutDesktop}";
Name: CreateLnkDeskCmd; Description: "Create Desktop shortcut for the ESP-IDF Tools Command Prompt Environment";
Name: CreateLnkDeskPs; Description: "Create Desktop shortcut for the ESP-IDF Tools Powershell Environment"; Name: CreateLinkStartCmd; GroupDescription: "{cm:CreateShortcutCMD}"; Description: "{cm:CreateShortcutStartMenu}";
; WD registration checkbox is identified by 'Windows Defender' substring anywhere in its caption, not by the position index in WizardForm.TasksList.Items Name: CreateLinkDeskCmd; GroupDescription: "{cm:CreateShortcutCMD}"; Description: "{cm:CreateShortcutDesktop}";
; Please, keep this in mind when making changes to the item's description - WD checkbox is to be disabled on systems without the Windows Defender installed
Name: wdexcl; Description: "Register the ESP-IDF Tools executables as Windows Defender exclusions (improves compilation speed, requires elevation)"; ; Optimization for Online mode
Name: idf_tools_use_mirror; Description: "Use Espressif download server instead of downloading tool packages from Github"; Flags: unchecked; Name: UseMirror; GroupDescription:"{cm:OptimizationTitle}"; Description: "{cm:OptimizationDownloadMirror}"; Flags: unchecked; Check: IsOnlineMode
[Run] [Run]
Filename: "{app}\dist\{#GitInstallerName}"; Parameters: "/silent /tasks="""" /norestart"; Description: "Installing Git"; Check: GitInstallRequired Filename: "{app}\dist\{#GitInstallerName}"; Parameters: "/silent /tasks="""" /norestart"; Description: "Installing Git"; Check: GitInstallRequired
Filename: "{group}\{#IDFPsShortcutFile}"; Flags: postinstall shellexec unchecked; Description: "Run ESP-IDF PowerShell Environment"; Check: IsPowerShellInstalled Filename: "{group}\{#IDFPsShortcutFile}"; Flags: postinstall shellexec unchecked; Description: "Run ESP-IDF PowerShell Environment"; Check: IsPowerShellInstalled
Filename: "{group}\{#IDFCmdExeShortcutFile}"; Flags: postinstall shellexec unchecked; Description: "Run ESP-IDF Command Prompt Environment"; Check: IsCmdInstalled Filename: "{group}\{#IDFCmdExeShortcutFile}"; Flags: postinstall shellexec unchecked; Description: "Run ESP-IDF Command Prompt Environment"; Check: IsCmdInstalled
; WD registration checkbox is identified by 'Windows Defender' substring anywhere in its caption, not by the position index in WizardForm.TasksList.Items
; Please, keep this in mind when making changes to the item's description - WD checkbox is to be disabled on systems without the Windows Defender installed
Filename: "powershell"; Parameters: "-ExecutionPolicy ByPass -File ""{app}\dist\tools_WD_excl.ps1"" -AddExclPath ""{app}\*.exe"""; Flags: postinstall shellexec runhidden; Description: "{cm:OptimizationWindowsDefender}"; Check: GetIsWindowsDefenderEnabled
[UninstallRun] [UninstallRun]
@@ -113,6 +158,7 @@ Root: HKCU; Subkey: "Environment"; ValueType: string; ValueName: "IDF_TOOLS_PATH
ValueData: "{app}"; Flags: preservestringtype createvalueifdoesntexist uninsdeletevalue deletevalue; ValueData: "{app}"; Flags: preservestringtype createvalueifdoesntexist uninsdeletevalue deletevalue;
[Code] [Code]
#include "configuration.iss.inc"
#include "utils.iss.inc" #include "utils.iss.inc"
#include "choice_page.iss.inc" #include "choice_page.iss.inc"
#include "cmdline_page.iss.inc" #include "cmdline_page.iss.inc"

View File

@@ -0,0 +1,2 @@
v4.2
v4.1.1

View File

@@ -40,11 +40,19 @@ var
DestPath: String; DestPath: String;
begin begin
Result := True; Result := True;
if CurPageID <> wpReady then if CurPageID <> wpReady then begin
exit; Exit;
end;
ForceDirectories(ExpandConstant('{app}\dist')); ForceDirectories(ExpandConstant('{app}\dist'));
if (IsOfflineMode) then begin
ForceDirectories(ExpandConstant('{app}\releases'));
IDFZIPFileVersion := IDFDownloadVersion;
IDFZIPFileName := ExpandConstant('{app}\releases\esp-idf-bundle.zip');
Exit;
end;
if not GitUseExisting then if not GitUseExisting then
begin begin
DestPath := ExpandConstant('{app}\dist\{#GitInstallerName}'); DestPath := ExpandConstant('{app}\dist\{#GitInstallerName}');
@@ -68,6 +76,8 @@ procedure AddPythonGitToPath();
var var
EnvPath: String; EnvPath: String;
PythonLibPath: String; PythonLibPath: String;
EnvPythonHome: String;
PythonNoUserSite: String;
begin begin
EnvPath := GetEnv('PATH'); EnvPath := GetEnv('PATH');
@@ -83,10 +93,28 @@ begin
new value to be visible to this process. } new value to be visible to this process. }
SetEnvironmentVariable('IDF_TOOLS_PATH', ExpandConstant('{app}')) SetEnvironmentVariable('IDF_TOOLS_PATH', ExpandConstant('{app}'))
{ Set PYTHONNOUSERSITE variable True to avoid loading packages from AppData\Roaming. }
{ https://doc.pypy.org/en/latest/man/pypy.1.html#environment }
{ If set to a non-empty value, equivalent to the -s option. Dont add the user site directory to sys.path. }
if (IsPythonNoUserSite) then begin
PythonNoUserSite := 'True';
end else begin
PythonNoUserSite := '';
end;
Log('PYTHONNOUSERSITE=' + PythonNoUserSite);
SetEnvironmentVariable('PYTHONNOUSERSITE', PythonNoUserSite);
{ Log and clear PYTHONPATH variable, as it might point to libraries of another Python version} { Log and clear PYTHONPATH variable, as it might point to libraries of another Python version}
PythonLibPath := GetEnv('PYTHONPATH') PythonLibPath := GetEnv('PYTHONPATH')
Log('PYTHONPATH=' + PythonLibPath) Log('PYTHONPATH=' + PythonLibPath)
SetEnvironmentVariable('PYTHONPATH', '') SetEnvironmentVariable('PYTHONPATH', '')
{ Log and clear PYTHONHOME, the existence of PYTHONHOME might cause trouble when creating virtualenv. }
{ The error message when creating virtualenv: }
{ Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding. }
EnvPythonHome := GetEnv('PYTHONHOME')
Log('PYTHONHOME=' + EnvPythonHome)
SetEnvironmentVariable('PYTHONHOME', '')
end; end;
procedure InstallEmbeddedPython(); procedure InstallEmbeddedPython();
@@ -102,10 +130,11 @@ begin
UpdatePythonVariables(EmbeddedPythonPath); UpdatePythonVariables(EmbeddedPythonPath);
Log('Checking existence of Embedded Python: ' + EmbeddedPythonPath); Log('Checking existence of Embedded Python: ' + EmbeddedPythonPath);
if (FileExists(EmbeddedPythonPath)) then begin if (FileExists(EmbeddedPythonPath)) then begin
Log('Embedded Python found.');
Exit; Exit;
end; end;
CmdLine := ExpandConstant('{tmp}\7za.exe x -o{app}\tools\python\' + PythonVersion + '\ -r -aoa "{app}\dist\idf-python-' + PythonVersion + '-embed-win64.zip"'); CmdLine := ExpandConstant('{tmp}\7za.exe x -o{app}\tools\idf-python\' + PythonVersion + '\ -r -aoa "{app}\dist\idf-python-' + PythonVersion + '-embed-win64.zip"');
DoCmdlineInstall('Extracting Python Interpreter', 'Using Embedded Python', CmdLine); DoCmdlineInstall('Extracting Python Interpreter', 'Using Embedded Python', CmdLine);
end; end;
@@ -117,16 +146,22 @@ begin
if CurStep <> ssPostInstall then if CurStep <> ssPostInstall then
exit; exit;
ExtractTemporaryFile('7za.exe') ExtractTemporaryFile('7za.exe');
InstallEmbeddedPython(); InstallEmbeddedPython();
try try
AddPythonGitToPath(); AddPythonGitToPath();
if not IDFUseExisting then if not IDFUseExisting then begin
IDFDownload(); if (IsOfflineMode) then begin
IDFOfflineInstall();
end else begin
IDFDownloadInstall();
end;
end;
if WizardIsTaskSelected('idf_tools_use_mirror') then if WizardIsTaskSelected('UseMirror') then
begin begin
SetEnvironmentVariable('IDF_GITHUB_ASSETS', 'dl.espressif.com/github_assets') SetEnvironmentVariable('IDF_GITHUB_ASSETS', 'dl.espressif.com/github_assets')
end; end;
@@ -134,31 +169,26 @@ begin
IDFToolsSetup(); IDFToolsSetup();
if WizardIsTaskSelected('CreateLnkStartCmd') then if WizardIsTaskSelected('CreateLinkStartCmd') then
begin begin
CreateIDFCommandPromptShortcut('{autostartmenu}\Programs\ESP-IDF'); CreateIDFCommandPromptShortcut('{autostartmenu}\Programs\ESP-IDF');
end; end;
if WizardIsTaskSelected('CreateLnkStartPs') then if WizardIsTaskSelected('CreateLinkStartPowerShell') then
begin begin
CreateIDFPowershellShortcut('{autostartmenu}\Programs\ESP-IDF' ); CreateIDFPowershellShortcut('{autostartmenu}\Programs\ESP-IDF' );
end; end;
if WizardIsTaskSelected('CreateLnkDeskCmd') then if WizardIsTaskSelected('CreateLinkDeskCmd') then
begin begin
CreateIDFCommandPromptShortcut('{autodesktop}'); CreateIDFCommandPromptShortcut('{autodesktop}');
end; end;
if WizardIsTaskSelected('CreateLnkDeskPs') then if WizardIsTaskSelected('CreateLinkDeskPowerShell') then
begin begin
CreateIDFPowershellShortcut('{autodesktop}'); CreateIDFPowershellShortcut('{autodesktop}');
end; end;
if WizardIsTaskSelected('wdexcl') then
begin
RegisterIDFToolsExecutablesInWD();
end;
except except
SetupAborted := True; SetupAborted := True;
if MsgBox('Installation log has been created, it may contain more information about the problem.' + #13#10 if MsgBox('Installation log has been created, it may contain more information about the problem.' + #13#10
@@ -184,10 +214,10 @@ end;
function IsPowerShellInstalled(): Boolean; function IsPowerShellInstalled(): Boolean;
begin begin
Result := ((not SetupAborted) and (WizardIsTaskSelected('CreateLnkDeskPs') or WizardIsTaskSelected('CreateLnkStartPs'))); Result := ((not SetupAborted) and (WizardIsTaskSelected('CreateLinkDeskPowerShell') or WizardIsTaskSelected('CreateLinkStartPowerShell')));
end; end;
function IsCmdInstalled(): Boolean; function IsCmdInstalled(): Boolean;
begin begin
Result := ((not SetupAborted) and (WizardIsTaskSelected('CreateLnkDeskCmd') or WizardIsTaskSelected('CreateLnkStartCmd'))); Result := ((not SetupAborted) and (WizardIsTaskSelected('CreateLinkDeskCmd') or WizardIsTaskSelected('CreateLinkStartCmd')));
end; end;

View File

@@ -128,13 +128,10 @@ end;
<event('ShouldSkipPage')> <event('ShouldSkipPage')>
function ShouldSkipPythonPage(PageID: Integer): Boolean; function ShouldSkipPythonPage(PageID: Integer): Boolean;
var
UseEmbeddedPythonParam: String;
begin begin
if (PageID = PythonPage.ID) then begin if (PageID = PythonPage.ID) then begin
{ Skip in case of embedded Python. } { Skip in case of embedded Python. }
UseEmbeddedPythonParam := ExpandConstant('{param:USEEMBEDDEDPYTHON|yes}'); if (UseEmbeddedPython) then begin
if (UseEmbeddedPythonParam = 'yes') then begin
ApplyPythonConfigurationByIndex(0); ApplyPythonConfigurationByIndex(0);
Result := True; Result := True;
end; end;

View File

@@ -6,6 +6,8 @@
set -e set -e
set -u set -u
INSTALLER_TYPE="${1-online}"
if [[ -z "${KEYFILE:-}" || -z "${CERTCHAIN:-}" ]]; then if [[ -z "${KEYFILE:-}" || -z "${CERTCHAIN:-}" ]]; then
echo "To sign the installer, set the following environment variables:" echo "To sign the installer, set the following environment variables:"
echo " KEYFILE - private key file" echo " KEYFILE - private key file"
@@ -19,8 +21,8 @@ umask 770 # for the process substitution FIFO
VERSION=`grep "#define MyAppVersion " idf_tool_setup.iss | cut -d ' ' -f3 | tr -d '"'` VERSION=`grep "#define MyAppVersion " idf_tool_setup.iss | cut -d ' ' -f3 | tr -d '"'`
echo "Installer version ${VERSION}" echo "Installer version ${VERSION}"
IN_FILE="Output/esp-idf-tools-setup-unsigned.exe" IN_FILE="Output/esp-idf-tools-setup-${INSTALLER_TYPE}-unsigned.exe"
OUT_FILE="Output/esp-idf-tools-setup-${VERSION}.exe" OUT_FILE="Output/esp-idf-tools-setup-${INSTALLER_TYPE}-${VERSION}.exe"
if [[ -n "${KEYPASSWORD:-}" ]]; then if [[ -n "${KEYPASSWORD:-}" ]]; then
PASSARG="-readpass <(echo \"$KEYPASSWORD\")" PASSARG="-readpass <(echo \"$KEYPASSWORD\")"

View File

@@ -29,7 +29,7 @@ begin
Result := Result + 'Using existing ESP-IDF copy: ' + NewLine Result := Result + 'Using existing ESP-IDF copy: ' + NewLine
+ Space + IDFExistingPath + NewLine + NewLine; + Space + IDFExistingPath + NewLine + NewLine;
end else begin end else begin
Result := Result + 'Will download ESP-IDF ' + IDFDownloadVersion + ' into:' + NewLine Result := Result + 'Will install ESP-IDF ' + IDFDownloadVersion + ' into:' + NewLine
+ Space + IDFDownloadPath + NewLine + NewLine; + Space + IDFDownloadPath + NewLine + NewLine;
end; end;

View File

@@ -472,10 +472,14 @@ begin
end; end;
end; end;
{ Wrapper function for Run task. Run tasks requires calling function. }
function GetIsWindowsDefenderEnabled(): Boolean;
begin
Result := IsWindowsDefenderEnabled;
end;
{ Execute system check } { Execute system check }
procedure ExecuteSystemCheck(); procedure ExecuteSystemCheck();
var
UseEmbeddedPythonParam: String;
begin begin
{ Execute system check only once. Avoid execution in case of back button. } { Execute system check only once. Avoid execution in case of back button. }
if (SystemCheckState <> SYSTEM_CHECK_STATE_INIT) then begin if (SystemCheckState <> SYSTEM_CHECK_STATE_INIT) then begin
@@ -486,11 +490,12 @@ begin
SystemLogTitle(CustomMessage('SystemCheckStart')); SystemLogTitle(CustomMessage('SystemCheckStart'));
StopSystemCheckButton.Enabled := True; StopSystemCheckButton.Enabled := True;
VerifyRootCertificates(); if (not IsOfflineMode) then begin
VerifyRootCertificates();
end;
{ Search for the installed Python version only on explicit user request. } { Search for the installed Python version only on explicit user request. }
UseEmbeddedPythonParam := ExpandConstant('{param:USEEMBEDDEDPYTHON|yes}'); if (not UseEmbeddedPython) then begin
if (UseEmbeddedPythonParam <> 'yes') then begin
FindInstalledPythonVersions(); FindInstalledPythonVersions();
end; end;
@@ -525,7 +530,6 @@ end;
{ Invoke scan of system environment. } { Invoke scan of system environment. }
procedure OnSystemCheckActivate(Sender: TWizardPage); procedure OnSystemCheckActivate(Sender: TWizardPage);
var SystemCheckParam:String;
begin begin
{ Display special controls. For some reason the first call of the page does not invoke SystemCheckOnCurPageChanged. } { Display special controls. For some reason the first call of the page does not invoke SystemCheckOnCurPageChanged. }
FullLogButton.Visible := True; FullLogButton.Visible := True;
@@ -533,8 +537,7 @@ begin
StopSystemCheckButton.Visible := True; StopSystemCheckButton.Visible := True;
SystemCheckViewer.Visible := True; SystemCheckViewer.Visible := True;
SystemCheckParam := ExpandConstant('{param:SKIPSYSTEMCHECK|no}'); if (SkipSystemCheck) then begin
if (SystemCheckParam = 'yes') then begin
SystemCheckState := SYSTEM_CHECK_STATE_STOPPED; SystemCheckState := SYSTEM_CHECK_STATE_STOPPED;
SystemLog('System Check disabled by command line option /SKIPSYSTEMCHECK.'); SystemLog('System Check disabled by command line option /SKIPSYSTEMCHECK.');
end; end;
@@ -598,7 +601,7 @@ begin
InstalledPythonVersions := TStringList.Create(); InstalledPythonVersions := TStringList.Create();
InstalledPythonDisplayNames := TStringList.Create(); InstalledPythonDisplayNames := TStringList.Create();
InstalledPythonExecutables := TStringList.Create(); InstalledPythonExecutables := TStringList.Create();
PythonVersionAdd('{#PythonVersion}', 'Use Python {#PythonVersion} Embedded (Recommended)', 'tools\python\{#PythonVersion}\python.exe'); PythonVersionAdd('{#PythonVersion}', 'Use Python {#PythonVersion} Embedded (Recommended)', 'tools\idf-python\{#PythonVersion}\python.exe');
{ Create Spinner animation. } { Create Spinner animation. }
Spinner := TStringList.Create(); Spinner := TStringList.Create();