diff --git a/HISTORY.rst b/HISTORY.rst index 9d120c1e..bcdc4578 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,12 +1,42 @@ Release History =============== +2.2.0 (2015-07-01) +------------------ + +* Allowed to exclude/include source files from build process using + `src_filter `__ + (`issue #240 `_) +* Launch own extra script before firmware building/uploading processes + (`issue #239 `_) +* Specify own path to the linker script (ld) using + `build_flags `__ + option + (`issue #233 `_) +* Specify library compatibility with the all platforms/frameworks + using ``*`` symbol in + `library.json `__ +* Added support for new embedded boards: *ST 32L0538DISCOVERY and Delta DFCM-NNN40* + to `Framework mbed `__ +* Updated packages for + `Framework Arduino (AVR, SAM, Espressif and Teensy cores `__, + `Framework mbed `__, + `Espressif ESP8266 SDK `__ + (`issue #246 `_) +* Fixed ``stk500v2_command(): command failed`` + (`issue #238 `_) +* Fixed IDE project generator when board is specified + (`issue #242 `_) +* Fixed relative path for includes when generating project for IDE + (`issue #243 `_) +* Fixed ESP8266 native SDK exception + (`issue #245 `_) + 2.1.2 (2015-06-21) ------------------ * Fixed broken link to SCons installer - 2.1.1 (2015-06-09) ------------------ @@ -43,9 +73,8 @@ Release History 2.0.1 (2015-05-27) ------------------ -* Handle new environment variables +* Handle new environment variable `PLATFORMIO_BUILD_FLAGS `_ - and `PLATFORMIO_LDF_CYCLIC `_ * Pass to API requests information about Continuous Integration system. This information will be used by PlatformIO-API. * Use ``include`` directories from toolchain when initialising project for IDE @@ -85,11 +114,11 @@ Release History (`issue #192 `_) * Control verbosity of `platformio run `_ command via ``-v/--verbose`` option * Add library dependencies for build environment using - `install_libs `_ + `lib_install `_ option in ``platformio.ini`` (`issue #134 `_) * Specify libraries which are compatible with build environment using - `use_libs `_ + `lib_use `_ option in ``platformio.ini`` (`issue #148 `_) * Add more boards to PlatformIO project with @@ -277,7 +306,7 @@ Release History commands which allows to return the output in `JSON `_ format (`issue #42 `_) * Allowed to ignore some libs from *Library Dependency Finder* via - `ignore_libs `_ option + `lib_ignore `_ option * Improved `platformio run `__ command: asynchronous output for build process, timing and detailed information about environment configuration @@ -445,10 +474,10 @@ Release History * Implemented `platformio serialports `_ command * Allowed to put special build flags only for ``src`` files via - `srcbuild_flags `_ + `src_build_flags `_ environment option * Allowed to override some of settings via system environment variables - such as: ``PLATFORMIO_SRCBUILD_FLAGS`` and ``PLATFORMIO_ENVS_DIR`` + such as: ``PLATFORMIO_SRC_BUILD_FLAGS`` and ``PLATFORMIO_ENVS_DIR`` * Added ``--upload-port`` option for `platformio run `__ command * Implemented (especially for `SmartAnthill `_) `platformio run -t uploadlazy `_ diff --git a/README.rst b/README.rst index aff892be..05c80928 100644 --- a/README.rst +++ b/README.rst @@ -38,15 +38,16 @@ PlatformIO `Reddit `_ | `Twitter `_ -*Atmel AVR & SAM, Espressif, Freescale Kinetis, Nordic nRF51, NXP LPC, -Silicon Labs EFM32, ST STM32, TI MSP430 & Tiva, Teensy, Arduino, mbed, -libOpenCM3, etc.* - .. image:: https://raw.githubusercontent.com/platformio/platformio/develop/docs/_static/platformio-logo.png :target: http://platformio.org `PlatformIO `_ is a cross-platform code builder -and the missing library manager. +and the missing library manager (Ready for embedded development, IDE and +Continuous integration, Arduino and MBED compatible). + +*Atmel AVR & SAM, Espressif, Freescale Kinetis, Nordic nRF51, NXP LPC, +Silicon Labs EFM32, ST STM32, TI MSP430 & Tiva, Teensy, Arduino, mbed, +libOpenCM3, etc.* * `Get Started `_ * `Web 2.0 Library Search `_ @@ -81,11 +82,13 @@ Embedded Development. *Easier Than Ever.* settings for most popular `Embedded Boards `_. * Colourful `command-line output `_ -* Built-in `Serial Port Monitor `_ -* Configurable `build -flags/-options `_ +* `IDE Integration `_ with + *Arduino, Eclipse, Energia, Qt Creator, Sublime Text, Vim, Visual Studio* +* `Continuous Integration `_ + with *AppVeyor, Circle CI, Drone, Shippable, Travis CI* +* Built-in `Serial Port Monitor `_ and configurable + `build -flags/-options `_ * Automatic **firmware uploading** -* Integration with `development environments (IDE) `_ -* Ready for **Cloud Compiling** and `Continuous Integration `_ * Pre-built tool chains, frameworks for the popular `Hardware Platforms `_ .. image:: https://raw.githubusercontent.com/platformio/platformio-web/develop/app/images/platformio-embedded-development.png diff --git a/docs/_static/ide-platformio-qtcreator-4.png b/docs/_static/ide-platformio-qtcreator-4.png index a3b044e1..e2c5517b 100644 Binary files a/docs/_static/ide-platformio-qtcreator-4.png and b/docs/_static/ide-platformio-qtcreator-4.png differ diff --git a/docs/_static/platformio-logo.png b/docs/_static/platformio-logo.png index 62bde5ca..8cbe937a 100644 Binary files a/docs/_static/platformio-logo.png and b/docs/_static/platformio-logo.png differ diff --git a/docs/envvars.rst b/docs/envvars.rst index 25414e27..383322f3 100644 --- a/docs/envvars.rst +++ b/docs/envvars.rst @@ -70,19 +70,26 @@ PLATFORMIO_BUILD_FLAGS Allows to set :ref:`projectconf` option :ref:`projectconf_build_flags`. -.. _envvar_PLATFORMIO_SRCBUILD_FLAGS: +.. _envvar_PLATFORMIO_SRC_BUILD_FLAGS: -PLATFORMIO_SRCBUILD_FLAGS -~~~~~~~~~~~~~~~~~~~~~~~~~ +PLATFORMIO_SRC_BUILD_FLAGS +~~~~~~~~~~~~~~~~~~~~~~~~~~ -Allows to set :ref:`projectconf` option :ref:`projectconf_srcbuild_flags`. +Allows to set :ref:`projectconf` option :ref:`projectconf_src_build_flags`. -.. _envvar_PLATFORMIO_LDF_CYCLIC: +.. _envvar_PLATFORMIO_SRC_FILTER: -PLATFORMIO_LDF_CYCLIC +PLATFORMIO_SRC_FILTER ~~~~~~~~~~~~~~~~~~~~~ -Allows to set :ref:`projectconf` option :ref:`projectconf_ldf_cyclic`. +Allows to set :ref:`projectconf` option :ref:`projectconf_src_filter`. + +.. _envvar_PLATFORMIO_EXTRA_SCRIPT: + +PLATFORMIO_EXTRA_SCRIPT +~~~~~~~~~~~~~~~~~~~~~~~ + +Allows to set :ref:`projectconf` option :ref:`projectconf_extra_script`. Settings -------- diff --git a/docs/faq.rst b/docs/faq.rst index 6065be35..59e8d400 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -100,3 +100,9 @@ Please upgrade *SetupTools* package: # Then re-install PlatformIO $ [sudo] pip uninstall platformio $ [sudo] pip install platformio + +ARM toolchain: ``cc1plus: error while loading shared libraries`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See related answers for +`error while loading shared libraries `_. diff --git a/docs/frameworks/mbed.rst b/docs/frameworks/mbed.rst index 9c60a9fb..4b2feb88 100644 --- a/docs/frameworks/mbed.rst +++ b/docs/frameworks/mbed.rst @@ -59,6 +59,26 @@ CQ Publishing - 64 Kb - 10 Kb +Delta +~~~~~ + +.. list-table:: + :header-rows: 1 + + * - Type ``board`` + - Name + - Microcontroller + - Frequency + - Flash + - RAM + + * - ``dfcm_nnn40`` + - `Delta DFCM-NNN40 `_ + - NRF51822 + - 32 MHz + - 256 Kb + - 32 Kb + Embedded Artists ~~~~~~~~~~~~~~~~ @@ -345,11 +365,11 @@ ST - 48 Kb * - ``disco_f334c8`` - - `ST 32F3348DISCOVERY `_ + - `ST 32F3348DISCOVERY `_ - STM32F334C8T6 - 72 MHz - 64 Kb - - 16 Kb + - 12 Kb * - ``disco_f401vc`` - `ST 32F401CDISCOVERY `_ @@ -372,6 +392,13 @@ ST - 2048 Kb - 256 Kb + * - ``disco_l053c8`` + - `ST 32L0538DISCOVERY `_ + - STM32L053C8T6 + - 32 MHz + - 64 Kb + - 8 Kb + * - ``nucleo_f030r8`` - `ST Nucleo F030R8 `_ - STM32F030R8T6 diff --git a/docs/ide/eclipse.rst b/docs/ide/eclipse.rst index ee89db47..e40fcbff 100644 --- a/docs/ide/eclipse.rst +++ b/docs/ide/eclipse.rst @@ -29,7 +29,7 @@ Integration Project Generator ^^^^^^^^^^^^^^^^^ -SSince PlatformIO 2.0 you can generate Eclipse compatible project using +Since PlatformIO 2.0 you can generate Eclipse compatible project using :option:`platformio init --ide` command. Please choose board type using :ref:`cmd_boards` command and run: @@ -52,4 +52,4 @@ Screenshot ---------- .. image:: ../_static/ide-platformio-eclipse.png - :target: http://www.ikravets.com/computer-life/programming/2014/06/20/building-and-debugging-atmel-avr-arduino-based-project-using- eclipse-ideplatformio + :target: http://www.ikravets.com/computer-life/programming/2014/06/20/building-and-debugging-atmel-avr-arduino-based-project-using-eclipse-ideplatformio diff --git a/docs/ide/qtcreator.rst b/docs/ide/qtcreator.rst index d5d97994..e53ff505 100644 --- a/docs/ide/qtcreator.rst +++ b/docs/ide/qtcreator.rst @@ -32,6 +32,11 @@ Since PlatformIO 2.0 you can generate Qt Creator compatible project using Then import this project via ``File > New File or Project > Import Project`` and specify root directory where is located :ref:`projectconf`. +After import, we need to delete default build and clean steps and configure project with PlatformIO source code builder (click on Projects label on left menu or ``Ctrl+5`` shortcut): + +.. image:: ../_static/ide-platformio-qtcreator-3.png + :target: http://docs.platformio.org/en/latest/_static/ide-platformio-qtcreator-3.png + Manual Integration ^^^^^^^^^^^^^^^^^^ @@ -41,14 +46,16 @@ Setup New Project First of all, let's create new project from Qt Creator Start Page: ``New Project`` or using ``Menu: File > New File or Project``, then select project with ``Empty Qt Project`` type (``Other Project > Empty Qt Project``), fill ``Name``, ``Create in``. .. image:: ../_static/ide-platformio-qtcreator-1.png + :target: http://docs.platformio.org/en/latest/_static/ide-platformio-qtcreator-1.png On the next steps select any available kit and click Finish button. .. image:: ../_static/ide-platformio-qtcreator-2.png -Secondly, we need to configure project with PlatformIO source code builder (click on Projects label on left menu or ``Ctrl+5`` shortcut): +Secondly, we need to delete default build and clean steps and configure project with PlatformIO source code builder (click on Projects label on left menu or ``Ctrl+5`` shortcut): .. image:: ../_static/ide-platformio-qtcreator-3.png + :target: http://docs.platformio.org/en/latest/_static/ide-platformio-qtcreator-3.png Thirdly, change project file by adding path to directories with header files. Please edit project file to match the following contents: @@ -58,15 +65,14 @@ Thirdly, change project file by adding path to directories with header files. Pl HOMEDIR += $$(USERPROFILE) } else { - HOMEDIR += $$(PWD) + HOMEDIR += $$(HOME) } - INCLUDEPATH += "$$HOMEDIR/.platformio/packages/framework-arduinoavr/cores/arduino" - INCLUDEPATH += "$$HOMEDIR/.platformio/packages/toolchain-atmelavr/avr/include" - - win32:INCLUDEPATH ~= s,/,\\,g + INCLUDEPATH += "$${HOMEDIR}/.platformio/packages/framework-arduinoavr/cores/arduino" + INCLUDEPATH += "$${HOMEDIR}/.platformio/packages/toolchain-atmelavr/avr/include" .. image:: ../_static/ide-platformio-qtcreator-4.png + :target: http://docs.platformio.org/en/latest/_static/ide-platformio-qtcreator-4.png First program in Qt Creator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -77,6 +83,7 @@ Simple "Blink" project will consist from two files: Let's create new text file named ``main.c`` using ``Menu: New File or Project > General > Text File``: .. image:: ../_static/ide-platformio-qtcreator-5.png + :target: http://docs.platformio.org/en/latest/_static/ide-platformio-qtcreator-5.png Copy the source code which is described below to file ``main.c``. @@ -101,6 +108,7 @@ Copy the source code which is described below to file ``main.c``. 3. Locate the project configuration file named ``platformio.ini`` at the root of the project directory and open it. .. image:: ../_static/ide-platformio-qtcreator-6.png + :target: http://docs.platformio.org/en/latest/_static/ide-platformio-qtcreator-6.png Edit the content to match the code described below. @@ -128,3 +136,5 @@ Conclusion Taking everything into account, we can build project with shortcut ``Ctrl+Shift+B`` or using ``Menu: Build > Build All``: .. image:: ../_static/ide-platformio-qtcreator-7.png + :target: http://docs.platformio.org/en/latest/_static/ide-platformio-qtcreator-7.png + diff --git a/docs/ide/visualstudio.rst b/docs/ide/visualstudio.rst index 4afb100d..ef365e78 100644 --- a/docs/ide/visualstudio.rst +++ b/docs/ide/visualstudio.rst @@ -123,3 +123,4 @@ Conclusion Taking everything into account, we can build project with shortcut ``Ctrl+Shift+B`` or using ``Menu: Build > Build Solution``: .. image:: ../_static/ide-vs-platformio-newproject-8.png + :target: http://docs.platformio.org/en/latest/_static/ide-vs-platformio-newproject-8.png diff --git a/docs/index.rst b/docs/index.rst index 2ff78019..a0d4a37c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,5 +1,8 @@ -PlatformIO: A cross-platform code builder and the missing library manager -========================================================================= +PlatformIO is a cross-platform code builder and the missing library manager +=========================================================================== + +**Ready for embedded development, IDE and Continuous integration, Arduino and +MBED compatible** *Atmel AVR & SAM, Espressif, Freescale Kinetis, Nordic nRF51, NXP LPC, Silicon Labs EFM32, ST STM32, TI MSP430 & Tiva, Teensy, Arduino, mbed, @@ -27,11 +30,13 @@ Embedded Development. *Easier Than Ever.* ----------------------------------------- * Colourful command-line output -* Built-in :ref:`Serial Port Monitor ` -* Configurable build :ref:`-flags/-options ` -* Integration with :ref:`development environments (IDE) ` -* Ready for Cloud Compiling and :ref:`ci` -* Pre-built tool chains, :ref:`frameworks` for the popular Hardware Platforms +* :ref:`IDE Integration ` with *Arduino, Eclipse, Energia, Qt Creator, + Sublime Text, Vim, Visual Studio* +* :ref:`ci` with *AppVeyor, Circle CI, Drone, Shippable, Travis CI* +* Built-in :ref:`Serial Port Monitor ` and + configurable build :ref:`-flags/-options ` +* Pre-built tool chains, :ref:`frameworks` for the + :ref:`Development Platforms ` Smart Code Builder. *Fast and Reliable.* ---------------------------------------- diff --git a/docs/installation.rst b/docs/installation.rst index 619253e7..26d6460f 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -122,18 +122,12 @@ Development Version .. warning:: We don't recommend to use ``develop`` version in production. -1. If you had have already installed PlatformIO, please uninstall it: - -.. code-block:: bash - - $ pip uninstall platformio - -2. Install the latest PlatformIO from the ``develop`` branch: +Install the latest PlatformIO from the ``develop`` branch: .. code-block:: bash $ pip install https://github.com/platformio/platformio/archive/develop.zip If you want to be up-to-date with the latest ``develop`` version of PlatformIO, -then you need to perform step #2 each time if you see the new commits in -`PlatformIO GitHub repository `_. +then you need to re-install PlatformIO each time if you see the new commits in +`PlatformIO GitHub repository (branch: develop) `_. diff --git a/docs/librarymanager/config.rst b/docs/librarymanager/config.rst index 1d0d64d2..8544ac35 100644 --- a/docs/librarymanager/config.rst +++ b/docs/librarymanager/config.rst @@ -249,6 +249,12 @@ patterns. A list with compatible frameworks. The available framework types are defined in the :ref:`platforms` section. +If the library is compatible with the all frameworks, then you can use ``*`` +symbol: + +.. code-block:: javascript + + "frameworks": "*" .. _libjson_platforms: @@ -260,6 +266,13 @@ the :ref:`platforms` section. A list with compatible platforms. The available platform types are defined in :ref:`platforms` section. +If the library is compatible with the all platforms, then you can use ``*`` +symbol: + +.. code-block:: javascript + + "platforms": "*" + .. _libjson_dependencies: diff --git a/docs/platforms/nordicnrf51.rst b/docs/platforms/nordicnrf51.rst index 6ae93a56..bb922543 100644 --- a/docs/platforms/nordicnrf51.rst +++ b/docs/platforms/nordicnrf51.rst @@ -49,6 +49,26 @@ Boards * For more detailed ``board`` information please scroll tables below by horizontal. +Delta +~~~~~ + +.. list-table:: + :header-rows: 1 + + * - Type ``board`` + - Name + - Microcontroller + - Frequency + - Flash + - RAM + + * - ``dfcm_nnn40`` + - `Delta DFCM-NNN40 `_ + - NRF51822 + - 32 MHz + - 256 Kb + - 32 Kb + JKSoft ~~~~~~ diff --git a/docs/platforms/ststm32.rst b/docs/platforms/ststm32.rst index 3aaec0d5..1276ddbf 100644 --- a/docs/platforms/ststm32.rst +++ b/docs/platforms/ststm32.rst @@ -142,11 +142,11 @@ ST - 48 Kb * - ``disco_f334c8`` - - `ST 32F3348DISCOVERY `_ + - `ST 32F3348DISCOVERY `_ - STM32F334C8T6 - 72 MHz - 64 Kb - - 16 Kb + - 12 Kb * - ``disco_f401vc`` - `ST 32F401CDISCOVERY `_ @@ -169,6 +169,13 @@ ST - 2048 Kb - 256 Kb + * - ``disco_l053c8`` + - `ST 32L0538DISCOVERY `_ + - STM32L053C8T6 + - 32 MHz + - 64 Kb + - 8 Kb + * - ``disco_l152rb`` - `ST STM32LDISCOVERY `_ - STM32L152RBT6 diff --git a/docs/projectconf.rst b/docs/projectconf.rst index 8aba9efe..66c8cd0c 100644 --- a/docs/projectconf.rst +++ b/docs/projectconf.rst @@ -145,7 +145,8 @@ need to specify ``board_mcu``, ``board_f_cpu``, ``upload_protocol`` or ``upload_speed`` options. Just define a ``board`` type and *PlatformIO* will pre-fill options described above with appropriate values. -You can find the ``board`` type in *Boards* section of each :ref:`platforms`. +You can find the ``board`` type in *Boards* section of each :ref:`platforms` or +using `PlatformIO Embedded Boards Explorer `_. ``board_mcu`` @@ -198,20 +199,6 @@ A protocol that "uploader" tool uses to talk to the board. A connection speed (`baud rate `_) which "uploader" tool uses when sending firmware to board. - -``targets`` -^^^^^^^^^^^ - -A list with targets which will be processed by :ref:`cmd_run` command by -default. You can enter more then one target separated with "space". - -When no targets are defined, *PlatformIO* will build only sources by default. - -.. note:: - This option is useful to enable "auto-uploading" after building operation - (``targets = upload``). - - .. _projectconf_build_flags: ``build_flags`` @@ -226,10 +213,6 @@ processes: * - Format - Scope - Description - * - ``-Wp,option`` - - CPPFLAGS - - Bypass the compiler driver and pass *option* directly through to the - preprocessor * - ``-D name`` - CPPDEFINES - Predefine *name* as a macro, with definition 1. @@ -241,6 +224,10 @@ processes: - CPPDEFINES - Cancel any previous definition of *name*, either built in or provided with a ``-D`` option. + * - ``-Wp,option`` + - CPPFLAGS + - Bypass the compiler driver and pass *option* directly through to the + preprocessor * - ``-Wall`` - CCFLAGS - Turns on all optional warnings which are desirable for normal code. @@ -254,10 +241,18 @@ processes: - CCFLAGS - Process *file* as if ``#include "file"`` appeared as the first line of the primary source file. + * - ``-Idir`` + - CPPPATH + - Add the directory *dir* to the list of directories to be searched + for header files. * - ``-Wa,option`` - ASFLAGS, CCFLAGS - Pass *option* as an option to the assembler. If *option* contains commas, it is split into multiple options at the commas. + * - ``-Wl,option`` + - LINKFLAGS + - Pass *option* as an option to the linker. If *option* contains + commas, it is split into multiple options at the commas. * - ``-llibrary`` - LIBS - Search the *library* named library when linking @@ -265,10 +260,6 @@ processes: - LIBPATH - Add directory *dir* to the list of directories to be searched for ``-l``. - * - ``-Idir`` - - CPPPATH - - Add the directory *dir* to the list of directories to be searched - for header files. This option can be set by global environment variable :ref:`envvar_PLATFORMIO_BUILD_FLAGS`. @@ -278,11 +269,14 @@ Example: .. code-block:: ini [env:specific_defines] - build_flags = -O2 -Dfoo -Dbar=1 + build_flags = -Dfoo -Dbar=1 [env:specific_inclibs] build_flags = -I/opt/include -L/opt/lib -lfoo + [env:specific_ld_script] + build_flags = -Wl,-T/path/to/ld_script.ld + For more detailed information about available flags/options go to: @@ -300,20 +294,42 @@ For more detailed information about available flags/options go to: * `Options for Directory Search `_ -.. _projectconf_srcbuild_flags: +.. _projectconf_src_build_flags: -``srcbuild_flags`` -^^^^^^^^^^^^^^^^^^ +``src_build_flags`` +^^^^^^^^^^^^^^^^^^^ -An option ``srcbuild_flags`` has the same behaviour like ``build_flags`` +An option ``src_build_flags`` has the same behaviour like ``build_flags`` but will be applied only for the project source code from :ref:`projectconf_pio_src_dir` directory. This option can be set by global environment variable -:ref:`envvar_PLATFORMIO_SRCBUILD_FLAGS`. +:ref:`envvar_PLATFORMIO_SRC_BUILD_FLAGS`. -``install_libs`` -^^^^^^^^^^^^^^^^ +.. _projectconf_src_filter: + +``src_filter`` +^^^^^^^^^^^^^^ + +This option allows to specify which source files should be included/excluded +from build process. Filter supports 2 templates: + +* ``+`` include template +* ``-`` exclude template + +``PATH`` MAST BE related from :ref:`projectconf_pio_src_dir`. All patterns will +be applied in theirs order. +`GLOB Patterns `_ are allowed. + +By default, ``src_filter`` is predefined to +``+<*> -<.git/> - -``, which means "includes ALL files, then +exclude ``.git`` and ``svn`` repository folders and exclude ``examples`` folder. + +This option can be set by global environment variable +:ref:`envvar_PLATFORMIO_SRC_FILTER`. + +``lib_install`` +^^^^^^^^^^^^^^^ Specify dependent libraries which should be installed before environment process. The only library IDs are allowed. Multiple libraries can be passed @@ -323,43 +339,41 @@ You can obtain library IDs using :ref:`cmd_lib_search` command. Example: -.. code-block:: ini +.. code-block:: ini [env:depends_on_some_libs] - install_libs = 1,13,19 + lib_install = 1,13,19 -``use_libs`` -^^^^^^^^^^^^ +``lib_use`` +^^^^^^^^^^^ Specify libraries which should be used by ``Library Dependency Finder (LDF)`` with the highest priority. Example: -.. code-block:: ini +.. code-block:: ini [env:libs_with_highest_priority] - use_libs = OneWire_ID1 + lib_use = OneWire_ID1,SPI -``ignore_libs`` -^^^^^^^^^^^^^^^ +``lib_ignore`` +^^^^^^^^^^^^^^ Specify libraries which should be ignored by ``Library Dependency Finder (LDF)`` Example: -.. code-block:: ini +.. code-block:: ini [env:ignore_some_libs] - ignore_libs = SPI,EngduinoV3_ID123 + lib_ignore = SPI,EngduinoV3_ID123 -.. _projectconf_ldf_cyclic: - -``ldf_cyclic`` -^^^^^^^^^^^^^^ +``lib_dfcyclic`` +^^^^^^^^^^^^^^^^ Control cyclic (recursive) behaviour for ``Library Dependency Finder (LDF)``. -By default, this option is turned OFF (``ldf_cyclic=False``) and means, that +By default, this option is turned OFF (``lib_dfcyclic=False``) and means, that ``LDF`` will find only libraries which are included in source files from the project :ref:`projectconf_pio_src_dir`. @@ -367,16 +381,76 @@ If you want to enable cyclic (recursive, nested) search, please set this option to ``True``. Founded library will be treated like a new source files and ``LDF`` will search dependencies for it. -This option can be set by global environment variable -:ref:`envvar_PLATFORMIO_LDF_CYCLIC`. - Example: -.. code-block:: ini +.. code-block:: ini [env:libs_with_enabled_ldf_cyclic] - ldf_cyclic = True + lib_dfcyclic = True +.. _projectconf_extra_script: + +``extra_script`` +^^^^^^^^^^^^^^^^ + +Allows to launch extra script using `SCons `_ software +construction tool. For more details please follow to "Construction Environments" +section of +`SCons documentation `_. + +This option can be set by global environment variable +:ref:`envvar_PLATFORMIO_EXTRA_SCRIPT`. + +Example, specify own upload command for :ref:`platform_atmelavr`: + +``platformio.ini``: + +.. code-block:: ini + + [env:env_with_specific_extra_script] + platform = atmelavr + extra_script = /path/to/extra_script.py + +``extra_script.py``: + +.. code-block:: python + + from SCons.Script import DefaultEnvironment + + env = DefaultEnvironment() + + env.Replace(UPLOADHEXCMD='"$UPLOADER" --uploader --flags') + + # uncomment line below to see environment variables + # print env.Dump() + +See built-in examples of `PlatformIO build scripts `_. + +``targets`` +^^^^^^^^^^^ + +A list with targets which will be processed by :ref:`cmd_run` command by +default. You can enter more then one target separated with "space". + +Pre-built targets: + +* ``clean`` delete compiled object files, libraries and firmware binaries +* ``upload`` enable "auto-uploading" for embedded platforms after building + operation +* ``envdump`` dump current build environment + +**Tip!** You can use these targets like an option to +:option:`platformio run --target` command. For example: + +.. code-block:: bash + + # clean project + platformio run -t clean + + # dump curent build environment + platformio run --target envdump + +When no targets are defined, *PlatformIO* will build only sources by default. .. _projectconf_examples: diff --git a/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library b/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library index 734b107c..6d40eb34 160000 --- a/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library +++ b/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library @@ -1 +1 @@ -Subproject commit 734b107c393e8a91d8c1d46a42f59a4dfb25b576 +Subproject commit 6d40eb3423c4245bf5725dbf1c65d33057c08579 diff --git a/platformio/__init__.py b/platformio/__init__.py index 138a06ba..4cb7841d 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -1,14 +1,15 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -VERSION = (2, 1, 2) +VERSION = (2, 2, 0) __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" -__description__ = ("A cross-platform code builder and the missing library " - "manager (Atmel AVR & SAM, Espressif, Freescale Kinetis, " - "Nordic nRF51, NXP LPC, Silicon Labs EFM32, ST STM32, " - "TI MSP430 & Tiva, Teensy, Arduino, mbed, libOpenCM3, etc)") +__description__ = ( + "Cross-platform code builder and the missing library manager " + "(Ready for embedded development, IDE and Continuous integration, " + "Arduino and MBED compatible)" +) __url__ = "http://platformio.org" __author__ = "Ivan Kravets" diff --git a/platformio/__main__.py b/platformio/__main__.py index a4e44146..9721e794 100644 --- a/platformio/__main__.py +++ b/platformio/__main__.py @@ -41,10 +41,10 @@ class PlatformioCLI(click.MultiCommand): # pylint: disable=R0904 def _handle_obsolate_command(name): if name in ("install", "list", "search", "show", "uninstall"): click.secho( - "Warning! `platformio %s` command is obsoleted and will be " + "Warning! `platformio %s` command is deprecated and will be " "removed in the next release! Please use " "`platformio platforms %s` instead." % (name, name), - fg="red" + fg="yellow" ) from platformio.commands import platforms return getattr(platforms, "platforms_" + name) diff --git a/platformio/boards/nordicnrf51.json b/platformio/boards/nordicnrf51.json index c76c1609..beaedcd9 100644 --- a/platformio/boards/nordicnrf51.json +++ b/platformio/boards/nordicnrf51.json @@ -126,5 +126,21 @@ }, "url": "http://developer.mbed.org/platforms/Seeed-Tiny-BLE/", "vendor": "SeeedStudio" + }, + "dfcm_nnn40": { + "build": { + "f_cpu": "32000000L", + "cpu": "cortex-m0", + "mcu": "nrf51822" + }, + "frameworks": ["mbed"], + "name": "Delta DFCM-NNN40", + "platform": "nordicnrf51", + "upload": { + "maximum_ram_size": 32768, + "maximum_size": 262144 + }, + "url": "https://developer.mbed.org/platforms/Delta-DFCM-NNN40/", + "vendor": "Delta" } -} \ No newline at end of file +} diff --git a/platformio/boards/ststm32.json b/platformio/boards/ststm32.json index a5fd3475..e57d9452 100644 --- a/platformio/boards/ststm32.json +++ b/platformio/boards/ststm32.json @@ -390,5 +390,37 @@ }, "url": "http://docs.armstrap.org/en/latest/hardware-overview.html", "vendor": "Armstrap" + }, + "disco_l053c8": { + "build": { + "f_cpu": "32000000L", + "cpu": "cortex-m0plus", + "mcu": "stm32l053c8t6" + }, + "frameworks": ["mbed"], + "name": "ST 32L0538DISCOVERY", + "platform": "ststm32", + "upload": { + "maximum_ram_size": 8192, + "maximum_size": 65536 + }, + "url": "http://www.st.com/web/en/catalog/tools/PF260319", + "vendor": "ST" + }, + "disco_f334c8": { + "build": { + "f_cpu": "72000000L", + "cpu": "cortex-m4", + "mcu": "stm32f334c8t6" + }, + "frameworks": ["mbed"], + "name": "ST 32F3348DISCOVERY", + "platform": "ststm32", + "upload": { + "maximum_ram_size": 12288, + "maximum_size": 65536 + }, + "url": "http://www.st.com/web/en/catalog/tools/PF260318", + "vendor": "ST" } -} \ No newline at end of file +} diff --git a/platformio/builder/main.py b/platformio/builder/main.py index a9f06099..d74f6c50 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -11,11 +11,13 @@ except ImportError: break from platformio import util +import json +from os import getenv from os.path import isfile, join from time import time -from SCons.Script import (DefaultEnvironment, Exit, SConscript, - SConscriptChdir, Variables) +from SCons.Script import (COMMAND_LINE_TARGETS, DefaultEnvironment, Exit, + SConscript, SConscriptChdir, Variables) from platformio.exception import UnknownBoard @@ -25,6 +27,7 @@ from platformio.exception import UnknownBoard commonvars = Variables(None) commonvars.AddVariables( ("BUILD_SCRIPT",), + ("EXTRA_SCRIPT",), ("PIOENV",), ("PLATFORM",), @@ -35,10 +38,11 @@ commonvars.AddVariables( # options ("FRAMEWORK",), ("BUILD_FLAGS",), - ("SRCBUILD_FLAGS",), - ("IGNORE_LIBS",), - ("USE_LIBS",), - ("LDF_CYCLIC",), + ("SRC_BUILD_FLAGS",), + ("SRC_FILTER",), + ("LIB_DFCYCLIC",), + ("LIB_IGNORE",), + ("LIB_USE",), # board options ("BOARD",), @@ -54,7 +58,7 @@ commonvars.AddVariables( DefaultEnvironment( tools=[ "gcc", "g++", "as", "ar", "gnulink", - "platformio", "pioupload", "pioar" + "platformio", "pioupload", "pioar", "piomisc" ], toolpath=[join("$PIOBUILDER_DIR", "tools")], variables=commonvars, @@ -71,6 +75,7 @@ DefaultEnvironment( PIOPACKAGES_DIR=join("$PIOHOME_DIR", "packages"), BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"), + BUILDSRC_DIR=join("$BUILD_DIR", "src"), LIBSOURCE_DIRS=[ "$PROJECTLIB_DIR", util.get_lib_dir(), @@ -113,8 +118,10 @@ if "BOARD" in env: env.get("BOARD_OPTIONS", {}).get("platform"))) -if "IGNORE_LIBS" in env: - env['IGNORE_LIBS'] = [l.strip() for l in env['IGNORE_LIBS'].split(",")] +for opt in ("LIB_IGNORE", "LIB_USE"): + if opt not in env: + continue + env[opt] = [l.strip() for l in env[opt].split(",") if l.strip()] env.PrependENVPath( "PATH", @@ -123,3 +130,14 @@ env.PrependENVPath( SConscriptChdir(0) SConscript(env.subst("$BUILD_SCRIPT")) + +if getenv("PLATFORMIO_EXTRA_SCRIPT", env.get("EXTRA_SCRIPT", None)): + SConscript(getenv("PLATFORMIO_EXTRA_SCRIPT", env.get("EXTRA_SCRIPT"))) + +if "envdump" in COMMAND_LINE_TARGETS: + print env.Dump() + Exit() + +if "idedata" in COMMAND_LINE_TARGETS: + print json.dumps(env.DumpIDEData()) + Exit() diff --git a/platformio/builder/scripts/atmelavr.py b/platformio/builder/scripts/atmelavr.py index f86f130f..1027b6a4 100644 --- a/platformio/builder/scripts/atmelavr.py +++ b/platformio/builder/scripts/atmelavr.py @@ -30,7 +30,10 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 env.Replace(UPLOAD_SPEED=None) if env.subst("$UPLOAD_SPEED"): - env.Append(UPLOADERFLAGS=["-b", "$UPLOAD_SPEED"]) + env.Append(UPLOADERFLAGS=[ + "-b", "$UPLOAD_SPEED", + "-D" + ]) if not upload_options.get("require_upload_port", False): return diff --git a/platformio/builder/scripts/espressif.py b/platformio/builder/scripts/espressif.py index ca4742c2..484765f6 100644 --- a/platformio/builder/scripts/espressif.py +++ b/platformio/builder/scripts/espressif.py @@ -77,7 +77,7 @@ env.Replace( "-cp", "$UPLOAD_PORT", "-ca", "0x00000", "-cf", "${SOURCES[0]}", - "-ca", "0x10000", + "-ca", "0x40000" if "FRAMEWORK" not in env else "0x10000", "-cf", "${SOURCES[1]}" ], UPLOADCMD='$UPLOADER $UPLOADERFLAGS' @@ -140,7 +140,8 @@ if "uploadlazy" in COMMAND_LINE_TARGETS: else: target_firm = env.ElfToBin( [join("$BUILD_DIR", "firmware_00000"), - join("$BUILD_DIR", "firmware_10000")], target_elf) + join("$BUILD_DIR", "firmware_%s" % + ("40000" if "FRAMEWORK" not in env else "10000"))], target_elf) # diff --git a/platformio/builder/scripts/frameworks/mbed.py b/platformio/builder/scripts/frameworks/mbed.py index e9e57ad0..6c3bcf8d 100644 --- a/platformio/builder/scripts/frameworks/mbed.py +++ b/platformio/builder/scripts/frameworks/mbed.py @@ -32,9 +32,6 @@ env.Replace( ) MBED_VARIANTS = { - "stm32f3discovery": "DISCO_F303VC", - "stm32f4discovery": "DISCO_F407VG", - "stm32f429discovery": "DISCO_F429ZI", "blueboard_lpc11u24": "LPC11U24", "dipcortexm0": "LPC11U24", "seeeduinoArchPro": "ARCH_PRO", @@ -54,7 +51,8 @@ MBED_VARIANTS = { "frdm_kl05z": "KL05Z", "frdm_k20d50m": "K20D50M", "frdm_k22f": "K22F", - "teensy31": "TEENSY3_1" + "teensy31": "TEENSY3_1", + "dfcm_nnn40": "DELTA_DFCM_NNN40" } MBED_LIBS_MAP = { diff --git a/platformio/builder/scripts/frameworks/spl.py b/platformio/builder/scripts/frameworks/spl.py index 130d8bf2..857de8c5 100644 --- a/platformio/builder/scripts/frameworks/spl.py +++ b/platformio/builder/scripts/frameworks/spl.py @@ -38,10 +38,7 @@ env.Append( envsafe = env.Clone() envsafe.Append( - CPPPATH=[ - join("$BUILD_DIR", "src") - ], - + CPPPATH=["$BUILDSRC_DIR"], CPPDEFINES=[ "USE_STDPERIPH_DRIVER" ] @@ -52,22 +49,22 @@ envsafe.Append( # extra_flags = env.get("BOARD_OPTIONS", {}).get("build", {}).get("extra_flags") -ignore_files = [] +src_filter_patterns = ["+<*>"] if "STM32F40_41xxx" in extra_flags: - ignore_files += ["stm32f4xx_fmc.c"] + src_filter_patterns += ["-"] if "STM32F427_437xx" in extra_flags: - ignore_files += ["stm32f4xx_fsmc.c"] + src_filter_patterns += ["-"] elif "STM32F303xC" in extra_flags: - ignore_files += ["stm32f30x_hrtim.c"] + src_filter_patterns += ["-"] elif "STM32L1XX_MD" in extra_flags: - ignore_files += ["stm32l1xx_flash_ramfunc.c"] + src_filter_patterns += ["-"] libs = [] libs.append(envsafe.BuildLibrary( join("$BUILD_DIR", "FrameworkSPL"), join("$PLATFORMFW_DIR", "${BOARD_OPTIONS['build']['core']}", "variants", "${BOARD_OPTIONS['build']['variant']}", "src"), - ignore_files + src_filter=" ".join(src_filter_patterns) )) env.Append(LIBS=libs) diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py new file mode 100644 index 00000000..0098d63b --- /dev/null +++ b/platformio/builder/tools/piomisc.py @@ -0,0 +1,167 @@ +# Copyright (C) Ivan Kravets +# See LICENSE for details. + +import atexit +import re +from glob import glob +from os import remove +from os.path import basename, join + + +class InoToCPPConverter(object): + + PROTOTYPE_RE = re.compile( + r"""^( + (\s*[a-z_\d]+){1,2} # return type + (\s+[a-z_\d]+\s*) # name of prototype + \([a-z_,\.\*\&\[\]\s\d]*\) # arguments + )\s*\{ # must end with { + """, + re.X | re.M | re.I + ) + + DETECTMAIN_RE = re.compile(r"void\s+(setup|loop)\s*\(", re.M | re.I) + + STRIPCOMMENTS_RE = re.compile(r"(/\*.*?\*/|(^|\s+)//[^\r\n]*$)", + re.M | re.S) + + def __init__(self, nodes): + self.nodes = nodes + + def is_main_node(self, contents): + return self.DETECTMAIN_RE.search(contents) + + @staticmethod + def _replace_comments_callback(match): + if "\n" in match.group(1): + return "\n" * match.group(1).count("\n") + else: + return " " + + def _parse_prototypes(self, contents): + prototypes = [] + reserved_keywords = set(["if", "else", "while"]) + for item in self.PROTOTYPE_RE.findall(contents): + if set([item[1].strip(), item[2].strip()]) & reserved_keywords: + continue + prototypes.append(item[0]) + return prototypes + + def append_prototypes(self, fname, contents, prototypes): + contents = self.STRIPCOMMENTS_RE.sub(self._replace_comments_callback, + contents) + result = [] + is_appended = False + linenum = 0 + for line in contents.splitlines(): + linenum += 1 + line = line.strip() + + if not is_appended and line and not line.startswith("#"): + is_appended = True + result.append("%s;" % ";\n".join(prototypes)) + result.append('#line %d "%s"' % (linenum, fname)) + + result.append(line) + + return result + + def convert(self): + prototypes = [] + data = [] + for node in self.nodes: + ino_contents = node.get_text_contents() + prototypes += self._parse_prototypes(ino_contents) + + item = (basename(node.get_path()), ino_contents) + if self.is_main_node(ino_contents): + data = [item] + data + else: + data.append(item) + + if not data: + return None + + result = ["#include "] + is_first = True + + for name, contents in data: + if is_first and prototypes: + result += self.append_prototypes(name, contents, prototypes) + else: + result.append('#line 1 "%s"' % name) + result.append(contents) + is_first = False + + return "\n".join(result) + + +def ConvertInoToCpp(env): + + def delete_tmpcpp_file(file_): + remove(file_) + + ino_nodes = (env.Glob(join("$PROJECTSRC_DIR", "*.ino")) + + env.Glob(join("$PROJECTSRC_DIR", "*.pde"))) + + c = InoToCPPConverter(ino_nodes) + data = c.convert() + + if not data: + return + + tmpcpp_file = join(env.subst("$PROJECTSRC_DIR"), "tmp_ino_to.cpp") + with open(tmpcpp_file, "w") as f: + f.write(data) + + atexit.register(delete_tmpcpp_file, tmpcpp_file) + + +def DumpIDEData(env): + data = { + "defines": [], + "includes": [] + } + + # includes from framework and libs + for item in env.get("VARIANT_DIRS", []): + if "$BUILDSRC_DIR" in item[0]: + continue + data['includes'].append(env.subst(item[1])) + + # includes from toolchain + toolchain_dir = env.subst( + join("$PIOPACKAGES_DIR", "$PIOPACKAGE_TOOLCHAIN")) + toolchain_incglobs = [ + join(toolchain_dir, "*", "include"), + join(toolchain_dir, "lib", "gcc", "*", "*", "include") + ] + for g in toolchain_incglobs: + data['includes'].extend(glob(g)) + + # global symbols + for item in env.get("CPPDEFINES", []): + if isinstance(item, list): + item = "=".join(item) + data['defines'].append(env.subst(item)) + + # special symbol for Atmel AVR MCU + board = env.get("BOARD_OPTIONS", {}) + if board and board['platform'] == "atmelavr": + data['defines'].append( + "__AVR_%s__" % board['build']['mcu'].upper() + .replace("ATMEGA", "ATmega") + .replace("ATTINY", "ATtiny") + ) + + return data + + +def exists(_): + return True + + +def generate(env): + env.AddMethod(ConvertInoToCpp) + env.AddMethod(DumpIDEData) + return env diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index 2cd8b44e..e13b0105 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -1,20 +1,24 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -import atexit -import json import re from glob import glob -from os import getenv, listdir, remove, sep, walk +from os import getenv, listdir, sep, walk from os.path import basename, dirname, isdir, isfile, join, normpath -from SCons.Script import (COMMAND_LINE_TARGETS, DefaultEnvironment, Exit, - SConscript, SConscriptChdir) +from SCons.Script import DefaultEnvironment, Exit, SConscript from SCons.Util import case_sensitive_suffixes from platformio.util import pioversion_to_intstr +SRC_BUILD_EXT = ["c", "cpp", "S", "spp", "SPP", "sx", "s", "asm", "ASM"] +SRC_HEADER_EXT = ["h", "hpp"] +SRC_DEFAULT_FILTER = " ".join([ + "+<*>", "-<.git%s>" % sep, "-" % sep, "-" % sep +]) + + def BuildFirmware(env): # fix ASM handling under non-casitive OS @@ -27,49 +31,41 @@ def BuildFirmware(env): env.ProcessFlags() env.BuildFramework() - firmenv = env.Clone() - vdirs = firmenv.VariantDirRecursive( - join("$BUILD_DIR", "src"), "$PROJECTSRC_DIR", duplicate=False) - # build dependent libs - deplibs = firmenv.BuildDependentLibraries("$PROJECTSRC_DIR") + deplibs = env.BuildDependentLibraries("$PROJECTSRC_DIR") # append specified LD_SCRIPT - if "LDSCRIPT_PATH" in firmenv: - firmenv.Append( - LINKFLAGS=["-T", "$LDSCRIPT_PATH"] + if ("LDSCRIPT_PATH" in env and + not any(["-Wl,-T" in f for f in env['LINKFLAGS']])): + env.Append( + LINKFLAGS=["-Wl,-T", "$LDSCRIPT_PATH"] ) # enable "cyclic reference" for linker - firmenv.Prepend( + env.Prepend( _LIBFLAGS="-Wl,--start-group " ) - firmenv.Append( + env.Append( _LIBFLAGS=" -Wl,--end-group" ) - # Handle SRCBUILD_FLAGS - if getenv("PLATFORMIO_SRCBUILD_FLAGS", None): - firmenv.MergeFlags(getenv("PLATFORMIO_SRCBUILD_FLAGS")) - if "SRCBUILD_FLAGS" in env: - firmenv.MergeFlags(env['SRCBUILD_FLAGS']) + # Handle SRC_BUILD_FLAGS + if getenv("PLATFORMIO_SRC_BUILD_FLAGS", None): + env.MergeFlags(getenv("PLATFORMIO_SRC_BUILD_FLAGS")) + if "SRC_BUILD_FLAGS" in env: + env.MergeFlags(env['SRC_BUILD_FLAGS']) - firmenv.Append( + env.Append( CPPDEFINES=["PLATFORMIO={0:02d}{1:02d}{2:02d}".format( *pioversion_to_intstr())] ) - if "envdump" in COMMAND_LINE_TARGETS: - print env.Dump() - Exit() - - if "idedata" in COMMAND_LINE_TARGETS: - print json.dumps(env.DumpIDEData()) - Exit() - - return firmenv.Program( + return env.Program( join("$BUILD_DIR", "firmware"), - [firmenv.GlobCXXFiles(vdir) for vdir in vdirs], + env.LookupSources( + "$BUILDSRC_DIR", "$PROJECTSRC_DIR", duplicate=False, + src_filter=getenv("PLATFORMIO_SRC_FILTER", + env.get("SRC_FILTER", None))), LIBS=env.get("LIBS", []) + deplibs, LIBPATH=env.get("LIBPATH", []) + ["$BUILD_DIR"], PROGSUFFIX=".elf" @@ -95,13 +91,13 @@ def ProcessFlags(env): env.Append(_CPPDEFFLAGS=" %s" % " ".join(undefines)) -def GlobCXXFiles(env, path): - files = [] - for suff in ["c", "cpp", "S", "spp", "SPP", "sx", "s", "asm", "ASM"]: - _list = env.Glob(join(path, "*.%s" % suff)) - if _list: - files += _list - return files +def IsFileWithExt(env, file_, ext): # pylint: disable=W0613 + if basename(file_).startswith("."): + return False + for e in ext: + if file_.endswith(".%s" % e): + return True + return False def VariantDirWrap(env, variant_dir, src_dir, duplicate=True): @@ -109,20 +105,53 @@ def VariantDirWrap(env, variant_dir, src_dir, duplicate=True): env.VariantDir(variant_dir, src_dir, duplicate) -def VariantDirRecursive(env, variant_dir, src_dir, duplicate=True, - ignore_pattern=None): - if not ignore_pattern: - ignore_pattern = (".git", ".svn") +def LookupSources(env, variant_dir, src_dir, duplicate=True, src_filter=None): + + SRC_FILTER_PATTERNS_RE = re.compile(r"(\+|\-)<([^>]+)>") + + def _append_build_item(items, item, src_dir): + if env.IsFileWithExt(item, SRC_BUILD_EXT + SRC_HEADER_EXT): + items.add(item.replace(src_dir + sep, "")) + + def _match_sources(src_dir, src_filter): + matches = set() + # correct fs directory separator + src_filter = src_filter.replace("/", sep).replace("\\", sep) + for (action, pattern) in SRC_FILTER_PATTERNS_RE.findall(src_filter): + items = set() + for item in glob(join(src_dir, pattern)): + if isdir(item): + for root, _, files in walk(item, followlinks=True): + for f in files: + _append_build_item(items, join(root, f), src_dir) + else: + _append_build_item(items, item, src_dir) + if action == "+": + matches |= items + else: + matches -= items + return sorted(list(matches)) + + sources = [] variants = [] + src_dir = env.subst(src_dir) - for root, _, _ in walk(src_dir, followlinks=True): - _src_dir = root - _var_dir = variant_dir + root.replace(src_dir, "") - if any([s in _var_dir.lower() for s in ignore_pattern]): - continue - env.VariantDirWrap(_var_dir, _src_dir, duplicate) - variants.append(_var_dir) - return variants + if src_dir.endswith(sep): + src_dir = src_dir[:-1] + + for item in _match_sources(src_dir, src_filter or SRC_DEFAULT_FILTER): + _reldir = dirname(item) + _src_dir = join(src_dir, _reldir) if _reldir else src_dir + _var_dir = join(variant_dir, _reldir) if _reldir else variant_dir + + if _var_dir not in variants: + variants.append(_var_dir) + env.VariantDirWrap(_var_dir, _src_dir, duplicate) + + if env.IsFileWithExt(item, SRC_BUILD_EXT): + sources.append(env.File(join(_var_dir, basename(item)))) + + return sources def BuildFramework(env): @@ -135,7 +164,6 @@ def BuildFramework(env): for f in env['FRAMEWORK'].split(","): framework = f.strip().lower() if framework in env.get("BOARD_OPTIONS", {}).get("frameworks"): - SConscriptChdir(0) SConscript( env.subst(join("$PIOBUILDER_DIR", "scripts", "frameworks", "%s.py" % framework)) @@ -145,18 +173,11 @@ def BuildFramework(env): framework) -def BuildLibrary(env, variant_dir, library_dir, ignore_files=None): +def BuildLibrary(env, variant_dir, src_dir, src_filter=None): lib = env.Clone() - vdirs = lib.VariantDirRecursive( - variant_dir, library_dir, ignore_pattern=(".git", ".svn", "examples")) - srcfiles = [] - for vdir in vdirs: - for item in lib.GlobCXXFiles(vdir): - if not ignore_files or item.name not in ignore_files: - srcfiles.append(item) return lib.Library( lib.subst(variant_dir), - srcfiles + lib.LookupSources(variant_dir, src_dir, src_filter=src_filter) ) @@ -165,8 +186,6 @@ def BuildDependentLibraries(env, src_dir): # pylint: disable=R0914 INCLUDES_RE = re.compile( r"^\s*#include\s+(\<|\")([^\>\"\']+)(?:\>|\")", re.M) LIBSOURCE_DIRS = [env.subst(d) for d in env.get("LIBSOURCE_DIRS", [])] - USE_LIBS = [l.strip() for l in env.get("USE_LIBS", "").split(",") - if l.strip()] # start internal prototypes @@ -207,7 +226,7 @@ def BuildDependentLibraries(env, src_dir): # pylint: disable=R0914 if not isdir(lsd_dir): continue - for ld in USE_LIBS + sorted(listdir(lsd_dir)): + for ld in env.get("LIB_USE", []) + sorted(listdir(lsd_dir)): if not isdir(join(lsd_dir, ld)): continue @@ -220,7 +239,7 @@ def BuildDependentLibraries(env, src_dir): # pylint: disable=R0914 lib_name = basename(lib_dir) # ignore user's specified libs - if "IGNORE_LIBS" in env and lib_name in env['IGNORE_LIBS']: + if lib_name in env.get("LIB_IGNORE", []): continue if not isfile(inc_path): @@ -250,10 +269,10 @@ def BuildDependentLibraries(env, src_dir): # pylint: disable=R0914 return result def _process_src_dir(state, src_dir): - for root, _, _ in walk(src_dir, followlinks=True): - for node in (env.GlobCXXFiles(root) + - env.Glob(join(root, "*.h"))): - state = _parse_includes(state, node) + for root, _, files in walk(src_dir, followlinks=True): + for f in files: + if env.IsFileWithExt(f, SRC_BUILD_EXT + SRC_HEADER_EXT): + state = _parse_includes(state, env.File(join(root, f))) return state def _parse_includes(state, node): @@ -279,8 +298,7 @@ def BuildDependentLibraries(env, src_dir): # pylint: disable=R0914 _lib_dir)) state['libs'].add(_lib_dir) - if getenv("PLATFORMIO_LDF_CYCLIC", - env.subst("$LDF_CYCLIC")).lower() == "true": + if env.subst("$LIB_DFCYCLIC").lower() == "true": state = _process_src_dir(state, _lib_dir) return state @@ -306,151 +324,6 @@ def BuildDependentLibraries(env, src_dir): # pylint: disable=R0914 return libs -class InoToCPPConverter(object): - - PROTOTYPE_RE = re.compile( - r"""^( - (\s*[a-z_\d]+){1,2} # return type - (\s+[a-z_\d]+\s*) # name of prototype - \([a-z_,\.\*\&\[\]\s\d]*\) # arguments - )\s*\{ # must end with { - """, - re.X | re.M | re.I - ) - - DETECTMAIN_RE = re.compile(r"void\s+(setup|loop)\s*\(", re.M | re.I) - - STRIPCOMMENTS_RE = re.compile(r"(/\*.*?\*/|(^|\s+)//[^\r\n]*$)", - re.M | re.S) - - def __init__(self, nodes): - self.nodes = nodes - - def is_main_node(self, contents): - return self.DETECTMAIN_RE.search(contents) - - @staticmethod - def _replace_comments_callback(match): - if "\n" in match.group(1): - return "\n" * match.group(1).count("\n") - else: - return " " - - def _parse_prototypes(self, contents): - prototypes = [] - reserved_keywords = set(["if", "else", "while"]) - for item in self.PROTOTYPE_RE.findall(contents): - if set([item[1].strip(), item[2].strip()]) & reserved_keywords: - continue - prototypes.append(item[0]) - return prototypes - - def append_prototypes(self, fname, contents, prototypes): - contents = self.STRIPCOMMENTS_RE.sub(self._replace_comments_callback, - contents) - result = [] - is_appended = False - linenum = 0 - for line in contents.splitlines(): - linenum += 1 - line = line.strip() - - if not is_appended and line and not line.startswith("#"): - is_appended = True - result.append("%s;" % ";\n".join(prototypes)) - result.append('#line %d "%s"' % (linenum, fname)) - - result.append(line) - - return result - - def convert(self): - prototypes = [] - data = [] - for node in self.nodes: - ino_contents = node.get_text_contents() - prototypes += self._parse_prototypes(ino_contents) - - item = (basename(node.get_path()), ino_contents) - if self.is_main_node(ino_contents): - data = [item] + data - else: - data.append(item) - - if not data: - return None - - result = ["#include "] - is_first = True - - for name, contents in data: - if is_first and prototypes: - result += self.append_prototypes(name, contents, prototypes) - else: - result.append('#line 1 "%s"' % name) - result.append(contents) - is_first = False - - return "\n".join(result) - - -def ConvertInoToCpp(env): - - def delete_tmpcpp_file(file_): - remove(file_) - - ino_nodes = (env.Glob(join("$PROJECTSRC_DIR", "*.ino")) + - env.Glob(join("$PROJECTSRC_DIR", "*.pde"))) - - c = InoToCPPConverter(ino_nodes) - data = c.convert() - - if not data: - return - - tmpcpp_file = join(env.subst("$PROJECTSRC_DIR"), "tmp_ino_to.cpp") - with open(tmpcpp_file, "w") as f: - f.write(data) - - atexit.register(delete_tmpcpp_file, tmpcpp_file) - - -def DumpIDEData(env): - data = { - "defines": [], - "includes": [] - } - - # includes from framework and libs - for item in env.get("VARIANT_DIRS", []): - data['includes'].append(env.subst(item[1])) - - # includes from toolchain - toolchain_dir = env.subst( - join("$PIOPACKAGES_DIR", "$PIOPACKAGE_TOOLCHAIN")) - toolchain_incglobs = [ - join(toolchain_dir, "*", "include"), - join(toolchain_dir, "lib", "gcc", "*", "*", "include") - ] - for g in toolchain_incglobs: - data['includes'].extend(glob(g)) - - # global symbols - for item in env.get("CPPDEFINES", []): - data['defines'].append(env.subst(item)) - - # special symbol for Atmel AVR MCU - board = env.get("BOARD_OPTIONS", {}) - if board and board['platform'] == "atmelavr": - data['defines'].append( - "__AVR_%s__" % board['build']['mcu'].upper() - .replace("ATMEGA", "ATmega") - .replace("ATTINY", "ATtiny") - ) - - return data - - def exists(_): return True @@ -458,12 +331,10 @@ def exists(_): def generate(env): env.AddMethod(BuildFirmware) env.AddMethod(ProcessFlags) - env.AddMethod(GlobCXXFiles) + env.AddMethod(IsFileWithExt) env.AddMethod(VariantDirWrap) - env.AddMethod(VariantDirRecursive) + env.AddMethod(LookupSources) env.AddMethod(BuildFramework) env.AddMethod(BuildLibrary) env.AddMethod(BuildDependentLibraries) - env.AddMethod(ConvertInoToCpp) - env.AddMethod(DumpIDEData) return env diff --git a/platformio/commands/ci.py b/platformio/commands/ci.py index cf4f5010..b65f09fc 100644 --- a/platformio/commands/ci.py +++ b/platformio/commands/ci.py @@ -4,7 +4,7 @@ import stat from glob import glob from os import chmod, getenv, makedirs, remove -from os.path import abspath, basename, isdir, isfile, join +from os.path import abspath, basename, expanduser, isdir, isfile, join from shutil import copyfile, copytree, rmtree from tempfile import mkdtemp @@ -19,8 +19,12 @@ from platformio.util import get_boards def validate_path(ctx, param, value): # pylint: disable=W0613 invalid_path = None - for p in value: - if not glob(p): + value = list(value) + for i, p in enumerate(value): + if p.startswith("~"): + value[i] = expanduser(p) + value[i] = abspath(value[i]) + if not glob(value[i]): invalid_path = p break try: @@ -109,7 +113,6 @@ def _copy_contents(dst_dir, contents): } for path in contents: - path = abspath(path) if isdir(path): items['dirs'].add(path) elif isfile(path): diff --git a/platformio/commands/init.py b/platformio/commands/init.py index 4799d5fc..3346b635 100644 --- a/platformio/commands/init.py +++ b/platformio/commands/init.py @@ -86,7 +86,7 @@ def cli(project_dir, board, ide, disable_auto_uploading, env_prefix): project_file, board, disable_auto_uploading, env_prefix) if ide: - pg = ProjectGenerator(project_dir, ide) + pg = ProjectGenerator(project_dir, ide, board[0] if board else None) pg.generate() click.secho( diff --git a/platformio/commands/run.py b/platformio/commands/run.py index 7f79c506..6eade5f9 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -73,11 +73,19 @@ def cli(ctx, environment, target, upload_port, # pylint: disable=R0913,R0914 class EnvironmentProcessor(object): + RENAMED_OPTIONS = { + "INSTALL_LIBS": "LIB_INSTALL", + "IGNORE_LIBS": "LIB_IGNORE", + "USE_LIBS": "LIB_USE", + "LDF_CYCLIC": "LIB_DFCYCLIC", + "SRCBUILD_FLAGS": "SRC_BUILD_FLAGS" + } + def __init__(self, cmd_ctx, name, options, # pylint: disable=R0913 targets, upload_port, verbose): self.cmd_ctx = cmd_ctx self.name = name - self.options = options + self.options = self._validate_options(options) self.targets = targets self.upload_port = upload_port self.verbose_level = int(verbose) @@ -108,6 +116,23 @@ class EnvironmentProcessor(object): return not is_error + def _validate_options(self, options): + result = {} + for k, v in options.items(): + _k = k.upper() + # process obsolete options + if _k in self.RENAMED_OPTIONS: + click.secho( + "Warning! `%s` option is deprecated and will be " + "removed in the next release! Please use " + "`%s` instead." % ( + k, self.RENAMED_OPTIONS[_k].lower()), + fg="yellow" + ) + k = self.RENAMED_OPTIONS[_k].lower() + result[k] = v + return result + def _get_build_variables(self): variables = ["PIOENV=" + self.name] if self.upload_port: @@ -116,7 +141,7 @@ class EnvironmentProcessor(object): k = k.upper() if k == "TARGETS" or (k == "UPLOAD_PORT" and self.upload_port): continue - variables.append("%s=%s" % (k.upper(), v)) + variables.append("%s=%s" % (k, v)) return variables def _get_build_targets(self): @@ -139,8 +164,8 @@ class EnvironmentProcessor(object): # install platform and libs dependencies _autoinstall_platform(self.cmd_ctx, platform) - if "install_libs" in self.options: - _autoinstall_libs(self.cmd_ctx, self.options['install_libs']) + if "lib_install" in self.options: + _autoinstall_libs(self.cmd_ctx, self.options['lib_install']) p = PlatformFactory.newPlatform(platform) return p.run(build_vars, build_targets, self.verbose_level) diff --git a/platformio/exception.py b/platformio/exception.py index 22b5978a..d8cb13fd 100644 --- a/platformio/exception.py +++ b/platformio/exception.py @@ -30,7 +30,7 @@ class UnknownPlatform(PlatformioException): class PlatformNotInstalledYet(PlatformioException): MESSAGE = ("The platform '%s' has not been installed yet. " - "Use `platformio install` command") + "Use `platformio platforms install` command") class UnknownCLICommand(PlatformioException): diff --git a/platformio/ide/projectgenerator.py b/platformio/ide/projectgenerator.py index c3ee89c9..2d6dbcc6 100644 --- a/platformio/ide/projectgenerator.py +++ b/platformio/ide/projectgenerator.py @@ -4,7 +4,7 @@ import json from glob import glob from os import listdir, walk -from os.path import basename, isdir, join +from os.path import abspath, basename, expanduser, isdir, join, relpath import bottle @@ -13,9 +13,10 @@ from platformio import util class ProjectGenerator(object): - def __init__(self, project_dir, ide): + def __init__(self, project_dir, ide, board=None): self.project_dir = project_dir self.ide = ide + self.board = board self._tplvars = {} self._gather_tplvars() @@ -26,6 +27,7 @@ class ProjectGenerator(object): return sorted([d for d in listdir(tpls_dir) if isdir(join(tpls_dir, d))]) + @util.memoized def get_project_env(self): data = {"env_name": "PlatformIO"} with util.cd(self.project_dir): @@ -33,9 +35,11 @@ class ProjectGenerator(object): for section in config.sections(): if not section.startswith("env:"): continue - data['env_name'] = section[4:] + data = {"env_name": section[4:]} for k, v in config.items(section): data[k] = v + if self.board and self.board == data.get("board"): + break return data @util.memoized @@ -63,12 +67,12 @@ class ProjectGenerator(object): def get_project_name(self): return basename(self.project_dir) - @staticmethod - def get_srcfiles(): + def get_srcfiles(self): result = [] - for root, _, files in walk(util.get_projectsrc_dir()): - for f in files: - result.append(join(root, f)) + with util.cd(self.project_dir): + for root, _, files in walk(util.get_projectsrc_dir()): + for f in files: + result.append(relpath(join(root, f))) return result def get_tpls(self): @@ -99,5 +103,6 @@ class ProjectGenerator(object): "defines": (build_data['defines'] if build_data and "defines" in build_data else []), "srcfiles": self.get_srcfiles(), + "user_home_dir": abspath(expanduser("~")), "project_dir": self.project_dir }) diff --git a/platformio/ide/tpls/eclipse/.cproject.tpl b/platformio/ide/tpls/eclipse/.cproject.tpl index ccd645ed..c6f6e077 100644 --- a/platformio/ide/tpls/eclipse/.cproject.tpl +++ b/platformio/ide/tpls/eclipse/.cproject.tpl @@ -24,8 +24,12 @@