From 1427b3a6d887cd486b60c6d739f87ebd9e5b699f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juraj=20Mich=C3=A1lek?= Date: Wed, 16 Dec 2020 17:40:13 +0100 Subject: [PATCH] tools: support for embedded python --- docs/en/api-guides/tools/idf-tools-notes.inc | 10 + .../tools/idf-windows-installer.rst | 49 ++++ docs/en/api-guides/tools/index.rst | 1 + docs/en/get-started/windows-setup.rst | 2 +- .../api-guides/tools/idf-tools-notes.inc | 10 + .../tools/idf-windows-installer.rst | 1 + docs/zh_CN/api-guides/tools/index.rst | 1 + docs/zh_CN/get-started/windows-setup.rst | 2 +- tools/idf_tools.py | 24 ++ tools/tools.json | 67 ++++++ tools/windows/tool_setup/README.md | 50 +++- .../tool_setup/Scripts/Install-Idf.ps1 | 15 ++ .../tool_setup/Scripts/Prepare-Cache.ps1 | 8 + tools/windows/tool_setup/Scripts/Test-Idf.ps1 | 28 +++ tools/windows/tool_setup/build_installer.sh | 18 +- tools/windows/tool_setup/choice_page.iss.inc | 2 +- tools/windows/tool_setup/cmdline_page.iss.inc | 2 +- tools/windows/tool_setup/docker-compose.yml | 24 ++ .../tool_setup/git_find_installed.iss.inc | 2 +- tools/windows/tool_setup/git_page.iss.inc | 2 +- .../tool_setup/idf_download_page.iss.inc | 45 +++- tools/windows/tool_setup/idf_page.iss.inc | 2 +- tools/windows/tool_setup/idf_setup.iss.inc | 215 +++++++++++------- tools/windows/tool_setup/idf_tool_setup.iss | 13 +- tools/windows/tool_setup/main.iss.inc | 39 ++-- .../tool_setup/python_find_installed.iss.inc | 2 +- tools/windows/tool_setup/python_page.iss.inc | 59 +++-- tools/windows/tool_setup/summary.iss.inc | 6 +- .../tool_setup/system_check_page.iss.inc | 18 +- 29 files changed, 556 insertions(+), 161 deletions(-) create mode 100644 docs/en/api-guides/tools/idf-windows-installer.rst create mode 100644 docs/zh_CN/api-guides/tools/idf-windows-installer.rst create mode 100644 tools/windows/tool_setup/Scripts/Install-Idf.ps1 create mode 100644 tools/windows/tool_setup/Scripts/Prepare-Cache.ps1 create mode 100644 tools/windows/tool_setup/Scripts/Test-Idf.ps1 create mode 100644 tools/windows/tool_setup/docker-compose.yml diff --git a/docs/en/api-guides/tools/idf-tools-notes.inc b/docs/en/api-guides/tools/idf-tools-notes.inc index 33be40347a..f01e64f41c 100644 --- a/docs/en/api-guides/tools/idf-tools-notes.inc +++ b/docs/en/api-guides/tools/idf-tools-notes.inc @@ -62,4 +62,14 @@ On Linux and macOS, it is recommended to install ninja using the OS-specific pac .. tool-dfu-util-notes +--- + +.. tool-idf-python-notes + + +--- + +.. tool-idf-python-wheels-notes + + --- diff --git a/docs/en/api-guides/tools/idf-windows-installer.rst b/docs/en/api-guides/tools/idf-windows-installer.rst new file mode 100644 index 0000000000..e83d4071e8 --- /dev/null +++ b/docs/en/api-guides/tools/idf-windows-installer.rst @@ -0,0 +1,49 @@ +IDF Windows Installer +===================== + +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`` +* ``/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. +* ``/HELP`` - Display command line options provided by Inno Setup installer. +* ``/IDFDIR=[PATH]`` - Path to directory where it will be installed. Default: ``{userdesktop}\esp-idf}`` +* ``/IDFVERSION=[v4.3|v4.1|master]`` - Use specific IDF version. E.g. v4.1, v4.2, master. Default: empty, pick the first version in the list. +* ``/IDFVERSIONSURL=[URL]`` - Use URL to download list of IDF versions. Default: https://dl.espressif.com/dl/esp-idf/idf_versions.txt +* ``/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. +* ``/USEEMBEDDEDPYTHON=[yes|no]`` - Use Embedded Python version for the installation. Set to ``no`` to allow Python selection screen in the installer. 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 +* ``/SKIPSYSTEMCHECK=[yes|no]`` - Skip System Check page. Default: no. +* ``/VERYSILENT /SUPPRESSMSGBOXES /SP- /NOCANCEL`` - Perform silent installation. + +Unattended installation +----------------------- + +The unattended installation of IDF can be achieved by following command-line parameters: + +.. code-block:: batch + + esp-idf-tools-setup-x.x.exe /VERYSILENT /SUPPRESSMSGBOXES /SP- /NOCANCEL + +The installer detaches its process from the command-line. Waiting for installation to finish could be achieved by following PowerShell script: + +.. code-block:: powershell + + esp-idf-tools-setup-x.x.exe /VERYSILENT /SUPPRESSMSGBOXES /SP- /NOCANCEL + $InstallerProcess = Get-Process esp-idf-tools-setup + Wait-Process -Id $InstallerProcess.id + +Custom Python and custom location of Python wheels +-------------------------------------------------- + +The IDF installer is using by default embedded Python with reference to Python Wheel mirror. + +Following parameters allows to select custom Python and custom location of Python wheels: + +.. code-block:: batch + + esp-idf-tools-setup-x.x.exe /USEEMBEDDEDPYTHON=no /PYTHONWHEELSURL=https://pypi.org/simple/ diff --git a/docs/en/api-guides/tools/index.rst b/docs/en/api-guides/tools/index.rst index 9e4eea70c2..862cbb4367 100644 --- a/docs/en/api-guides/tools/index.rst +++ b/docs/en/api-guides/tools/index.rst @@ -7,3 +7,4 @@ Tools IDF Tools IDF Monitor IDF Docker image + IDF Windows Installer diff --git a/docs/en/get-started/windows-setup.rst b/docs/en/get-started/windows-setup.rst index 80681cff1d..fb0f610fb7 100644 --- a/docs/en/get-started/windows-setup.rst +++ b/docs/en/get-started/windows-setup.rst @@ -34,7 +34,7 @@ ESP-IDF Tools Installer The easiest way to install ESP-IDF's prerequisites is to download the ESP-IDF Tools installer from this URL: -https://dl.espressif.com/dl/esp-idf-tools-setup-2.3.exe +https://dl.espressif.com/dl/esp-idf-tools-setup-2.4.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. diff --git a/docs/zh_CN/api-guides/tools/idf-tools-notes.inc b/docs/zh_CN/api-guides/tools/idf-tools-notes.inc index 0e6f0fe70a..51cca6fd09 100644 --- a/docs/zh_CN/api-guides/tools/idf-tools-notes.inc +++ b/docs/zh_CN/api-guides/tools/idf-tools-notes.inc @@ -64,4 +64,14 @@ On Linux and macOS, it is recommended to install ninja using the OS package mana .. tool-dfu-util-notes +--- + +.. tool-idf-python-notes + + +--- + +.. tool-idf-python-wheels-notes + + --- diff --git a/docs/zh_CN/api-guides/tools/idf-windows-installer.rst b/docs/zh_CN/api-guides/tools/idf-windows-installer.rst new file mode 100644 index 0000000000..4073aee68f --- /dev/null +++ b/docs/zh_CN/api-guides/tools/idf-windows-installer.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-guides/tools/idf-windows-installer.rst diff --git a/docs/zh_CN/api-guides/tools/index.rst b/docs/zh_CN/api-guides/tools/index.rst index 3f1dcd7b6e..ef6903c591 100644 --- a/docs/zh_CN/api-guides/tools/index.rst +++ b/docs/zh_CN/api-guides/tools/index.rst @@ -7,3 +7,4 @@ IDF Tools IDF 监视器 IDF Docker image + IDF Windows Installer diff --git a/docs/zh_CN/get-started/windows-setup.rst b/docs/zh_CN/get-started/windows-setup.rst index cf10960894..625b6c76e7 100644 --- a/docs/zh_CN/get-started/windows-setup.rst +++ b/docs/zh_CN/get-started/windows-setup.rst @@ -33,7 +33,7 @@ ESP-IDF 工具安装器 安装 ESP-IDF 必备工具最简易的方式是下载 ESP-IDF 工具安装器,地址如下: -https://dl.espressif.com/dl/esp-idf-tools-setup-2.3.exe +https://dl.espressif.com/dl/esp-idf-tools-setup-2.4.exe .. 重要:下次更新此链接时,请重新写文件 get-started/index.rst 中“其它文件下载方式”这一章节,然后将此条注意事项删除。 diff --git a/tools/idf_tools.py b/tools/idf_tools.py index fdf35e890d..7520ea6315 100755 --- a/tools/idf_tools.py +++ b/tools/idf_tools.py @@ -1310,6 +1310,19 @@ def action_install(args): tool_obj.install(tool_version) +def get_wheels_dir(): + tools_info = load_tools_info() + wheels_package_name = 'idf-python-wheels' + if wheels_package_name not in tools_info: + return None + wheels_package = tools_info[wheels_package_name] + recommended_version = wheels_package.get_recommended_version() + wheels_dir = wheels_package.get_path_for_version(recommended_version) + if not os.path.exists(wheels_dir): + return None + return wheels_dir + + def action_install_python_env(args): idf_python_env_path, _, virtualenv_python = get_python_env_path() @@ -1339,6 +1352,15 @@ def action_install_python_env(args): run_args += ['-r', requirements_txt] if args.extra_wheels_dir: run_args += ['--find-links', args.extra_wheels_dir] + if args.no_index: + run_args += ['--no-index'] + if args.extra_wheels_url: + run_args += ['--extra-index-url', args.extra_wheels_url] + + wheels_dir = get_wheels_dir() + if wheels_dir is not None: + run_args += ['--find-links', wheels_dir] + info('Installing Python packages from {}'.format(requirements_txt)) subprocess.check_call(run_args, stdout=sys.stdout, stderr=sys.stderr) @@ -1542,6 +1564,8 @@ def main(argv): action='store_true') install_python_env.add_argument('--extra-wheels-dir', help='Additional directories with wheels ' + 'to use during installation') + install_python_env.add_argument('--extra-wheels-url', help='Additional URL with wheels', default='https://dl.espressif.com/pypi') + install_python_env.add_argument('--no-index', help='Work offline without retrieving wheels index') if IDF_MAINTAINER: add_version = subparsers.add_parser('add-version', help='Add or update download info for a version') diff --git a/tools/tools.json b/tools/tools.json index f4ac12a8f5..83e0709c99 100644 --- a/tools/tools.json +++ b/tools/tools.json @@ -627,6 +627,73 @@ } } ] + }, + { + "description": "Embeddable Python distribution", + "export_paths": [], + "export_vars": {}, + "info_url": "https://github.com/espressif/esp-idf/tree/master/tools/windows/", + "install": "never", + "license": "PSF License", + "name": "idf-python", + "platform_overrides": [ + { + "install": "on_request", + "platforms": [ + "win64" + ] + } + ], + "version_cmd": [ + "python", + "--version" + ], + "version_regex": "Python ([0-9.]+)", + "versions": [ + { + "name": "3.9.1", + "status": "recommended", + "win64": { + "sha256": "d5a0e625dd5b2bc6872de90292d71009c17e2396e3d1575d886a94d0dfb00c87", + "size": 20362758, + "url": "https://dl.espressif.com/dl/idf-python/idf-python-3.9.1-embed-win64.zip" + } + } + ] + }, + { + "description": "Python Wheels distribution bundled for the specific version of IDF and Python", + "export_paths": [], + "export_vars": {}, + "info_url": "https://github.com/espressif/esp-idf/tree/master/tools/windows/", + "install": "never", + "license": "Open-source licenses", + "name": "idf-python-wheels", + "platform_overrides": [ + { + "install": "always", + "platforms": [ + "win64" + ] + } + ], + "version_cmd": [ + "cmd", + "/c", + "echo idf4.3_py3.9_2021-01-07" + ], + "version_regex": "(idf4.3_py3.9_2021-01-07)", + "versions": [ + { + "name": "idf4.3_py3.9_2021-01-07", + "status": "recommended", + "win64": { + "sha256": "2a33dbaa106aec9c5098b1af46f04c69923be947291c19855ff355b9707314b6", + "size": 8316997, + "url": "https://dl.espressif.com/dl/idf-python-wheels/idf-python-wheels-idf4.3_py3.9_2021-01-07-win64.zip" + } + } + ] } ], "version": 1 diff --git a/tools/windows/tool_setup/README.md b/tools/windows/tool_setup/README.md index 56739bfd92..4b2d3e49b4 100644 --- a/tools/windows/tool_setup/README.md +++ b/tools/windows/tool_setup/README.md @@ -12,9 +12,9 @@ Some functionality of the installer depends on additional programs: * [7-zip](https://www.7-zip.org) — used to extract downloaded IDF archives. -* [cmdlinerunner](cmdlinerunner/cmdlinerunner.c) — a helper DLL used to run external command line programs from the installer, capture live console output, and get the exit code. +* [cmdlinerunner](cmdlinerunner/cmdlinerunner.c) — a helper DLL used to run external command-line programs from the installer, capture live console output, and get the exit code. -## Instalation of dependencies via Chocolatey +## Installation of dependencies via Chocolatey Run with Administrator privileges: @@ -22,7 +22,7 @@ Run with Administrator privileges: choco install inno-download-plugin ``` -## Building the installer +## Building the installer ### In Docker @@ -60,3 +60,47 @@ docker run --rm -v $IDF_PATH:/idf -w /idf/tools/windows/tool_setup -it $CI_DOCKE - `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. + +Select Run - Parameters in Inno Setup and add parameters. + +Example of parameters: + +``` +/SKIPSYSTEMCHECK=yes /IDFVERSIONSURL=http://localhost:8000/idf_versions.txt /GITRESET=no /GITREPO=C:/projects/esp-idf /GITRECURSIVE=no +``` + +These combinations of parameters will result: +* ``SKIPSYSTEMCHECK=yes`` - The screen with System Check will be skipped. +* ``IDFVERSIONURL`` - idf_versions.txt will be downloaded from localhost:8000 + - it's possible to add branch name into idf_versions.txt, e.g. feature/win_inst +* ``GITRESET=no`` - Git repository won't be reset after clone, it can save time and add custom changes in case of the zip archive with repository +* ``GITREPO`` - The version will be cloned from the specific location, e.g. from a local directory +* ``GITRECURSIVE=no`` - The clone of the repo won't contain modules, it speeds up the cloning process. Use when modules are not necessary. + +Documentation of parameters is available in api-guides/tools/idf-windows-installer.rst + +### 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. + +Commands for testing multiple versions: + +``` +$env:IDF_VERSION="v4.1"; docker-compose.exe run idf-setup-test +$env:IDF_VERSION="v4.0.2"; docker-compose.exe run idf-setup-test +$env:IDF_VERSION="v3.3.4"; docker-compose.exe run idf-setup-test +$env:IDF_VERSION="release/v4.2"; docker-compose.exe run idf-setup-test +$env:IDF_VERSION="release/v4.1"; docker-compose.exe run idf-setup-test +$env:IDF_VERSION="release/v4.0"; docker-compose.exe run idf-setup-test +$env:IDF_VERSION="release/v3.3"; docker-compose.exe run idf-setup-test +$env:IDF_VERSION="master"; docker-compose.exe run idf-setup-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. + +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. diff --git a/tools/windows/tool_setup/Scripts/Install-Idf.ps1 b/tools/windows/tool_setup/Scripts/Install-Idf.ps1 new file mode 100644 index 0000000000..6938c57cef --- /dev/null +++ b/tools/windows/tool_setup/Scripts/Install-Idf.ps1 @@ -0,0 +1,15 @@ +param ( + [string]$Installer="C:\Output\esp-idf-tools-setup-unsigned.exe", + [string]$IdfPath = "C:\Users\ContainerAdministrator\Desktop\esp-idf", + [string]$IdfVersion = "v4.1" +) + +$Installer +$IdfPath +$IdfVersion + +mkdir C:\Temp +C:\Output\esp-idf-tools-setup-unsigned.exe /VERYSILENT /LOG=C:\Temp\install.txt /SUPPRESSMSGBOXES /SP- /NOCANCEL /NORESTART /IDFVERSION=${IdfVersion} +$InstallerProcess = Get-Process esp-idf-tools-setup-unsigned +Wait-Process -Id $InstallerProcess.id +Get-Content C:\Temp\install.txt diff --git a/tools/windows/tool_setup/Scripts/Prepare-Cache.ps1 b/tools/windows/tool_setup/Scripts/Prepare-Cache.ps1 new file mode 100644 index 0000000000..41d78aefc8 --- /dev/null +++ b/tools/windows/tool_setup/Scripts/Prepare-Cache.ps1 @@ -0,0 +1,8 @@ +param ( + [string]$IdfVersion = "v4.1" +) +$ErrorActionPreference = "Stop" +New-Item -Path C:\Users\ContainerAdministrator\ -Name .espressif -ItemType "directory" +New-Item -Path C:\Users\ContainerAdministrator\.espressif -Name releases -ItemType "directory" +Copy-Item -Recurse -Verbose -Path C:\Cache\dist -Destination C:\Users\ContainerAdministrator\.espressif\dist +Copy-Item -Verbose -Path C:\Cache\releases\esp-idf-${IdfVersion}.zip -Destination C:\Users\ContainerAdministrator\.espressif\releases diff --git a/tools/windows/tool_setup/Scripts/Test-Idf.ps1 b/tools/windows/tool_setup/Scripts/Test-Idf.ps1 new file mode 100644 index 0000000000..9b4b70c292 --- /dev/null +++ b/tools/windows/tool_setup/Scripts/Test-Idf.ps1 @@ -0,0 +1,28 @@ +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" diff --git a/tools/windows/tool_setup/build_installer.sh b/tools/windows/tool_setup/build_installer.sh index 3364ec0bb1..d5b9b0d33b 100755 --- a/tools/windows/tool_setup/build_installer.sh +++ b/tools/windows/tool_setup/build_installer.sh @@ -10,6 +10,19 @@ set -e set -u +INSTALLER_TYPE="$1" +if [[ -z "$INSTALLER_TYPE" ]]; then + INSTALLER_TYPE="full" +fi + +echo "Selected installer type: $INSTALLER_TYPE" +echo "Available installer types: full, netinst" + +PACKAGES="all" +if [[ "$INSTALLER_TYPE" == "netinst" ]]; then + PACKAGES="idf-python" +fi + iscc_path=$(which iscc) if [[ -z "$iscc_path" ]]; then echo "Inno setup compiler (iscc) not found. Are you running wine-innosetup Docker image?" @@ -24,7 +37,7 @@ fi echo "Downloading IDF Tools..." mkdir -p idf_tools_tmp export IDF_TOOLS_PATH=$PWD/idf_tools_tmp -$IDF_PATH/tools/idf_tools.py --non-interactive download --platform Windows-x86_64 all +$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 mkdir -p dist cp idf_tools_tmp/dist/* dist/ @@ -40,4 +53,5 @@ echo "Downloading idf_versions.txt..." wget --no-verbose -O idf_versions.txt https://dl.espressif.com/dl/esp-idf/idf_versions.txt echo "Running ISCC..." -iscc idf_tool_setup.iss +# https://jrsoftware.org/ishelp/index.php?topic=compilercmdline +iscc /F "esp-idf-tools-setup-$INSTALLER_TYPE-unsigned" idf_tool_setup.iss diff --git a/tools/windows/tool_setup/choice_page.iss.inc b/tools/windows/tool_setup/choice_page.iss.inc index db1f25db43..0a8e24c73e 100644 --- a/tools/windows/tool_setup/choice_page.iss.inc +++ b/tools/windows/tool_setup/choice_page.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } var diff --git a/tools/windows/tool_setup/cmdline_page.iss.inc b/tools/windows/tool_setup/cmdline_page.iss.inc index 099a4ebbf6..d6f612e2e5 100644 --- a/tools/windows/tool_setup/cmdline_page.iss.inc +++ b/tools/windows/tool_setup/cmdline_page.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Progress & log page for command line tools ------------------------------ } diff --git a/tools/windows/tool_setup/docker-compose.yml b/tools/windows/tool_setup/docker-compose.yml new file mode 100644 index 0000000000..968e2f0ad3 --- /dev/null +++ b/tools/windows/tool_setup/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3" + +# This docker-compose is for testing the installation process. +# In starts the installation and executes also build of get-started example. +services: + idf-setup-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-unsigned.exe' -IdfVersion ${IDF_VERSION}; C:/Scripts/Test-Idf.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 + # releases volume to speed up installation and avoid downloading of files + - type: bind + source: C:\projects\esp-tests\installer-docker-runner\.espressif\ + target: C:\Cache + read_only: true diff --git a/tools/windows/tool_setup/git_find_installed.iss.inc b/tools/windows/tool_setup/git_find_installed.iss.inc index 3ef24f2e4f..c8e34da322 100644 --- a/tools/windows/tool_setup/git_find_installed.iss.inc +++ b/tools/windows/tool_setup/git_find_installed.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Find installed copies of Git ------------------------------ } diff --git a/tools/windows/tool_setup/git_page.iss.inc b/tools/windows/tool_setup/git_page.iss.inc index 1072260176..b272f2dcc6 100644 --- a/tools/windows/tool_setup/git_page.iss.inc +++ b/tools/windows/tool_setup/git_page.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Page to select Git ------------------------------ } diff --git a/tools/windows/tool_setup/idf_download_page.iss.inc b/tools/windows/tool_setup/idf_download_page.iss.inc index d5b8bd0163..ec6f059549 100644 --- a/tools/windows/tool_setup/idf_download_page.iss.inc +++ b/tools/windows/tool_setup/idf_download_page.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Page to select the version of ESP-IDF to download ------------------------------ } @@ -46,7 +46,7 @@ var Url: String; VersionFile: String; begin - Url := '{#IDFVersionsURL}'; + Url := ExpandConstant('{param:IDFVERSIONSURL|https://dl.espressif.com/dl/esp-idf/idf_versions.txt}') VersionFile := ExpandConstant('{tmp}\idf_versions.txt'); if idpDownloadFile(Url, VersionFile) then begin @@ -62,6 +62,7 @@ var Page: TInputOptionWizardPage; VersionFile: String; i: Integer; + SuggestedIDFDirectory: String; begin Page := TInputOptionWizardPage(Sender); Log('OnIDFDownloadPagePrepare'); @@ -86,7 +87,26 @@ begin end; Page.SelectedValueIndex := 0; - ChoicePageSetInputText(Page, GetSuggestedIDFDirectory()); + SuggestedIDFDirectory := ExpandConstant('{param:IDFDIR|' + GetSuggestedIDFDirectory() + '}'); + ChoicePageSetInputText(Page, SuggestedIDFDirectory); +end; + +{ Validation of PATH for IDF releases which does not support special characters. } +{ Source: https://stackoverflow.com/questions/21623515/is-it-possible-to-filter-require-installation-path-to-be-ascii-in-innosetup } +function IsCharValid(Value: Char): Boolean; +begin + Result := Ord(Value) <= $007F; +end; + +function IsDirNameValid(const Value: string): Boolean; +var + I: Integer; +begin + Result := False; + for I := 1 to Length(Value) do + if not IsCharValid(Value[I]) then + Exit; + Result := True; end; procedure OnIDFDownloadSelectionChange(Sender: TObject); @@ -122,7 +142,24 @@ begin end; IDFDownloadPath := IDFPath; - IDFDownloadVersion := IDFDownloadAvailableVersions[Page.SelectedValueIndex]; + + { Use parameter /IDFVE=x to override selection in the box. } + IDFDownloadVersion := ExpandConstant('{param:IDFVERSION|}'); + if (IDFDownloadVersion = '') then begin + IDFDownloadVersion := IDFDownloadAvailableVersions[Page.SelectedValueIndex]; + end; + + { Following ZIP versions of IDF does not support installation on path with special characters. } + { Issue: https://github.com/espressif/esp-idf/issues/5996 } + if ((IDFDownloadVersion = 'v4.1') or (IDFDownloadVersion = 'v4.0.2') or + (IDFDownloadVersion = 'v3.3.4')) 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 + 'Please choose a different directory.', mbError, MB_OK); + exit; + end; + end; + Result := True; end; diff --git a/tools/windows/tool_setup/idf_page.iss.inc b/tools/windows/tool_setup/idf_page.iss.inc index cec63da03f..e0c7941794 100644 --- a/tools/windows/tool_setup/idf_page.iss.inc +++ b/tools/windows/tool_setup/idf_page.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Page to select whether to download ESP-IDF, or use an existing copy ------------------------------ } diff --git a/tools/windows/tool_setup/idf_setup.iss.inc b/tools/windows/tool_setup/idf_setup.iss.inc index a2837cc0e9..cfaaec429f 100644 --- a/tools/windows/tool_setup/idf_setup.iss.inc +++ b/tools/windows/tool_setup/idf_setup.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Downloading ESP-IDF ------------------------------ } @@ -140,7 +140,9 @@ var 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. @@ -158,7 +160,6 @@ begin NeedToClone := True; end; - ExtractTemporaryFile('7za.exe') CmdLine := ExpandConstant('{tmp}\7za.exe x -o' + ExpandConstant('{tmp}') + ' -r -aoa "' + IDFZIPFileName + '"'); IDFTempPath := ExpandConstant('{tmp}\esp-idf-') + IDFZIPFileVersion; Log('Extracting ESP-IDF reference repository: ' + CmdLine); @@ -172,12 +173,19 @@ begin if NeedToClone then begin - CmdLine := GitExecutablePath + ' clone --recursive --progress -b ' + IDFDownloadVersion; + 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; - CmdLine := CmdLine + ' https://github.com/espressif/esp-idf.git ' + IDFPath; + 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); @@ -202,7 +210,14 @@ begin CmdLine := ExpandConstant('cmd.exe /c ""xcopy" /s /e /i /h /q "' + IDFTempPath + '" "' + IDFPath + '""'); DoCmdlineInstall('Extracting ESP-IDF', 'Copying ESP-IDF into the destination directory', CmdLine); GitRepoFixFileMode(IDFPath); - GitRepoFixNewlines(IDFPath); + + 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; @@ -222,51 +237,6 @@ begin end; end; -procedure IDFToolsSetup(); -var - CmdLine: String; - IDFPath: String; - IDFToolsPyPath: String; - IDFToolsPyCmd: String; - BundledIDFToolsPyPath: String; - JSONArg: String; -begin - IDFPath := GetIDFPath(''); - IDFToolsPyPath := IDFPath + '\tools\idf_tools.py'; - BundledIDFToolsPyPath := ExpandConstant('{app}\idf_tools_fallback.py'); - JSONArg := ''; - - if FileExists(IDFToolsPyPath) then - begin - Log('idf_tools.py exists in IDF directory'); - if UseBundledIDFToolsPy(IDFDownloadVersion) then - begin - Log('Using the bundled idf_tools.py copy'); - IDFToolsPyCmd := BundledIDFToolsPyPath; - end else begin - IDFToolsPyCmd := IDFToolsPyPath; - end; - end else begin - Log('idf_tools.py does not exist in IDF directory, using a fallback version'); - IDFToolsPyCmd := BundledIDFToolsPyPath; - JSONArg := ExpandConstant('--tools "{app}\tools_fallback.json"'); - end; - - { IDFPath not quoted, as it can not contain spaces } - IDFToolsPyCmd := PythonExecutablePath + ' "' + IDFToolsPyCmd + '" --idf-path ' + IDFPath + JSONArg; - - SetEnvironmentVariable('PYTHONUNBUFFERED', '1') - - Log('idf_tools.py command: ' + IDFToolsPyCmd); - CmdLine := IDFToolsPyCmd + ' install'; - Log('Installing tools:' + CmdLine); - DoCmdlineInstall('Installing ESP-IDF tools', '', CmdLine); - - CmdLine := IDFToolsPyCmd + ' install-python-env'; - Log('Installing Python environment:' + CmdLine); - DoCmdlineInstall('Installing Python environment', '', CmdLine); -end; - { Find Major and Minor version in esp_idf_version.h file. } function GetIDFVersionFromHeaderFile():String; var @@ -300,17 +270,119 @@ begin 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; - VersionIndex: Integer; - MajorString: String; - MinorString: String; - DotIndex: Integer; - IDFVersionString: String; PythonVirtualEnvPath: String; Command: String; begin @@ -318,39 +390,14 @@ begin Destination := ExpandConstant(LnkString + '\{#IDFCmdExeShortcutFile}'); Description := '{#IDFCmdExeShortcutDescription}'; - IDFVersionString := IDFDownloadVersion; - { Transform version vx.y or release/vx.y to x.y } - VersionIndex := pos('v', IDFVersionString); - if (VersionIndex > 0) then begin - Delete(IDFVersionString, 1, VersionIndex); - end; - - { Transform version x.y.z to x.y } - DotIndex := pos('.', IDFVersionString); - if (DotIndex > 0) then begin - MajorString := Copy(IDFVersionString, 1, DotIndex - 1); - Delete(IDFVersionString, 1, DotIndex); - { Trim trailing version numbers. } - DotIndex := pos('.', IDFVersionString); - if (DotIndex > 0) then begin - MinorString := Copy(IDFVersionString, 1, DotIndex - 1); - IDFVersionString := MajorString + '.' + MinorString; - end else begin - IDFVersionString := MajorString + '.' + IDFVersionString; - end; - end; - - { Transform master to x.y } - if (IDFVersionString = 'master') then begin - IDFVersionString := GetIDFVersionFromHeaderFile(); - end; - { The links should contain reference to Python vitual env } - PythonVirtualEnvPath := ExpandConstant('{app}\python_env\idf') + IDFVersionString + '_py' + PythonVersion + '_env\Scripts'; + 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 diff --git a/tools/windows/tool_setup/idf_tool_setup.iss b/tools/windows/tool_setup/idf_tool_setup.iss index db6fab0266..269297ae3b 100644 --- a/tools/windows/tool_setup/idf_tool_setup.iss +++ b/tools/windows/tool_setup/idf_tool_setup.iss @@ -1,24 +1,22 @@ -; Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +; Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD ; SPDX-License-Identifier: Apache-2.0 #pragma include __INCLUDE__ + ";" + ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir") #include #define MyAppName "ESP-IDF Tools" -#define MyAppVersion "2.3" +#define MyAppVersion "2.4" #define MyAppPublisher "Espressif Systems (Shanghai) Co. Ltd." #define MyAppURL "https://github.com/espressif/esp-idf" -#define PythonVersion "3.7" -#define PythonInstallerName "python-3.7.3-amd64.exe" -#define PythonInstallerDownloadURL "https://www.python.org/ftp/python/3.7.3/python-3.7.3-amd64.exe" +#define PythonVersion "3.9.1" +#define PythonInstallerName "idf-python-3.9.1-embed-win64.zip" +#define PythonInstallerDownloadURL "https://dl.espressif.com/dl/idf-python/idf-python-3.9.1-embed-win64.zip" #define GitVersion "2.21.0" #define GitInstallerName "Git-2.21.0-64-bit.exe" #define GitInstallerDownloadURL "https://github.com/git-for-windows/git/releases/download/v2.21.0.windows.1/Git-2.21.0-64-bit.exe" -#define IDFVersionsURL "https://dl.espressif.com/dl/esp-idf/idf_versions.txt" - #define IDFCmdExeShortcutDescription "Open ESP-IDF Command Prompt (cmd.exe)" #define IDFCmdExeShortcutFile "ESP-IDF Command Prompt (cmd.exe).lnk" @@ -90,7 +88,6 @@ Name: wdexcl; Description: "Register the ESP-IDF Tools executables as Windows De Name: idf_tools_use_mirror; Description: "Use Espressif download server instead of downloading tool packages from Github"; Flags: unchecked; [Run] -Filename: "{app}\dist\{#PythonInstallerName}"; Parameters: "/passive PrependPath=1 InstallLauncherAllUsers=0 Include_dev=0 Include_tcltk=0 Include_launcher=0 Include_test=0 Include_doc=0"; Description: "Installing Python"; Check: PythonInstallRequired Filename: "{app}\dist\{#GitInstallerName}"; Parameters: "/silent /tasks="""" /norestart"; Description: "Installing Git"; Check: GitInstallRequired Filename: "{group}\{#IDFCmdExeShortcutFile}"; Flags: postinstall shellexec; Description: "Run ESP-IDF Command Prompt (cmd.exe)"; Check: InstallationSuccessful diff --git a/tools/windows/tool_setup/main.iss.inc b/tools/windows/tool_setup/main.iss.inc index 420cd4114d..0649d38760 100644 --- a/tools/windows/tool_setup/main.iss.inc +++ b/tools/windows/tool_setup/main.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Custom steps before the main installation flow ------------------------------ } @@ -45,17 +45,6 @@ begin ForceDirectories(ExpandConstant('{app}\dist')); - if not PythonUseExisting then - begin - DestPath := ExpandConstant('{app}\dist\{#PythonInstallerName}'); - if FileExists(DestPath) then - begin - Log('Python installer already downloaded: ' + DestPath); - end else begin - idpAddFile('{#PythonInstallerDownloadURL}', DestPath); - end; - end; - if not GitUseExisting then begin DestPath := ExpandConstant('{app}\dist\{#GitInstallerName}'); @@ -82,9 +71,6 @@ var begin EnvPath := GetEnv('PATH'); - if not PythonUseExisting then - PythonExecutablePathUpdateAfterInstall(); - if not GitUseExisting then GitExecutablePathUpdateAfterInstall(); @@ -103,6 +89,26 @@ begin SetEnvironmentVariable('PYTHONPATH', '') end; +procedure InstallEmbeddedPython(); +var + EmbeddedPythonPath: String; + CmdLine: String; +begin + if (Pos('tools', PythonPath) <> 1) then begin + Exit; + end; + + EmbeddedPythonPath := ExpandConstant('{app}\') + PythonExecutablePath; + UpdatePythonVariables(EmbeddedPythonPath); + Log('Checking existence of Embedded Python: ' + EmbeddedPythonPath); + if (FileExists(EmbeddedPythonPath)) then begin + Exit; + end; + + CmdLine := ExpandConstant('{tmp}\7za.exe x -o{app}\tools\python\' + PythonVersion + '\ -r -aoa "{app}\dist\idf-python-' + PythonVersion + '-embed-win64.zip"'); + DoCmdlineInstall('Extracting Python Interpreter', 'Using Embedded Python', CmdLine); +end; + procedure PostInstallSteps(CurStep: TSetupStep); var @@ -111,6 +117,9 @@ begin if CurStep <> ssPostInstall then exit; + ExtractTemporaryFile('7za.exe') + InstallEmbeddedPython(); + try AddPythonGitToPath(); diff --git a/tools/windows/tool_setup/python_find_installed.iss.inc b/tools/windows/tool_setup/python_find_installed.iss.inc index 43f7e1a468..bc90a1b547 100644 --- a/tools/windows/tool_setup/python_find_installed.iss.inc +++ b/tools/windows/tool_setup/python_find_installed.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Find installed Python interpreters in Windows Registry (see PEP 514) ------------------------------ } diff --git a/tools/windows/tool_setup/python_page.iss.inc b/tools/windows/tool_setup/python_page.iss.inc index 3a9da659ac..f158f307e8 100644 --- a/tools/windows/tool_setup/python_page.iss.inc +++ b/tools/windows/tool_setup/python_page.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Page to select Python interpreter ------------------------------ } @@ -8,7 +8,6 @@ var PythonPage: TInputOptionWizardPage; PythonVersion, PythonPath, PythonExecutablePath: String; - PythonUseExisting: Boolean; function GetPythonPath(Unused: String): String; @@ -16,11 +15,6 @@ begin Result := PythonPath; end; -function PythonInstallRequired(): Boolean; -begin - Result := not PythonUseExisting; -end; - function PythonVersionSupported(Version: String): Boolean; var Major, Minor: Integer; @@ -93,40 +87,26 @@ begin Log('OnPythonSelectionChange index=' + IntToStr(Page.SelectedValueIndex)); end; +procedure ApplyPythonConfigurationByIndex(Index:Integer); +begin + Log('ApplyPythonConfigurationByIndex index=' + IntToStr(Index)); + PythonExecutablePath := InstalledPythonExecutables[Index]; + PythonPath := ExtractFilePath(PythonExecutablePath); + PythonVersion := InstalledPythonVersions[Index]; + Log('ApplyPythonConfigurationByIndex: PythonPath='+PythonPath+' PythonExecutablePath='+PythonExecutablePath); +end; + function OnPythonPageValidate(Sender: TWizardPage): Boolean; var Page: TInputOptionWizardPage; begin Page := TInputOptionWizardPage(Sender); - Log('OnPythonPageValidate index=' + IntToStr(Page.SelectedValueIndex)); - if Page.SelectedValueIndex < InstalledPythonExecutables.Count then - begin - PythonUseExisting := True; - PythonExecutablePath := InstalledPythonExecutables[Page.SelectedValueIndex]; - PythonPath := ExtractFilePath(PythonExecutablePath); - PythonVersion := InstalledPythonVersions[Page.SelectedValueIndex]; - end else begin - PythonUseExisting := False; - PythonExecutablePath := ''; - PythonPath := ''; - PythonVersion := '{#PythonVersion}'; - end; - Log('OnPythonPageValidate: PythonPath='+PythonPath+' PythonExecutablePath='+PythonExecutablePath); + ApplyPythonConfigurationByIndex(Page.SelectedValueIndex); Result := True; end; -procedure PythonExecutablePathUpdateAfterInstall(); -var - Version, DisplayName, ExecutablePath, BaseDir: String; +procedure UpdatePythonVariables(ExecutablePath: String); begin - if not GetPythonVersionInfoFromKey( - HKEY_CURRENT_USER, 'Software\Python', 'PythonCore', '{#PythonVersion}', - Version, DisplayName, ExecutablePath, BaseDir) then - begin - Log('Failed to find ExecutablePath for the installed copy of Python'); - exit; - end; - Log('Found ExecutablePath for ' + DisplayName + ': ' + ExecutablePath); PythonExecutablePath := ExecutablePath; PythonPath := ExtractFilePath(PythonExecutablePath); Log('PythonExecutablePathUpdateAfterInstall: PythonPath='+PythonPath+' PythonExecutablePath='+PythonExecutablePath); @@ -145,3 +125,18 @@ begin @OnPythonSelectionChange, @OnPythonPageValidate); end; + + +function ShouldSkipPythonPage(PageID: Integer): Boolean; +var + UseEmbeddedPythonParam: String; +begin + if (PageID = PythonPage.ID) then begin + { Skip in case of embedded Python. } + UseEmbeddedPythonParam := ExpandConstant('{param:USEEMBEDDEDPYTHON|yes}'); + if (UseEmbeddedPythonParam = 'yes') then begin + ApplyPythonConfigurationByIndex(0); + Result := True; + end; + end; +end; diff --git a/tools/windows/tool_setup/summary.iss.inc b/tools/windows/tool_setup/summary.iss.inc index 5b7baf79e8..95c618f100 100644 --- a/tools/windows/tool_setup/summary.iss.inc +++ b/tools/windows/tool_setup/summary.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { ------------------------------ Installation summary page ------------------------------ } @@ -8,12 +8,12 @@ function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, begin Result := '' - if PythonUseExisting then + if (FileExists(PythonExecutablePath)) then begin Result := Result + 'Using Python ' + PythonVersion + ':' + NewLine + Space + PythonExecutablePath + NewLine + NewLine; end else begin - Result := Result + 'Will download and install Python ' + PythonVersion + NewLine + NewLine; + Result := Result + 'Using embedded Python ' + PythonVersion + NewLine + NewLine; end; if GitUseExisting then diff --git a/tools/windows/tool_setup/system_check_page.iss.inc b/tools/windows/tool_setup/system_check_page.iss.inc index 05d1d5cb39..fb38fe5b87 100644 --- a/tools/windows/tool_setup/system_check_page.iss.inc +++ b/tools/windows/tool_setup/system_check_page.iss.inc @@ -1,4 +1,4 @@ -{ Copyright 2019-2020 Espressif Systems (Shanghai) CO LTD +{ Copyright 2019-2021 Espressif Systems (Shanghai) CO LTD SPDX-License-Identifier: Apache-2.0 } { SystemCheck states } @@ -474,6 +474,8 @@ end; { Execute system check } procedure ExecuteSystemCheck(); +var + UseEmbeddedPythonParam: String; begin { Execute system check only once. Avoid execution in case of back button. } if (SystemCheckState <> SYSTEM_CHECK_STATE_INIT) then begin @@ -486,7 +488,11 @@ begin VerifyRootCertificates(); - FindInstalledPythonVersions(); + { Search for the installed Python version only on explicit user request. } + UseEmbeddedPythonParam := ExpandConstant('{param:USEEMBEDDEDPYTHON|yes}'); + if (UseEmbeddedPythonParam <> 'yes') then begin + FindInstalledPythonVersions(); + end; if (SystemCheckState <> SYSTEM_CHECK_STATE_STOPPED) then begin SystemLogTitle(CustomMessage('SystemCheckForDefender') + ' '); @@ -519,6 +525,7 @@ end; { Invoke scan of system environment. } procedure OnSystemCheckActivate(Sender: TWizardPage); +var SystemCheckParam:String; begin { Display special controls. For some reason the first call of the page does not invoke SystemCheckOnCurPageChanged. } FullLogButton.Visible := True; @@ -526,6 +533,12 @@ begin StopSystemCheckButton.Visible := True; SystemCheckViewer.Visible := True; + SystemCheckParam := ExpandConstant('{param:SKIPSYSTEMCHECK|no}'); + if (SystemCheckParam = 'yes') then begin + SystemCheckState := SYSTEM_CHECK_STATE_STOPPED; + SystemLog('System Check disabled by command line option /SKIPSYSTEMCHECK.'); + end; + ExecuteSystemCheck(); end; @@ -585,6 +598,7 @@ begin InstalledPythonVersions := TStringList.Create(); InstalledPythonDisplayNames := TStringList.Create(); InstalledPythonExecutables := TStringList.Create(); + PythonVersionAdd('{#PythonVersion}', 'Use Python {#PythonVersion} Embedded (Recommended)', 'tools\python\{#PythonVersion}\python.exe'); { Create Spinner animation. } Spinner := TStringList.Create();