Merge branch 'feature/idf_tools_dir_user_facing' into 'master'
IDF Tools directory: user facing changes Closes IDF-61 See merge request idf/esp-idf!4808
This commit is contained in:
commit
bca4afb466
45 changed files with 3246 additions and 522 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -58,13 +58,6 @@ TEST_LOGS
|
|||
coverage.info
|
||||
coverage_report/
|
||||
|
||||
# Windows tools installer build
|
||||
tools/windows/tool_setup/.*
|
||||
tools/windows/tool_setup/input
|
||||
tools/windows/tool_setup/dl
|
||||
tools/windows/tool_setup/keys
|
||||
tools/windows/tool_setup/Output
|
||||
|
||||
test_multi_heap_host
|
||||
|
||||
# VS Code Settings
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
if [ -z ${IDF_PATH} ]; then
|
||||
echo "IDF_PATH must be set before including this script."
|
||||
else
|
||||
IDF_ADD_PATHS_EXTRAS=
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/esptool_py/esptool"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/esptool"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/espcoredump"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/partition_table/"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/tools/"
|
||||
|
|
|
@ -1,75 +1,3 @@
|
|||
Add IDF_PATH & idf.py PATH to User Profile (CMake)
|
||||
==================================================
|
||||
:orphan:
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
.. include:: ../cmake-warning.rst
|
||||
|
||||
To use the CMake-based build system and the idf.py tool, two modifications need to be made to system environment variables:
|
||||
|
||||
- ``IDF_PATH`` needs to be set to the path of the directory containing ESP-IDF.
|
||||
- System ``PATH`` variable to include the directory containing the ``idf.py`` tool (part of ESP-IDF).
|
||||
|
||||
To preserve setting of these variables between system restarts, add them to the user profile by following the instructions below.
|
||||
|
||||
.. note:: If using an IDE, you can optionally set these environment variables in your IDE's project environment rather than from the command line as described below.
|
||||
|
||||
.. note:: If you don't ever use the command line ``idf.py`` tool, but run cmake directly or via an IDE, then it is not necessary to set the ``PATH`` variable - only ``IDF_PATH``. However it can be useful to set both.
|
||||
|
||||
.. note:: If you only ever use the command line ``idf.py`` tool, and never use cmake directly or via an IDE, then it is not necessary to set the ``IDF_PATH`` variable - ``idf.py`` will detect the directory it is contained within and set ``IDF_PATH`` appropriately if it is missing.
|
||||
|
||||
.. _add-paths-to-profile-windows-cmake:
|
||||
|
||||
Windows
|
||||
-------
|
||||
|
||||
To edit Environment Variables on Windows 10, search for "Edit Environment Variables" under the Start menu.
|
||||
|
||||
On earlier Windows versions, open the System Control Panel then choose "Advanced" and look for the Environment Variables button.
|
||||
|
||||
You can set these environment variables for all users, or only for the current user, depending on whether other users of your computer will be using ESP-IDF.
|
||||
|
||||
- Click ``New...`` to add a new system variable named ``IDF_PATH``. Set the path to directory containing ESP-IDF, for example ``C:\Users\user-name\esp\esp-idf``.
|
||||
- Locate the ``Path`` environment variable and double-click to edit it. Append the following to the end: ``;%IDF_PATH%\tools``. This will allow you to run ``idf.py`` and other tools from Windows Command Prompt.
|
||||
|
||||
If you got here from :ref:`get-started-setup-path-cmake`, while installing s/w for ESP32 development, then you can continue with :ref:`get-started-get-packages-cmake`.
|
||||
|
||||
|
||||
.. _add-idf_path-to-profile-linux-macos-cmake:
|
||||
|
||||
Linux and MacOS
|
||||
---------------
|
||||
|
||||
Set up ``IDF_PATH`` and add ``idf.py`` to the PATH by adding the following two lines to your ``~/.profile`` file::
|
||||
|
||||
export IDF_PATH=~/esp/esp-idf
|
||||
export PATH="$IDF_PATH/tools:$PATH"
|
||||
|
||||
.. note::
|
||||
|
||||
``~/.profile`` means a file named ``.profile`` in your user's home directory (which is abbreviated ``~`` in the shell).
|
||||
|
||||
Log off and log in back to make this change effective.
|
||||
|
||||
.. note::
|
||||
|
||||
Not all shells use ``.profile``. If you have ``/bin/bash`` and ``.bash_profile`` exists then update this file instead. For ``zsh``, update ``.zprofile``. Other shells may use other profile files (consult the shell's documentation).
|
||||
|
||||
Run the following command to check if ``IDF_PATH`` is set::
|
||||
|
||||
printenv IDF_PATH
|
||||
|
||||
The path previously entered in ``~/.profile`` file (or set manually) should be printed out.
|
||||
|
||||
To verify ``idf.py`` is now on the ``PATH``, you can run the following::
|
||||
|
||||
which idf.py
|
||||
|
||||
A path like ``${IDF_PATH}/tools/idf.py`` should be printed.
|
||||
|
||||
If you do not like to have ``IDF_PATH`` or ``PATH`` modifications set, you can enter it manually in terminal window on each restart or logout::
|
||||
|
||||
export IDF_PATH=~/esp/esp-idf
|
||||
export PATH="$IDF_PATH/tools:$PATH"
|
||||
|
||||
If you got here from :ref:`get-started-setup-path-cmake`, while installing s/w for ESP32 development, then you can continue with :ref:`get-started-get-packages-cmake`.
|
||||
.. Remove this file when the Chinese translation of CMake getting started guide is updated
|
||||
|
|
|
@ -78,10 +78,10 @@ This is a detailed roadmap to walk you through the installation process.
|
|||
Setting up Development Environment
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* :ref:`get-started-setup-toolchain-cmake` for :doc:`Windows <windows-setup>`, :doc:`Linux <linux-setup>` or :doc:`MacOS <macos-setup>`
|
||||
* :ref:`get-started-get-prerequisites-cmake` for :doc:`Windows <windows-setup>`, :doc:`Linux <linux-setup>` or :doc:`macOS <macos-setup>`
|
||||
* :ref:`get-started-get-esp-idf-cmake`
|
||||
* :ref:`get-started-setup-path-cmake`
|
||||
* :ref:`get-started-get-packages-cmake`
|
||||
* :ref:`get-started-set-up-tools-cmake`
|
||||
* :ref:`get-started-set-up-env-cmake`
|
||||
|
||||
Creating Your First Project
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -94,60 +94,40 @@ Creating Your First Project
|
|||
* :ref:`get-started-build-monitor-cmake`
|
||||
|
||||
|
||||
.. _get-started-setup-toolchain-cmake:
|
||||
.. _get-started-get-prerequisites-cmake:
|
||||
|
||||
Step 1. Set up the Toolchain
|
||||
============================
|
||||
Step 1. Install prerequisites
|
||||
=============================
|
||||
|
||||
The toolchain is a set of programs for compiling code and building applications.
|
||||
|
||||
The quickest way to start development with ESP32 is by installing a prebuilt toolchain. Pick up your OS below and follow the provided instructions.
|
||||
Some tools need to be installed on the computer before proceeding to the next steps. Follow the links below for the instructions for your OS:
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
Windows <windows-setup>
|
||||
Linux <linux-setup>
|
||||
MacOS <macos-setup>
|
||||
|
||||
+-------------------+-------------------+-------------------+
|
||||
| |windows-logo| | |linux-logo| | |macos-logo| |
|
||||
+-------------------+-------------------+-------------------+
|
||||
| `Windows`_ | `Linux`_ | `Mac OS`_ |
|
||||
+-------------------+-------------------+-------------------+
|
||||
|
||||
.. |windows-logo| image:: ../../_static/windows-logo.png
|
||||
:target: ../get-started-cmake/windows-setup.html
|
||||
|
||||
.. |linux-logo| image:: ../../_static/linux-logo.png
|
||||
:target: ../get-started-cmake/linux-setup.html
|
||||
|
||||
.. |macos-logo| image:: ../../_static/macos-logo.png
|
||||
:target: ../get-started-cmake/macos-setup.html
|
||||
|
||||
.. _Windows: ../get-started-cmake/windows-setup.html
|
||||
.. _Linux: ../get-started-cmake/linux-setup.html
|
||||
.. _Mac OS: ../get-started-cmake/macos-setup.html
|
||||
|
||||
.. note::
|
||||
|
||||
This guide uses the directory ``~/esp`` on Linux and macOS or ``%userprofile%\esp`` on Windows as an installation folder for ESP-IDF. You can use any directory, but you will need to adjust paths for the commands respectively. Keep in mind that ESP-IDF does not support spaces in paths.
|
||||
|
||||
Depending on your experience and preferences, you may want to customize your environment instead of using a prebuilt toolchain. To set up the system your own way go to Section :ref:`get-started-customized-setup-cmake`.
|
||||
Linux <linux-setup>
|
||||
macOS <macos-setup>
|
||||
|
||||
* :doc:`windows-setup`
|
||||
* :doc:`linux-setup`
|
||||
* :doc:`macos-setup`
|
||||
|
||||
.. _get-started-get-esp-idf-cmake:
|
||||
|
||||
Step 2. Get ESP-IDF
|
||||
===================
|
||||
|
||||
Besides the toolchain, you also need ESP32-specific API (software libraries and source code). They are provided by Espressif in `ESP-IDF repository <https://github.com/espressif/esp-idf>`_.
|
||||
To build applications for the ESP32, you need the software libraries provided by Espressif in `ESP-IDF repository <https://github.com/espressif/esp-idf>`_.
|
||||
|
||||
Get ESP-IDF in accordance with your operating system.
|
||||
|
||||
To get ESP-IDF, navigate to your installation directory and clone the repository with ``git clone``.
|
||||
|
||||
Linux and MacOS
|
||||
.. note::
|
||||
|
||||
This guide uses the directory ``~/esp`` on Linux and macOS or ``%userprofile%\esp`` on Windows as an installation folder for ESP-IDF. You can use any directory, but you will need to adjust paths for the commands respectively. Keep in mind that ESP-IDF does not support spaces in paths.
|
||||
|
||||
Linux and macOS
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Open Terminal, and run the following commands:
|
||||
|
@ -161,60 +141,76 @@ Consult :doc:`/versions` for information about which ESP-IDF version to use in a
|
|||
Windows
|
||||
~~~~~~~
|
||||
|
||||
.. note::
|
||||
|
||||
Previous versions of ESP-IDF used the **MSYS2 bash terminal** command line. The current cmake-based build system can run in the regular **Windows Command Prompt** which is used here.
|
||||
|
||||
If you use a bash-based terminal or PowerShell, please note that some command syntax will be different to what is shown below.
|
||||
|
||||
Open Command Prompt and run the following commands:
|
||||
|
||||
.. include:: /_build/inc/git-clone-windows.inc
|
||||
|
||||
ESP-IDF will be downloaded into ``%userprofile%\esp\esp-idf``.
|
||||
In addition to installing the tools, :ref:`get-started-cmake-windows-tools-installer` for Windows introduced in Step 1 can also download a copy of ESP-IDF.
|
||||
|
||||
Consult :doc:`/versions` for information about which ESP-IDF version to use in a given situation.
|
||||
|
||||
.. include:: /_build/inc/git-clone-notes.inc
|
||||
If you wish to download ESP-IDF without the help of ESP-IDF Tools Installer, refer to these :ref:`instructions <get-esp-idf-windows-command-line-cmake>`.
|
||||
|
||||
.. note::
|
||||
.. _get-started-set-up-tools-cmake:
|
||||
|
||||
Do not miss the ``--recursive`` option. If you have already cloned ESP-IDF without this option, run another command to get all the submodules::
|
||||
Step 3. Set up the tools
|
||||
========================
|
||||
|
||||
cd esp-idf
|
||||
git submodule update --init
|
||||
Aside from the ESP-IDF, you also need to install the tools used by ESP-IDF, such as the compiler, debugger, Python packages, etc.
|
||||
|
||||
Windows
|
||||
~~~~~~~
|
||||
|
||||
.. _get-started-setup-path-cmake:
|
||||
:ref:`get-started-cmake-windows-tools-installer` for Windows introduced in Step 1 installs all the required tools.
|
||||
|
||||
Step 3. Set Environment Variables
|
||||
=================================
|
||||
If you want to install the tools without the help of ESP-IDF Tools Installer, open the Command Prompt and follow these steps:
|
||||
|
||||
Set the following environment variables on your computer, so that projects can be built:
|
||||
.. code-block:: batch
|
||||
|
||||
- Create ``IDF_PATH`` and assign it the path to the ESP-IDF directory.
|
||||
- Add to ``PATH`` the path to the ``tools`` directory inside the ``IDF_PATH`` directory.
|
||||
cd %userprofile%\esp\esp-idf
|
||||
install.bat
|
||||
|
||||
These variables can be set temporarily (per session) or permanently. Please follow the instructions specific to :ref:`Windows <add-paths-to-profile-windows-cmake>` , :ref:`Linux and MacOS <add-idf_path-to-profile-linux-macos-cmake>` in Section :doc:`add-idf_path-to-profile`.
|
||||
Linux and macOS
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
.. _get-started-get-packages-cmake:
|
||||
cd ~/esp/esp-idf
|
||||
./install.sh
|
||||
|
||||
Step 4. Install the Required Python Packages
|
||||
============================================
|
||||
Customizing the tools installation path
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The python packages required by ESP-IDF are located in ``IDF_PATH/requirements.txt``. You can install them by running::
|
||||
The scripts introduced in this step install compilation tools required by ESP-IDF inside the user home directory: ``$HOME/.espressif`` on Linux and macOS, ``%USERPROFILE%\.espressif`` on Windows. If you wish to install the tools into a different directory, set the environment variable ``IDF_TOOLS_PATH`` before running the installation scripts. Make sure that your user has sufficient permissions to read and write this path.
|
||||
|
||||
python -m pip install --user -r $IDF_PATH/requirements.txt
|
||||
If changing the ``IDF_TOOLS_PATH``, make sure it is set to the same value every time the ``install.bat``/``install.sh`` and ``export.bat``/``export.sh`` scripts are executed.
|
||||
|
||||
.. note::
|
||||
.. _get-started-set-up-env-cmake:
|
||||
|
||||
Please check the version of the Python interpreter that you will be using with ESP-IDF. For this, run
|
||||
the command ``python --version`` and depending on the result, you might want to use ``python2``, ``python2.7``
|
||||
or similar instead of just ``python``, e.g.::
|
||||
Step 4. Set up the environment variables
|
||||
========================================
|
||||
|
||||
python2.7 -m pip install --user -r $IDF_PATH/requirements.txt
|
||||
The installed tools are not yet added to the PATH environment variable. To make the tools usable from the command line, some environment variables must be set. ESP-IDF provides another script which does that.
|
||||
|
||||
Windows
|
||||
~~~~~~~
|
||||
|
||||
:ref:`get-started-cmake-windows-tools-installer` for Windows creates an "ESP-IDF Command Prompt" shortcut in the Start Menu. This shortcut opens the Command Prompt and sets up all the required environment variables. You can open this shortcut and proceed to the next step.
|
||||
|
||||
Alternatively, if you want to use ESP-IDF in an existing Command Prompt window, you can run:
|
||||
|
||||
.. code-block:: batch
|
||||
|
||||
%userprofile%\esp\esp-idf\export.bat
|
||||
|
||||
Linux and macOS
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
In the terminal where you are going to use ESP-IDF, run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
. $HOME/esp/esp-idf/export.sh
|
||||
|
||||
Note the space between the leading dot and the path!
|
||||
|
||||
You can also automate this step, making ESP-IDF tools available in every terminal, by adding this line to your ``.profile`` or ``.bash_profile`` script.
|
||||
|
||||
.. _get-started-start-project-cmake:
|
||||
|
||||
|
@ -225,7 +221,7 @@ Now you are ready to prepare your application for ESP32. You can start with :exa
|
|||
|
||||
Copy :example:`get-started/hello_world` to ``~/esp`` directory:
|
||||
|
||||
Linux and MacOS
|
||||
Linux and macOS
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -247,7 +243,7 @@ It is also possible to build examples in-place, without copying them first.
|
|||
|
||||
.. important::
|
||||
|
||||
The esp-idf build system does not support spaces in the paths to either esp-idf or to projects.
|
||||
The ESP-IDF build system does not support spaces in the paths to either ESP-IDF or to projects.
|
||||
|
||||
.. _get-started-connect-cmake:
|
||||
|
||||
|
@ -276,7 +272,7 @@ Step 7. Configure
|
|||
|
||||
Navigate to your ``hello_world`` directory from :ref:`get-started-start-project-cmake` and run the project configuration utility ``menuconfig``.
|
||||
|
||||
Linux and MacOS
|
||||
Linux and macOS
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -294,12 +290,6 @@ Windows
|
|||
cd %userprofile%\esp\hello_world
|
||||
idf.py menuconfig
|
||||
|
||||
The Python 2.7 installer will try to configure Windows to associate ``.py`` files with Python 2. If a separately installed program, such as Visual Studio Python Tools, has created an association with a different version of Python, then running ``idf.py`` may not work (it opens the file in Visual Studio instead). You can either run ``C:\Python27\python idf.py`` each time instead, or change the association that Windows uses for ``.py`` files.
|
||||
|
||||
.. note::
|
||||
|
||||
If you get an error ``idf.py not found``, make sure that the ``PATH`` environment variable was set correctly in :ref:`get-started-setup-path-cmake`. If there is no ``idf.py`` in ``tools``, make sure you have the correct branch for the CMake preview as shown under :ref:`get-started-get-esp-idf-cmake`.
|
||||
|
||||
If the previous steps have been done correctly, the following menu appears:
|
||||
|
||||
.. figure:: ../../_static/project-configuration.png
|
||||
|
@ -480,17 +470,18 @@ Updating ESP-IDF
|
|||
|
||||
You should update ESP-IDF from time to time, as newer versions fix bugs and provide new features. The simplest way to do the update is to delete the existing ``esp-idf`` folder and clone it again, as if performing the initial installation described in :ref:`get-started-get-esp-idf-cmake`.
|
||||
|
||||
If downloading to a new path, remember to :doc:`add-idf_path-to-profile` so that the toolchain scripts can find ESP-IDF in its release specific location.
|
||||
|
||||
Another solution is to update only what has changed. :ref:`The update procedure depends on the version of ESP-IDF you are using <updating>`.
|
||||
|
||||
After updating ESP-IDF, execute ``install.sh`` (``install.bat`` on Windows) again, in case the new ESP-IDF version requires different versions of tools. See instructions at :ref:`get-started-set-up-tools-cmake`.
|
||||
|
||||
Once the new tools are installed, update the environment using ``export.sh`` (``export.bat`` on Windows). See instructions at :ref:`get-started-set-up-env-cmake`.
|
||||
|
||||
Related Documents
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
add-idf_path-to-profile
|
||||
establish-serial-connection
|
||||
eclipse-setup
|
||||
../api-guides/tools/idf-monitor
|
||||
|
|
|
@ -68,7 +68,7 @@ Build the toolchain::
|
|||
./ct-ng build
|
||||
chmod -R u+w builds/xtensa-esp32-elf
|
||||
|
||||
Toolchain will be built in ``~/esp/crosstool-NG/builds/xtensa-esp32-elf``. Follow `instructions for standard setup <setup-linux-toolchain-add-it-to-path-cmake>`_ to add the toolchain to your ``PATH``.
|
||||
Toolchain will be built in ``~/esp/crosstool-NG/builds/xtensa-esp32-elf``. To use it, you need to add ``~/esp/crosstool-NG/builds/xtensa-esp32-elf/bin`` to ``PATH`` environment variable.
|
||||
|
||||
|
||||
Next Steps
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
*********************************************
|
||||
Standard Setup of Toolchain for Linux (CMake)
|
||||
*********************************************
|
||||
***********************************************
|
||||
Installation of Prerequisites for Linux (CMake)
|
||||
***********************************************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
|
@ -26,61 +26,9 @@ To compile with ESP-IDF you need to get the following packages:
|
|||
.. note::
|
||||
CMake version 3.5 or newer is required for use with ESP-IDF. Older Linux distributions may require updating, enabling of a "backports" repository, or installing of a "cmake3" package rather than "cmake".
|
||||
|
||||
Toolchain Setup
|
||||
Additional Tips
|
||||
===============
|
||||
|
||||
.. include:: /_build/inc/download-links.inc
|
||||
|
||||
ESP32 toolchain for Linux is available for download from Espressif website:
|
||||
|
||||
- for 64-bit Linux:
|
||||
|
||||
|download_link_linux64|
|
||||
|
||||
- for 32-bit Linux:
|
||||
|
||||
|download_link_linux32|
|
||||
|
||||
1. Download this file, then extract it in ``~/esp`` directory:
|
||||
|
||||
- for 64-bit Linux:
|
||||
|
||||
.. include:: /_build/inc/unpack-code-linux64.inc
|
||||
|
||||
- for 32-bit Linux:
|
||||
|
||||
.. include:: /_build/inc/unpack-code-linux32.inc
|
||||
|
||||
.. _setup-linux-toolchain-add-it-to-path-cmake:
|
||||
|
||||
2. The toolchain will be extracted into ``~/esp/xtensa-esp32-elf/`` directory.
|
||||
|
||||
To use it, you will need to update your ``PATH`` environment variable in ``~/.profile`` file. To make ``xtensa-esp32-elf`` available for all terminal sessions, add the following line to your ``~/.profile`` file::
|
||||
|
||||
export PATH="$HOME/esp/xtensa-esp32-elf/bin:$PATH"
|
||||
|
||||
Alternatively, you may create an alias for the above command. This way you can get the toolchain only when you need it. To do this, add different line to your ``~/.profile`` file::
|
||||
|
||||
alias get_esp32='export PATH="$HOME/esp/xtensa-esp32-elf/bin:$PATH"'
|
||||
|
||||
Then when you need the toolchain you can type ``get_esp32`` on the command line and the toolchain will be added to your ``PATH``.
|
||||
|
||||
.. note::
|
||||
|
||||
If you have ``/bin/bash`` set as login shell, and both ``.bash_profile`` and ``.profile`` exist, then update ``.bash_profile`` instead.
|
||||
|
||||
3. Log off and log in back to make the ``.profile`` changes effective. Run the following command to verify if ``PATH`` is correctly set::
|
||||
|
||||
printenv PATH
|
||||
|
||||
You are looking for similar result containing toolchain's path at the beginning of displayed string::
|
||||
|
||||
$ printenv PATH
|
||||
/home/user-name/esp/xtensa-esp32-elf/bin:/home/user-name/bin:/home/user-name/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
|
||||
|
||||
Instead of ``/home/user-name`` there should be a home path specific to your installation.
|
||||
|
||||
|
||||
Permission issues /dev/ttyUSB0
|
||||
------------------------------
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ Build the toolchain::
|
|||
./ct-ng build
|
||||
chmod -R u+w builds/xtensa-esp32-elf
|
||||
|
||||
Toolchain will be built in ``~/esp/ctng-volume/crosstool-NG/builds/xtensa-esp32-elf``. Follow :ref:`instructions for standard setup <setup-macos-toolchain-add-it-to-path-cmake>` to add the toolchain to your ``PATH``.
|
||||
Toolchain will be built in ``~/esp/ctng-volume/crosstool-NG/builds/xtensa-esp32-elf``. To use it, you need to add ``~/esp/ctng-volume/crosstool-NG/builds/xtensa-esp32-elf/bin`` to ``PATH`` environment variable.
|
||||
|
||||
|
||||
Next Steps
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
**********************************************
|
||||
Standard Setup of Toolchain for Mac OS (CMake)
|
||||
**********************************************
|
||||
***********************************************
|
||||
Installation of Prerequisites for macOS (CMake)
|
||||
***********************************************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
|
@ -9,7 +9,7 @@ Standard Setup of Toolchain for Mac OS (CMake)
|
|||
Install Prerequisites
|
||||
=====================
|
||||
|
||||
ESP-IDF will use the version of Python installed by default on Mac OS.
|
||||
ESP-IDF will use the version of Python installed by default on macOS.
|
||||
|
||||
- install pip::
|
||||
|
||||
|
@ -29,7 +29,7 @@ ESP-IDF will use the version of Python installed by default on Mac OS.
|
|||
|
||||
sudo port install cmake ninja
|
||||
|
||||
- Otherwise, consult the CMake_ and Ninja_ home pages for Mac OS installation downloads.
|
||||
- Otherwise, consult the CMake_ and Ninja_ home pages for macOS installation downloads.
|
||||
|
||||
- It is strongly recommended to also install ccache_ for faster builds. If you have HomeBrew_, this can be done via ``brew install ccache`` or ``sudo port install ccache`` on MacPorts_.
|
||||
|
||||
|
@ -38,39 +38,7 @@ ESP-IDF will use the version of Python installed by default on Mac OS.
|
|||
|
||||
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
|
||||
|
||||
Then you will need to install the XCode command line tools to continue. You can install these by running ``xcode-select --install``.
|
||||
|
||||
Toolchain Setup
|
||||
===============
|
||||
|
||||
.. include:: /_build/inc/download-links.inc
|
||||
|
||||
ESP32 toolchain for macOS is available for download from Espressif website:
|
||||
|
||||
|download_link_osx|
|
||||
|
||||
Download this file, then extract it in ``~/esp`` directory:
|
||||
|
||||
.. include:: /_build/inc/unpack-code-osx.inc
|
||||
|
||||
.. _setup-macos-toolchain-add-it-to-path-cmake:
|
||||
|
||||
The toolchain will be extracted into ``~/esp/xtensa-esp32-elf/`` directory.
|
||||
|
||||
To use it, you will need to update your ``PATH`` environment variable in ``~/.profile`` file. To make ``xtensa-esp32-elf`` available for all terminal sessions, add the following line to your ``~/.profile`` file::
|
||||
|
||||
export PATH=$HOME/esp/xtensa-esp32-elf/bin:$PATH
|
||||
|
||||
Alternatively, you may create an alias for the above command. This way you can get the toolchain only when you need it. To do this, add different line to your ``~/.profile`` file::
|
||||
|
||||
alias get_esp32="export PATH=$HOME/esp/xtensa-esp32-elf/bin:$PATH"
|
||||
|
||||
Then when you need the toolchain you can type ``get_esp32`` on the command line and the toolchain will be added to your ``PATH``.
|
||||
|
||||
Log off and log in back to make the ``.profile`` changes effective. Run the following command to verify if ``PATH`` is correctly set::
|
||||
|
||||
printenv PATH
|
||||
|
||||
Then you will need to install the XCode command line tools to continue. You can install these by running ``xcode-select --install``.
|
||||
|
||||
Next Steps
|
||||
==========
|
||||
|
|
|
@ -6,7 +6,7 @@ Customized Setup of Toolchain (CMake)
|
|||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Instead of downloading binary toolchain from Espressif website (see :ref:`get-started-setup-toolchain-cmake`) you may build the toolchain yourself.
|
||||
Instead of downloading binary toolchain from Espressif website (see :ref:`get-started-set-up-tools-cmake`) you may build the toolchain yourself.
|
||||
|
||||
If you can't think of a reason why you need to build it yourself, then probably it's better to stick with the binary version. However, here are some of the reasons why you might want to compile it from source:
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
********************************************
|
||||
Setup Windows Toolchain from Scratch (CMake)
|
||||
********************************************
|
||||
**********************************
|
||||
Windows Setup from Scratch (CMake)
|
||||
**********************************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
|
@ -10,10 +10,38 @@ This is a step-by-step alternative to running the :doc:`ESP-IDF Tools Installer
|
|||
|
||||
To quickly setup the toolchain and other tools in standard way, using the ESP-IDF Tools installer, proceed to section :doc:`windows-setup`.
|
||||
|
||||
|
||||
.. note::
|
||||
The GNU Make based build system requires the MSYS2_ Unix compatibility environment on Windows. The CMake-based build system does not require this environment.
|
||||
|
||||
.. _get-esp-idf-windows-command-line-cmake:
|
||||
|
||||
Get ESP-IDF
|
||||
===========
|
||||
|
||||
.. note::
|
||||
|
||||
Previous versions of ESP-IDF used the **MSYS2 bash terminal** command line. The current cmake-based build system can run in the regular **Windows Command Prompt** which is used here.
|
||||
|
||||
If you use a bash-based terminal or PowerShell, please note that some command syntax will be different to what is shown below.
|
||||
|
||||
Open Command Prompt and run the following commands:
|
||||
|
||||
.. include:: /_build/inc/git-clone-windows.inc
|
||||
|
||||
ESP-IDF will be downloaded into ``%userprofile%\esp\esp-idf``.
|
||||
|
||||
Consult :doc:`/versions` for information about which ESP-IDF version to use in a given situation.
|
||||
|
||||
.. include:: /_build/inc/git-clone-notes.inc
|
||||
|
||||
.. note::
|
||||
|
||||
Do not miss the ``--recursive`` option. If you have already cloned ESP-IDF without this option, run another command to get all the submodules::
|
||||
|
||||
cd esp-idf
|
||||
git submodule update --init
|
||||
|
||||
|
||||
Tools
|
||||
=====
|
||||
|
||||
|
@ -90,4 +118,5 @@ To carry on with development environment setup, proceed to :ref:`get-started-get
|
|||
.. _ninja: https://ninja-build.org/
|
||||
.. _Python: https://www.python.org/downloads/windows/
|
||||
.. _MSYS2: https://msys2.github.io/
|
||||
.. _Stable version: https://docs.espressif.com/projects/esp-idf/en/stable/
|
||||
|
||||
|
|
31
docs/en/get-started-cmake/windows-setup-update.rst
Normal file
31
docs/en/get-started-cmake/windows-setup-update.rst
Normal file
|
@ -0,0 +1,31 @@
|
|||
*********************************
|
||||
Updating ESP-IDF tools on Windows
|
||||
*********************************
|
||||
|
||||
.. _get-started-cmake-install_bat-windows:
|
||||
|
||||
Install ESP-IDF tools using ``install.bat``
|
||||
===========================================
|
||||
|
||||
From the Windows Command Prompt, change to the directory where ESP-IDF is installed. Then run::
|
||||
|
||||
install.bat
|
||||
|
||||
This will download and install the tools necessary to use ESP-IDF. If the specific version of the tool is already installed, no action will be taken.
|
||||
The tools are downloaded and installed into a directory specified during ESP-IDF Tools Installer process. By default, this is ``C:\Users\username\.espressif``.
|
||||
|
||||
.. _get-started-cmake-export_bat-windows:
|
||||
|
||||
Add ESP-IDF tools to PATH using ``export.bat``
|
||||
==============================================
|
||||
|
||||
ESP-IDF tools installer creates a Start menu shortcut for "ESP-IDF Command Prompt". This shortcut opens a Command Prompt window where all the tools are already available.
|
||||
|
||||
In some cases, you may want to work with ESP-IDF in a Command Prompt window which wasn't started using that shortcut. If this is the case, follow the instructions below to add ESP-IDF tools to PATH.
|
||||
|
||||
In the command prompt where you need to use ESP-IDF, change to the directory where ESP-IDF is installed, then execute ``export.bat``::
|
||||
|
||||
cd %userprofile%\esp\esp-idf
|
||||
export.bat
|
||||
|
||||
When this is done, the tools will be available in this command prompt.
|
|
@ -1,6 +1,6 @@
|
|||
***********************************************
|
||||
Standard Setup of Toolchain for Windows (CMake)
|
||||
***********************************************
|
||||
*************************************************
|
||||
Installation of Prerequisites for Windows (CMake)
|
||||
*************************************************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
|
@ -12,46 +12,43 @@ Standard Setup of Toolchain for Windows (CMake)
|
|||
Introduction
|
||||
============
|
||||
|
||||
ESP-IDF requires some prerequisite tools to be installed so you can build firmware for the ESP32. The prerequisite tools include Git, a cross-compiler and the CMake build tool. We'll go over each one in this document.
|
||||
ESP-IDF requires some prerequisite tools to be installed so you can build firmware for the ESP32. The prerequisite tools include Python, Git, cross-compilers, menuconfig tool, CMake and Ninja build tools.
|
||||
|
||||
For this Getting Started we're going to use a command prompt, but after ESP-IDF is installed you can use :doc:`Eclipse <eclipse-setup>` or another graphical IDE with CMake support instead.
|
||||
For this Getting Started we're going to use the Command Prompt, but after ESP-IDF is installed you can use :doc:`Eclipse <eclipse-setup>` or another graphical IDE with CMake support instead.
|
||||
|
||||
.. note::
|
||||
The GNU Make based build system requires the MSYS2_ Unix compatibility environment on Windows. The CMake-based build system does not require this environment.
|
||||
|
||||
.. _get-started-cmake-windows-tools-installer:
|
||||
|
||||
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-1.2.exe
|
||||
https://dl.espressif.com/dl/esp-idf-tools-setup-2.0.exe
|
||||
|
||||
The installer will automatically install the ESP32 Xtensa gcc toolchain, Ninja_ build tool, and a configuration tool called mconf-idf_. The installer can also download and run installers for CMake_ and Python_ 2.7 if these are not already installed on the computer.
|
||||
The installer includes the cross-compilers, OpenOCD, cmake_ and Ninja_ build tool, and a configuration tool called mconf-idf_. The installer can also download and run installers for Python_ 3.7 and `Git For Windows`_ if they are not already installed on the computer.
|
||||
|
||||
By default, the installer updates the Windows ``Path`` environment variable so all of these tools can be run from anywhere. If you disable this option, you will need to configure the environment where you are using ESP-IDF (terminal or chosen IDE) with the correct paths.
|
||||
The installer also offers to download one of the ESP-IDF release versions.
|
||||
|
||||
Note that this installer is for the ESP-IDF Tools package, it doesn't include ESP-IDF itself.
|
||||
Using the Command Prompt
|
||||
========================
|
||||
|
||||
Installing Git
|
||||
==============
|
||||
For the remaining Getting Started steps, we're going to use the Windows Command Prompt.
|
||||
|
||||
The ESP-IDF tools installer does not install Git. By default, the getting started guide assumes you will be using Git on the command line. You can download and install a command line Git for Windows (along with the "Git Bash" terminal) from `Git For Windows`_.
|
||||
ESP-IDF Tools Installer creates a shortcut in the Start menu to launch the ESP-IDF Command Prompt. This shortcut launches the Command Prompt (cmd.exe) and runs ``export.bat`` script to set up the environment variables (``PATH``, ``IDF_PATH`` and others). Inside this command prompt, all the installed tools are available.
|
||||
|
||||
If you prefer to use a different graphical Git client, then you can install one such as `Github Desktop`. You will need to translate the Git commands in the Getting Started guide for use with your chosen Git client.
|
||||
Note that this shortcut is specific to the ESP-IDF directory selected in the ESP-IDF Tools Installer. If you have multiple ESP-IDF directories on the computer (for example, to work with different versions of ESP-IDF), you have two options to use them:
|
||||
|
||||
Using a Terminal
|
||||
================
|
||||
1. Create a copy of the shortcut created by the ESP-IDF Tools Installer, and change the working directory of the new shortcut to the ESP-IDF directory you wish to use.
|
||||
|
||||
For the remaining Getting Started steps, we're going to use a terminal command prompt. It doesn't matter which command prompt you use:
|
||||
|
||||
- You can use the built-in Windows Command Prompt, under the Start menu. All Windows command line instructions in this documentation are "batch" commands for use with the Windows Command Prompt.
|
||||
- You can use the "Git Bash" terminal which is part of `Git for Windows`_. This uses the same "bash" command prompt syntax as is given for Mac OS or Linux. You can find it in the Start menu once installed.
|
||||
- If you have MSYS2_ installed (maybe from a previous ESP-IDF version), then you can also use the MSYS terminal.
|
||||
2. Alternatively, run ``cmd.exe``, then change to the ESP-IDF directory you wish to use, and run ``export.bat``. Note that unlike the previous option, this way requires Python and Git to be present in ``PATH``. If you get errors related to Python or Git not being found, use the first option.
|
||||
|
||||
Next Steps
|
||||
==========
|
||||
|
||||
To carry on with development environment setup, proceed to :ref:`get-started-get-esp-idf-cmake`.
|
||||
If the ESP-IDF Tools Installer has finished successfully, then the development environment setup is complete. Proceed directly to :ref:`get-started-start-project-cmake`.
|
||||
|
||||
Related Documents
|
||||
=================
|
||||
|
@ -62,7 +59,7 @@ For advanced users who want to customize the install process:
|
|||
:maxdepth: 1
|
||||
|
||||
windows-setup-scratch
|
||||
|
||||
windows-setup-update
|
||||
|
||||
.. _MSYS2: https://msys2.github.io/
|
||||
.. _cmake: https://cmake.org/download/
|
||||
|
|
3
docs/zh_CN/get-started-cmake/windows-setup-update.rst
Normal file
3
docs/zh_CN/get-started-cmake/windows-setup-update.rst
Normal file
|
@ -0,0 +1,3 @@
|
|||
:orphan:
|
||||
|
||||
.. Remove this file when the Chinese translation of CMake getting started guide is updated
|
70
export.bat
Normal file
70
export.bat
Normal file
|
@ -0,0 +1,70 @@
|
|||
@echo off
|
||||
if defined MSYSTEM (
|
||||
echo This .bat file is for Windows CMD.EXE shell only. When using MSYS, run:
|
||||
echo . ./export.sh.
|
||||
goto :eof
|
||||
)
|
||||
|
||||
:: Infer IDF_PATH from script location
|
||||
set IDF_PATH=%~dp0
|
||||
set IDF_PATH=%IDF_PATH:~0,-1%
|
||||
|
||||
set IDF_TOOLS_PY_PATH=%IDF_PATH%\tools\idf_tools.py
|
||||
set IDF_TOOLS_JSON_PATH=%IDF_PATH%\tools\tools.json
|
||||
set IDF_TOOLS_EXPORT_CMD=%IDF_PATH%\export.bat
|
||||
set IDF_TOOLS_INSTALL_CMD=%IDF_PATH%\install.bat
|
||||
echo Setting IDF_PATH: %IDF_PATH%
|
||||
echo.
|
||||
|
||||
set "OLD_PATH=%PATH%"
|
||||
echo Adding ESP-IDF tools to PATH...
|
||||
:: Export tool paths and environment variables.
|
||||
:: It is possible to do this without a temporary file (running idf_tools.py from for /r command),
|
||||
:: but that way it is impossible to get the exit code of idf_tools.py.
|
||||
set "IDF_TOOLS_EXPORTS_FILE=%TEMP%\idf_export_vars.tmp"
|
||||
python.exe %IDF_PATH%\tools\idf_tools.py export --format key-value >"%IDF_TOOLS_EXPORTS_FILE%"
|
||||
if %errorlevel% neq 0 goto :end
|
||||
|
||||
for /f "usebackq tokens=1,2 eol=# delims==" %%a in ("%IDF_TOOLS_EXPORTS_FILE%") do (
|
||||
call set "%%a=%%b"
|
||||
)
|
||||
|
||||
:: This removes OLD_PATH substring from PATH, leaving only the paths which have been added,
|
||||
:: and prints semicolon-delimited components of the path on separate lines
|
||||
call set PATH_ADDITIONS=%%PATH:%OLD_PATH%=%%
|
||||
if "%PATH_ADDITIONS%"=="" call :print_nothing_added
|
||||
if not "%PATH_ADDITIONS%"=="" echo %PATH_ADDITIONS:;=&echo. %
|
||||
|
||||
echo Checking if Python packages are up to date...
|
||||
python.exe %IDF_PATH%\tools\check_python_dependencies.py
|
||||
if %errorlevel% neq 0 goto :end
|
||||
|
||||
echo.
|
||||
echo Done! You can now compile ESP-IDF projects.
|
||||
echo Go to the project directory and run:
|
||||
echo.
|
||||
echo idf.py build
|
||||
echo.
|
||||
|
||||
goto :end
|
||||
|
||||
:print_nothing_added
|
||||
echo No directories added to PATH:
|
||||
echo.
|
||||
echo %PATH%
|
||||
echo.
|
||||
goto :eof
|
||||
|
||||
:end
|
||||
|
||||
:: Clean up
|
||||
if not "%IDF_TOOLS_EXPORTS_FILE%"=="" (
|
||||
del "%IDF_TOOLS_EXPORTS_FILE%" 1>nul 2>nul
|
||||
)
|
||||
set IDF_TOOLS_EXPORTS_FILE=
|
||||
set IDF_TOOLS_EXPORT_CMD=
|
||||
set IDF_TOOLS_INSTALL_CMD=
|
||||
set IDF_TOOLS_PY_PATH=
|
||||
set IDF_TOOLS_JSON_PATH=
|
||||
set OLD_PATH=
|
||||
set PATH_ADDITIONS=
|
82
export.sh
Normal file
82
export.sh
Normal file
|
@ -0,0 +1,82 @@
|
|||
# This script should be sourced, not executed.
|
||||
|
||||
function idf_export_main() {
|
||||
# The file doesn't have executable permissions, so this shouldn't really happen.
|
||||
# Doing this in case someone tries to chmod +x it and execute...
|
||||
if [[ -n "${BASH_SOURCE}" && ( "${BASH_SOURCE[0]}" == "${0}" ) ]]; then
|
||||
echo "This script should be sourced, not executed:"
|
||||
echo ". ${BASH_SOURCE[0]}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -z "${IDF_PATH}" ]]
|
||||
then
|
||||
# If using bash, try to guess IDF_PATH from script location
|
||||
if [[ -n "${BASH_SOURCE}" ]]
|
||||
then
|
||||
script_name="$(readlink -f $BASH_SOURCE)"
|
||||
export IDF_PATH="$(dirname ${script_name})"
|
||||
else
|
||||
echo "IDF_PATH must be set before sourcing this script"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
old_path=$PATH
|
||||
|
||||
echo "Adding ESP-IDF tools to PATH..."
|
||||
# Call idf_tools.py to export tool paths
|
||||
export IDF_TOOLS_EXPORT_CMD=${IDF_PATH}/export.sh
|
||||
export IDF_TOOLS_INSTALL_CMD=${IDF_PATH}/install.sh
|
||||
idf_exports=$(${IDF_PATH}/tools/idf_tools.py export) || return 1
|
||||
eval "${idf_exports}"
|
||||
|
||||
echo "Checking if Python packages are up to date..."
|
||||
python ${IDF_PATH}/tools/check_python_dependencies.py || return 1
|
||||
|
||||
|
||||
# Allow calling some IDF python tools without specifying the full path
|
||||
# ${IDF_PATH}/tools is already added by 'idf_tools.py export'
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/esptool"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/espcoredump"
|
||||
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/partition_table/"
|
||||
export PATH="${IDF_ADD_PATHS_EXTRAS}:${PATH}"
|
||||
|
||||
if [[ -n "$BASH" ]]
|
||||
then
|
||||
path_prefix=${PATH%%${old_path}}
|
||||
paths="${path_prefix//:/ }"
|
||||
if [ -n "${paths}" ]; then
|
||||
echo "Added the following directories to PATH:"
|
||||
else
|
||||
echo "All paths are already set."
|
||||
fi
|
||||
for path_entry in ${paths}
|
||||
do
|
||||
echo " ${path_entry}"
|
||||
done
|
||||
else
|
||||
echo "Updated PATH variable:"
|
||||
echo " ${PATH}"
|
||||
fi
|
||||
|
||||
# Clean up
|
||||
unset old_path
|
||||
unset paths
|
||||
unset path_prefix
|
||||
unset path_entry
|
||||
unset IDF_ADD_PATHS_EXTRAS
|
||||
unset idf_exports
|
||||
# Not unsetting IDF_PYTHON_ENV_PATH, it can be used by IDF build system
|
||||
# to check whether we are using a private Python environment
|
||||
|
||||
echo "Done! You can now compile ESP-IDF projects."
|
||||
echo "Go to the project directory and run:"
|
||||
echo ""
|
||||
echo " idf.py build"
|
||||
echo ""
|
||||
}
|
||||
|
||||
idf_export_main
|
||||
|
||||
unset idf_export_main
|
19
install.bat
Normal file
19
install.bat
Normal file
|
@ -0,0 +1,19 @@
|
|||
@echo off
|
||||
if defined MSYSTEM (
|
||||
echo This .bat file is for Windows CMD.EXE shell only. When using MSYS, run:
|
||||
echo ./install.sh.
|
||||
goto end
|
||||
)
|
||||
:: Infer IDF_PATH from script location
|
||||
set IDF_PATH=%~dp0
|
||||
set IDF_PATH=%IDF_PATH:~0,-1%
|
||||
|
||||
echo Installing ESP-IDF tools
|
||||
python.exe %IDF_PATH%\tools\idf_tools.py install
|
||||
|
||||
echo Setting up Python environment
|
||||
python.exe %IDF_PATH%\tools\idf_tools.py install-python-env
|
||||
|
||||
echo All done! You can now run:
|
||||
echo export.bat
|
||||
:: Clean up
|
18
install.sh
Executable file
18
install.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
export IDF_PATH=$(cd $(dirname $0); pwd)
|
||||
|
||||
echo "Installing ESP-IDF tools"
|
||||
${IDF_PATH}/tools/idf_tools.py install
|
||||
|
||||
echo "Installing Python environment and packages"
|
||||
${IDF_PATH}/tools/idf_tools.py install-python-env
|
||||
|
||||
basedir="$(dirname $0)"
|
||||
echo "All done! You can now run:"
|
||||
echo ""
|
||||
echo " . ${basedir}/export.sh"
|
||||
echo ""
|
|
@ -26,6 +26,7 @@ examples/storage/parttool/parttool_example.sh
|
|||
examples/system/ota/otatool/get_running_partition.py
|
||||
examples/system/ota/otatool/otatool_example.py
|
||||
examples/system/ota/otatool/otatool_example.sh
|
||||
install.sh
|
||||
tools/check_kconfigs.py
|
||||
tools/check_python_dependencies.py
|
||||
tools/ci/apply_bot_filter.py
|
||||
|
|
|
@ -559,10 +559,10 @@ class IDFTool(object):
|
|||
expected_size = download_obj.size
|
||||
file_size, file_sha256 = get_file_size_sha256(local_path)
|
||||
if file_size != expected_size:
|
||||
warn('file size mismatch for {0}'.format(local_path))
|
||||
warn('file size mismatch for {}, expected {}, got {}'.format(local_path, expected_size, file_size))
|
||||
return False
|
||||
if file_sha256 != expected_sha256:
|
||||
warn('hash mismatch for {0}'.format(local_path))
|
||||
warn('hash mismatch for {}, expected {}, got {}'.format(local_path, expected_sha256, file_sha256))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
|
|
@ -243,17 +243,17 @@
|
|||
"version_regex": "mconf-idf version mconf-([a-z0-9.-]+)-win32",
|
||||
"versions": [
|
||||
{
|
||||
"name": "v4.6.0.0-idf-20190313",
|
||||
"name": "v4.6.0.0-idf-20190628",
|
||||
"status": "recommended",
|
||||
"win32": {
|
||||
"sha256": "051bef09c782bc31b737b047808d1b6588b0965101b77dc979af9139773c4b4f",
|
||||
"size": 826167,
|
||||
"url": "https://github.com/espressif/kconfig-frontends/releases/download/v4.6.0.0-idf-20190313/mconf-v4.6.0.0-idf-20190313-win32.zip"
|
||||
"sha256": "1b8f17f48740ab669c13bd89136e8cc92efe0cd29872f0d6c44148902a2dc40c",
|
||||
"size": 826114,
|
||||
"url": "https://github.com/espressif/kconfig-frontends/releases/download/v4.6.0.0-idf-20190628/mconf-v4.6.0.0-idf-20190628-win32.zip"
|
||||
},
|
||||
"win64": {
|
||||
"sha256": "051bef09c782bc31b737b047808d1b6588b0965101b77dc979af9139773c4b4f",
|
||||
"size": 826167,
|
||||
"url": "https://github.com/espressif/kconfig-frontends/releases/download/v4.6.0.0-idf-20190313/mconf-v4.6.0.0-idf-20190313-win32.zip"
|
||||
"sha256": "1b8f17f48740ab669c13bd89136e8cc92efe0cd29872f0d6c44148902a2dc40c",
|
||||
"size": 826114,
|
||||
"url": "https://github.com/espressif/kconfig-frontends/releases/download/v4.6.0.0-idf-20190628/mconf-v4.6.0.0-idf-20190628-win32.zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -306,6 +306,49 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "IDF wrapper tool for Windows",
|
||||
"export_paths": [
|
||||
[
|
||||
""
|
||||
]
|
||||
],
|
||||
"export_vars": {},
|
||||
"info_url": "https://github.com/espressif/esp-idf/tree/master/tools/windows/idf_exe",
|
||||
"install": "never",
|
||||
"license": "Apache-2.0",
|
||||
"name": "idf-exe",
|
||||
"platform_overrides": [
|
||||
{
|
||||
"install": "always",
|
||||
"platforms": [
|
||||
"win32",
|
||||
"win64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"version_cmd": [
|
||||
"idf.py.exe",
|
||||
"-v"
|
||||
],
|
||||
"version_regex": "([0-9.]+)",
|
||||
"versions": [
|
||||
{
|
||||
"name": "1.0",
|
||||
"status": "recommended",
|
||||
"win32": {
|
||||
"sha256": "83a83ac7a246cbae93884db7c5f2ef9a7607d602340b1cf1e64ec2a925071748",
|
||||
"size": 11289,
|
||||
"url": "https://dl.espressif.com/dl/idf-exe-v1.0.zip"
|
||||
},
|
||||
"win64": {
|
||||
"sha256": "83a83ac7a246cbae93884db7c5f2ef9a7607d602340b1cf1e64ec2a925071748",
|
||||
"size": 11289,
|
||||
"url": "https://dl.espressif.com/dl/idf-exe-v1.0.zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Ccache (compiler cache)",
|
||||
"export_paths": [
|
||||
|
|
25
tools/windows/idf_exe/CMakeLists.txt
Normal file
25
tools/windows/idf_exe/CMakeLists.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
project(idfexe)
|
||||
|
||||
set(VERSION 1.0)
|
||||
set(ARCHIVE_NAME idf-exe-v${VERSION}.zip)
|
||||
|
||||
add_executable(idf idf_main.c)
|
||||
set_target_properties(idf PROPERTIES C_STANDARD 99)
|
||||
target_link_libraries(idf "-lshlwapi")
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL Release)
|
||||
add_custom_command(TARGET idf
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_STRIP} idf.exe)
|
||||
endif()
|
||||
|
||||
add_custom_target(dist ALL DEPENDS idf)
|
||||
|
||||
add_custom_command(
|
||||
TARGET dist
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_CURRENT_BINARY_DIR}/idf.exe" "${CMAKE_CURRENT_BINARY_DIR}/idf.py.exe"
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E tar cfv ${ARCHIVE_NAME} --format=zip
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/idf.py.exe"
|
||||
)
|
34
tools/windows/idf_exe/README.md
Normal file
34
tools/windows/idf_exe/README.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
# IDF wrapper tool (idf.py.exe)
|
||||
|
||||
This tools helps invoke idf.py in Windows CMD shell.
|
||||
|
||||
In Windows CMD shell, python scripts can be executed directly (by typing their name) if `.py` extension is associated with Python. The issue with such association is that it is incompatible with virtual environments. That is, if `.py` extension is associated with a global (or user-specific) copy of `python.exe`, then the virtual environment will not be used when running the script. [Python Launcher](https://www.python.org/dev/peps/pep-0397/) solves this issue, but it is installed by default only with Python 3.6 and newer. In addition to that, the user may choose not to install Python Launcher (for example, to keep `.py` files associated with an editor).
|
||||
|
||||
Hence, `idf.py.exe` is introduced. It is a simple program which forwards the command line arguments to `idf.py`. That is,
|
||||
|
||||
```
|
||||
idf.py args...
|
||||
```
|
||||
has the same effect as:
|
||||
|
||||
```
|
||||
python.exe %IDF_PATH%\tools\idf.py args...
|
||||
```
|
||||
|
||||
`python.exe` location is determined using the default search rules, which include searching the directories in `%PATH%`. Standard I/O streams are forwarded between `idf.py.exe` and `python.exe` processes. The exit code of `idf.py.exe` is the same as the exit code of `python.exe` process.
|
||||
|
||||
For compatibility with `idf_tools.py`, a flag to obtain the version of `idf.py.exe` is provided: `idf.py.exe -v` or `idf.py.exe --version`. Note that this flag only works when `idf.py.exe` is started by the full name (with `.exe` extension). Running `idf.py -v` results in same behavior as `python idf.py -v`, that is `-v` argument is propagated to the Python script.
|
||||
|
||||
## Building
|
||||
|
||||
On Linux/Mac, install mingw-w64 toolchain (`i686-w64-mingw32-gcc`). Then build `idf.py.exe` using CMake:
|
||||
|
||||
```
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-i686-w64-mingw32.cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
On Windows, it is also possible to build using Visual Studio, with CMake support installed.
|
||||
|
111
tools/windows/idf_exe/idf_main.c
Normal file
111
tools/windows/idf_exe/idf_main.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at",
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define LINESIZE 1024
|
||||
#define VERSION "1.0"
|
||||
|
||||
static void fail(LPCSTR message, ...) __attribute__((noreturn));
|
||||
|
||||
static void fail(LPCSTR message, ...)
|
||||
{
|
||||
DWORD written;
|
||||
char msg[LINESIZE];
|
||||
va_list args = NULL;
|
||||
va_start(args, message);
|
||||
StringCchVPrintfA(msg, sizeof(msg), message, args);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), message, lstrlen(msg), &written, NULL);
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
int main(int argc, LPTSTR argv[])
|
||||
{
|
||||
/* Print the version of this wrapper tool, but only if invoked as "idf.exe".
|
||||
* "idf -v" will invoke idf.py as expected.
|
||||
*/
|
||||
|
||||
LPCTSTR cmdname = PathFindFileName(argv[0]);
|
||||
int cmdname_length = strlen(cmdname);
|
||||
|
||||
if (argc == 2 &&
|
||||
cmdname_length > 4 &&
|
||||
StrCmp(cmdname + cmdname_length - 4, TEXT(".exe")) == 0 &&
|
||||
(StrCmp(argv[1], TEXT("--version")) == 0 ||
|
||||
StrCmp(argv[1], TEXT("-v")) == 0)) {
|
||||
LPCSTR msg = VERSION "\n";
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msg, lstrlen(msg), NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPCTSTR idfpy_script_name = TEXT("idf.py");
|
||||
|
||||
/* Get IDF_PATH */
|
||||
TCHAR idf_path[LINESIZE] = {};
|
||||
if (GetEnvironmentVariable(TEXT("IDF_PATH"), idf_path, sizeof(idf_path)) == 0) {
|
||||
DWORD err = GetLastError();
|
||||
if (err == ERROR_ENVVAR_NOT_FOUND) {
|
||||
fail("IDF_PATH environment variable needs to be set to use this tool\n");
|
||||
} else {
|
||||
fail("Unknown error (%u)\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare the command line: python.exe %IDF_PATH%\\tools\idf.py <rest of the args> */
|
||||
TCHAR cmdline[LINESIZE] = {};
|
||||
StringCchCat(cmdline, sizeof(cmdline), TEXT("python.exe "));
|
||||
StringCchCat(cmdline, sizeof(cmdline), idf_path);
|
||||
StringCchCat(cmdline, sizeof(cmdline), TEXT("\\tools\\"));
|
||||
StringCchCat(cmdline, sizeof(cmdline), idfpy_script_name);
|
||||
StringCchCat(cmdline, sizeof(cmdline), TEXT(" "));
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
StringCchCat(cmdline, sizeof(cmdline), argv[i]);
|
||||
StringCchCat(cmdline, sizeof(cmdline), TEXT(" "));
|
||||
}
|
||||
|
||||
SetEnvironmentVariable(TEXT("IDF_PY_PROGRAM_NAME"), idfpy_script_name);
|
||||
|
||||
/* Reuse the standard streams of this process */
|
||||
STARTUPINFO start_info = {
|
||||
.cb = sizeof(STARTUPINFO),
|
||||
.hStdError = GetStdHandle(STD_ERROR_HANDLE),
|
||||
.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE),
|
||||
.hStdInput = GetStdHandle(STD_INPUT_HANDLE),
|
||||
.dwFlags = STARTF_USESTDHANDLES
|
||||
};
|
||||
|
||||
/* Run the child process */
|
||||
PROCESS_INFORMATION child_process;
|
||||
if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &start_info, &child_process)) {
|
||||
DWORD err = GetLastError();
|
||||
if (err == ERROR_FILE_NOT_FOUND) {
|
||||
fail("Can not find Python\n");
|
||||
} else {
|
||||
fail("Unknown error (%u)\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for it to complete */
|
||||
WaitForSingleObject(child_process.hProcess, INFINITE);
|
||||
|
||||
/* Return with the exit code of the child process */
|
||||
DWORD exitcode;
|
||||
if (!GetExitCodeProcess(child_process.hProcess, &exitcode)) {
|
||||
fail("Couldn't get the exit code (%u)\n", GetLastError());
|
||||
}
|
||||
return exitcode;
|
||||
}
|
7
tools/windows/idf_exe/toolchain-i686-w64-mingw32.cmake
Normal file
7
tools/windows/idf_exe/toolchain-i686-w64-mingw32.cmake
Normal file
|
@ -0,0 +1,7 @@
|
|||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86)
|
||||
set(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
|
||||
set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
6
tools/windows/tool_setup/.gitignore
vendored
Normal file
6
tools/windows/tool_setup/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
Output
|
||||
cmdlinerunner/build
|
||||
dist
|
||||
unzip
|
||||
keys
|
||||
idf_versions.txt
|
39
tools/windows/tool_setup/README.md
Normal file
39
tools/windows/tool_setup/README.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
# ESP-IDF Tools Installer for Windows
|
||||
|
||||
This directory contains source files required to build the tools installer for Windows.
|
||||
|
||||
The installer is built using [Inno Setup](http://www.jrsoftware.org/isinfo.php). At the time of writing, the installer can be built with Inno Setup version 6.0.2.
|
||||
|
||||
The main source file of the installer is `idf_tools_setup.iss`. PascalScript code is split into multiple `*.iss.inc` files.
|
||||
|
||||
Some functionality of the installer depends on additional programs:
|
||||
|
||||
* [Inno Download Plugin](https://bitbucket.org/mitrich_k/inno-download-plugin) — used to download additional files during the installation.
|
||||
|
||||
* [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.
|
||||
|
||||
## Steps required to build the installer
|
||||
|
||||
* Build cmdlinerunner DLL.
|
||||
- On Linux/Mac, install mingw-w64 toolchain (`i686-w64-mingw32-gcc`). Then build the DLL using CMake:
|
||||
```
|
||||
mkdir -p cmdlinerunner/build
|
||||
cd cmdlinerunner/build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-i686-w64-mingw32.cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build .
|
||||
```
|
||||
This will produce `cmdlinerunner.dll` in the build directory.
|
||||
- On Windows, it is possible to build using Visual Studio, with CMake support installed. By default, VS produces build artifacts in some hard to find directory. You can adjust this in CmakeSettings.json file generated by VS.
|
||||
|
||||
* Download 7zip.exe [("standalone console version")](https://www.7-zip.org/download.html) and put it into `unzip` directory (to get `unzip/7za.exe`).
|
||||
|
||||
* Download [idf_versions.txt](https://dl.espressif.com/dl/esp-idf/idf_versions.txt) and place it into the current directory. The installer will use it as a fallback, if it can not download idf_versions.txt at run time.
|
||||
|
||||
* Create the `dist` directory and populate it with the tools which should be bundled with the installer. At the moment the easiest way to obtain it is to use `install.sh`/`install.bat` in IDF, and then copy the contents of `$HOME/.espressif/dist` directory. If the directory is empty, the installer should still work, and the tools will be downloaded during the installation.
|
||||
|
||||
* Build the installer using Inno Setup Compiler: `ISCC.exe idf_tools_setup.iss`.
|
||||
|
||||
* Obtain the signing keys, then sign `Output/esp-idf-tools-setup-unsigned.exe`.
|
||||
|
247
tools/windows/tool_setup/choice_page.iss.inc
Normal file
247
tools/windows/tool_setup/choice_page.iss.inc
Normal file
|
@ -0,0 +1,247 @@
|
|||
var
|
||||
ChoicePagePrepare: array of TNotifyEvent;
|
||||
ChoicePageSelectionChange: array of TNotifyEvent;
|
||||
ChoicePageValidate: array of TWizardPageButtonEvent;
|
||||
ChoicePageMaxTag: Integer;
|
||||
ChoicePages: array of TInputOptionWizardPage;
|
||||
|
||||
procedure ChoicePageOnClickCheck(Sender: TObject);
|
||||
var
|
||||
ListBox: TNewCheckListBox;
|
||||
Id: Integer;
|
||||
begin
|
||||
ListBox := TNewCheckListBox(Sender);
|
||||
Id := Integer(ListBox.Tag);
|
||||
ChoicePageSelectionChange[Id](ChoicePages[Id]);
|
||||
end;
|
||||
|
||||
function ChoicePageGetInput(Page: TInputOptionWizardPage): TNewEdit;
|
||||
begin
|
||||
Result := TNewEdit(Page.FindComponent('ChoicePageInput'));
|
||||
end;
|
||||
|
||||
function ChoicePageGetLabel(Page: TInputOptionWizardPage): TNewStaticText;
|
||||
begin
|
||||
Result := TNewStaticText(Page.FindComponent('ChoicePageLabel'));
|
||||
end;
|
||||
|
||||
function ChoicePageGetButton(Page: TInputOptionWizardPage): TNewButton;
|
||||
begin
|
||||
Result := TNewButton(Page.FindComponent('ChoicePageBrowseButton'));
|
||||
end;
|
||||
|
||||
procedure ChoicePageSetEditLabel(Page: TInputOptionWizardPage; Caption: String);
|
||||
var
|
||||
InputLabel: TNewStaticText;
|
||||
begin
|
||||
InputLabel := ChoicePageGetLabel(Page);
|
||||
InputLabel.Caption := Caption;
|
||||
end;
|
||||
|
||||
function ChoicePageGetInputText(Page: TInputOptionWizardPage): String;
|
||||
begin
|
||||
Result := ChoicePageGetInput(Page).Text;
|
||||
end;
|
||||
|
||||
procedure ChoicePageSetInputText(Page: TInputOptionWizardPage; Text: String);
|
||||
begin
|
||||
ChoicePageGetInput(Page).Text := Text;
|
||||
end;
|
||||
|
||||
procedure ChoicePageSetInputEnabled(Page: TInputOptionWizardPage; Enabled: Boolean);
|
||||
begin
|
||||
ChoicePageGetLabel(Page).Enabled := Enabled;
|
||||
ChoicePageGetInput(Page).Enabled := Enabled;
|
||||
ChoicePageGetButton(Page).Enabled := Enabled;
|
||||
end;
|
||||
|
||||
|
||||
procedure ChoicePageOnBrowseButtonClick(Sender: TObject);
|
||||
var
|
||||
Button: TNewButton;
|
||||
Page: TInputOptionWizardPage;
|
||||
InputLabel: TNewStaticText;
|
||||
Input: TNewEdit;
|
||||
Dir: String;
|
||||
begin
|
||||
Button := TNewButton(Sender);
|
||||
Page := TInputOptionWizardPage(Button.Owner);
|
||||
Input := ChoicePageGetInput(Page);
|
||||
InputLabel := ChoicePageGetLabel(Page);
|
||||
Dir := Input.Text;
|
||||
if BrowseForFolder(InputLabel.Caption, Dir, True) then
|
||||
begin
|
||||
Input.Text := Dir;
|
||||
end;
|
||||
end;
|
||||
|
||||
<event('CurPageChanged')>
|
||||
procedure ChoicePageOnCurPageChanged(CurPageID: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 1 to ChoicePageMaxTag do
|
||||
begin
|
||||
if ChoicePages[i].ID = CurPageID then
|
||||
begin
|
||||
ChoicePagePrepare[i](ChoicePages[i]);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
<event('NextButtonClick')>
|
||||
function ChoicePageOnNextButtonClick(CurPageID: Integer): Boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := True;
|
||||
for i := 1 to ChoicePageMaxTag do
|
||||
begin
|
||||
if ChoicePages[i].ID = CurPageID then
|
||||
begin
|
||||
Result := ChoicePageValidate[i](ChoicePages[i]);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
<event('InitializeWizard')>
|
||||
procedure InitChoicePages();
|
||||
begin
|
||||
ChoicePages := [ ];
|
||||
ChoicePagePrepare := [ ];
|
||||
ChoicePageSelectionChange := [ ];
|
||||
ChoicePageValidate := [ ];
|
||||
end;
|
||||
|
||||
function FindLinkInText(Text: String): String;
|
||||
var
|
||||
Tmp: String;
|
||||
LinkStartPos, LinkEndPos: Integer;
|
||||
begin
|
||||
Result := '';
|
||||
Tmp := Text;
|
||||
LinkStartPos := Pos('https://', Tmp);
|
||||
if LinkStartPos = 0 then exit;
|
||||
Delete(Tmp, 1, LinkStartPos - 1);
|
||||
|
||||
{ Try to find the end of the link }
|
||||
LinkEndPos := 0
|
||||
if LinkEndPos = 0 then LinkEndPos := Pos(' ', Tmp);
|
||||
if LinkEndPos = 0 then LinkEndPos := Pos(',', Tmp);
|
||||
if LinkEndPos = 0 then LinkEndPos := Pos('.', Tmp);
|
||||
if LinkEndPos = 0 then LinkEndPos := Length(Tmp);
|
||||
Delete(Text, LinkEndPos, Length(Tmp));
|
||||
|
||||
Log('Found link in "' + Text + '": "' + Tmp + '"');
|
||||
Result := Tmp;
|
||||
end;
|
||||
|
||||
procedure OnStaticTextClick(Sender: TObject);
|
||||
var
|
||||
StaticText: TNewStaticText;
|
||||
Link: String;
|
||||
Err: Integer;
|
||||
begin
|
||||
StaticText := TNewStaticText(Sender);
|
||||
Link := FindLinkInText(StaticText.Caption);
|
||||
if Link = '' then
|
||||
exit;
|
||||
|
||||
ShellExec('open', Link, '', '', SW_SHOWNORMAL, ewNoWait, Err);
|
||||
end;
|
||||
|
||||
procedure MakeStaticTextClickable(StaticText: TNewStaticText);
|
||||
begin
|
||||
if FindLinkInText(StaticText.Caption) = '' then
|
||||
exit;
|
||||
|
||||
StaticText.OnClick := @OnStaticTextClick;
|
||||
StaticText.Cursor := crHand;
|
||||
end;
|
||||
|
||||
function ChoicePageCreate(
|
||||
const AfterID: Integer;
|
||||
const Caption, Description, SubCaption, EditCaption: String;
|
||||
HasDirectoryChooser: Boolean;
|
||||
Prepare: TNotifyEvent;
|
||||
SelectionChange: TNotifyEvent;
|
||||
Validate: TWizardPageButtonEvent): TInputOptionWizardPage;
|
||||
var
|
||||
VSpace, Y : Integer;
|
||||
ChoicePage: TInputOptionWizardPage;
|
||||
InputLabel: TNewStaticText;
|
||||
Input: TNewEdit;
|
||||
Button: TNewButton;
|
||||
|
||||
begin
|
||||
ChoicePageMaxTag := ChoicePageMaxTag + 1;
|
||||
VSpace := ScaleY(8);
|
||||
ChoicePage := CreateInputOptionPage(AfterID, Caption,
|
||||
Description, SubCaption, True, True);
|
||||
|
||||
MakeStaticTextClickable(ChoicePage.SubCaptionLabel);
|
||||
|
||||
ChoicePage.Tag := ChoicePageMaxTag;
|
||||
ChoicePage.CheckListBox.OnClickCheck := @ChoicePageOnClickCheck;
|
||||
ChoicePage.CheckListBox.Tag := ChoicePageMaxTag;
|
||||
|
||||
if HasDirectoryChooser then
|
||||
begin
|
||||
ChoicePage.CheckListBox.Anchors := [ akLeft, akTop, akRight ];
|
||||
ChoicePage.CheckListBox.Height := ChoicePage.CheckListBox.Height - ScaleY(60);
|
||||
Y := ChoicePage.CheckListBox.Top + ChoicePage.CheckListBox.Height + VSpace;
|
||||
|
||||
InputLabel := TNewStaticText.Create(ChoicePage);
|
||||
with InputLabel do
|
||||
begin
|
||||
Top := Y;
|
||||
Anchors := [akTop, akLeft, akRight];
|
||||
Caption := EditCaption;
|
||||
AutoSize := True;
|
||||
Parent := ChoicePage.Surface;
|
||||
Name := 'ChoicePageLabel';
|
||||
end;
|
||||
MakeStaticTextClickable(InputLabel);
|
||||
Y := Y + InputLabel.Height + VSpace;
|
||||
|
||||
Input := TNewEdit.Create(ChoicePage);
|
||||
with Input do
|
||||
begin
|
||||
Top := Y;
|
||||
Anchors := [akTop, akLeft, akRight];
|
||||
Parent := ChoicePage.Surface;
|
||||
Name := 'ChoicePageInput';
|
||||
Text := '';
|
||||
end;
|
||||
|
||||
Button := TNewButton.Create(ChoicePage);
|
||||
with Button do
|
||||
begin
|
||||
Anchors := [akTop, akRight];
|
||||
Parent := ChoicePage.Surface;
|
||||
Width := WizardForm.NextButton.Width;
|
||||
Height := WizardForm.NextButton.Height;
|
||||
Top := Y - (Height - Input.Height) / 2;
|
||||
Left := ChoicePage.SurfaceWidth - Button.Width;
|
||||
Name := 'ChoicePageBrowseButton';
|
||||
Caption := SetupMessage(msgButtonWizardBrowse);
|
||||
OnClick := @ChoicePageOnBrowseButtonClick;
|
||||
end;
|
||||
|
||||
Input.Width := Button.Left - ScaleX(8);
|
||||
end;
|
||||
|
||||
SetArrayLength(ChoicePages, ChoicePageMaxTag+1);
|
||||
SetArrayLength(ChoicePagePrepare, ChoicePageMaxTag+1);
|
||||
SetArrayLength(ChoicePageSelectionChange, ChoicePageMaxTag+1);
|
||||
SetArrayLength(ChoicePageValidate, ChoicePageMaxTag+1);
|
||||
|
||||
ChoicePages[ChoicePageMaxTag] := ChoicePage;
|
||||
ChoicePagePrepare[ChoicePageMaxTag] := Prepare;
|
||||
ChoicePageSelectionChange[ChoicePageMaxTag] := SelectionChange;
|
||||
ChoicePageValidate[ChoicePageMaxTag] := Validate;
|
||||
|
||||
Result := ChoicePage;
|
||||
end;
|
154
tools/windows/tool_setup/cmdline_page.iss.inc
Normal file
154
tools/windows/tool_setup/cmdline_page.iss.inc
Normal file
|
@ -0,0 +1,154 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Progress & log page for command line tools ------------------------------ }
|
||||
|
||||
var
|
||||
CmdlineInstallCancel: Boolean;
|
||||
|
||||
{ ------------------------------ Splitting strings into lines and adding them to TStrings ------------------------------ }
|
||||
|
||||
procedure StringsAddLine(Dest: TStrings; Line: String; var ReplaceLastLine: Boolean);
|
||||
begin
|
||||
if ReplaceLastLine then
|
||||
begin
|
||||
Dest.Strings[Dest.Count - 1] := Line;
|
||||
ReplaceLastLine := False;
|
||||
end else begin
|
||||
Dest.Add(Line);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure StrSplitAppendToList(Text: String; Dest: TStrings; var LastLine: String);
|
||||
var
|
||||
pCR, pLF, Len: Integer;
|
||||
Tmp: String;
|
||||
ReplaceLastLine: Boolean;
|
||||
begin
|
||||
if Length(LastLine) > 0 then
|
||||
begin
|
||||
ReplaceLastLine := True;
|
||||
Text := LastLine + Text;
|
||||
end;
|
||||
repeat
|
||||
Len := Length(Text);
|
||||
pLF := Pos(#10, Text);
|
||||
pCR := Pos(#13, Text);
|
||||
if (pLF > 0) and ((pCR = 0) or (pLF < pCR) or (pLF = pCR + 1)) then
|
||||
begin
|
||||
if pLF < pCR then
|
||||
Tmp := Copy(Text, 1, pLF - 1)
|
||||
else
|
||||
Tmp := Copy(Text, 1, pLF - 2);
|
||||
StringsAddLine(Dest, Tmp, ReplaceLastLine);
|
||||
Text := Copy(Text, pLF + 1, Len)
|
||||
end else begin
|
||||
if (pCR = Len) or (pCR = 0) then
|
||||
begin
|
||||
break;
|
||||
end;
|
||||
Text := Copy(Text, pCR + 1, Len)
|
||||
end;
|
||||
until (pLF = 0) and (pCR = 0);
|
||||
|
||||
LastLine := Text;
|
||||
if pCR = Len then
|
||||
begin
|
||||
Text := Copy(Text, 1, pCR - 1);
|
||||
end;
|
||||
if Length(LastLine) > 0 then
|
||||
begin
|
||||
StringsAddLine(Dest, Text, ReplaceLastLine);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
{ ------------------------------ The actual command line install page ------------------------------ }
|
||||
|
||||
procedure OnCmdlineInstallCancel(Sender: TObject);
|
||||
begin
|
||||
CmdlineInstallCancel := True;
|
||||
end;
|
||||
|
||||
function DoCmdlineInstall(caption, description, command: String): Boolean;
|
||||
var
|
||||
CmdlineInstallPage: TOutputProgressWizardPage;
|
||||
Res: Integer;
|
||||
Handle: Longword;
|
||||
ExitCode: Integer;
|
||||
LogTextAnsi: AnsiString;
|
||||
LogText, LeftOver: String;
|
||||
Memo: TNewMemo;
|
||||
PrevCancelButtonOnClick: TNotifyEvent;
|
||||
|
||||
begin
|
||||
CmdlineInstallPage := CreateOutputProgressPage('', '')
|
||||
CmdlineInstallPage.Caption := caption;
|
||||
CmdlineInstallPage.Description := description;
|
||||
|
||||
Memo := TNewMemo.Create(CmdlineInstallPage);
|
||||
Memo.Top := CmdlineInstallPage.ProgressBar.Top + CmdlineInstallPage.ProgressBar.Height + ScaleY(8);
|
||||
Memo.Width := CmdlineInstallPage.SurfaceWidth;
|
||||
Memo.Height := ScaleY(120);
|
||||
Memo.ScrollBars := ssVertical;
|
||||
Memo.Parent := CmdlineInstallPage.Surface;
|
||||
Memo.Lines.Clear();
|
||||
|
||||
CmdlineInstallPage.Show();
|
||||
|
||||
try
|
||||
WizardForm.CancelButton.Visible := True;
|
||||
WizardForm.CancelButton.Enabled := True;
|
||||
PrevCancelButtonOnClick := WizardForm.CancelButton.OnClick;
|
||||
WizardForm.CancelButton.OnClick := @OnCmdlineInstallCancel;
|
||||
|
||||
CmdlineInstallPage.SetProgress(0, 100);
|
||||
CmdlineInstallPage.ProgressBar.Style := npbstMarquee;
|
||||
|
||||
ExitCode := -1;
|
||||
Memo.Lines.Append('Running command: ' + command);
|
||||
Handle := ProcStart(command, ExpandConstant('{tmp}'))
|
||||
if Handle = 0 then
|
||||
begin
|
||||
Log('ProcStart failed');
|
||||
ExitCode := -2;
|
||||
end;
|
||||
while (ExitCode = -1) and not CmdlineInstallCancel do
|
||||
begin
|
||||
ExitCode := ProcGetExitCode(Handle);
|
||||
SetLength(LogTextAnsi, 4096);
|
||||
Res := ProcGetOutput(Handle, LogTextAnsi, 4096)
|
||||
if Res > 0 then
|
||||
begin
|
||||
SetLength(LogTextAnsi, Res);
|
||||
LogText := LeftOver + String(LogTextAnsi);
|
||||
StrSplitAppendToList(LogText, Memo.Lines, LeftOver);
|
||||
end;
|
||||
CmdlineInstallPage.SetProgress(0, 100);
|
||||
Sleep(10);
|
||||
end;
|
||||
ProcEnd(Handle);
|
||||
finally
|
||||
Log('Done, exit code=' + IntToStr(ExitCode));
|
||||
Log('--------');
|
||||
Log(Memo.Lines.Text);
|
||||
Log('--------');
|
||||
if CmdlineInstallCancel then
|
||||
begin
|
||||
MsgBox('Installation has been cancelled.', mbError, MB_OK);
|
||||
Result := False;
|
||||
end else if ExitCode <> 0 then
|
||||
begin
|
||||
MsgBox('Installation has failed with exit code ' + IntToStr(ExitCode), mbError, MB_OK);
|
||||
Result := False;
|
||||
end else begin
|
||||
Result := True;
|
||||
end;
|
||||
CmdlineInstallPage.Hide;
|
||||
CmdlineInstallPage.Free;
|
||||
WizardForm.CancelButton.OnClick := PrevCancelButtonOnClick;
|
||||
end;
|
||||
if not Result then
|
||||
RaiseException('Installation has failed at step: ' + caption);
|
||||
end;
|
||||
|
8
tools/windows/tool_setup/cmdlinerunner/CMakeLists.txt
Normal file
8
tools/windows/tool_setup/cmdlinerunner/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
project(cmdlinerunner)
|
||||
set(CMAKE_EXE_LINKER_FLAGS " -static")
|
||||
add_library(cmdlinerunner SHARED cmdlinerunner.c)
|
||||
target_compile_definitions(cmdlinerunner PUBLIC UNICODE _UNICODE)
|
||||
set_target_properties(cmdlinerunner PROPERTIES PREFIX "")
|
||||
set_target_properties(cmdlinerunner PROPERTIES C_STANDARD 99)
|
||||
target_link_libraries(cmdlinerunner "-static-libgcc")
|
194
tools/windows/tool_setup/cmdlinerunner/cmdlinerunner.c
Normal file
194
tools/windows/tool_setup/cmdlinerunner/cmdlinerunner.c
Normal file
|
@ -0,0 +1,194 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at",
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
#define CMDLINERUNNER_EXPORTS
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <strsafe.h>
|
||||
#include "cmdlinerunner.h"
|
||||
|
||||
#define LINESIZE 1024
|
||||
|
||||
#ifdef WITH_DEBUG
|
||||
#include <stdio.h>
|
||||
#define DEBUGV(...) do { fprintf(stderr, __VA_ARG__); } while(0)
|
||||
#else
|
||||
#define DEBUGV(...)
|
||||
#endif
|
||||
|
||||
struct proc_instance_s {
|
||||
PROCESS_INFORMATION child_process;
|
||||
HANDLE pipe_server_handle;
|
||||
HANDLE pipe_client_handle;
|
||||
};
|
||||
|
||||
#ifdef WITH_DEBUG
|
||||
static void print_last_error()
|
||||
{
|
||||
DWORD dw;
|
||||
TCHAR errmsg[LINESIZE];
|
||||
dw = GetLastError();
|
||||
|
||||
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
errmsg, sizeof(errmsg) - 1, NULL );
|
||||
DEBUGV("error %d: %s\n", dw, errmsg);
|
||||
}
|
||||
#define PRINT_LAST_ERROR() print_last_error()
|
||||
#else
|
||||
#define PRINT_LAST_ERROR()
|
||||
#endif
|
||||
|
||||
static proc_instance_t *proc_instance_allocate()
|
||||
{
|
||||
return (proc_instance_t*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(proc_instance_t));
|
||||
}
|
||||
|
||||
static void proc_instance_free(proc_instance_t *instance)
|
||||
{
|
||||
if (instance->pipe_server_handle) {
|
||||
CloseHandle(instance->pipe_server_handle);
|
||||
}
|
||||
if (instance->pipe_client_handle) {
|
||||
CloseHandle(instance->pipe_client_handle);
|
||||
}
|
||||
if (instance->child_process.hProcess) {
|
||||
TerminateProcess(instance->child_process.hProcess, 1);
|
||||
CloseHandle(instance->child_process.hProcess);
|
||||
CloseHandle(instance->child_process.hThread);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, instance);
|
||||
}
|
||||
|
||||
void proc_end(proc_instance_t *inst)
|
||||
{
|
||||
if (inst == NULL) {
|
||||
return;
|
||||
}
|
||||
proc_instance_free(inst);
|
||||
}
|
||||
|
||||
CMDLINERUNNER_API proc_instance_t * proc_start(LPCTSTR cmdline, LPCTSTR workdir)
|
||||
{
|
||||
proc_instance_t *inst = proc_instance_allocate();
|
||||
if (inst == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SECURITY_ATTRIBUTES sec_attr = {
|
||||
.nLength = sizeof(SECURITY_ATTRIBUTES),
|
||||
.bInheritHandle = TRUE,
|
||||
.lpSecurityDescriptor = NULL
|
||||
};
|
||||
|
||||
LPCTSTR pipename = TEXT("\\\\.\\pipe\\cmdlinerunner_pipe");
|
||||
|
||||
inst->pipe_server_handle = CreateNamedPipe(pipename, PIPE_ACCESS_DUPLEX,
|
||||
PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024 * 16, 1024 * 16,
|
||||
NMPWAIT_WAIT_FOREVER, &sec_attr);
|
||||
if (inst->pipe_server_handle == INVALID_HANDLE_VALUE) {
|
||||
DEBUGV("inst->pipe_server_handle == INVALID_HANDLE_VALUE\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
inst->pipe_client_handle = CreateFile(pipename, GENERIC_WRITE | GENERIC_READ,
|
||||
0, &sec_attr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (inst->pipe_client_handle == INVALID_HANDLE_VALUE) {
|
||||
DEBUGV("inst->pipe_client_handle == INVALID_HANDLE_VALUE\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
DWORD new_mode = PIPE_READMODE_BYTE | PIPE_NOWAIT;
|
||||
if (!SetNamedPipeHandleState(inst->pipe_server_handle, &new_mode, NULL,
|
||||
NULL)) {
|
||||
DEBUGV("SetNamedPipeHandleState failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!SetHandleInformation(inst->pipe_server_handle, HANDLE_FLAG_INHERIT, 0)) {
|
||||
DEBUGV("SetHandleInformation failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!SetHandleInformation(inst->pipe_client_handle, HANDLE_FLAG_INHERIT,
|
||||
HANDLE_FLAG_INHERIT)) {
|
||||
DEBUGV("SetHandleInformation failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
STARTUPINFO siStartInfo = {
|
||||
.cb = sizeof(STARTUPINFO),
|
||||
.hStdError = inst->pipe_client_handle,
|
||||
.hStdOutput = inst->pipe_client_handle,
|
||||
.hStdInput = inst->pipe_client_handle,
|
||||
.dwFlags = STARTF_USESTDHANDLES
|
||||
};
|
||||
|
||||
size_t workdir_len = 0;
|
||||
StringCbLength(workdir, STRSAFE_MAX_CCH * sizeof(TCHAR), &workdir_len);
|
||||
if (workdir_len == 0) {
|
||||
workdir = NULL;
|
||||
}
|
||||
|
||||
TCHAR cmdline_tmp[LINESIZE];
|
||||
StringCbCopy(cmdline_tmp, sizeof(cmdline_tmp), cmdline);
|
||||
if (!CreateProcess(NULL, cmdline_tmp,
|
||||
NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, workdir, &siStartInfo,
|
||||
&inst->child_process)) {
|
||||
DEBUGV("CreateProcess failed\n");
|
||||
goto error;
|
||||
}
|
||||
return inst;
|
||||
|
||||
error:
|
||||
PRINT_LAST_ERROR();
|
||||
proc_instance_free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int proc_get_exit_code(proc_instance_t *inst)
|
||||
{
|
||||
DWORD result;
|
||||
if (!GetExitCodeProcess(inst->child_process.hProcess, &result)) {
|
||||
return -2;
|
||||
}
|
||||
if (result == STILL_ACTIVE) {
|
||||
return -1;
|
||||
}
|
||||
return (int) result;
|
||||
}
|
||||
|
||||
DWORD proc_get_output(proc_instance_t *inst, LPSTR dest, DWORD sz)
|
||||
{
|
||||
DWORD read_bytes;
|
||||
BOOL res = ReadFile(inst->pipe_server_handle, dest,
|
||||
sz - 1, &read_bytes, NULL);
|
||||
if (!res) {
|
||||
if (GetLastError() == ERROR_NO_DATA) {
|
||||
return 0;
|
||||
} else {
|
||||
PRINT_LAST_ERROR();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
dest[read_bytes] = 0;
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
32
tools/windows/tool_setup/cmdlinerunner/cmdlinerunner.h
Normal file
32
tools/windows/tool_setup/cmdlinerunner/cmdlinerunner.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at",
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
struct proc_instance_s;
|
||||
typedef struct proc_instance_s proc_instance_t;
|
||||
|
||||
#ifdef CMDLINERUNNER_EXPORTS
|
||||
#define CMDLINERUNNER_API __declspec(dllexport)
|
||||
#else
|
||||
#define CMDLINERUNNER_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
CMDLINERUNNER_API proc_instance_t * proc_start(LPCTSTR cmdline, LPCTSTR workdir);
|
||||
CMDLINERUNNER_API int proc_get_exit_code(proc_instance_t *inst);
|
||||
CMDLINERUNNER_API DWORD proc_get_output(proc_instance_t *inst, LPSTR dest, DWORD sz);
|
||||
CMDLINERUNNER_API void proc_end(proc_instance_t *inst);
|
||||
CMDLINERUNNER_API BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved );
|
|
@ -0,0 +1,7 @@
|
|||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86)
|
||||
set(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
|
||||
set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
98
tools/windows/tool_setup/git_find_installed.iss.inc
Normal file
98
tools/windows/tool_setup/git_find_installed.iss.inc
Normal file
|
@ -0,0 +1,98 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Find installed copies of Git ------------------------------ }
|
||||
|
||||
var
|
||||
InstalledGitVersions: TStringList;
|
||||
InstalledGitDisplayNames: TStringList;
|
||||
InstalledGitExecutables: TStringList;
|
||||
|
||||
|
||||
procedure GitVersionAdd(Version, DisplayName, Executable: String);
|
||||
begin
|
||||
Log('Adding Git version=' + Version + ' name='+DisplayName+' executable='+Executable);
|
||||
InstalledGitVersions.Append(Version);
|
||||
InstalledGitDisplayNames.Append(DisplayName);
|
||||
InstalledGitExecutables.Append(Executable);
|
||||
end;
|
||||
|
||||
function GetVersionOfGitExe(Path: String; var Version: String; var ErrStr: String): Boolean;
|
||||
var
|
||||
VersionOutputFile: String;
|
||||
Args: String;
|
||||
GitVersionAnsi: AnsiString;
|
||||
GitVersion: String;
|
||||
GitVersionPrefix: String;
|
||||
Err: Integer;
|
||||
begin
|
||||
VersionOutputFile := ExpandConstant('{tmp}\gitver.txt');
|
||||
|
||||
DeleteFile(VersionOutputFile);
|
||||
Args := '/C "' + Path + '" --version >gitver.txt';
|
||||
Log('Running ' + Args);
|
||||
if not ShellExec('', 'cmd.exe', Args,
|
||||
ExpandConstant('{tmp}'), SW_HIDE, ewWaitUntilTerminated, Err) then
|
||||
begin
|
||||
ErrStr := 'Failed to get git version, error=' + IntToStr(err);
|
||||
Log(ErrStr);
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
|
||||
LoadStringFromFile(VersionOutputFile, GitVersionAnsi);
|
||||
GitVersion := Trim(String(GitVersionAnsi));
|
||||
GitVersionPrefix := 'git version ';
|
||||
if Pos(GitVersionPrefix, GitVersion) <> 1 then
|
||||
begin
|
||||
ErrStr := 'Unexpected git version format: ' + GitVersion;
|
||||
Log(ErrStr);
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
|
||||
Delete(GitVersion, 1, Length(GitVersionPrefix));
|
||||
Version := GitVersion;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure FindGitInPath();
|
||||
var
|
||||
Args: String;
|
||||
GitListFile: String;
|
||||
GitPaths: TArrayOfString;
|
||||
GitVersion: String;
|
||||
ErrStr: String;
|
||||
Err: Integer;
|
||||
i: Integer;
|
||||
begin
|
||||
GitListFile := ExpandConstant('{tmp}\gitlist.txt');
|
||||
Args := '/C where git.exe >"' + GitListFile + '"';
|
||||
if not ShellExec('', 'cmd.exe', Args,
|
||||
'', SW_HIDE, ewWaitUntilTerminated, Err) then
|
||||
begin
|
||||
Log('Failed to find git using "where", error='+IntToStr(Err));
|
||||
exit;
|
||||
end;
|
||||
|
||||
LoadStringsFromFile(GitListFile, GitPaths);
|
||||
|
||||
for i:= 0 to GetArrayLength(GitPaths) - 1 do
|
||||
begin
|
||||
Log('Git path: ' + GitPaths[i]);
|
||||
if not GetVersionOfGitExe(GitPaths[i], GitVersion, ErrStr) then
|
||||
continue;
|
||||
|
||||
Log('Git version: ' + GitVersion);
|
||||
GitVersionAdd(GitVersion, GitVersion, GitPaths[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure FindInstalledGitVersions();
|
||||
begin
|
||||
InstalledGitVersions := TStringList.Create();
|
||||
InstalledGitDisplayNames := TStringList.Create();
|
||||
InstalledGitExecutables := TStringList.Create();
|
||||
|
||||
FindGitInPath();
|
||||
end;
|
194
tools/windows/tool_setup/git_page.iss.inc
Normal file
194
tools/windows/tool_setup/git_page.iss.inc
Normal file
|
@ -0,0 +1,194 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Page to select Git ------------------------------ }
|
||||
|
||||
#include "git_find_installed.iss.inc"
|
||||
|
||||
var
|
||||
GitPage: TInputOptionWizardPage;
|
||||
GitPath, GitExecutablePath, GitVersion: String;
|
||||
GitUseExisting: Boolean;
|
||||
GitSelectionInstallIndex: Integer;
|
||||
GitSelectionCustomPathIndex: Integer;
|
||||
|
||||
function GetGitPath(Unused: String): String;
|
||||
begin
|
||||
Result := GitPath;
|
||||
end;
|
||||
|
||||
function GitInstallRequired(): Boolean;
|
||||
begin
|
||||
Result := not GitUseExisting;
|
||||
end;
|
||||
|
||||
function GitVersionSupported(Version: String): Boolean;
|
||||
var
|
||||
Major, Minor: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
if not VersionExtractMajorMinor(Version, Major, Minor) then
|
||||
begin
|
||||
Log('GitVersionSupported: Could not parse version=' + Version);
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ Need at least git 2.12 for 'git clone --reference' to work with submodules }
|
||||
if (Major = 2) and (Minor >= 12) then Result := True;
|
||||
if (Major > 2) then Result := True;
|
||||
end;
|
||||
|
||||
procedure GitCustomPathUpdateEnabled();
|
||||
var
|
||||
Enable: Boolean;
|
||||
begin
|
||||
if GitPage.SelectedValueIndex = GitSelectionCustomPathIndex then
|
||||
Enable := True;
|
||||
|
||||
ChoicePageSetInputEnabled(GitPage, Enable);
|
||||
end;
|
||||
|
||||
procedure OnGitPagePrepare(Sender: TObject);
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
FullName: String;
|
||||
i, Index, FirstEnabledIndex: Integer;
|
||||
OfferToInstall: Boolean;
|
||||
VersionToInstall: String;
|
||||
VersionSupported: Boolean;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnGitPagePrepare');
|
||||
if Page.CheckListBox.Items.Count > 0 then
|
||||
exit;
|
||||
|
||||
FindInstalledGitVersions();
|
||||
|
||||
VersionToInstall := '{#GitVersion}';
|
||||
OfferToInstall := True;
|
||||
FirstEnabledIndex := -1;
|
||||
|
||||
for i := 0 to InstalledGitVersions.Count - 1 do
|
||||
begin
|
||||
VersionSupported := GitVersionSupported(InstalledGitVersions[i]);
|
||||
FullName := InstalledGitDisplayNames.Strings[i];
|
||||
if not VersionSupported then
|
||||
begin
|
||||
FullName := FullName + ' (unsupported)';
|
||||
end;
|
||||
FullName := FullName + #13#10 + InstalledGitExecutables.Strings[i];
|
||||
Index := Page.Add(FullName);
|
||||
if not VersionSupported then
|
||||
begin
|
||||
Page.CheckListBox.ItemEnabled[Index] := False;
|
||||
end else begin
|
||||
if FirstEnabledIndex < 0 then FirstEnabledIndex := Index;
|
||||
end;
|
||||
if InstalledGitVersions[i] = VersionToInstall then
|
||||
begin
|
||||
OfferToInstall := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
if OfferToInstall then
|
||||
begin
|
||||
Index := Page.Add('Install Git ' + VersionToInstall);
|
||||
if FirstEnabledIndex < 0 then FirstEnabledIndex := Index;
|
||||
GitSelectionInstallIndex := Index;
|
||||
end;
|
||||
|
||||
Index := Page.Add('Custom git.exe location');
|
||||
if FirstEnabledIndex < 0 then FirstEnabledIndex := Index;
|
||||
GitSelectionCustomPathIndex := Index;
|
||||
|
||||
Page.SelectedValueIndex := FirstEnabledIndex;
|
||||
GitCustomPathUpdateEnabled();
|
||||
end;
|
||||
|
||||
procedure OnGitSelectionChange(Sender: TObject);
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnGitSelectionChange index=' + IntToStr(Page.SelectedValueIndex));
|
||||
GitCustomPathUpdateEnabled();
|
||||
end;
|
||||
|
||||
function OnGitPageValidate(Sender: TWizardPage): Boolean;
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
Version, ErrStr: String;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnGitPageValidate index=' + IntToStr(Page.SelectedValueIndex));
|
||||
if Page.SelectedValueIndex = GitSelectionInstallIndex then
|
||||
begin
|
||||
GitUseExisting := False;
|
||||
GitExecutablePath := '';
|
||||
GitPath := '';
|
||||
GitVersion := '{#GitVersion}';
|
||||
Result := True;
|
||||
end else if Page.SelectedValueIndex = GitSelectionCustomPathIndex then
|
||||
begin
|
||||
GitPath := ChoicePageGetInputText(Page);
|
||||
GitExecutablePath := GitPath + '\git.exe';
|
||||
if not FileExists(GitExecutablePath) then
|
||||
begin
|
||||
MsgBox('Can not find git.exe in ' + GitPath, mbError, MB_OK);
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if not GetVersionOfGitExe(GitExecutablePath, Version, ErrStr) then
|
||||
begin
|
||||
MsgBox('Can not determine version of git.exe.' + #13#10
|
||||
+ 'Please check that this copy of git works from cmd.exe.', mbError, MB_OK);
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
Log('Version of ' + GitExecutablePath + ' is ' + Version);
|
||||
if not GitVersionSupported(Version) then
|
||||
begin
|
||||
MsgBox('Selected git version (' + Version + ') is not supported.', mbError, MB_OK);
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
Log('Version of git is supported');
|
||||
GitUseExisting := True;
|
||||
GitVersion := Version;
|
||||
end else begin
|
||||
GitUseExisting := True;
|
||||
GitExecutablePath := InstalledGitExecutables[Page.SelectedValueIndex];
|
||||
GitPath := ExtractFilePath(GitExecutablePath);
|
||||
GitVersion := InstalledGitVersions[Page.SelectedValueIndex];
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GitExecutablePathUpdateAfterInstall();
|
||||
var
|
||||
GitInstallPath: String;
|
||||
begin
|
||||
GitInstallPath := GetInstallPath('SOFTWARE\GitForWindows', 'InstallPath');
|
||||
if GitInstallPath = '' then
|
||||
begin
|
||||
Log('Failed to find Git install path');
|
||||
exit;
|
||||
end;
|
||||
GitPath := GitInstallPath + '\cmd';
|
||||
GitExecutablePath := GitPath + '\git.exe';
|
||||
end;
|
||||
|
||||
<event('InitializeWizard')>
|
||||
procedure CreateGitPage();
|
||||
begin
|
||||
GitPage := ChoicePageCreate(
|
||||
wpLicense,
|
||||
'Git choice', 'Please choose Git version',
|
||||
'Available Git versions',
|
||||
'Enter custom location of git.exe',
|
||||
True,
|
||||
@OnGitPagePrepare,
|
||||
@OnGitSelectionChange,
|
||||
@OnGitPageValidate);
|
||||
end;
|
117
tools/windows/tool_setup/idf_cmd_init.bat
Normal file
117
tools/windows/tool_setup/idf_cmd_init.bat
Normal file
|
@ -0,0 +1,117 @@
|
|||
@echo off
|
||||
|
||||
:: This script is called from a shortcut (cmd.exe /k export_fallback.bat), with
|
||||
:: the working directory set to an ESP-IDF directory.
|
||||
:: Its purpose is to support using the "IDF Tools Directory" method of
|
||||
:: installation for ESP-IDF versions older than IDF v4.0.
|
||||
:: It does the same thing as "export.bat" in IDF v4.0.
|
||||
|
||||
set IDF_PATH=%CD%
|
||||
if not exist "%IDF_PATH%\tools\idf.py" (
|
||||
echo This script must be invoked from ESP-IDF directory.
|
||||
goto :end
|
||||
)
|
||||
|
||||
if "%~2"=="" (
|
||||
echo Usage: idf_cmd_init.bat ^<Python directory^> ^<Git directory^>
|
||||
echo This script must be invoked from ESP-IDF directory.
|
||||
goto :end
|
||||
)
|
||||
|
||||
set IDF_PYTHON_DIR=%1
|
||||
set IDF_GIT_DIR=%2
|
||||
|
||||
:: Strip quoutes
|
||||
set "IDF_PYTHON_DIR=%IDF_PYTHON_DIR:"=%"
|
||||
set "IDF_GIT_DIR=%IDF_GIT_DIR:"=%"
|
||||
|
||||
:: Clear PYTHONPATH as it may contain libraries of other Python versions
|
||||
if not "%PYTHONPATH%"=="" (
|
||||
echo Clearing PYTHONPATH, was set to %PYTHONPATH%
|
||||
set PYTHONPATH=
|
||||
)
|
||||
|
||||
:: Add Python and Git paths to PATH
|
||||
set "PATH=%IDF_PYTHON_DIR%;%IDF_GIT_DIR%;%PATH%"
|
||||
echo Using Python in %IDF_PYTHON_DIR%
|
||||
python.exe --version
|
||||
echo Using Git in %IDF_GIT_DIR%
|
||||
git.exe --version
|
||||
|
||||
:: Check if this is a recent enough copy of ESP-IDF.
|
||||
:: If so, use export.bat provided there.
|
||||
:: Note: no "call", will not return into this batch file.
|
||||
if exist "%IDF_PATH%\export.bat" %IDF_PATH%\export.bat
|
||||
|
||||
echo IDF version does not include export.bat. Using the fallback version.
|
||||
|
||||
if exist "%IDF_PATH%\tools\tools.json" (
|
||||
set "IDF_TOOLS_JSON_PATH=%IDF_PATH%\tools\tools.json"
|
||||
) else (
|
||||
echo IDF version does not include tools\tools.json. Using the fallback version.
|
||||
set "IDF_TOOLS_JSON_PATH=%~dp0%tools_fallback.json"
|
||||
)
|
||||
|
||||
if exist "%IDF_PATH%\tools\idf_tools.py" (
|
||||
set "IDF_TOOLS_PY_PATH=%IDF_PATH%\tools\idf_tools.py"
|
||||
) else (
|
||||
echo IDF version does not include tools\idf_tools.py. Using the fallback version.
|
||||
set "IDF_TOOLS_PY_PATH=%~dp0%idf_tools_fallback.py"
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Setting IDF_PATH: %IDF_PATH%
|
||||
echo.
|
||||
|
||||
set "OLD_PATH=%PATH%"
|
||||
echo Adding ESP-IDF tools to PATH...
|
||||
:: Export tool paths and environment variables.
|
||||
:: It is possible to do this without a temporary file (running idf_tools.py from for /r command),
|
||||
:: but that way it is impossible to get the exit code of idf_tools.py.
|
||||
set "IDF_TOOLS_EXPORTS_FILE=%TEMP%\idf_export_vars.tmp"
|
||||
python.exe %IDF_TOOLS_PY_PATH% --tools-json %IDF_TOOLS_JSON_PATH% export --format key-value >"%IDF_TOOLS_EXPORTS_FILE%"
|
||||
if %errorlevel% neq 0 goto :end
|
||||
|
||||
for /f "usebackq tokens=1,2 eol=# delims==" %%a in ("%IDF_TOOLS_EXPORTS_FILE%") do (
|
||||
call set "%%a=%%b"
|
||||
)
|
||||
|
||||
:: This removes OLD_PATH substring from PATH, leaving only the paths which have been added,
|
||||
:: and prints semicolon-delimited components of the path on separate lines
|
||||
call set PATH_ADDITIONS=%%PATH:%OLD_PATH%=%%
|
||||
if "%PATH_ADDITIONS%"=="" call :print_nothing_added
|
||||
if not "%PATH_ADDITIONS%"=="" echo %PATH_ADDITIONS:;=&echo. %
|
||||
|
||||
echo Checking if Python packages are up to date...
|
||||
python.exe %IDF_PATH%\tools\check_python_dependencies.py
|
||||
if %errorlevel% neq 0 goto :end
|
||||
|
||||
echo.
|
||||
echo Done! You can now compile ESP-IDF projects.
|
||||
echo Go to the project directory and run:
|
||||
echo.
|
||||
echo idf.py build
|
||||
echo.
|
||||
|
||||
goto :end
|
||||
|
||||
:print_nothing_added
|
||||
echo No directories added to PATH:
|
||||
echo.
|
||||
echo %PATH%
|
||||
echo.
|
||||
goto :eof
|
||||
|
||||
:end
|
||||
|
||||
:: Clean up
|
||||
if not "%IDF_TOOLS_EXPORTS_FILE%"=="" (
|
||||
del "%IDF_TOOLS_EXPORTS_FILE%" 1>nul 2>nul
|
||||
)
|
||||
set IDF_TOOLS_EXPORTS_FILE=
|
||||
set IDF_PYTHON_DIR=
|
||||
set IDF_GIT_DIR=
|
||||
set IDF_TOOLS_PY_PATH=
|
||||
set IDF_TOOLS_JSON_PATH=
|
||||
set OLD_PATH=
|
||||
set PATH_ADDITIONS=
|
142
tools/windows/tool_setup/idf_download_page.iss.inc
Normal file
142
tools/windows/tool_setup/idf_download_page.iss.inc
Normal file
|
@ -0,0 +1,142 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Page to select the version of ESP-IDF to download ------------------------------ }
|
||||
|
||||
var
|
||||
IDFDownloadPage: TInputOptionWizardPage;
|
||||
IDFDownloadAvailableVersions: TArrayOfString;
|
||||
IDFDownloadPath, IDFDownloadVersion: String;
|
||||
|
||||
function GetSuggestedIDFDirectory(): String;
|
||||
var
|
||||
BaseName: String;
|
||||
RepeatIndex: Integer;
|
||||
begin
|
||||
{ Start with Desktop\esp-idf name and if it already exists,
|
||||
keep trying with Desktop\esp-idf-N for N=2 and above. }
|
||||
BaseName := ExpandConstant('{userdesktop}\esp-idf');
|
||||
Result := BaseName;
|
||||
RepeatIndex := 1;
|
||||
while DirExists(Result) do
|
||||
begin
|
||||
RepeatIndex := RepeatIndex + 1;
|
||||
Result := BaseName + '-' + IntToStr(RepeatIndex);
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetIDFVersionDescription(Version: String): String;
|
||||
begin
|
||||
if WildCardMatch(Version, 'v*-beta*') then
|
||||
Result := 'beta version'
|
||||
else if WildCardMatch(Version, 'v*-rc*') then
|
||||
Result := 'pre-release version'
|
||||
else if WildCardMatch(Version, 'v*') then
|
||||
Result := 'release version'
|
||||
else if WildCardMatch(Version, 'release/v*') then
|
||||
Result := 'release branch'
|
||||
else if WildCardMatch(Version, 'master') then
|
||||
Result := 'development branch'
|
||||
else
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
procedure DownloadIDFVersionsList();
|
||||
var
|
||||
Url: String;
|
||||
VersionFile: String;
|
||||
begin
|
||||
Url := '{#IDFVersionsURL}';
|
||||
VersionFile := ExpandConstant('{tmp}\idf_versions.txt');
|
||||
if idpDownloadFile(Url, VersionFile) then
|
||||
begin
|
||||
Log('Downloaded ' + Url + ' to ' + VersionFile);
|
||||
end else begin
|
||||
Log('Download of ' + Url + ' failed, using a fallback versions list');
|
||||
ExtractTemporaryFile('idf_versions.txt');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure OnIDFDownloadPagePrepare(Sender: TObject);
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
VersionFile: String;
|
||||
i: Integer;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnIDFDownloadPagePrepare');
|
||||
if Page.CheckListBox.Items.Count > 0 then
|
||||
exit;
|
||||
|
||||
DownloadIDFVersionsList();
|
||||
|
||||
VersionFile := ExpandConstant('{tmp}\idf_versions.txt');
|
||||
if not LoadStringsFromFile(VersionFile, IDFDownloadAvailableVersions) then
|
||||
begin
|
||||
Log('Failed to load versions from ' + VersionFile);
|
||||
exit;
|
||||
end;
|
||||
|
||||
Log('Versions count: ' + IntToStr(GetArrayLength(IDFDownloadAvailableVersions)))
|
||||
for i := 0 to GetArrayLength(IDFDownloadAvailableVersions) - 1 do
|
||||
begin
|
||||
Log('Version ' + IntToStr(i) + ': ' + IDFDownloadAvailableVersions[i]);
|
||||
Page.Add(IDFDownloadAvailableVersions[i] + ' ('
|
||||
+ GetIDFVersionDescription(IDFDownloadAvailableVersions[i]) + ')');
|
||||
end;
|
||||
Page.SelectedValueIndex := 0;
|
||||
|
||||
ChoicePageSetInputText(Page, GetSuggestedIDFDirectory());
|
||||
end;
|
||||
|
||||
procedure OnIDFDownloadSelectionChange(Sender: TObject);
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnIDFDownloadSelectionChange index=' + IntToStr(Page.SelectedValueIndex));
|
||||
end;
|
||||
|
||||
function OnIDFDownloadPageValidate(Sender: TWizardPage): Boolean;
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
IDFPath: String;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnIDFDownloadPageValidate index=' + IntToStr(Page.SelectedValueIndex));
|
||||
|
||||
IDFPath := ChoicePageGetInputText(Page);
|
||||
if DirExists(IDFPath) and not DirIsEmpty(IDFPath) then
|
||||
begin
|
||||
MsgBox('Directory already exists and is not empty:' + #13#10 +
|
||||
IDFPath + #13#10 + 'Please choose a different directory.', mbError, MB_OK);
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
|
||||
IDFDownloadPath := IDFPath;
|
||||
IDFDownloadVersion := IDFDownloadAvailableVersions[Page.SelectedValueIndex];
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
<event('ShouldSkipPage')>
|
||||
function ShouldSkipIDFDownloadPage(PageID: Integer): Boolean;
|
||||
begin
|
||||
if (PageID = IDFDownloadPage.ID) and not IDFDownloadRequired() then
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
<event('InitializeWizard')>
|
||||
procedure CreateIDFDownloadPage();
|
||||
begin
|
||||
IDFDownloadPage := ChoicePageCreate(
|
||||
IDFPage.ID,
|
||||
'Download ESP-IDF', 'Please choose ESP-IDF version to download',
|
||||
'For more information about ESP-IDF versions, see' + #13#10 +
|
||||
'https://docs.espressif.com/projects/esp-idf/en/latest/versions.html',
|
||||
'Choose a directory to download ESP-IDF to',
|
||||
True,
|
||||
@OnIDFDownloadPagePrepare,
|
||||
@OnIDFDownloadSelectionChange,
|
||||
@OnIDFDownloadPageValidate);
|
||||
end;
|
111
tools/windows/tool_setup/idf_page.iss.inc
Normal file
111
tools/windows/tool_setup/idf_page.iss.inc
Normal file
|
@ -0,0 +1,111 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Page to select whether to download ESP-IDF, or use an existing copy ------------------------------ }
|
||||
|
||||
var
|
||||
IDFPage: TInputOptionWizardPage;
|
||||
IDFSelectionDownloadIndex: Integer;
|
||||
IDFSelectionCustomPathIndex: Integer;
|
||||
IDFUseExisting: Boolean;
|
||||
IDFExistingPath: String;
|
||||
|
||||
function IDFDownloadRequired(): Boolean;
|
||||
begin
|
||||
Result := not IDFUseExisting;
|
||||
end;
|
||||
|
||||
procedure IDFPageUpdateInput();
|
||||
var
|
||||
Enable: Boolean;
|
||||
begin
|
||||
if IDFPage.SelectedValueIndex = IDFSelectionCustomPathIndex then
|
||||
Enable := True;
|
||||
|
||||
ChoicePageSetInputEnabled(IDFPage, Enable);
|
||||
end;
|
||||
|
||||
procedure OnIDFPagePrepare(Sender: TObject);
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnIDFPagePrepare');
|
||||
if Page.CheckListBox.Items.Count > 0 then
|
||||
exit;
|
||||
|
||||
IDFSelectionDownloadIndex := Page.Add('Download ESP-IDF')
|
||||
IDFSelectionCustomPathIndex := Page.Add('Use an existing ESP-IDF directory');
|
||||
|
||||
Page.SelectedValueIndex := 0;
|
||||
IDFPageUpdateInput();
|
||||
end;
|
||||
|
||||
procedure OnIDFSelectionChange(Sender: TObject);
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnIDFSelectionChange index=' + IntToStr(Page.SelectedValueIndex));
|
||||
IDFPageUpdateInput();
|
||||
end;
|
||||
|
||||
function OnIDFPageValidate(Sender: TWizardPage): Boolean;
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
NotSupportedMsg, IDFPath, IDFPyPath, RequirementsPath: String;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnIDFPageValidate index=' + IntToStr(Page.SelectedValueIndex));
|
||||
|
||||
if Page.SelectedValueIndex = IDFSelectionDownloadIndex then
|
||||
begin
|
||||
IDFUseExisting := False;
|
||||
Result := True;
|
||||
end else begin
|
||||
IDFUseExisting := True;
|
||||
Result := False;
|
||||
NotSupportedMsg := 'The selected version of ESP-IDF is not supported:' + #13#10;
|
||||
IDFPath := ChoicePageGetInputText(Page);
|
||||
|
||||
if not DirExists(IDFPath) then
|
||||
begin
|
||||
MsgBox('Directory doesn''t exist: ' + IDFPath + #13#10 +
|
||||
'Please choose an existing ESP-IDF directory', mbError, MB_OK);
|
||||
exit;
|
||||
end;
|
||||
|
||||
IDFPyPath := IDFPath + '\tools\idf.py';
|
||||
if not FileExists(IDFPyPath) then
|
||||
begin
|
||||
MsgBox(NotSupportedMsg +
|
||||
'Can not find idf.py in ' + IDFPath + '\tools', mbError, MB_OK);
|
||||
exit;
|
||||
end;
|
||||
|
||||
RequirementsPath := IDFPath + '\requirements.txt';
|
||||
if not FileExists(RequirementsPath) then
|
||||
begin
|
||||
MsgBox(NotSupportedMsg +
|
||||
'Can not find requirements.txt in ' + IDFPath, mbError, MB_OK);
|
||||
exit;
|
||||
end;
|
||||
|
||||
IDFExistingPath := IDFPath;
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
<event('InitializeWizard')>
|
||||
procedure CreateIDFPage();
|
||||
begin
|
||||
IDFPage := ChoicePageCreate(
|
||||
wpLicense,
|
||||
'Download or use ESP-IDF', 'Please choose ESP-IDF version to download, or use an existing ESP-IDF copy',
|
||||
'Available ESP-IDF versions',
|
||||
'Choose existing ESP-IDF directory',
|
||||
True,
|
||||
@OnIDFPagePrepare,
|
||||
@OnIDFSelectionChange,
|
||||
@OnIDFPageValidate);
|
||||
end;
|
255
tools/windows/tool_setup/idf_setup.iss.inc
Normal file
255
tools/windows/tool_setup/idf_setup.iss.inc
Normal file
|
@ -0,0 +1,255 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Downloading ESP-IDF ------------------------------ }
|
||||
|
||||
var
|
||||
IDFZIPFileVersion, IDFZIPFileName: String;
|
||||
|
||||
function GetIDFPath(Unused: String): String;
|
||||
begin
|
||||
if IDFUseExisting then
|
||||
Result := IDFExistingPath
|
||||
else
|
||||
Result := IDFDownloadPath;
|
||||
end;
|
||||
|
||||
function GetIDFZIPFileVersion(Version: String): String;
|
||||
var
|
||||
ReleaseVerPart: String;
|
||||
i: Integer;
|
||||
Found: Boolean;
|
||||
begin
|
||||
if WildCardMatch(Version, 'v*') or WildCardMatch(Version, 'v*-rc*') then
|
||||
Result := Version
|
||||
else if Version = 'master' then
|
||||
Result := ''
|
||||
else if WildCardMatch(Version, 'release/v*') then
|
||||
begin
|
||||
ReleaseVerPart := Version;
|
||||
Log('ReleaseVerPart=' + ReleaseVerPart)
|
||||
Delete(ReleaseVerPart, 1, Length('release/'));
|
||||
Log('ReleaseVerPart=' + ReleaseVerPart)
|
||||
Found := False;
|
||||
for i := 0 to GetArrayLength(IDFDownloadAvailableVersions) - 1 do
|
||||
begin
|
||||
if Pos(ReleaseVerPart, IDFDownloadAvailableVersions[i]) = 1 then
|
||||
begin
|
||||
Result := IDFDownloadAvailableVersions[i];
|
||||
Found := True;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if not Found then
|
||||
Result := '';
|
||||
end;
|
||||
Log('GetIDFZIPFileVersion(' + Version + ')=' + Result);
|
||||
end;
|
||||
|
||||
procedure IDFAddDownload();
|
||||
var
|
||||
Url, MirrorUrl: String;
|
||||
begin
|
||||
IDFZIPFileVersion := GetIDFZIPFileVersion(IDFDownloadVersion);
|
||||
if IDFZIPFileVersion <> '' then
|
||||
begin
|
||||
Url := 'https://github.com/espressif/esp-idf/releases/download/' + IDFZIPFileVersion + '/esp-idf-' + IDFZIPFileVersion + '.zip';
|
||||
MirrorUrl := 'https://dl.espressif.com/dl/esp-idf/releases/esp-idf-' + IDFZIPFileVersion + '.zip';
|
||||
IDFZIPFileName := ExpandConstant('{app}\releases\esp-idf-' + IDFZIPFileVersion + '.zip')
|
||||
if not FileExists(IDFZIPFileName) then
|
||||
begin
|
||||
ForceDirectories(ExpandConstant('{app}\releases'))
|
||||
Log('Adding download: ' + Url + ', mirror: ' + MirrorUrl + ', destination: ' + IDFZIPFileName);
|
||||
idpAddFile(Url, IDFZIPFileName);
|
||||
idpAddMirror(Url, MirrorUrl);
|
||||
end else begin
|
||||
Log(IDFZIPFileName + ' already exists')
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure RemoveAlternatesFile(Path: String);
|
||||
begin
|
||||
Log('Removing ' + Path);
|
||||
DeleteFile(Path);
|
||||
end;
|
||||
|
||||
{
|
||||
Replacement of the '--dissociate' flag of 'git clone', to support older versions of Git.
|
||||
'--reference' is supported for submodules since git 2.12, but '--dissociate' only from 2.18.
|
||||
}
|
||||
procedure GitRepoDissociate(Path: String);
|
||||
var
|
||||
CmdLine: String;
|
||||
begin
|
||||
CmdLine := GitExecutablePath + ' -C ' + Path + ' repack -d -a'
|
||||
DoCmdlineInstall('Finishing ESP-IDF installation', 'Re-packing the repository', CmdLine);
|
||||
CmdLine := GitExecutablePath + ' -C ' + Path + ' submodule foreach git repack -d -a'
|
||||
DoCmdlineInstall('Finishing ESP-IDF installation', 'Re-packing the submodules', CmdLine);
|
||||
|
||||
FindFileRecusive(Path + '\.git', 'alternates', @RemoveAlternatesFile);
|
||||
end;
|
||||
|
||||
{ Run git reset --hard in the repo and in the submodules, to fix the newlines. }
|
||||
procedure GitRepoFixNewlines(Path: String);
|
||||
var
|
||||
CmdLine: String;
|
||||
begin
|
||||
CmdLine := GitExecutablePath + ' -C ' + Path + ' reset --hard';
|
||||
Log('Resetting the repository: ' + CmdLine);
|
||||
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating newlines', CmdLine);
|
||||
|
||||
Log('Resetting the submodules: ' + CmdLine);
|
||||
CmdLine := GitExecutablePath + ' -C ' + Path + ' submodule foreach git reset --hard';
|
||||
DoCmdlineInstall('Finishing ESP-IDF installation', 'Updating newlines in submodules', CmdLine);
|
||||
end;
|
||||
|
||||
{
|
||||
There are 3 possible ways how an ESP-IDF copy can be obtained:
|
||||
- Download the .zip archive with submodules included, extract to destination directory,
|
||||
then do 'git reset --hard' and 'git submodule foreach git reset --hard' to correct for
|
||||
possibly different newlines. This is done for release versions.
|
||||
- Do a git clone of the Github repository into the destination directory.
|
||||
This is done for the master branch.
|
||||
- Download the .zip archive of a "close enough" release version, extract into a temporary
|
||||
directory. Then do a git clone of the Github repository, using the temporary directory
|
||||
as a '--reference'. This is done for other versions (such as release branches).
|
||||
}
|
||||
|
||||
procedure IDFDownload();
|
||||
var
|
||||
CmdLine: String;
|
||||
IDFTempPath: String;
|
||||
IDFPath: String;
|
||||
NeedToClone: Boolean;
|
||||
Res: Boolean;
|
||||
|
||||
begin
|
||||
IDFPath := IDFDownloadPath;
|
||||
{ If there is a release archive to download, IDFZIPFileName and IDFZIPFileVersion will be set.
|
||||
See GetIDFZIPFileVersion function.
|
||||
}
|
||||
|
||||
if IDFZIPFileName <> '' then
|
||||
begin
|
||||
if IDFZIPFileVersion <> IDFDownloadVersion then
|
||||
begin
|
||||
{ The version of .zip file downloaded is not the same as the version the user has requested.
|
||||
Will use 'git clone --reference' to obtain the correct version, using the contents
|
||||
of the .zip file as reference.
|
||||
}
|
||||
NeedToClone := True;
|
||||
end;
|
||||
|
||||
ExtractTemporaryFile('7za.exe')
|
||||
CmdLine := ExpandConstant('{tmp}\7za.exe x -o' + ExpandConstant('{tmp}') + ' -r -aoa ' + IDFZIPFileName);
|
||||
IDFTempPath := ExpandConstant('{tmp}\esp-idf-') + IDFZIPFileVersion;
|
||||
Log('Extracting ESP-IDF reference repository: ' + CmdLine);
|
||||
Log('Reference repository path: ' + IDFTempPath);
|
||||
DoCmdlineInstall('Extracting ESP-IDF', 'Setting up reference repository', CmdLine);
|
||||
end else begin
|
||||
{ IDFZIPFileName is not set, meaning that we will rely on 'git clone'. }
|
||||
NeedToClone := True;
|
||||
Log('Not .zip release archive. Will do full clone.');
|
||||
end;
|
||||
|
||||
if NeedToClone then
|
||||
begin
|
||||
CmdLine := GitExecutablePath + ' clone --recursive --progress -b ' + IDFDownloadVersion;
|
||||
|
||||
if IDFTempPath <> '' then
|
||||
CmdLine := CmdLine + ' --reference ' + IDFTempPath;
|
||||
|
||||
CmdLine := CmdLine + ' https://github.com/espressif/esp-idf.git ' + IDFPath;
|
||||
Log('Cloning IDF: ' + CmdLine);
|
||||
DoCmdlineInstall('Downloading ESP-IDF', 'Using git to clone ESP-IDF repository', CmdLine);
|
||||
|
||||
if IDFTempPath <> '' then
|
||||
GitRepoDissociate(IDFPath);
|
||||
|
||||
end else begin
|
||||
Log('Moving ' + IDFTempPath + ' to ' + IDFPath);
|
||||
if DirExists(IDFPath) then
|
||||
begin
|
||||
if not DirIsEmpty(IDFPath) then
|
||||
begin
|
||||
MsgBox('Destination directory exists and is not empty: ' + IDFPath, mbError, MB_OK);
|
||||
RaiseException('Failed to copy ESP-IDF')
|
||||
end;
|
||||
|
||||
Res := RemoveDir(IDFPath);
|
||||
if not Res then
|
||||
begin
|
||||
MsgBox('Failed to remove destination directory: ' + IDFPath, mbError, MB_OK);
|
||||
RaiseException('Failed to copy ESP-IDF')
|
||||
end;
|
||||
end;
|
||||
Res := RenameFile(IDFTempPath, IDFPath);
|
||||
if not Res then
|
||||
begin
|
||||
MsgBox('Failed to copy ESP-IDF to the destination directory: ' + IDFPath, mbError, MB_OK);
|
||||
RaiseException('Failed to copy ESP-IDF');
|
||||
end;
|
||||
GitRepoFixNewlines(IDFPath);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ------------------------------ IDF Tools setup, Python environment setup ------------------------------ }
|
||||
|
||||
procedure IDFToolsSetup();
|
||||
var
|
||||
CmdLine: String;
|
||||
IDFPath: String;
|
||||
IDFToolsPyPath: String;
|
||||
IDFToolsPyCmd: String;
|
||||
begin
|
||||
IDFPath := GetIDFPath('');
|
||||
IDFToolsPyPath := IDFPath + '\tools\idf_tools.py';
|
||||
if FileExists(IDFToolsPyPath) then
|
||||
begin
|
||||
Log('idf_tools.py exists in IDF directory');
|
||||
IDFToolsPyCmd := PythonExecutablePath + ' ' + IDFToolsPyPath;
|
||||
end else begin
|
||||
Log('idf_tools.py does not exist in IDF directory, using a fallback version');
|
||||
IDFToolsPyCmd := ExpandConstant(PythonExecutablePath
|
||||
+ ' {app}\idf_tools_fallback.py'
|
||||
+ ' --idf-path ' + IDFPath
|
||||
+ ' --tools {app}\tools_fallback.json');
|
||||
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();
|
||||
var
|
||||
Destination: String;
|
||||
Description: String;
|
||||
Command: String;
|
||||
begin
|
||||
ForceDirectories(ExpandConstant('{group}'));
|
||||
Destination := ExpandConstant('{group}\{#IDFCmdExeShortcutFile}');
|
||||
Description := '{#IDFCmdExeShortcutDescription}';
|
||||
Command := ExpandConstant('/k {app}\idf_cmd_init.bat "') + PythonPath + '" "' + GitPath + '"';
|
||||
Log('CreateShellLink Destination=' + Destination + ' Description=' + Description + ' Command=' + Command)
|
||||
try
|
||||
CreateShellLink(
|
||||
Destination,
|
||||
Description,
|
||||
'cmd.exe',
|
||||
Command,
|
||||
GetIDFPath(''),
|
||||
'', 0, SW_SHOWNORMAL);
|
||||
except
|
||||
MsgBox('Failed to create the Start menu shortcut: ' + Destination, mbError, MB_OK);
|
||||
RaiseException('Failed to create the shortcut');
|
||||
end;
|
||||
end;
|
|
@ -1,242 +1,95 @@
|
|||
; Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
; SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma include __INCLUDE__ + ";" + ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir")
|
||||
#include <idp.iss>
|
||||
|
||||
[Setup]
|
||||
AppName=ESP-IDF Tools
|
||||
AppVersion=1.2
|
||||
OutputBaseFilename=esp-idf-tools-setup-unsigned
|
||||
#define MyAppName "ESP-IDF Tools"
|
||||
#define MyAppVersion "2.0"
|
||||
#define MyAppPublisher "Espressif Systems (Shanghai) Co. Ltd."
|
||||
#define MyAppURL "https://github.com/espressif/esp-idf"
|
||||
|
||||
DefaultDirName={pf}\Espressif\ESP-IDF Tools
|
||||
DefaultGroupName=ESP-IDF Tools
|
||||
Compression=lzma2
|
||||
#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 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"
|
||||
|
||||
[Setup]
|
||||
; NOTE: The value of AppId uniquely identifies this application.
|
||||
; Do not use the same AppId value in installers for other applications.
|
||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||
AppId={{9E068D99-5C4B-4E5F-96A3-B17CF291E6BD}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppVerName={#MyAppName} {#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={%USERPROFILE}\.espressif
|
||||
DirExistsWarning=no
|
||||
DefaultGroupName=ESP-IDF
|
||||
DisableProgramGroupPage=yes
|
||||
OutputBaseFilename=esp-idf-tools-setup-unsigned
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
ChangesEnvironment=yes
|
||||
LicenseFile=license.txt
|
||||
; Note: the rest of the installer setup is written to work cleanly on win32 also, *however*
|
||||
; Ninja doesn't ship a 32-bit binary so there's no way yet to install on win32 :(
|
||||
; See https://github.com/ninja-build/ninja/issues/1339
|
||||
ArchitecturesAllowed=x64
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
LicenseFile=license.txt
|
||||
PrivilegesRequired=lowest
|
||||
SetupLogging=yes
|
||||
ChangesEnvironment=yes
|
||||
WizardStyle=modern
|
||||
|
||||
[Types]
|
||||
Name: "full"; Description: "Default installation"
|
||||
Name: "custom"; Description: "Custom installation"; Flags: iscustom
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Components]
|
||||
Name: xtensa_esp32; Description: ESP32 Xtensa GCC Cross-Toolchain; Types: full custom;
|
||||
Name: mconf_idf; Description: ESP-IDF console menuconfig tool; Types: full custom;
|
||||
Name: openocd_esp32; Description: openocd debug interface for ESP32; Types: full custom;
|
||||
Name: esp32ulp_elf_binutils; Description: ULP binutils toolchain for ESP32; Types: full custom;
|
||||
Name: ninja; Description: Install Ninja build v1.8.2; Types: full custom
|
||||
|
||||
[Tasks]
|
||||
; Should installer prepend to Path (does this by default)
|
||||
Name: addpath; Description: "Add tools to Path"; GroupDescription: "Add to Path:";
|
||||
Name: addpath\allusers; Description: "For all users"; GroupDescription: "Add to Path:"; Flags: exclusive
|
||||
Name: addpath\user; Description: "For the current user only"; GroupDescription: "Add to Path:"; Flags: exclusive unchecked
|
||||
|
||||
; External installation tasks
|
||||
;
|
||||
; Note: The Check conditions here auto-select 32-bit or 64-bit installers, as needed
|
||||
; The tasks won't appear if CMake/Python27 already appear to be installed on this system
|
||||
Name: cmake32; Description: Download and Run CMake 3.11.1 Installer; GroupDescription: "Other Required Tools:"; Check: not IsWin64 and not CMakeInstalled
|
||||
Name: cmake64; Description: Download and Run CMake 3.11.1 Installer; GroupDescription: "Other Required Tools:"; Check: IsWin64 and not CMakeInstalled
|
||||
Name: python32; Description: Download and Run Python 2.7.14 Installer and install Python dependencies; GroupDescription: "Other Required Tools:"; Check: not IsWin64 and not Python27Installed
|
||||
Name: python64; Description: Download and Run Python 2.7.14 Installer and install Python dependencies; GroupDescription: "Other Required Tools:"; Check: IsWin64 and not Python27Installed
|
||||
Name: python_requirements; Description: Install any missing Python dependencies; GroupDescription: "Other Required Tools:"; Check: Python27Installed
|
||||
[Dirs]
|
||||
Name: "{app}\dist"
|
||||
|
||||
[Files]
|
||||
Components: xtensa_esp32; Source: "input\xtensa-esp32-elf\*"; DestDir: "{app}\tools\"; Flags: recursesubdirs;
|
||||
Components: mconf_idf; Source: "input\mconf-v4.6.0.0-idf-20180525-win32\*"; DestDir: "{app}\mconf-idf\";
|
||||
Components: esp32ulp_elf_binutils; Source: "input\esp32ulp-elf-binutils\*"; DestDir: "{app}\tools\"; Flags: recursesubdirs;
|
||||
; Excludes for openocd are because some config files contain Cyrillic characters and inno can't encode them
|
||||
Components: openocd_esp32; Source: "input\openocd-esp32\*"; DestDir: "{app}\tools\"; Flags: recursesubdirs; Excludes: "target\1986*.cfg,target\*1879*.cfg"
|
||||
Components: ninja; Source: "input\ninja.exe"; DestDir: "{app}\tools\bin\";
|
||||
Tasks: python32 python64 python_requirements; Source: "..\..\..\requirements.txt"; DestDir: "{tmp}"; Flags: deleteafterinstall;
|
||||
Source: "cmdlinerunner\build\cmdlinerunner.dll"; Flags: dontcopy
|
||||
Source: "unzip\7za.exe"; Flags: dontcopy
|
||||
Source: "idf_versions.txt"; Flags: dontcopy
|
||||
Source: "..\..\idf_tools.py"; DestDir: "{app}"; DestName: "idf_tools_fallback.py"
|
||||
; Note: this tools.json matches the requirements of IDF v3.x versions.
|
||||
Source: "tools_fallback.json"; DestDir: "{app}"; DestName: "tools_fallback.json"
|
||||
Source: "idf_cmd_init.bat"; DestDir: "{app}"
|
||||
Source: "dist\*"; DestDir: "{app}\dist"
|
||||
|
||||
[UninstallDelete]
|
||||
Type: filesandordirs; Name: "{app}\dist"
|
||||
Type: filesandordirs; Name: "{app}\releases"
|
||||
Type: filesandordirs; Name: "{app}\tools"
|
||||
Type: filesandordirs; Name: "{app}\python_env"
|
||||
|
||||
[Run]
|
||||
Tasks: cmake32 cmake64; Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\cmake.msi"" /qb! {code:GetCMakeInstallerArgs}"; StatusMsg: Running CMake installer...;
|
||||
Tasks: python32 python64; Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\python.msi"" /qb! {code:GetPythonInstallerArgs} REBOOT=Supress"; StatusMsg: Running Python installer...;
|
||||
Tasks: python32 python64; Filename: "C:\Python27\Scripts\pip.exe"; Parameters: "install -r ""{tmp}\requirements.txt"""; StatusMsg: Installing Python modules...;
|
||||
Tasks: python_requirements; Filename: "{code:Python27InstallPathInclude}\Scripts\pip.exe"; Parameters: "install -r ""{tmp}\requirements.txt"""; StatusMsg: Installing Python modules...;
|
||||
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
|
||||
|
||||
[Registry]
|
||||
; Prepend various entries to Path in the registry. Can either be HKLM (all users) or HKCU (single user only)
|
||||
|
||||
; "tools" bin dir (ninja, xtensa & ULP toolchains, openocd all in this dir)
|
||||
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
|
||||
ValueType: expandsz; ValueName: "Path"; ValueData: "{app}\tools\bin;{olddata}"; Check: not IsInPath('{app}'); \
|
||||
Components: xtensa_esp32 esp32ulp_elf_binutils openocd_esp32 ninja; Tasks: addpath\allusers
|
||||
Root: HKCU; Subkey: "Environment"; \
|
||||
ValueType: expandsz; ValueName: "Path"; ValueData: "{app}\tools\bin;{olddata}"; Check: not IsInPath('{app}'); \
|
||||
Components: xtensa_esp32 esp32ulp_elf_binutils openocd_esp32 ninja; Tasks: addpath\user
|
||||
|
||||
; mconf-idf path
|
||||
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
|
||||
ValueType: expandsz; ValueName: "Path"; ValueData: "{app}\mconf-idf;{olddata}"; Check: not IsInPath('{app}\mconf-idf'); \
|
||||
Components: mconf_idf; Tasks: addpath\allusers
|
||||
Root: HKCU; Subkey: "Environment"; \
|
||||
ValueType: expandsz; ValueName: "Path"; ValueData: "{app}\mconf-idf;{olddata}"; Check: not IsInPath('{app}\mconf-idf'); \
|
||||
Components: mconf_idf; Tasks: addpath\user
|
||||
|
||||
; set OPENOCD_SCRIPTS environment variable
|
||||
[Registry]
|
||||
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
|
||||
ValueType:string; ValueName: "OPENOCD_SCRIPTS"; \
|
||||
ValueData: "{app}\tools\share\openocd\scripts"; Flags: preservestringtype createvalueifdoesntexist; \
|
||||
Components: openocd_esp32; Tasks: addpath\allusers
|
||||
Root: HKCU; Subkey: "Environment"; ValueType:string; ValueName: "OPENOCD_SCRIPTS"; \
|
||||
ValueData: "{app}\tools\share\openocd\scripts"; Flags: preservestringtype createvalueifdoesntexist; \
|
||||
Components: openocd_esp32; Tasks: addpath\user
|
||||
|
||||
Root: HKCU; Subkey: "Environment"; ValueType: string; ValueName: "IDF_TOOLS_PATH"; \
|
||||
ValueData: "{app}"; Flags: preservestringtype createvalueifdoesntexist;
|
||||
|
||||
[Code]
|
||||
procedure InitializeWizard;
|
||||
begin
|
||||
idpDownloadAfter(wpReady);
|
||||
end;
|
||||
|
||||
procedure CurPageChanged(CurPageID: Integer);
|
||||
begin
|
||||
{ When the Ready page is being displayed, initialise downloads based on which Tasks are selected }
|
||||
if CurPageID=wpReady then
|
||||
begin
|
||||
if IsTaskSelected('python32') then
|
||||
begin
|
||||
idpAddFile('https://www.python.org/ftp/python/2.7.14/python-2.7.14.msi', ExpandConstant('{tmp}\python.msi'));
|
||||
end;
|
||||
if IsTaskSelected('python64') then
|
||||
begin
|
||||
idpAddFile('https://www.python.org/ftp/python/2.7.14/python-2.7.14.amd64.msi', ExpandConstant('{tmp}\python.msi'));
|
||||
end;
|
||||
if IsTaskSelected('cmake32') then
|
||||
begin
|
||||
idpAddFile('https://cmake.org/files/v3.11/cmake-3.11.1-win32-x86.msi', ExpandConstant('{tmp}\cmake.msi'));
|
||||
end;
|
||||
if IsTaskSelected('cmake64') then
|
||||
begin
|
||||
idpAddFile('https://cmake.org/files/v3.11/cmake-3.11.1-win64-x64.msi', ExpandConstant('{tmp}\cmake.msi'));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Utility to search in HKLM for an installation path. Looks in both 64-bit & 32-bit registry. }
|
||||
function GetInstallPath(key, valuename : String) : Variant;
|
||||
var
|
||||
value : string;
|
||||
begin
|
||||
Result := Null;
|
||||
if RegQueryStringValue(HKEY_LOCAL_MACHINE, key, valuename, value) then
|
||||
begin
|
||||
Result := value;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ This is 32-bit setup running on 64-bit Windows, but ESP-IDF can use 64-bit tools also }
|
||||
if IsWin64 and RegQueryStringValue(HKLM64, key, valuename, value) then
|
||||
begin
|
||||
Result := value;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Return the path of the CMake install, if there is one }
|
||||
function CMakeInstallPath() : Variant;
|
||||
begin
|
||||
Result := GetInstallPath('SOFTWARE\Kitware\CMake', 'InstallDir');
|
||||
end;
|
||||
|
||||
{ Return 'True' if CMake is installed }
|
||||
function CMakeInstalled() : Boolean;
|
||||
begin
|
||||
Result := not VarIsNull(CMakeInstallPath());
|
||||
end;
|
||||
|
||||
{ Return the path where Python 2.7 is installed, if there is one }
|
||||
function Python27InstallPath() : Variant;
|
||||
begin
|
||||
Result := GetInstallPath('SOFTWARE\Python\PythonCore\2.7\InstallPath', '');
|
||||
end;
|
||||
|
||||
{ Return the path where Python 2.7 is installed, suitable for including in code: tag }
|
||||
function Python27InstallPathInclude(Ignored : String) : String;
|
||||
begin
|
||||
Result := Python27InstallPath();
|
||||
end;
|
||||
|
||||
{ Return True if Python 2.7 is installed }
|
||||
function Python27Installed() : Boolean;
|
||||
begin
|
||||
Result := not VarIsNull(Python27InstallPath());
|
||||
end;
|
||||
|
||||
{ Return arguments to pass to CMake installer, ie should it add CMake to the Path }
|
||||
function GetCMakeInstallerArgs(Param : String) : String;
|
||||
begin
|
||||
if IsTaskSelected('addpath\allusers') then
|
||||
begin
|
||||
Result := 'ADD_CMAKE_TO_PATH=System';
|
||||
end
|
||||
else if IsTaskSelected('addpath\user') then
|
||||
begin
|
||||
Result := 'ADD_CMAKE_TO_PATH=User';
|
||||
end
|
||||
else begin
|
||||
Result := 'ADD_CMAKE_TO_PATH=None';
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Return arguments to pass to the Python installer,
|
||||
ie should it install for all users and should it prepend to the Path }
|
||||
function GetPythonInstallerArgs(Param : String) : String;
|
||||
begin
|
||||
{ Note: The Python 2.7 installer appears to always add PATH to
|
||||
system environment variables, regardless of ALLUSERS setting.
|
||||
|
||||
This appears to be fixed in the Python 3.x installers (which use WiX) }
|
||||
if IsTaskSelected('addpath') then
|
||||
begin
|
||||
Result := 'ADDLOCAL=ALL ';
|
||||
end
|
||||
else begin
|
||||
Result := ''
|
||||
end;
|
||||
if IsTaskSelected('addpath\allusers') then
|
||||
begin
|
||||
Result := Result + 'ALLUSERS=1';
|
||||
end
|
||||
else begin
|
||||
Result := Result + 'ALLUSERS=';
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Return True if the param is already set in the Path
|
||||
(user or system, depending on which Task is chosen)
|
||||
|
||||
Adapted from https://stackoverflow.com/a/3431379
|
||||
}
|
||||
function IsInPath(Param: string): boolean;
|
||||
var
|
||||
OrigPath: string;
|
||||
RootKey : Integer;
|
||||
SubKey : String;
|
||||
begin
|
||||
if IsTaskSelected('addpath\allusers') then
|
||||
begin
|
||||
RootKey := HKEY_LOCAL_MACHINE;
|
||||
SubKey := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
|
||||
end
|
||||
else begin
|
||||
RootKey := HKEY_CURRENT_USER;
|
||||
SubKey := 'Environment';
|
||||
end;
|
||||
|
||||
if not RegQueryStringValue(RootKey, SubKey, 'Path', OrigPath)
|
||||
then begin
|
||||
Result := False;
|
||||
end
|
||||
else begin
|
||||
{ look for the path with leading and trailing semicolon }
|
||||
Result := Pos(';' + Param + ';', ';' + OrigPath + ';') > 0;
|
||||
end;
|
||||
end;
|
||||
#include "utils.iss.inc"
|
||||
#include "choice_page.iss.inc"
|
||||
#include "cmdline_page.iss.inc"
|
||||
#include "idf_page.iss.inc"
|
||||
#include "git_page.iss.inc"
|
||||
#include "python_page.iss.inc"
|
||||
#include "idf_download_page.iss.inc"
|
||||
#include "idf_setup.iss.inc"
|
||||
#include "summary.iss.inc"
|
||||
#include "main.iss.inc"
|
||||
|
|
121
tools/windows/tool_setup/main.iss.inc
Normal file
121
tools/windows/tool_setup/main.iss.inc
Normal file
|
@ -0,0 +1,121 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Custom steps before the main installation flow ------------------------------ }
|
||||
|
||||
var
|
||||
SetupAborted: Boolean;
|
||||
|
||||
function InstallationSuccessful(): Boolean;
|
||||
begin
|
||||
Result := not SetupAborted;
|
||||
end;
|
||||
|
||||
<event('InitializeWizard')>
|
||||
procedure InitializeDownloader();
|
||||
begin
|
||||
idpDownloadAfter(wpReady);
|
||||
end;
|
||||
|
||||
<event('NextButtonClick')>
|
||||
function PreInstallSteps(CurPageID: Integer): Boolean;
|
||||
var
|
||||
DestPath: String;
|
||||
begin
|
||||
Result := True;
|
||||
if CurPageID <> wpReady then
|
||||
exit;
|
||||
|
||||
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}');
|
||||
if FileExists(DestPath) then
|
||||
begin
|
||||
Log('Git installer already downloaded: ' + DestPath);
|
||||
end else begin
|
||||
idpAddFile('{#GitInstallerDownloadURL}', DestPath);
|
||||
end;
|
||||
end;
|
||||
|
||||
if not IDFUseExisting then
|
||||
begin
|
||||
IDFAddDownload();
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ------------------------------ Custom steps after the main installation flow ------------------------------ }
|
||||
|
||||
procedure AddPythonGitToPath();
|
||||
var
|
||||
EnvPath: String;
|
||||
PythonLibPath: String;
|
||||
begin
|
||||
EnvPath := GetEnv('PATH');
|
||||
|
||||
if not PythonUseExisting then
|
||||
PythonExecutablePathUpdateAfterInstall();
|
||||
|
||||
if not GitUseExisting then
|
||||
GitExecutablePathUpdateAfterInstall();
|
||||
|
||||
EnvPath := PythonPath + ';' + GitPath + ';' + EnvPath;
|
||||
Log('Setting PATH for this process: ' + EnvPath);
|
||||
SetEnvironmentVariable('PATH', EnvPath);
|
||||
|
||||
{ Log and clear PYTHONPATH variable, as it might point to libraries of another Python version}
|
||||
PythonLibPath := GetEnv('PYTHONPATH')
|
||||
Log('PYTHONPATH=' + PythonLibPath)
|
||||
SetEnvironmentVariable('PYTHONPATH', '')
|
||||
end;
|
||||
|
||||
<event('CurStepChanged')>
|
||||
procedure PostInstallSteps(CurStep: TSetupStep);
|
||||
var
|
||||
Err: Integer;
|
||||
begin
|
||||
if CurStep <> ssPostInstall then
|
||||
exit;
|
||||
|
||||
try
|
||||
AddPythonGitToPath();
|
||||
|
||||
if not IDFUseExisting then
|
||||
IDFDownload();
|
||||
|
||||
IDFToolsSetup();
|
||||
|
||||
CreateIDFCommandPromptShortcut();
|
||||
except
|
||||
SetupAborted := True;
|
||||
if MsgBox('Installation log has been created, it may contain more information about the problem.' + #13#10
|
||||
+ 'Display the installation log now?', mbConfirmation, MB_YESNO or MB_DEFBUTTON1) = IDYES then
|
||||
begin
|
||||
ShellExec('', 'notepad.exe', ExpandConstant('{log}'), ExpandConstant('{tmp}'), SW_SHOW, ewNoWait, Err);
|
||||
end;
|
||||
Abort();
|
||||
end;
|
||||
end;
|
||||
|
||||
<event('ShouldSkipPage')>
|
||||
function SkipFinishedPage(PageID: Integer): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
if PageID = wpFinished then
|
||||
begin
|
||||
Result := SetupAborted;
|
||||
end;
|
||||
end;
|
113
tools/windows/tool_setup/python_find_installed.iss.inc
Normal file
113
tools/windows/tool_setup/python_find_installed.iss.inc
Normal file
|
@ -0,0 +1,113 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Find installed Python interpreters in Windows Registry (see PEP 514) ------------------------------ }
|
||||
|
||||
var
|
||||
InstalledPythonVersions: TStringList;
|
||||
InstalledPythonDisplayNames: TStringList;
|
||||
InstalledPythonExecutables: TStringList;
|
||||
|
||||
procedure PythonVersionAdd(Version, DisplayName, Executable: String);
|
||||
begin
|
||||
Log('Adding Python version=' + Version + ' name='+DisplayName+' executable='+Executable);
|
||||
InstalledPythonVersions.Append(Version);
|
||||
InstalledPythonDisplayNames.Append(DisplayName);
|
||||
InstalledPythonExecutables.Append(Executable);
|
||||
end;
|
||||
|
||||
function GetPythonVersionInfoFromKey(RootKey: Integer; SubKeyName, CompanyName, TagName: String;
|
||||
var Version: String;
|
||||
var DisplayName: String;
|
||||
var ExecutablePath: String): Boolean;
|
||||
var
|
||||
TagKey, InstallPathKey, DefaultPath: String;
|
||||
begin
|
||||
TagKey := SubKeyName + '\' + CompanyName + '\' + TagName;
|
||||
InstallPathKey := TagKey + '\InstallPath';
|
||||
|
||||
if not RegQueryStringValue(RootKey, InstallPathKey, '', DefaultPath) then
|
||||
begin
|
||||
Log('No (Default) key, skipping');
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if not RegQueryStringValue(RootKey, InstallPathKey, 'ExecutablePath', ExecutablePath) then
|
||||
begin
|
||||
Log('No ExecutablePath, using the default');
|
||||
ExecutablePath := DefaultPath + '\python.exe';
|
||||
end;
|
||||
|
||||
if not RegQueryStringValue(RootKey, TagKey, 'SysVersion', Version) then
|
||||
begin
|
||||
if CompanyName = 'PythonCore' then
|
||||
begin
|
||||
Version := TagName;
|
||||
Delete(Version, 4, Length(Version));
|
||||
end else begin
|
||||
Log('Can not determine SysVersion');
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
if not RegQueryStringValue(RootKey, TagKey, 'DisplayName', DisplayName) then
|
||||
begin
|
||||
DisplayName := 'Python ' + Version;
|
||||
end;
|
||||
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure FindPythonVersionsFromKey(RootKey: Integer; SubKeyName: String);
|
||||
var
|
||||
CompanyNames: TArrayOfString;
|
||||
CompanyName, CompanySubKey, TagName, TagSubKey: String;
|
||||
ExecutablePath, DisplayName, Version: String;
|
||||
TagNames: TArrayOfString;
|
||||
CompanyId, TagId: Integer;
|
||||
begin
|
||||
if not RegGetSubkeyNames(RootKey, SubKeyName, CompanyNames) then
|
||||
begin
|
||||
Log('Nothing found in ' + IntToStr(RootKey) + '\' + SubKeyName);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
for CompanyId := 0 to GetArrayLength(CompanyNames) - 1 do
|
||||
begin
|
||||
CompanyName := CompanyNames[CompanyId];
|
||||
|
||||
if CompanyName = 'PyLauncher' then
|
||||
continue;
|
||||
|
||||
CompanySubKey := SubKeyName + '\' + CompanyName;
|
||||
Log('In ' + IntToStr(RootKey) + '\' + CompanySubKey);
|
||||
|
||||
if not RegGetSubkeyNames(RootKey, CompanySubKey, TagNames) then
|
||||
continue;
|
||||
|
||||
for TagId := 0 to GetArrayLength(TagNames) - 1 do
|
||||
begin
|
||||
TagName := TagNames[TagId];
|
||||
TagSubKey := CompanySubKey + '\' + TagName;
|
||||
Log('In ' + IntToStr(RootKey) + '\' + TagSubKey);
|
||||
|
||||
if not GetPythonVersionInfoFromKey(RootKey, SubKeyName, CompanyName, TagName, Version, DisplayName, ExecutablePath) then
|
||||
continue;
|
||||
|
||||
PythonVersionAdd(Version, DisplayName, ExecutablePath);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure FindInstalledPythonVersions();
|
||||
begin
|
||||
InstalledPythonVersions := TStringList.Create();
|
||||
InstalledPythonDisplayNames := TStringList.Create();
|
||||
InstalledPythonExecutables := TStringList.Create();
|
||||
|
||||
FindPythonVersionsFromKey(HKEY_CURRENT_USER, 'Software\Python');
|
||||
FindPythonVersionsFromKey(HKEY_LOCAL_MACHINE, 'Software\Python');
|
||||
FindPythonVersionsFromKey(HKEY_LOCAL_MACHINE, 'Software\Wow6432Node\Python');
|
||||
end;
|
149
tools/windows/tool_setup/python_page.iss.inc
Normal file
149
tools/windows/tool_setup/python_page.iss.inc
Normal file
|
@ -0,0 +1,149 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Page to select Python interpreter ------------------------------ }
|
||||
|
||||
#include "python_find_installed.iss.inc"
|
||||
|
||||
var
|
||||
PythonPage: TInputOptionWizardPage;
|
||||
PythonVersion, PythonPath, PythonExecutablePath: String;
|
||||
PythonUseExisting: Boolean;
|
||||
|
||||
|
||||
function GetPythonPath(Unused: String): String;
|
||||
begin
|
||||
Result := PythonPath;
|
||||
end;
|
||||
|
||||
function PythonInstallRequired(): Boolean;
|
||||
begin
|
||||
Result := not PythonUseExisting;
|
||||
end;
|
||||
|
||||
function PythonVersionSupported(Version: String): Boolean;
|
||||
var
|
||||
Major, Minor: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
if not VersionExtractMajorMinor(Version, Major, Minor) then
|
||||
begin
|
||||
Log('PythonVersionSupported: Could not parse version=' + Version);
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (Major = 2) and (Minor = 7) then Result := True;
|
||||
if (Major = 3) and (Minor >= 5) then Result := True;
|
||||
end;
|
||||
|
||||
procedure OnPythonPagePrepare(Sender: TObject);
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
FullName: String;
|
||||
i, Index, FirstEnabledIndex: Integer;
|
||||
OfferToInstall: Boolean;
|
||||
VersionToInstall: String;
|
||||
VersionSupported: Boolean;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnPythonPagePrepare');
|
||||
if Page.CheckListBox.Items.Count > 0 then
|
||||
exit;
|
||||
|
||||
FindInstalledPythonVersions();
|
||||
|
||||
VersionToInstall := '{#PythonVersion}';
|
||||
OfferToInstall := True;
|
||||
FirstEnabledIndex := -1;
|
||||
|
||||
for i := 0 to InstalledPythonVersions.Count - 1 do
|
||||
begin
|
||||
VersionSupported := PythonVersionSupported(InstalledPythonVersions[i]);
|
||||
FullName := InstalledPythonDisplayNames.Strings[i];
|
||||
if not VersionSupported then
|
||||
begin
|
||||
FullName := FullName + ' (unsupported)';
|
||||
end;
|
||||
FullName := FullName + #13#10 + InstalledPythonExecutables.Strings[i];
|
||||
Index := Page.Add(FullName);
|
||||
if not VersionSupported then
|
||||
begin
|
||||
Page.CheckListBox.ItemEnabled[Index] := False;
|
||||
end else begin
|
||||
if FirstEnabledIndex < 0 then FirstEnabledIndex := Index;
|
||||
end;
|
||||
if InstalledPythonVersions[i] = VersionToInstall then
|
||||
begin
|
||||
OfferToInstall := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
if OfferToInstall then
|
||||
begin
|
||||
Index := Page.Add('Install Python ' + VersionToInstall);
|
||||
if FirstEnabledIndex < 0 then FirstEnabledIndex := Index;
|
||||
end;
|
||||
|
||||
Page.SelectedValueIndex := FirstEnabledIndex;
|
||||
end;
|
||||
|
||||
procedure OnPythonSelectionChange(Sender: TObject);
|
||||
var
|
||||
Page: TInputOptionWizardPage;
|
||||
begin
|
||||
Page := TInputOptionWizardPage(Sender);
|
||||
Log('OnPythonSelectionChange index=' + IntToStr(Page.SelectedValueIndex));
|
||||
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);
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure PythonExecutablePathUpdateAfterInstall();
|
||||
var
|
||||
Version, DisplayName, ExecutablePath: String;
|
||||
begin
|
||||
if not GetPythonVersionInfoFromKey(
|
||||
HKEY_CURRENT_USER, 'Software\Python', 'PythonCore', '{#PythonVersion}',
|
||||
Version, DisplayName, ExecutablePath) 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);
|
||||
end;
|
||||
|
||||
<event('InitializeWizard')>
|
||||
procedure CreatePythonPage();
|
||||
begin
|
||||
PythonPage := ChoicePageCreate(
|
||||
wpLicense,
|
||||
'Python choice', 'Please choose Python version',
|
||||
'Available Python versions',
|
||||
'',
|
||||
False,
|
||||
@OnPythonPagePrepare,
|
||||
@OnPythonSelectionChange,
|
||||
@OnPythonPageValidate);
|
||||
end;
|
40
tools/windows/tool_setup/summary.iss.inc
Normal file
40
tools/windows/tool_setup/summary.iss.inc
Normal file
|
@ -0,0 +1,40 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Installation summary page ------------------------------ }
|
||||
|
||||
function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo,
|
||||
MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
|
||||
begin
|
||||
Result := ''
|
||||
|
||||
if PythonUseExisting 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;
|
||||
end;
|
||||
|
||||
if GitUseExisting then
|
||||
begin
|
||||
Result := Result + 'Using Git ' + GitVersion + ':' + NewLine
|
||||
+ Space + GitExecutablePath + NewLine + NewLine;
|
||||
end else begin
|
||||
Result := Result + 'Will download and install Git for Windows ' + GitVersion + NewLine + NewLine;
|
||||
end;
|
||||
|
||||
if IDFUseExisting then
|
||||
begin
|
||||
Result := Result + 'Using existing ESP-IDF copy: ' + NewLine
|
||||
+ Space + IDFExistingPath + NewLine + NewLine;
|
||||
end else begin
|
||||
Result := Result + 'Will download ESP-IDF ' + IDFDownloadVersion + ' into:' + NewLine
|
||||
+ Space + IDFDownloadPath + NewLine + NewLine;
|
||||
end;
|
||||
|
||||
Result := Result + 'IDF tools directory (IDF_TOOLS_PATH):' + NewLine +
|
||||
Space + ExpandConstant('{app}') + NewLine + NewLine;
|
||||
|
||||
Log('Summary message: ' + NewLine + Result);
|
||||
end;
|
390
tools/windows/tool_setup/tools_fallback.json
Normal file
390
tools/windows/tool_setup/tools_fallback.json
Normal file
|
@ -0,0 +1,390 @@
|
|||
{
|
||||
"tools": [
|
||||
{
|
||||
"description": "Toolchain for Xtensa (ESP32) based on GCC",
|
||||
"export_paths": [
|
||||
[
|
||||
"xtensa-esp32-elf",
|
||||
"bin"
|
||||
]
|
||||
],
|
||||
"export_vars": {},
|
||||
"info_url": "https://github.com/espressif/crosstool-NG",
|
||||
"install": "always",
|
||||
"license": "GPL-3.0-with-GCC-exception",
|
||||
"name": "xtensa-esp32-elf",
|
||||
"version_cmd": [
|
||||
"xtensa-esp32-elf-gcc",
|
||||
"--version"
|
||||
],
|
||||
"version_regex": "\\(crosstool-NG\\s+(?:crosstool-ng-)?([0-9a-z\\.\\-]+)\\)\\s*([0-9\\.]+)",
|
||||
"version_regex_replace": "\\1-\\2",
|
||||
"versions": [
|
||||
{
|
||||
"name": "1.22.0-80-g6c4433a5-5.2.0",
|
||||
"status": "recommended",
|
||||
"win32": {
|
||||
"sha256": "f217fccbeaaa8c92db239036e0d6202458de4488b954a3a38f35ac2ec48058a4",
|
||||
"size": 125719261,
|
||||
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-win32-1.22.0-80-g6c4433a-5.2.0.zip"
|
||||
},
|
||||
"win64": {
|
||||
"sha256": "f217fccbeaaa8c92db239036e0d6202458de4488b954a3a38f35ac2ec48058a4",
|
||||
"size": 125719261,
|
||||
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-win32-1.22.0-80-g6c4433a-5.2.0.zip"
|
||||
}
|
||||
},
|
||||
{
|
||||
"linux-amd64": {
|
||||
"sha256": "3fe96c151d46c1d4e5edc6ed690851b8e53634041114bad04729bc16b0445156",
|
||||
"size": 44219107,
|
||||
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz"
|
||||
},
|
||||
"linux-i686": {
|
||||
"sha256": "b4055695ffc2dfc0bcb6dafdc2572a6e01151c4179ef5fa972b3fcb2183eb155",
|
||||
"size": 45566336,
|
||||
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-linux32-1.22.0-80-g6c4433a-5.2.0.tar.gz"
|
||||
},
|
||||
"macos": {
|
||||
"sha256": "a4307a97945d2f2f2745f415fbe80d727750e19f91f9a1e7e2f8a6065652f9da",
|
||||
"size": 46517409,
|
||||
"url": "https://dl.espressif.com/dl/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz"
|
||||
},
|
||||
"name": "1.22.0-80-g6c4433a-5.2.0",
|
||||
"status": "recommended"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Toolchain for ESP32 ULP coprocessor",
|
||||
"export_paths": [
|
||||
[
|
||||
"esp32ulp-elf-binutils",
|
||||
"bin"
|
||||
]
|
||||
],
|
||||
"export_vars": {},
|
||||
"info_url": "https://github.com/espressif/binutils-esp32ulp",
|
||||
"install": "always",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"name": "esp32ulp-elf",
|
||||
"version_cmd": [
|
||||
"esp32ulp-elf-as",
|
||||
"--version"
|
||||
],
|
||||
"version_regex": "\\(GNU Binutils\\)\\s+([0-9a-z\\.\\-]+)",
|
||||
"versions": [
|
||||
{
|
||||
"linux-amd64": {
|
||||
"sha256": "c1bbcd65e1e30c7312a50344c8dbc70c2941580a79aa8f8abbce8e0e90c79566",
|
||||
"size": 8246604,
|
||||
"url": "https://dl.espressif.com/dl/binutils-esp32ulp-linux64-2.28.51-esp32ulp-20180809.tar.gz"
|
||||
},
|
||||
"macos": {
|
||||
"sha256": "c92937d85cc9a90eb6c6099ce767ca021108c18c94e34bd7b1fa0cde168f94a0",
|
||||
"size": 5726662,
|
||||
"url": "https://dl.espressif.com/dl/binutils-esp32ulp-macos-2.28.51-esp32ulp-20180809.tar.gz"
|
||||
},
|
||||
"name": "2.28.51.20170517",
|
||||
"status": "recommended",
|
||||
"win32": {
|
||||
"sha256": "92dc83e69e534c9f73d7b939088f2e84f757d2478483415d17fe9dd1c236f2fd",
|
||||
"size": 12231559,
|
||||
"url": "https://dl.espressif.com/dl/binutils-esp32ulp-win32-2.28.51-esp32ulp-20180809.zip"
|
||||
},
|
||||
"win64": {
|
||||
"sha256": "92dc83e69e534c9f73d7b939088f2e84f757d2478483415d17fe9dd1c236f2fd",
|
||||
"size": 12231559,
|
||||
"url": "https://dl.espressif.com/dl/binutils-esp32ulp-win32-2.28.51-esp32ulp-20180809.zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "CMake build system",
|
||||
"export_paths": [
|
||||
[
|
||||
"bin"
|
||||
]
|
||||
],
|
||||
"export_vars": {},
|
||||
"info_url": "https://github.com/Kitware/CMake",
|
||||
"install": "on_request",
|
||||
"license": "BSD-3-Clause",
|
||||
"name": "cmake",
|
||||
"platform_overrides": [
|
||||
{
|
||||
"install": "always",
|
||||
"platforms": [
|
||||
"win32",
|
||||
"win64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"export_paths": [
|
||||
[
|
||||
"CMake.app",
|
||||
"Contents",
|
||||
"bin"
|
||||
]
|
||||
],
|
||||
"platforms": [
|
||||
"macos"
|
||||
]
|
||||
}
|
||||
],
|
||||
"strip_container_dirs": 1,
|
||||
"version_cmd": [
|
||||
"cmake",
|
||||
"--version"
|
||||
],
|
||||
"version_regex": "cmake version ([0-9.]+)",
|
||||
"versions": [
|
||||
{
|
||||
"linux-amd64": {
|
||||
"sha256": "563a39e0a7c7368f81bfa1c3aff8b590a0617cdfe51177ddc808f66cc0866c76",
|
||||
"size": 38405896,
|
||||
"url": "https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4-Linux-x86_64.tar.gz"
|
||||
},
|
||||
"macos": {
|
||||
"sha256": "fef537614d73fda848f6168273b6c7ba45f850484533361e7bc50ac1d315f780",
|
||||
"size": 32062124,
|
||||
"url": "https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4-Darwin-x86_64.tar.gz"
|
||||
},
|
||||
"name": "3.13.4",
|
||||
"status": "recommended",
|
||||
"win32": {
|
||||
"sha256": "28daf772f55d817a13ef14e25af2a5569f8326dac66a6aa3cc5208cf1f8e943f",
|
||||
"size": 26385104,
|
||||
"url": "https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4-win32-x86.zip"
|
||||
},
|
||||
"win64": {
|
||||
"sha256": "bcd477d49e4a9400b41213d53450b474beaedb264631693c958ef9affa8e5623",
|
||||
"size": 29696565,
|
||||
"url": "https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4-win64-x64.zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "OpenOCD for ESP32",
|
||||
"export_paths": [
|
||||
[
|
||||
"openocd-esp32",
|
||||
"bin"
|
||||
]
|
||||
],
|
||||
"export_vars": {
|
||||
"OPENOCD_SCRIPTS": "${TOOL_PATH}/openocd-esp32/share/openocd/scripts"
|
||||
},
|
||||
"info_url": "https://github.com/espressif/openocd-esp32",
|
||||
"install": "always",
|
||||
"license": "GPL-2.0-only",
|
||||
"name": "openocd-esp32",
|
||||
"version_cmd": [
|
||||
"openocd",
|
||||
"--version"
|
||||
],
|
||||
"version_regex": "Open On-Chip Debugger\\s+([a-z0-9.-]+)\\s+",
|
||||
"versions": [
|
||||
{
|
||||
"linux-amd64": {
|
||||
"sha256": "e5b5579edffde090e426b4995b346e281843bf84394f8e68c8e41bd1e4c576bd",
|
||||
"size": 1681596,
|
||||
"url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20190313/openocd-esp32-linux64-0.10.0-esp32-20190313.tar.gz"
|
||||
},
|
||||
"macos": {
|
||||
"sha256": "09504eea5aa92646a117f16573c95b34e04b4010791a2f8fefcd2bd8c430f081",
|
||||
"size": 1760536,
|
||||
"url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20190313/openocd-esp32-macos-0.10.0-esp32-20190313.tar.gz"
|
||||
},
|
||||
"name": "v0.10.0-esp32-20190313",
|
||||
"status": "recommended",
|
||||
"win32": {
|
||||
"sha256": "b86a7f9f39dfc4d8e289fc819375bbb7a5e9fcb8895805ba2b5faf67b8b25ce2",
|
||||
"size": 2098513,
|
||||
"url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20190313/openocd-esp32-win32-0.10.0-esp32-20190313.zip"
|
||||
},
|
||||
"win64": {
|
||||
"sha256": "b86a7f9f39dfc4d8e289fc819375bbb7a5e9fcb8895805ba2b5faf67b8b25ce2",
|
||||
"size": 2098513,
|
||||
"url": "https://github.com/espressif/openocd-esp32/releases/download/v0.10.0-esp32-20190313/openocd-esp32-win32-0.10.0-esp32-20190313.zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "menuconfig tool",
|
||||
"export_paths": [
|
||||
[
|
||||
""
|
||||
]
|
||||
],
|
||||
"export_vars": {},
|
||||
"info_url": "https://github.com/espressif/kconfig-frontends",
|
||||
"install": "never",
|
||||
"license": "GPL-2.0-only",
|
||||
"name": "mconf",
|
||||
"platform_overrides": [
|
||||
{
|
||||
"install": "always",
|
||||
"platforms": [
|
||||
"win32",
|
||||
"win64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"strip_container_dirs": 1,
|
||||
"version_cmd": [
|
||||
"mconf-idf",
|
||||
"-v"
|
||||
],
|
||||
"version_regex": "mconf-idf version mconf-([a-z0-9.-]+)-win32",
|
||||
"versions": [
|
||||
{
|
||||
"name": "v4.6.0.0-idf-20190628",
|
||||
"status": "recommended",
|
||||
"win32": {
|
||||
"sha256": "1b8f17f48740ab669c13bd89136e8cc92efe0cd29872f0d6c44148902a2dc40c",
|
||||
"size": 826114,
|
||||
"url": "https://github.com/espressif/kconfig-frontends/releases/download/v4.6.0.0-idf-20190628/mconf-v4.6.0.0-idf-20190628-win32.zip"
|
||||
},
|
||||
"win64": {
|
||||
"sha256": "1b8f17f48740ab669c13bd89136e8cc92efe0cd29872f0d6c44148902a2dc40c",
|
||||
"size": 826114,
|
||||
"url": "https://github.com/espressif/kconfig-frontends/releases/download/v4.6.0.0-idf-20190628/mconf-v4.6.0.0-idf-20190628-win32.zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Ninja build system",
|
||||
"export_paths": [
|
||||
[
|
||||
""
|
||||
]
|
||||
],
|
||||
"export_vars": {},
|
||||
"info_url": "https://github.com/ninja-build/ninja",
|
||||
"install": "on_request",
|
||||
"license": "Apache-2.0",
|
||||
"name": "ninja",
|
||||
"platform_overrides": [
|
||||
{
|
||||
"install": "always",
|
||||
"platforms": [
|
||||
"win32",
|
||||
"win64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"version_cmd": [
|
||||
"ninja",
|
||||
"--version"
|
||||
],
|
||||
"version_regex": "([0-9.]+)",
|
||||
"versions": [
|
||||
{
|
||||
"linux-amd64": {
|
||||
"sha256": "978fd9e26c2db8d33392c6daef50e9edac0a3db6680710a9f9ad47e01f3e49b7",
|
||||
"size": 85276,
|
||||
"url": "https://dl.espressif.com/dl/ninja-1.9.0-linux64.tar.gz"
|
||||
},
|
||||
"macos": {
|
||||
"sha256": "9504cd1783ef3c242d06330a50d54dc8f838b605f5fc3e892c47254929f7350c",
|
||||
"size": 91457,
|
||||
"url": "https://dl.espressif.com/dl/ninja-1.9.0-osx.tar.gz"
|
||||
},
|
||||
"name": "1.9.0",
|
||||
"status": "recommended",
|
||||
"win64": {
|
||||
"sha256": "2d70010633ddaacc3af4ffbd21e22fae90d158674a09e132e06424ba3ab036e9",
|
||||
"size": 254497,
|
||||
"url": "https://dl.espressif.com/dl/ninja-1.9.0-win64.zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "IDF wrapper tool for Windows",
|
||||
"export_paths": [
|
||||
[
|
||||
""
|
||||
]
|
||||
],
|
||||
"export_vars": {},
|
||||
"info_url": "https://github.com/espressif/esp-idf/tree/master/tools/windows/idf_exe",
|
||||
"install": "never",
|
||||
"license": "Apache-2.0",
|
||||
"name": "idf-exe",
|
||||
"platform_overrides": [
|
||||
{
|
||||
"install": "always",
|
||||
"platforms": [
|
||||
"win32",
|
||||
"win64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"version_cmd": [
|
||||
"idf.py.exe",
|
||||
"-v"
|
||||
],
|
||||
"version_regex": "([0-9.]+)",
|
||||
"versions": [
|
||||
{
|
||||
"name": "1.0",
|
||||
"status": "recommended",
|
||||
"win32": {
|
||||
"sha256": "83a83ac7a246cbae93884db7c5f2ef9a7607d602340b1cf1e64ec2a925071748",
|
||||
"size": 11289,
|
||||
"url": "https://dl.espressif.com/dl/idf-exe-v1.0.zip"
|
||||
},
|
||||
"win64": {
|
||||
"sha256": "83a83ac7a246cbae93884db7c5f2ef9a7607d602340b1cf1e64ec2a925071748",
|
||||
"size": 11289,
|
||||
"url": "https://dl.espressif.com/dl/idf-exe-v1.0.zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Ccache (compiler cache)",
|
||||
"export_paths": [
|
||||
[
|
||||
""
|
||||
]
|
||||
],
|
||||
"export_vars": {},
|
||||
"info_url": "https://github.com/ccache/ccache",
|
||||
"install": "never",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"name": "ccache",
|
||||
"platform_overrides": [
|
||||
{
|
||||
"install": "always",
|
||||
"platforms": [
|
||||
"win64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"version_cmd": [
|
||||
"ccache.exe",
|
||||
"--version"
|
||||
],
|
||||
"version_regex": "ccache version ([0-9.]+)",
|
||||
"versions": [
|
||||
{
|
||||
"name": "3.7",
|
||||
"status": "recommended",
|
||||
"win64": {
|
||||
"sha256": "37e833f3f354f1145503533e776c1bd44ec2e77ff8a2476a1d2039b0b10c78d6",
|
||||
"size": 142401,
|
||||
"url": "https://dl.espressif.com/dl/ccache-3.7-w64.zip"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 1
|
||||
}
|
157
tools/windows/tool_setup/utils.iss.inc
Normal file
157
tools/windows/tool_setup/utils.iss.inc
Normal file
|
@ -0,0 +1,157 @@
|
|||
{ Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
SPDX-License-Identifier: Apache-2.0 }
|
||||
|
||||
{ ------------------------------ Helper functions from libcmdlinerunner.dll ------------------------------ }
|
||||
|
||||
function ProcStart(cmdline, workdir: string): Longword;
|
||||
external 'proc_start@files:cmdlinerunner.dll cdecl';
|
||||
|
||||
function ProcGetExitCode(inst: Longword): DWORD;
|
||||
external 'proc_get_exit_code@files:cmdlinerunner.dll cdecl';
|
||||
|
||||
function ProcGetOutput(inst: Longword; dest: PAnsiChar; sz: DWORD): DWORD;
|
||||
external 'proc_get_output@files:cmdlinerunner.dll cdecl';
|
||||
|
||||
procedure ProcEnd(inst: Longword);
|
||||
external 'proc_end@files:cmdlinerunner.dll cdecl';
|
||||
|
||||
{ ------------------------------ WinAPI functions ------------------------------ }
|
||||
|
||||
#ifdef UNICODE
|
||||
#define AW "W"
|
||||
#else
|
||||
#define AW "A"
|
||||
#endif
|
||||
|
||||
function SetEnvironmentVariable(lpName: string; lpValue: string): BOOL;
|
||||
external 'SetEnvironmentVariable{#AW}@kernel32.dll stdcall';
|
||||
|
||||
{ ------------------------------ Functions to query the registry ------------------------------ }
|
||||
|
||||
{ Utility to search in HKLM and HKCU for an installation path. Looks in both 64-bit & 32-bit registry. }
|
||||
function GetInstallPath(key, valuename : String) : String;
|
||||
var
|
||||
value: String;
|
||||
begin
|
||||
Result := '';
|
||||
if RegQueryStringValue(HKEY_LOCAL_MACHINE, key, valuename, value) then
|
||||
begin
|
||||
Result := value;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if RegQueryStringValue(HKEY_CURRENT_USER, key, valuename, value) then
|
||||
begin
|
||||
Result := value;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ This is 32-bit setup running on 64-bit Windows, but ESP-IDF can use 64-bit tools also }
|
||||
if IsWin64 and RegQueryStringValue(HKLM64, key, valuename, value) then
|
||||
begin
|
||||
Result := value;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if IsWin64 and RegQueryStringValue(HKCU64, key, valuename, value) then
|
||||
begin
|
||||
Result := value;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ------------------------------ Function to exit from the installer ------------------------------ }
|
||||
|
||||
procedure AbortInstallation(Message: String);
|
||||
begin
|
||||
MsgBox(Message, mbError, MB_OK);
|
||||
Abort();
|
||||
end;
|
||||
|
||||
{ ------------------------------ File system related functions ------------------------------ }
|
||||
|
||||
function DirIsEmpty(DirName: String): Boolean;
|
||||
var
|
||||
FindRec: TFindRec;
|
||||
begin
|
||||
Result := True;
|
||||
if FindFirst(DirName+'\*', FindRec) then begin
|
||||
try
|
||||
repeat
|
||||
if (FindRec.Name <> '.') and (FindRec.Name <> '..') then begin
|
||||
Result := False;
|
||||
break;
|
||||
end;
|
||||
until not FindNext(FindRec);
|
||||
finally
|
||||
FindClose(FindRec);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
type
|
||||
TFindFileCallback = procedure(Filename: String);
|
||||
|
||||
procedure FindFileRecusive(Directory: string; FileName: string; Callback: TFindFileCallback);
|
||||
var
|
||||
FindRec: TFindRec;
|
||||
FilePath: string;
|
||||
begin
|
||||
if FindFirst(Directory + '\*', FindRec) then
|
||||
begin
|
||||
try
|
||||
repeat
|
||||
if (FindRec.Name = '.') or (FindRec.Name = '..') then
|
||||
continue;
|
||||
|
||||
FilePath := Directory + '\' + FindRec.Name;
|
||||
if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
|
||||
begin
|
||||
FindFileRecusive(FilePath, FileName, Callback);
|
||||
end else if CompareText(FindRec.Name, FileName) = 0 then
|
||||
begin
|
||||
Callback(FilePath);
|
||||
end;
|
||||
until not FindNext(FindRec);
|
||||
finally
|
||||
FindClose(FindRec);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ------------------------------ Version related functions ------------------------------ }
|
||||
|
||||
function VersionExtractMajorMinor(Version: String; var Major: Integer; var Minor: Integer): Boolean;
|
||||
var
|
||||
Delim: Integer;
|
||||
MajorStr, MinorStr: String;
|
||||
OrigVersion, ExpectedPrefix: String;
|
||||
begin
|
||||
Result := False;
|
||||
OrigVersion := Version;
|
||||
Delim := Pos('.', Version);
|
||||
if Delim = 0 then exit;
|
||||
|
||||
MajorStr := Version;
|
||||
Delete(MajorStr, Delim, Length(MajorStr));
|
||||
Delete(Version, 1, Delim);
|
||||
Major := StrToInt(MajorStr);
|
||||
|
||||
Delim := Pos('.', Version);
|
||||
if Delim = 0 then Delim := Length(MinorStr);
|
||||
|
||||
MinorStr := Version;
|
||||
Delete(MinorStr, Delim, Length(MinorStr));
|
||||
Delete(Version, 1, Delim);
|
||||
Minor := StrToInt(MinorStr);
|
||||
|
||||
{ Sanity check }
|
||||
ExpectedPrefix := IntToStr(Major) + '.' + IntToStr(Minor);
|
||||
if Pos(ExpectedPrefix, OrigVersion) <> 1 then
|
||||
begin
|
||||
Log('VersionExtractMajorMinor: version=' + OrigVersion + ', expected=' + ExpectedPrefix);
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := True;
|
||||
end;
|
Loading…
Reference in a new issue