mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-29 17:47:14 +02:00
Introduce "Library Dependency Finder"
This commit is contained in:
31
docs/faq.rst
31
docs/faq.rst
@ -33,37 +33,6 @@ What is ``.pioenvs`` directory
|
||||
|
||||
Please refer to :ref:`projectconf_pio_envs_dir`.
|
||||
|
||||
.. _faq_ldf:
|
||||
|
||||
How works Library Dependency Finder (LDF)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Library Dependency Finder is a part of PlatformIO Library Build System. It
|
||||
operates with the C/C++ source files and looks for ``#include <...>``
|
||||
directives. Also, LDF interprets C Preprocessor conditional macros
|
||||
(``#if``, ``ifdef``, etc.). Library Dependency Finder starts
|
||||
work from analyzing source files from :ref:`projectconf_pio_src_dir` by default.
|
||||
|
||||
If project or library contains own ``dependencies`` list (see
|
||||
:ref:`libjson_dependencies`), the LDF will not looking for dependencies in
|
||||
the source code. The specified libraries will be built automatically without
|
||||
check.
|
||||
|
||||
There are different library storages where Library Dependency Finder looks for
|
||||
dependencies. These storages/folders have priority. LDF operates in the next
|
||||
order:
|
||||
|
||||
1. :ref:`projectconf_lib_extra_dirs`
|
||||
2. :ref:`projectconf_pio_lib_dir`
|
||||
3. :ref:`projectconf_pio_home_dir`/lib
|
||||
|
||||
Library Dependency Finder has a few controls from :ref:`projectconf`:
|
||||
|
||||
* :ref:`projectconf_lib_ignore`
|
||||
* :ref:`projectconf_lib_deep_search`
|
||||
* :ref:`projectconf_lib_extra_dirs`
|
||||
* :ref:`projectconf_lib_compat_mode`
|
||||
|
||||
Command completion in Terminal
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -119,6 +119,7 @@ Contents
|
||||
|
||||
Quickstart <librarymanager/index>
|
||||
User Guide <userguide/lib/index.rst>
|
||||
librarymanager/ldf
|
||||
librarymanager/config
|
||||
librarymanager/creating
|
||||
|
||||
|
171
docs/librarymanager/ldf.rst
Normal file
171
docs/librarymanager/ldf.rst
Normal file
@ -0,0 +1,171 @@
|
||||
.. Copyright 2014-present Ivan Kravets <me@ikravets.com>
|
||||
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.
|
||||
|
||||
.. _ldf:
|
||||
|
||||
Library Dependency Finder (LDF)
|
||||
===============================
|
||||
|
||||
.. versionadded:: 3.0
|
||||
|
||||
Library Dependency Finder is a core part of PlatformIO Build System that
|
||||
operates with the C/C++ source files and looks for ``#include ...``
|
||||
directives.
|
||||
|
||||
In spite of the fact that Library Dependency Finder is written in pure Python,
|
||||
it interprets (emulates) :ref:`ldf_c_cond_syntax` (``#ifdef``, ``if``, ``defined``,
|
||||
``else``, and ``elif``) without calling ``gcc -E``. This approach allows
|
||||
significantly reduce total compilation time.
|
||||
|
||||
Library Dependency Finder has controls that can be set up in :ref:`projectconf`:
|
||||
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
* :ref:`projectconf_lib_extra_dirs`
|
||||
* :ref:`projectconf_lib_force`
|
||||
* :ref:`projectconf_lib_ignore`
|
||||
* :ref:`projectconf_lib_compat_mode`
|
||||
* :ref:`projectconf_lib_ldf_mode`
|
||||
|
||||
-----------
|
||||
|
||||
.. contents::
|
||||
|
||||
Storage
|
||||
-------
|
||||
|
||||
There are different storages/folders where Library Dependency Finder looks for
|
||||
libraries. These folders/path have priority and LDF operates in the next order:
|
||||
|
||||
1. :ref:`projectconf_lib_extra_dirs` - extra storages per build environment
|
||||
2. :ref:`projectconf_pio_lib_dir` - own/private library storage per project
|
||||
3. :ref:`projectconf_pio_piolibdeps_dir` - project dependencies storage used by
|
||||
:ref:`librarymanager`
|
||||
4. :ref:`projectconf_pio_home_dir`/lib - global storage per all projects.
|
||||
|
||||
.. _ldf_mode:
|
||||
|
||||
Dependency Finder Mode
|
||||
----------------------
|
||||
|
||||
Library Dependency Finder starts work from analyzing source files of the
|
||||
project (:ref:`projectconf_pio_src_dir`) and can work in the next modes:
|
||||
|
||||
* ``0`` - "manual mode", does not process source files of a project and
|
||||
dependent libraries. Builds only the libraries that are specified in
|
||||
manifests (:ref:`library_config`, ``module.json``) or in the :ref:`projectconf`.
|
||||
* ``1`` - parses ALL C/C++ source code of the project and follows only by
|
||||
nested includes/chain (``#include ...``) from the libraries.
|
||||
* ``2`` - **default** - parses ALL C/C++ source code of the project and parses
|
||||
ALL C/C++ source code of the each dependent library (recursively).
|
||||
|
||||
This mode can be changed using :ref:`projectconf_lib_ldf_mode` option in
|
||||
:ref:`projectconf`.
|
||||
|
||||
A difference between ``1`` and ``2`` modes. For example, there are 2 libraries:
|
||||
|
||||
* Library "Foo" with files:
|
||||
|
||||
- ``Foo/foo.h``
|
||||
- ``Foo/foo.cpp``
|
||||
|
||||
* Library "Bar" with files:
|
||||
|
||||
- ``Bar/bar.h``
|
||||
- ``Bar/bar.cpp``
|
||||
|
||||
:Case 1:
|
||||
|
||||
* ``lib_ldf_mode = 1``
|
||||
* ``Foo/foo.h`` depends on "Bar" library (contains ``#include <bar.h>``)
|
||||
* ``#include <foo.h>`` is located in one of the project source files
|
||||
|
||||
Here are nested includes (``project file > foo.h > bar.h``) and ``LDF``
|
||||
will find both libraries "Foo" and "Bar".
|
||||
|
||||
:Case 2:
|
||||
|
||||
* ``lib_ldf_mode = 1``
|
||||
* ``Foo/foo.cpp`` depends on "Bar" library (contains ``#include <bar.h>``)
|
||||
* ``#include <foo.h>`` is located in one of the project source files
|
||||
|
||||
In this case, ``LDF`` will not find "Bar" library because it doesn't know
|
||||
about CPP file (``Foo/foo.cpp``).
|
||||
|
||||
:Case 3:
|
||||
|
||||
* ``lib_ldf_mode = 2``
|
||||
* ``Foo/foo.cpp`` depends on "Bar" library (contains ``#include <bar.h>``)
|
||||
* ``#include <foo.h>`` is located in one of the project source files
|
||||
|
||||
Firstly, ``LDF`` finds "Foo" library, then it parses all sources from "Foo"
|
||||
library and finds ``Foo/foo.cpp`` that depends on ``#include <bar.h>``.
|
||||
Secondly, it will parse all sources from "Bar" library and this operation
|
||||
continues until all dependent libraries will not be parsed.
|
||||
|
||||
.. _ldf_compat_mode:
|
||||
|
||||
Compatibility Mode
|
||||
------------------
|
||||
|
||||
Compatibility mode allows to control strictness of Library Dependency Finder.
|
||||
If library contains one of manifest file (:ref:`library_config`,
|
||||
``library.properties``, ``module.json``), then LDF check compatibility of this
|
||||
library with real build environment. Available compatibility modes:
|
||||
|
||||
* ``0`` - does not check for compatibility (is not recommended)
|
||||
* ``1`` - **default** - checks for the compatibility with
|
||||
:ref:`projectconf_env_framework` from build environment
|
||||
* ``2`` - checks for the compatibility with :ref:`projectconf_env_framework`
|
||||
and :ref:`projectconf_env_platform` from build environment.
|
||||
|
||||
This mode can be changed using :ref:`projectconf_lib_compat_mode` option in
|
||||
:ref:`projectconf`.
|
||||
|
||||
Manual dependencies
|
||||
-------------------
|
||||
|
||||
If project or library contains own ``dependencies`` list (see
|
||||
:ref:`libjson_dependencies`), the LDF will not looking for dependencies in
|
||||
the source code. The specified libraries will be built automatically without
|
||||
check.
|
||||
|
||||
.. _ldf_c_cond_syntax:
|
||||
|
||||
C Preprocessor conditional syntax
|
||||
---------------------------------
|
||||
|
||||
In spite of the fact that Library Dependency Finder is written in pure Python,
|
||||
it interprets (emulates) `C Preprocessor conditional syntax <https://gcc.gnu.org/onlinedocs/cpp/Conditional-Syntax.html#Conditional-Syntax>`_
|
||||
(``#ifdef``, ``if``, ``defined``, ``else``, and ``elif``) without calling
|
||||
``gcc -E``. For example,
|
||||
|
||||
``platformio.ini``
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[env:myenv]
|
||||
build_flags = -D MY_PROJECT_VERSION=13
|
||||
|
||||
``mylib.h``
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#ifdef PROJECT_VERSION
|
||||
// include common file for the project
|
||||
#include "my_common.h"
|
||||
#endif
|
||||
|
||||
#if PROJECT_VERSION < 10
|
||||
// this include will be ignored because does not satisfy condition above
|
||||
#include "my_old.h"
|
||||
#endif
|
@ -14,6 +14,8 @@
|
||||
Unit Testing
|
||||
============
|
||||
|
||||
.. versionadded:: 3.0
|
||||
|
||||
`Unit Testing (wiki) <https://en.wikipedia.org/wiki/Unit_testing>`_
|
||||
is a software testing method by which individual units of source code, sets
|
||||
of one or more MCU program modules together with associated control data,
|
||||
|
@ -44,8 +44,8 @@ Options
|
||||
``home_dir``
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Is used to store platform toolchains, frameworks, external libraries,
|
||||
service data and etc.
|
||||
Is used to store platform toolchains, frameworks, global libraries for
|
||||
:ref: `ldf`, service data and etc.
|
||||
|
||||
A default value is User's home directory:
|
||||
|
||||
@ -60,18 +60,59 @@ This option can be overridden by global environment variable
|
||||
``lib_dir``
|
||||
^^^^^^^^^^^
|
||||
|
||||
This directory is used to store external libraries downloaded by
|
||||
:ref:`librarymanager`.
|
||||
You can put here your own/private libraries. The source code of each library
|
||||
should be placed in separate directory, like
|
||||
``lib/private_lib/[here are source files]``. This directory has the highest
|
||||
priority for :ref:`ldf`.
|
||||
|
||||
A default value is ``%home_dir%/lib``.
|
||||
A default value is ``lib`` that means that folder is located in the root of
|
||||
project.
|
||||
|
||||
This option can be overridden by global environment variable
|
||||
:envvar:`PLATFORMIO_LIB_DIR`.
|
||||
|
||||
.. note::
|
||||
You can put here your own/private libraries. The source code of each
|
||||
library should be placed in separate directory. For example,
|
||||
``%lib_dir%/private_lib/[here are source files]``.
|
||||
For example, see how can be organized ``Foo`` and ``Bar`` libraries:
|
||||
|
||||
.. code::
|
||||
|
||||
|--lib
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
|
||||
Then in ``src/main.c`` you should use:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
// rest H/C/CPP code
|
||||
|
||||
PlatformIO will find your libraries automatically, configure preprocessor's
|
||||
include paths and build them.
|
||||
|
||||
.. _projectconf_pio_piolibdeps_dir:
|
||||
|
||||
``piolibdeps_dir``
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Internal storage where :ref:`librarymanager` will install project dependencies.
|
||||
A default value is ``.piolibdeps`` that means that folder is located in the root of
|
||||
project.
|
||||
|
||||
This option can be overridden by global environment variable
|
||||
:envvar:`PLATFORMIO_PIOLIBDEPS_DIR`.
|
||||
|
||||
.. _projectconf_pio_src_dir:
|
||||
|
||||
@ -79,10 +120,8 @@ This option can be overridden by global environment variable
|
||||
^^^^^^^^^^^
|
||||
|
||||
A path to project's source directory. PlatformIO uses it for :ref:`cmd_run`
|
||||
command.
|
||||
|
||||
A default value is ``src`` which means that folder is located in the root of
|
||||
project.
|
||||
command. A default value is ``src`` that means that folder is located in the
|
||||
root of project.
|
||||
|
||||
This option can be overridden by global environment variable
|
||||
:envvar:`PLATFORMIO_SRC_DIR`.
|
||||
@ -110,7 +149,7 @@ fast!
|
||||
then PlatformIO will remove this folder automatically. It will be created on the
|
||||
next build operation.
|
||||
|
||||
A default value is ``.pioenvs`` which means that folder is located in the root of
|
||||
A default value is ``.pioenvs`` that means that folder is located in the root of
|
||||
project.
|
||||
|
||||
This option can be overridden by global environment variable
|
||||
@ -127,8 +166,7 @@ This option can be overridden by global environment variable
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Data directory to store contents and :ref:`platform_espressif_uploadfs`.
|
||||
|
||||
A default value is ``data`` which means that folder is located in the root of
|
||||
A default value is ``data`` that means that folder is located in the root of
|
||||
project.
|
||||
|
||||
This option can be overridden by global environment variable
|
||||
@ -139,9 +177,8 @@ This option can be overridden by global environment variable
|
||||
``test_dir``
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Directory for :ref:`unit_testing`.
|
||||
|
||||
A default value is ``test`` which means that folder is located in the root of
|
||||
Directory where :ref:`unit_testing` engine will look for the tests.
|
||||
A default value is ``test`` that means that folder is located in the root of
|
||||
project.
|
||||
|
||||
This option can be overridden by global environment variable
|
||||
@ -206,6 +243,9 @@ For example, ``[env:hello_world]``.
|
||||
General options
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
.. _projectconf_env_platform:
|
||||
|
||||
``platform``
|
||||
@ -265,6 +305,9 @@ using `PlatformIO Embedded Boards Explorer <http://platformio.org/boards>`_.
|
||||
Board options
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
``board_mcu``
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
@ -309,8 +352,11 @@ This option isn't available for the all development platforms. The only
|
||||
Flash chip interface mode. This option isn't available for the all development
|
||||
platforms. The only :ref:`platform_espressif` supports it.
|
||||
|
||||
Building options
|
||||
~~~~~~~~~~~~~~~~
|
||||
Build options
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
.. _projectconf_build_flags:
|
||||
|
||||
@ -456,7 +502,7 @@ be applied in theirs order.
|
||||
|
||||
By default, ``src_filter`` is predefined to
|
||||
``+<*> -<.git/> -<svn/> -<example/> -<examples/> -<test/> -<tests/>``,
|
||||
which means "includes ALL files, then
|
||||
that means "includes ALL files, then
|
||||
exclude ``.git`` and ``svn`` repository folders, ``example`` ... folder.
|
||||
|
||||
This option can be set by global environment variable
|
||||
@ -529,8 +575,11 @@ The list with available targets is located in :option:`platformio run --target`.
|
||||
When no targets are defined, *PlatformIO* will build only sources by default.
|
||||
|
||||
|
||||
Uploading options
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Upload options
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
.. _projectconf_upload_port:
|
||||
|
||||
@ -587,6 +636,9 @@ development platforms. The only :ref:`platform_espressif` supports it.
|
||||
Library options
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
``lib_install``
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
@ -603,12 +655,17 @@ Example:
|
||||
[env:depends_on_some_libs]
|
||||
lib_install = 1,13,19
|
||||
|
||||
.. _projectconf_lib_force:
|
||||
|
||||
``lib_force``
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Force Library Build System to build specified libraries if they even are not
|
||||
included in the project source code. Also, these libraries will be processed
|
||||
in the first order.
|
||||
.. seealso::
|
||||
Please make sure to read :ref:`ldf` guide first.
|
||||
|
||||
Force Library Dependency Finder to depend on the specified libraries if
|
||||
they even are not included in the project source code. Also, these
|
||||
libraries will be processed in the first order.
|
||||
|
||||
The correct value for this option is library name (not
|
||||
folder name). In the most cases, library name is pre-defined in manifest file
|
||||
@ -627,7 +684,8 @@ Example:
|
||||
``lib_ignore``
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Please make sure to read :ref:`faq_ldf` guides first.
|
||||
.. seealso::
|
||||
Please make sure to read :ref:`ldf` guide first.
|
||||
|
||||
Specify libraries which should be ignored by Library Dependency Finder.
|
||||
|
||||
@ -643,72 +701,14 @@ Example:
|
||||
[env:ignore_some_libs]
|
||||
lib_ignore = SPI, Ethernet
|
||||
|
||||
.. _projectconf_lib_deep_search:
|
||||
|
||||
``lib_deep_search``
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Please make sure to read :ref:`faq_ldf` guides first.
|
||||
|
||||
By default, this option is turned ON (``lib_deep_search = true``) and means
|
||||
that Library Dependency Finder will analyze ALL source files from the library
|
||||
and will try automatically find all dependencies.
|
||||
|
||||
If you want to disable deep search, please set this option to ``false``.
|
||||
Note! Some libraries depend on other libraries and the
|
||||
``#include <...>`` directives for these libraries are not declared in the
|
||||
"main" header file that is used by upper library. If LDF is turned OFF
|
||||
(``lib_deep_search = false``), it will not handle these libraries automatically
|
||||
because it doesn't analyze "each source file" of the nested libraries
|
||||
(only "nested includes/chain").
|
||||
|
||||
For example, there are 2 libraries:
|
||||
|
||||
* Library "Foo" with files:
|
||||
|
||||
- ``Foo/foo.h``
|
||||
- ``Foo/foo.cpp``
|
||||
|
||||
* Library "Bar" with files:
|
||||
|
||||
- ``Bar/bar.h``
|
||||
- ``Bar/bar.cpp``
|
||||
|
||||
:Case 1:
|
||||
|
||||
* ``lib_deep_search = false``
|
||||
* ``Foo/foo.h`` depends on "Bar" library (contains ``#include <bar.h>``)
|
||||
* ``#include <foo.h>`` is located in one of the project source files
|
||||
|
||||
Here are nested includes (``project file > foo.h > bar.h``) and ``LDF`` will
|
||||
find both libraries "Foo" and "Bar".
|
||||
|
||||
:Case 2:
|
||||
|
||||
* ``lib_deep_search = false``
|
||||
* ``Foo/foo.cpp`` depends on "Bar" library (contains ``#include <bar.h>``)
|
||||
* ``#include <foo.h>`` is located in one of the project source files
|
||||
|
||||
In this case, ``LDF`` will not find "Bar" library because it doesn't know
|
||||
about CPP file (``Foo/foo.cpp``).
|
||||
|
||||
:Case 3:
|
||||
|
||||
* ``lib_deep_search = true``
|
||||
* ``Foo/foo.cpp`` depends on "Bar" library (contains ``#include <bar.h>``)
|
||||
* ``#include <foo.h>`` is located in one of the project source files
|
||||
|
||||
Firstly, ``LDF`` finds "Foo" library, then it parses all sources from "Foo"
|
||||
library and finds ``Foo/foo.cpp`` that depends on ``#include <bar.h>``.
|
||||
Secondly, it will parse all sources from "Bar" library and this operation
|
||||
continues until all dependent libraries will not be parsed.
|
||||
|
||||
.. _projectconf_lib_extra_dirs:
|
||||
|
||||
``lib_extra_dirs``
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Please make sure to read :ref:`faq_ldf` guides first.
|
||||
.. versionadded:: 3.0
|
||||
.. seealso::
|
||||
Please make sure to read :ref:`ldf` guide first.
|
||||
|
||||
A list with extra directories/storages where Library Dependency Finder will
|
||||
look for dependencies. Multiple paths are allowed. Please separate them
|
||||
@ -729,23 +729,34 @@ Example:
|
||||
[env:custom_lib_dirs]
|
||||
lib_extra_dirs = /path/to/private/dir1,/path/to/private/dir2
|
||||
|
||||
.. _projectconf_lib_ldf_mode:
|
||||
|
||||
``lib_ldf_mode``
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 3.0
|
||||
.. seealso::
|
||||
Please make sure to read :ref:`ldf` guide first.
|
||||
|
||||
Library Dependency Finder starts work from analyzing source files of the
|
||||
project (:ref:`projectconf_pio_src_dir`) and can work in the different modes
|
||||
(see :ref:`ldf_mode`).
|
||||
|
||||
By default, this value is set to ``lib_ldf_mode = 2`` and means that LDF
|
||||
will parse ALL C/C++ source code of the project and will parse ALL C/C++
|
||||
source code of the each dependent library (recursively).
|
||||
|
||||
.. _projectconf_lib_compat_mode:
|
||||
|
||||
``lib_compat_mode``
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Please make sure to read :ref:`faq_ldf` guides first.
|
||||
.. versionadded:: 3.0
|
||||
.. seealso::
|
||||
Please make sure to read :ref:`ldf` guide first.
|
||||
|
||||
Library compatibility mode that allows to control Library Dependency Finder
|
||||
strictness. If library contains manifest file (:ref:`library_config`,
|
||||
``library.properties``, ``module.json``), then LDF check compatibility of this
|
||||
library with real build environment. Available compatibility modes:
|
||||
|
||||
* ``0`` - don't check for compatibility
|
||||
* ``1`` - check for the compatibility with :ref:`projectconf_env_framework`
|
||||
from build environment
|
||||
* ``2`` - check for the compatibility with :ref:`projectconf_env_framework`
|
||||
and :ref:`projectconf_env_platform` from build environment.
|
||||
Library compatibility mode allows to control strictness of Library Dependency
|
||||
Finder. More details :ref:`ldf_compat_mode`.
|
||||
|
||||
By default, this value is set to ``lib_compat_mode = 1`` and means that LDF
|
||||
will check only for framework compatibility.
|
||||
|
@ -14,6 +14,8 @@
|
||||
platformio test
|
||||
===============
|
||||
|
||||
.. versionadded:: 3.0
|
||||
|
||||
.. contents::
|
||||
|
||||
Usage
|
||||
|
@ -44,7 +44,7 @@ commonvars.AddVariables(
|
||||
("SRC_FILTER",),
|
||||
|
||||
# library options
|
||||
("LIB_DEEP_SEARCH",),
|
||||
("LIB_LDF_MODE",),
|
||||
("LIB_COMPAT_MODE",),
|
||||
("LIB_IGNORE",),
|
||||
("LIB_FORCE",),
|
||||
@ -63,41 +63,35 @@ commonvars.AddVariables(
|
||||
("UPLOAD_SPEED",),
|
||||
("UPLOAD_FLAGS",),
|
||||
("UPLOAD_RESETMETHOD",)
|
||||
)
|
||||
) # yapf: disable
|
||||
|
||||
DefaultEnvironment(
|
||||
tools=[
|
||||
"ar", "as", "gcc", "g++", "gnulink",
|
||||
"platformio", "devplatform",
|
||||
"piolib", "piotest", "pioupload", "pioar", "piomisc"
|
||||
],
|
||||
], # yapf: disable
|
||||
toolpath=[join(util.get_source_dir(), "builder", "tools")],
|
||||
variables=commonvars,
|
||||
|
||||
# Propagating External Environment
|
||||
ENV=environ,
|
||||
|
||||
UNIX_TIME=int(time()),
|
||||
PROGNAME="program",
|
||||
|
||||
PIOHOME_DIR=util.get_home_dir(),
|
||||
PROJECT_DIR=util.get_project_dir(),
|
||||
PROJECTLIB_DIR=util.get_projectlib_dir(),
|
||||
PROJECTSRC_DIR=util.get_projectsrc_dir(),
|
||||
PROJECTTEST_DIR=util.get_projecttest_dir(),
|
||||
PROJECTDATA_DIR=util.get_projectdata_dir(),
|
||||
PIOENVS_DIR=util.get_pioenvs_dir(),
|
||||
|
||||
BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"),
|
||||
PROJECTPIOENVS_DIR=util.get_projectpioenvs_dir(),
|
||||
BUILD_DIR=join("$PROJECTPIOENVS_DIR", "$PIOENV"),
|
||||
BUILDSRC_DIR=join("$BUILD_DIR", "src"),
|
||||
BUILDTEST_DIR=join("$BUILD_DIR", "test"),
|
||||
LIBSOURCE_DIRS=[
|
||||
"$PROJECTLIB_DIR",
|
||||
util.get_lib_dir()
|
||||
util.get_projectlib_dir(), util.get_projectlibdeps_dir(),
|
||||
join("$PIOHOME_DIR", "lib")
|
||||
],
|
||||
|
||||
PYTHONEXE=normpath(sys.executable)
|
||||
)
|
||||
PYTHONEXE=normpath(sys.executable))
|
||||
|
||||
env = DefaultEnvironment()
|
||||
|
||||
@ -126,10 +120,9 @@ env.Prepend(LIBSOURCE_DIRS=env.get("LIB_EXTRA_DIRS", []))
|
||||
env.LoadDevPlatform(commonvars)
|
||||
|
||||
env.SConscriptChdir(0)
|
||||
env.SConsignFile(join("$PIOENVS_DIR", ".sconsign.dblite"))
|
||||
env.SConsignFile(join("$PROJECTPIOENVS_DIR", ".sconsign.dblite"))
|
||||
env.SConscript("$BUILD_SCRIPT")
|
||||
|
||||
|
||||
if "UPLOAD_FLAGS" in env:
|
||||
env.Append(UPLOADERFLAGS=["$UPLOAD_FLAGS"])
|
||||
|
||||
|
@ -194,7 +194,7 @@ class LibBuilderBase(object): # pylint: disable=too-many-instance-attributes
|
||||
if not search_paths:
|
||||
search_paths = tuple()
|
||||
assert isinstance(search_paths, tuple)
|
||||
deep_search = self.env.get("LIB_DEEP_SEARCH", "true").lower() == "true"
|
||||
deep_search = int(self.env.get("LIB_LDF_MODE", 2)) == 2
|
||||
|
||||
if not self._scanned_paths and (
|
||||
isinstance(self, ProjectAsLibBuilder) or deep_search):
|
||||
@ -270,6 +270,10 @@ class LibBuilderBase(object): # pylint: disable=too-many-instance-attributes
|
||||
"Error: Could not find `%s` dependency for `%s` "
|
||||
"library\n" % (item['name'], self.name))
|
||||
self.env.Exit(2)
|
||||
|
||||
# when LDF is disabled
|
||||
if "LIB_LDF_MODE" in self.env and \
|
||||
int(self.env.get("LIB_LDF_MODE")) == 0:
|
||||
return
|
||||
|
||||
lib_inc_map = {}
|
||||
|
@ -109,7 +109,7 @@ class FDSHASumMismatch(PlatformioException):
|
||||
"is not equal to remote '{2}'"
|
||||
|
||||
|
||||
class NotPlatformProject(PlatformioException):
|
||||
class NotPlatformIOProject(PlatformioException):
|
||||
|
||||
MESSAGE = "Not a PlatformIO project. `platformio.ini` file has not been "\
|
||||
"found in current working directory ({0}). To initialize new project "\
|
||||
|
@ -156,7 +156,7 @@ def _get_projconf_option_dir(name, default=None):
|
||||
if option_dir.startswith("~"):
|
||||
option_dir = expanduser(option_dir)
|
||||
return abspath(option_dir)
|
||||
except exception.NotPlatformProject:
|
||||
except exception.NotPlatformIOProject:
|
||||
pass
|
||||
return default
|
||||
|
||||
@ -180,13 +180,6 @@ def get_home_dir():
|
||||
return home_dir
|
||||
|
||||
|
||||
def get_lib_dir():
|
||||
return _get_projconf_option_dir(
|
||||
"lib_dir",
|
||||
join(get_home_dir(), "lib")
|
||||
)
|
||||
|
||||
|
||||
def get_source_dir():
|
||||
curpath = abspath(__file__)
|
||||
if not isfile(curpath):
|
||||
@ -201,29 +194,33 @@ def get_project_dir():
|
||||
return os.getcwd()
|
||||
|
||||
|
||||
def get_projectsrc_dir():
|
||||
return _get_projconf_option_dir(
|
||||
"src_dir",
|
||||
join(get_project_dir(), "src")
|
||||
)
|
||||
|
||||
|
||||
def get_projecttest_dir():
|
||||
return _get_projconf_option_dir(
|
||||
"test_dir",
|
||||
join(get_project_dir(), "test")
|
||||
)
|
||||
def is_platformio_project(project_dir=None):
|
||||
if not project_dir:
|
||||
project_dir = get_project_dir()
|
||||
return isfile(join(project_dir, "platformio.ini"))
|
||||
|
||||
|
||||
def get_projectlib_dir():
|
||||
return join(get_project_dir(), "lib")
|
||||
return _get_projconf_option_dir("lib_dir", join(get_project_dir(), "lib"))
|
||||
|
||||
|
||||
def get_pioenvs_dir():
|
||||
path = _get_projconf_option_dir(
|
||||
"envs_dir",
|
||||
join(get_project_dir(), ".pioenvs")
|
||||
)
|
||||
def get_projectlibdeps_dir():
|
||||
return _get_projconf_option_dir("libdeps_dir",
|
||||
join(get_project_dir(), ".piolibdeps"))
|
||||
|
||||
|
||||
def get_projectsrc_dir():
|
||||
return _get_projconf_option_dir("src_dir", join(get_project_dir(), "src"))
|
||||
|
||||
|
||||
def get_projecttest_dir():
|
||||
return _get_projconf_option_dir("test_dir", join(get_project_dir(),
|
||||
"test"))
|
||||
|
||||
|
||||
def get_projectpioenvs_dir():
|
||||
path = _get_projconf_option_dir("envs_dir",
|
||||
join(get_project_dir(), ".pioenvs"))
|
||||
if not isdir(path):
|
||||
os.makedirs(path)
|
||||
dontmod_path = join(path, "do-not-modify-files-here.url")
|
||||
@ -247,18 +244,12 @@ def load_project_config(project_dir=None):
|
||||
if not project_dir:
|
||||
project_dir = get_project_dir()
|
||||
if not is_platformio_project(project_dir):
|
||||
raise exception.NotPlatformProject(project_dir)
|
||||
raise exception.NotPlatformIOProject(project_dir)
|
||||
cp = ConfigParser()
|
||||
cp.read(join(project_dir, "platformio.ini"))
|
||||
return cp
|
||||
|
||||
|
||||
def is_platformio_project(project_dir=None):
|
||||
if not project_dir:
|
||||
project_dir = get_project_dir()
|
||||
return isfile(join(project_dir, "platformio.ini"))
|
||||
|
||||
|
||||
def change_filemtime(path, time):
|
||||
os.utime(path, (time, time))
|
||||
|
||||
@ -358,6 +349,12 @@ def get_request_defheaders():
|
||||
)}
|
||||
|
||||
|
||||
@memoized
|
||||
def _api_request_session():
|
||||
import requests
|
||||
return requests.Session()
|
||||
|
||||
|
||||
def get_api_result(path, params=None, data=None, skipdns=False):
|
||||
import requests
|
||||
result = None
|
||||
@ -371,12 +368,14 @@ def get_api_result(path, params=None, data=None, skipdns=False):
|
||||
|
||||
try:
|
||||
if data:
|
||||
r = requests.post(
|
||||
r = _api_request_session().post(
|
||||
url + path, params=params, data=data, headers=headers)
|
||||
else:
|
||||
r = requests.get(url + path, params=params, headers=headers)
|
||||
r.raise_for_status()
|
||||
r = _api_request_session().get(url + path,
|
||||
params=params,
|
||||
headers=headers)
|
||||
result = r.json()
|
||||
r.raise_for_status()
|
||||
except requests.exceptions.HTTPError as e:
|
||||
if result and "errors" in result:
|
||||
raise exception.APIRequestError(result['errors'][0]['title'])
|
||||
|
Reference in New Issue
Block a user