mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-30 18:17:13 +02:00
Dynamic variables/templates for "platformio.ini" // Resolve #705
This commit is contained in:
@ -7,6 +7,8 @@ PlatformIO 3.0
|
||||
3.1.0 (2016-09-??)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* New! Dynamic variables/templates for `Project Configuration File "platformio.ini" <http://docs.platformio.org/en/stable/projectconf.html>`__
|
||||
(`issue #705 <https://github.com/platformio/platformio/issues/705>`_)
|
||||
* Implemented LocalCache system for API and improved a work in off-line mode
|
||||
* Improved Project Generator when custom ``--project-option`` is passed to
|
||||
`platformio init <http://docs.platformio.org/en/stable/userguide/cmd_init.html>`__
|
||||
|
@ -21,13 +21,73 @@ The Project configuration file is named ``platformio.ini``. This is a
|
||||
key / value pairs within the sections. Lines beginning with ``;``
|
||||
are ignored and may be used to provide comments.
|
||||
|
||||
The sections and their allowable values are described below.
|
||||
There are 2 system reserved sections:
|
||||
|
||||
* Base PlatformIO settings: :ref:`projectconf_section_platformio`
|
||||
* Build Environment settings: :ref:`projectconf_section_env`
|
||||
|
||||
The other sections can be used by users, for example, for
|
||||
:ref:`projectconf_dynamic_vars`. The sections and their allowable values are
|
||||
described below.
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
|
||||
.. _projectconf_dynamic_vars:
|
||||
|
||||
Dynamic variables
|
||||
-----------------
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
Dynamic variables/templates are useful when you have common configuration data
|
||||
between build environments. For examples, common :ref:`projectconf_build_flags`
|
||||
or project dependencies :ref:`projectconf_lib_deps`.
|
||||
|
||||
Each variable should have a next format: ``${<section>.<option>}``, where
|
||||
``<section>`` is a value from ``[<section>]`` group, and ``<option>`` is a
|
||||
first item from pair ``<option> = value``.
|
||||
|
||||
* Variable can be applied only for the option's value
|
||||
* Multiple variables are allowed
|
||||
* The ``platformio`` section is reserved and could not be used as custom
|
||||
section. Some good section names might be ``common`` or ``global``.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[common]
|
||||
build_flags = -D VERSION=1.2.3 -D DEBUG=1
|
||||
lib_deps_builtin = SPI, Wire
|
||||
lib_deps_external = ArduinoJson@>5.6.0
|
||||
|
||||
[env:uno]
|
||||
platform = atmelavr
|
||||
framework = arduino
|
||||
board = uno
|
||||
build_flags = ${common.build_flags}
|
||||
lib_deps = ${common.lib_deps_builtin}, ${common.lib_deps_external}
|
||||
|
||||
[env:nodemcuv2]
|
||||
platform = espressif8266
|
||||
framework = arduino
|
||||
board = nodemcuv2
|
||||
build_flags = ${common.build_flags} -DSSID_NAME=HELLO -DSSID_PASWORD=WORLD
|
||||
lib_deps =
|
||||
${common.lib_deps_builtin}
|
||||
${common.lib_deps_external}
|
||||
PubSubClient@2.6
|
||||
OneWire
|
||||
|
||||
.. _projectconf_section_platformio:
|
||||
|
||||
Section ``[platformio]``
|
||||
------------------------
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
A ``platformio`` section is used for overriding default configuration options
|
||||
|
||||
.. note::
|
||||
@ -45,7 +105,8 @@ Options
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Is used to store platform toolchains, frameworks, global libraries for
|
||||
:ref: `ldf`, service data and etc.
|
||||
:ref: `ldf`, service data and etc. The size of this folder will depend on
|
||||
number of installed development platforms.
|
||||
|
||||
A default value is User's home directory:
|
||||
|
||||
@ -55,6 +116,13 @@ A default value is User's home directory:
|
||||
This option can be overridden by global environment variable
|
||||
:envvar:`PLATFORMIO_HOME_DIR`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[platformio]
|
||||
home_dir = /path/to/custom/pio/storage
|
||||
|
||||
.. _projectconf_pio_lib_dir:
|
||||
|
||||
``lib_dir``
|
||||
@ -223,11 +291,14 @@ Multiple environments are allowed if they are separated with ", "
|
||||
board = lpmsp430g2553
|
||||
build_flags = -D LED_BUILTIN=RED_LED
|
||||
|
||||
----------
|
||||
.. _projectconf_section_env:
|
||||
|
||||
Section ``[env:NAME]``
|
||||
----------------------
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
A section with ``env:`` prefix is used to define virtual environment with
|
||||
specific options that will be processed with :ref:`cmd_run` command. You can
|
||||
define unlimited numbers of environments.
|
||||
@ -703,6 +774,9 @@ Specify project dependencies that should be installed automatically to
|
||||
:ref:`projectconf_pio_libdeps_dir` before environment processing.
|
||||
Multiple dependencies are allowed (multi-lines or separated with comma+space ", ").
|
||||
|
||||
If you have multiple build environments that depend on the same libraries,
|
||||
you can use :ref:`projectconf_dynamic_vars` to use common configuration.
|
||||
|
||||
**Valid forms**
|
||||
|
||||
.. code-block:: ini
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
import sys
|
||||
|
||||
VERSION = (3, 1, "0a3")
|
||||
VERSION = (3, 1, "0a4")
|
||||
__version__ = ".".join([str(s) for s in VERSION])
|
||||
|
||||
__title__ = "platformio"
|
||||
|
@ -26,12 +26,6 @@ from platformio.commands.init import validate_boards
|
||||
from platformio.commands.run import cli as cmd_run
|
||||
from platformio.exception import CIBuildEnvsEmpty
|
||||
|
||||
# pylint: disable=wrong-import-order
|
||||
try:
|
||||
from configparser import ConfigParser
|
||||
except ImportError:
|
||||
from ConfigParser import ConfigParser
|
||||
|
||||
|
||||
def validate_path(ctx, param, value): # pylint: disable=unused-argument
|
||||
invalid_path = None
|
||||
@ -175,9 +169,8 @@ def _exclude_contents(dst_dir, patterns):
|
||||
|
||||
|
||||
def _copy_project_conf(build_dir, project_conf):
|
||||
cp = ConfigParser()
|
||||
cp.read(project_conf)
|
||||
if cp.has_section("platformio"):
|
||||
cp.remove_section("platformio")
|
||||
config = util.load_project_config(project_conf)
|
||||
if config.has_section("platformio"):
|
||||
config.remove_section("platformio")
|
||||
with open(join(build_dir, "platformio.ini"), "w") as fp:
|
||||
cp.write(fp)
|
||||
config.write(fp)
|
||||
|
@ -82,12 +82,8 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose,
|
||||
|
||||
results = []
|
||||
for section in config.sections():
|
||||
# skip main configuration section
|
||||
if section == "platformio":
|
||||
continue
|
||||
|
||||
if not section.startswith("env:"):
|
||||
raise exception.InvalidEnvName(section)
|
||||
continue
|
||||
|
||||
envname = section[4:]
|
||||
skipenv = any([environment and envname not in environment,
|
||||
|
@ -131,11 +131,6 @@ class ProjectEnvsNotAvailable(PlatformioException):
|
||||
MESSAGE = "Please setup environments in `platformio.ini` file"
|
||||
|
||||
|
||||
class InvalidEnvName(PlatformioException):
|
||||
|
||||
MESSAGE = "Invalid environment '{0}'. The name must start with 'env:'"
|
||||
|
||||
|
||||
class UnknownEnvNames(PlatformioException):
|
||||
|
||||
MESSAGE = "Unknown environment names '{0}'. Valid names are '{1}'"
|
||||
|
@ -33,13 +33,35 @@ import requests
|
||||
|
||||
from platformio import __apiurl__, __version__, exception
|
||||
|
||||
# pylint: disable=wrong-import-order
|
||||
# pylint: disable=wrong-import-order, too-many-ancestors
|
||||
|
||||
try:
|
||||
from configparser import ConfigParser
|
||||
except ImportError:
|
||||
from ConfigParser import ConfigParser
|
||||
|
||||
|
||||
class ProjectConfig(ConfigParser):
|
||||
|
||||
VARTPL_RE = re.compile(r"\$\{([^\.\}]+)\.([^\}]+)\}")
|
||||
|
||||
def items(self, section, **_):
|
||||
ConfigParser.items()
|
||||
items = []
|
||||
for option in ConfigParser.options(self, section):
|
||||
items.append((option, self.get(section, option)))
|
||||
return items
|
||||
|
||||
def get(self, section, option, **kwargs):
|
||||
value = ConfigParser.get(self, section, option, **kwargs)
|
||||
if "${" not in value or "}" not in value:
|
||||
return value
|
||||
return self.VARTPL_RE.sub(self._re_sub_handler, value)
|
||||
|
||||
def _re_sub_handler(self, match):
|
||||
return self.get(match.group(1), match.group(2))
|
||||
|
||||
|
||||
class AsyncPipe(Thread):
|
||||
|
||||
def __init__(self, outcallback=None):
|
||||
@ -256,13 +278,15 @@ def get_projectdata_dir():
|
||||
join(get_project_dir(), "data"))
|
||||
|
||||
|
||||
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.NotPlatformIOProject(project_dir)
|
||||
cp = ConfigParser()
|
||||
cp.read(join(project_dir, "platformio.ini"))
|
||||
def load_project_config(path=None):
|
||||
if not path or isdir(path):
|
||||
project_dir = path or get_project_dir()
|
||||
if not is_platformio_project(project_dir):
|
||||
raise exception.NotPlatformIOProject(project_dir)
|
||||
path = join(project_dir, "platformio.ini")
|
||||
assert isfile(path)
|
||||
cp = ProjectConfig()
|
||||
cp.read(path)
|
||||
return cp
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user