forked from platformio/platformio-core
Share common (global) options between declared build environments using "[env]" section // Resolve #1643 Resolve #790
This commit is contained in:
@ -9,6 +9,8 @@ PlatformIO 4.0
|
|||||||
|
|
||||||
* Python 3 support
|
* Python 3 support
|
||||||
(`issue #895 <https://github.com/platformio/platformio-core/issues/895>`_)
|
(`issue #895 <https://github.com/platformio/platformio-core/issues/895>`_)
|
||||||
|
* Share common (global) options between declared build environments using ``[env]`` section in `"platformio.ini" (Project Configuration File) <https://docs.platformio.org/page/projectconf.html>`__
|
||||||
|
(`issue #1643 <https://github.com/platformio/platformio-core/issues/1643>`_)
|
||||||
* Include external configuration files with `extra_configs <http://docs.platformio.org/page/projectconf/section_platformio.html#extra-configs>`__ option
|
* Include external configuration files with `extra_configs <http://docs.platformio.org/page/projectconf/section_platformio.html#extra-configs>`__ option
|
||||||
(`issue #1590 <https://github.com/platformio/platformio-core/issues/1590>`_)
|
(`issue #1590 <https://github.com/platformio/platformio-core/issues/1590>`_)
|
||||||
* Override default source and include directories for a library via `library.json <http://docs.platformio.org/page/librarymanager/config.html>`__ manifest using ``includeDir`` and ``srcDir`` fields
|
* Override default source and include directories for a library via `library.json <http://docs.platformio.org/page/librarymanager/config.html>`__ manifest using ``includeDir`` and ``srcDir`` fields
|
||||||
|
2
docs
2
docs
Submodule docs updated: 5df8f4b066...45a3b5a365
@ -19,9 +19,8 @@ class PlatformioException(Exception):
|
|||||||
|
|
||||||
def __str__(self): # pragma: no cover
|
def __str__(self): # pragma: no cover
|
||||||
if self.MESSAGE:
|
if self.MESSAGE:
|
||||||
return self.MESSAGE.format(
|
return self.MESSAGE.format(*self.args # pylint: disable=not-an-iterable
|
||||||
*self.args # pylint: disable=not-an-iterable
|
)
|
||||||
)
|
|
||||||
return super(PlatformioException, self).__str__()
|
return super(PlatformioException, self).__str__()
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from os.path import isfile
|
from os.path import isfile
|
||||||
@ -198,7 +199,22 @@ class ProjectConfig(object):
|
|||||||
assert section or env
|
assert section or env
|
||||||
if not section:
|
if not section:
|
||||||
section = "env:" + env
|
section = "env:" + env
|
||||||
return self._parser.options(section)
|
options = self._parser.options(section)
|
||||||
|
|
||||||
|
# handle global options from [env]
|
||||||
|
if ((env or section.startswith("env:"))
|
||||||
|
and self._parser.has_section("env")):
|
||||||
|
for option in self._parser.options("env"):
|
||||||
|
if option not in options:
|
||||||
|
options.append(option)
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
|
def has_option(self, section, option):
|
||||||
|
if self._parser.has_option(section, option):
|
||||||
|
return True
|
||||||
|
return (section.startswith("env:") and self._parser.has_section("env")
|
||||||
|
and self._parser.has_option("env", option))
|
||||||
|
|
||||||
def items(self, section=None, env=None, as_dict=False):
|
def items(self, section=None, env=None, as_dict=False):
|
||||||
assert section or env
|
assert section or env
|
||||||
@ -215,24 +231,21 @@ class ProjectConfig(object):
|
|||||||
def get(self, section, option):
|
def get(self, section, option):
|
||||||
if not self.expand_interpolations:
|
if not self.expand_interpolations:
|
||||||
return self._parser.get(section, option)
|
return self._parser.get(section, option)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = self._parser.get(section, option)
|
value = self._parser.get(section, option)
|
||||||
|
except ConfigParser.NoOptionError:
|
||||||
|
value = self._parser.get("env", option)
|
||||||
except ConfigParser.Error as e:
|
except ConfigParser.Error as e:
|
||||||
raise exception.InvalidProjectConf(self.path, str(e))
|
raise exception.InvalidProjectConf(self.path, str(e))
|
||||||
|
|
||||||
if "${" not in value or "}" not in value:
|
if "${" not in value or "}" not in value:
|
||||||
return value
|
return value
|
||||||
return self.VARTPL_RE.sub(self._re_sub_handler, value)
|
return self.VARTPL_RE.sub(self._re_sub_handler, value)
|
||||||
|
|
||||||
def _re_sub_handler(self, match):
|
def _re_sub_handler(self, match):
|
||||||
section, option = match.group(1), match.group(2)
|
section, option = match.group(1), match.group(2)
|
||||||
if section in ("env",
|
if section == "sysenv":
|
||||||
"sysenv") and not self._parser.has_section(section):
|
|
||||||
if section == "env":
|
|
||||||
click.secho(
|
|
||||||
"Warning! Access to system environment variable via "
|
|
||||||
"`${{env.{0}}}` is deprecated. Please use "
|
|
||||||
"`${{sysenv.{0}}}` instead".format(option),
|
|
||||||
fg="yellow")
|
|
||||||
return os.getenv(option)
|
return os.getenv(option)
|
||||||
return self.get(section, option)
|
return self.get(section, option)
|
||||||
|
|
||||||
@ -271,7 +284,7 @@ class ProjectConfig(object):
|
|||||||
|
|
||||||
# check [env:*] sections
|
# check [env:*] sections
|
||||||
for section in self._parser.sections():
|
for section in self._parser.sections():
|
||||||
if not section.startswith("env:"):
|
if section != "env" and not section.startswith("env:"):
|
||||||
continue
|
continue
|
||||||
for option in self._parser.options(section):
|
for option in self._parser.options(section):
|
||||||
# obsolete
|
# obsolete
|
||||||
@ -302,6 +315,12 @@ class ProjectConfig(object):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
result = {}
|
||||||
|
for section in self.sections():
|
||||||
|
result[section] = self.items(section, as_dict=True)
|
||||||
|
return json.dumps(result)
|
||||||
|
|
||||||
def save(self, path=None):
|
def save(self, path=None):
|
||||||
with open(path or self.path, "w") as fp:
|
with open(path or self.path, "w") as fp:
|
||||||
fp.write(CONFIG_HEADER)
|
fp.write(CONFIG_HEADER)
|
||||||
|
@ -18,43 +18,42 @@ from platformio.project.config import ProjectConfig
|
|||||||
|
|
||||||
BASE_CONFIG = """
|
BASE_CONFIG = """
|
||||||
[platformio]
|
[platformio]
|
||||||
env_default = esp32dev, lolin32
|
env_default = base, extra_2
|
||||||
extra_configs =
|
extra_configs =
|
||||||
extra_envs.ini
|
extra_envs.ini
|
||||||
extra_debug.ini
|
extra_debug.ini
|
||||||
|
|
||||||
[common]
|
# global options per [env:*]
|
||||||
|
[env]
|
||||||
|
monitor_speed = 115200
|
||||||
|
lib_deps = Lib1, Lib2
|
||||||
|
lib_ignore = ${custom.lib_ignore}
|
||||||
|
|
||||||
|
[custom]
|
||||||
debug_flags = -D RELEASE
|
debug_flags = -D RELEASE
|
||||||
lib_flags = -lc -lm
|
lib_flags = -lc -lm
|
||||||
extra_flags = ${sysenv.__PIO_TEST_CNF_EXTRA_FLAGS}
|
extra_flags = ${sysenv.__PIO_TEST_CNF_EXTRA_FLAGS}
|
||||||
|
lib_ignore = LibIgnoreCustom
|
||||||
|
|
||||||
[env:esp-wrover-kit]
|
[env:base]
|
||||||
platform = espressif32
|
build_flags = ${custom.debug_flags} ${custom.extra_flags}
|
||||||
framework = espidf
|
|
||||||
board = esp-wrover-kit
|
|
||||||
build_flags = ${common.debug_flags} ${common.extra_flags}
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXTRA_ENVS_CONFIG = """
|
EXTRA_ENVS_CONFIG = """
|
||||||
[env:esp32dev]
|
[env:extra_1]
|
||||||
platform = espressif32
|
build_flags = ${custom.lib_flags} ${custom.debug_flags}
|
||||||
framework = espidf
|
|
||||||
board = esp32dev
|
|
||||||
build_flags = ${common.lib_flags} ${common.debug_flags}
|
|
||||||
|
|
||||||
[env:lolin32]
|
[env:extra_2]
|
||||||
platform = espressif32
|
build_flags = ${custom.debug_flags} ${custom.extra_flags}
|
||||||
framework = espidf
|
lib_ignore = ${env.lib_ignore}, Lib3
|
||||||
board = lolin32
|
|
||||||
build_flags = ${common.debug_flags} ${common.extra_flags}
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXTRA_DEBUG_CONFIG = """
|
EXTRA_DEBUG_CONFIG = """
|
||||||
# Override base "common.debug_flags"
|
# Override original "custom.debug_flags"
|
||||||
[common]
|
[custom]
|
||||||
debug_flags = -D DEBUG=1
|
debug_flags = -D DEBUG=1
|
||||||
|
|
||||||
[env:lolin32]
|
[env:extra_2]
|
||||||
build_flags = -Og
|
build_flags = -Og
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -71,32 +70,47 @@ def test_parser(tmpdir):
|
|||||||
|
|
||||||
# sections
|
# sections
|
||||||
assert config.sections() == [
|
assert config.sections() == [
|
||||||
"platformio", "common", "env:esp-wrover-kit", "env:esp32dev",
|
"platformio", "env", "custom", "env:base", "env:extra_1", "env:extra_2"
|
||||||
"env:lolin32"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# envs
|
||||||
|
assert config.envs() == ["base", "extra_1", "extra_2"]
|
||||||
|
assert config.default_envs() == ["base", "extra_2"]
|
||||||
|
|
||||||
|
# options
|
||||||
|
assert config.options(env="base") == [
|
||||||
|
"build_flags", "monitor_speed", "lib_deps", "lib_ignore"
|
||||||
|
]
|
||||||
|
|
||||||
|
# has_option
|
||||||
|
assert config.has_option("env:base", "monitor_speed")
|
||||||
|
assert not config.has_option("custom", "monitor_speed")
|
||||||
|
|
||||||
# sysenv
|
# sysenv
|
||||||
assert config.get("common", "extra_flags") == ""
|
assert config.get("custom", "extra_flags") == ""
|
||||||
os.environ["__PIO_TEST_CNF_EXTRA_FLAGS"] = "-L /usr/local/lib"
|
os.environ["__PIO_TEST_CNF_EXTRA_FLAGS"] = "-L /usr/local/lib"
|
||||||
assert config.get("common", "extra_flags") == "-L /usr/local/lib"
|
assert config.get("custom", "extra_flags") == "-L /usr/local/lib"
|
||||||
|
|
||||||
# get
|
# get
|
||||||
assert config.get("common", "debug_flags") == "-D DEBUG=1"
|
assert config.get("custom", "debug_flags") == "-D DEBUG=1"
|
||||||
assert config.get("env:esp32dev", "build_flags") == "-lc -lm -D DEBUG=1"
|
assert config.get("env:extra_1", "build_flags") == "-lc -lm -D DEBUG=1"
|
||||||
assert config.get("env:lolin32", "build_flags") == "-Og"
|
assert config.get("env:extra_2", "build_flags") == "-Og"
|
||||||
assert config.get("env:esp-wrover-kit",
|
assert config.get("env:extra_2", "monitor_speed") == "115200"
|
||||||
|
assert config.get("env:base",
|
||||||
"build_flags") == ("-D DEBUG=1 -L /usr/local/lib")
|
"build_flags") == ("-D DEBUG=1 -L /usr/local/lib")
|
||||||
|
|
||||||
# items
|
# items
|
||||||
assert config.items("common") == [("debug_flags", "-D DEBUG=1"),
|
assert config.items("custom") == [("debug_flags", "-D DEBUG=1"),
|
||||||
("lib_flags", "-lc -lm"),
|
("lib_flags", "-lc -lm"),
|
||||||
("extra_flags", "-L /usr/local/lib")]
|
("extra_flags", "-L /usr/local/lib"),
|
||||||
assert config.items(env="esp32dev") == [("platform", "espressif32"),
|
("lib_ignore", "LibIgnoreCustom")]
|
||||||
("framework", "espidf"),
|
assert config.items(env="extra_1") == [("build_flags",
|
||||||
("board", "esp32dev"),
|
"-lc -lm -D DEBUG=1"),
|
||||||
("build_flags",
|
("monitor_speed", "115200"),
|
||||||
"-lc -lm -D DEBUG=1")]
|
("lib_deps", "Lib1, Lib2"),
|
||||||
|
("lib_ignore", "LibIgnoreCustom")]
|
||||||
# envs
|
assert config.items(env="extra_2") == [("build_flags", "-Og"),
|
||||||
assert config.envs() == ["esp-wrover-kit", "esp32dev", "lolin32"]
|
("lib_ignore",
|
||||||
assert config.default_envs() == ["esp32dev", "lolin32"]
|
"LibIgnoreCustom, Lib3"),
|
||||||
|
("monitor_speed", "115200"),
|
||||||
|
("lib_deps", "Lib1, Lib2")]
|
||||||
|
Reference in New Issue
Block a user