mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-29 17:47:14 +02:00
Use common IDE data loading for IDE and DEBUG
This commit is contained in:
@ -24,7 +24,8 @@ from platformio import exception, util
|
||||
from platformio.commands.debug import helpers
|
||||
from platformio.managers.core import inject_contrib_pysite
|
||||
from platformio.project.config import ProjectConfig
|
||||
from platformio.project.helpers import is_platformio_project
|
||||
from platformio.project.helpers import (is_platformio_project,
|
||||
load_project_ide_data)
|
||||
|
||||
|
||||
@click.command("debug",
|
||||
@ -81,7 +82,7 @@ def cli(ctx, project_dir, project_conf, environment, verbose, interface,
|
||||
return helpers.predebug_project(ctx, project_dir, env_name, False,
|
||||
verbose)
|
||||
|
||||
configuration = helpers.load_configuration(ctx, project_dir, env_name)
|
||||
configuration = load_project_ide_data(project_dir, env_name)
|
||||
if not configuration:
|
||||
raise exception.DebugInvalidOptions(
|
||||
"Could not load debug configuration")
|
||||
@ -116,8 +117,8 @@ def cli(ctx, project_dir, project_conf, environment, verbose, interface,
|
||||
|
||||
if rebuild_prog:
|
||||
if helpers.is_mi_mode(__unprocessed):
|
||||
output = helpers.GDBBytesIO()
|
||||
click.echo('~"Preparing firmware for debugging...\\n"')
|
||||
output = helpers.GDBBytesIO()
|
||||
with helpers.capture_std_streams(output):
|
||||
helpers.predebug_project(ctx, project_dir, env_name, preload,
|
||||
verbose)
|
||||
|
@ -12,7 +12,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
from contextlib import contextmanager
|
||||
@ -39,6 +38,17 @@ class GDBBytesIO(BytesIO): # pylint: disable=too-few-public-methods
|
||||
self.STDOUT.flush()
|
||||
|
||||
|
||||
@contextmanager
|
||||
def capture_std_streams(stdout, stderr=None):
|
||||
_stdout = sys.stdout
|
||||
_stderr = sys.stderr
|
||||
sys.stdout = stdout
|
||||
sys.stderr = stderr or stdout
|
||||
yield
|
||||
sys.stdout = _stdout
|
||||
sys.stderr = _stderr
|
||||
|
||||
|
||||
def is_mi_mode(args):
|
||||
return "--interpreter" in " ".join(args)
|
||||
|
||||
@ -59,6 +69,16 @@ def get_default_debug_env(config):
|
||||
return default_envs[0] if default_envs else all_envs[0]
|
||||
|
||||
|
||||
def predebug_project(ctx, project_dir, env_name, preload, verbose):
|
||||
ctx.invoke(cmd_run,
|
||||
project_dir=project_dir,
|
||||
environment=[env_name],
|
||||
target=["debug"] + (["upload"] if preload else []),
|
||||
verbose=verbose)
|
||||
if preload:
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
def validate_debug_options(cmd_ctx, env_options):
|
||||
|
||||
def _cleanup_cmds(items):
|
||||
@ -144,45 +164,6 @@ def validate_debug_options(cmd_ctx, env_options):
|
||||
return result
|
||||
|
||||
|
||||
def predebug_project(ctx, project_dir, env_name, preload, verbose):
|
||||
ctx.invoke(cmd_run,
|
||||
project_dir=project_dir,
|
||||
environment=[env_name],
|
||||
target=["debug"] + (["upload"] if preload else []),
|
||||
verbose=verbose)
|
||||
if preload:
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def capture_std_streams(stdout, stderr=None):
|
||||
_stdout = sys.stdout
|
||||
_stderr = sys.stderr
|
||||
sys.stdout = stdout
|
||||
sys.stderr = stderr or stdout
|
||||
yield
|
||||
sys.stdout = _stdout
|
||||
sys.stderr = _stderr
|
||||
|
||||
|
||||
def load_configuration(ctx, project_dir, env_name):
|
||||
output = BytesIO()
|
||||
with capture_std_streams(output):
|
||||
ctx.invoke(cmd_run,
|
||||
project_dir=project_dir,
|
||||
environment=[env_name],
|
||||
target=["idedata"])
|
||||
result = output.getvalue().decode()
|
||||
output.close()
|
||||
if '"includes":' not in result:
|
||||
return None
|
||||
for line in result.split("\n"):
|
||||
line = line.strip()
|
||||
if line.startswith('{"') and "cxx_path" in line:
|
||||
return json.loads(line[:line.rindex("}") + 1])
|
||||
return None
|
||||
|
||||
|
||||
def configure_esp32_load_cmds(debug_options, configuration):
|
||||
ignore_conds = [
|
||||
debug_options['load_cmds'] != ["load"],
|
||||
|
@ -132,7 +132,7 @@ def cli(
|
||||
|
||||
|
||||
def get_best_envname(project_dir, boards=None):
|
||||
config = ProjectConfig(join(project_dir, "platformio.ini"))
|
||||
config = ProjectConfig.get_instance(join(project_dir, "platformio.ini"))
|
||||
config.validate()
|
||||
|
||||
envname = None
|
||||
|
@ -20,8 +20,8 @@ import click
|
||||
|
||||
from platformio import exception, util
|
||||
from platformio.commands.device import device_monitor as cmd_device_monitor
|
||||
from platformio.commands.run.helpers import (_clean_build_dir,
|
||||
_handle_legacy_libdeps,
|
||||
from platformio.commands.run.helpers import (clean_build_dir,
|
||||
handle_legacy_libdeps,
|
||||
print_summary)
|
||||
from platformio.commands.run.processor import EnvironmentProcessor
|
||||
from platformio.project.config import ProjectConfig
|
||||
@ -64,7 +64,7 @@ def cli(ctx, environment, target, upload_port, project_dir, project_conf,
|
||||
# clean obsolete build dir
|
||||
if not disable_auto_clean:
|
||||
try:
|
||||
_clean_build_dir(get_project_build_dir())
|
||||
clean_build_dir(get_project_build_dir())
|
||||
except: # pylint: disable=bare-except
|
||||
click.secho(
|
||||
"Can not remove temporary directory `%s`. Please remove "
|
||||
@ -76,7 +76,7 @@ def cli(ctx, environment, target, upload_port, project_dir, project_conf,
|
||||
project_conf or join(project_dir, "platformio.ini"))
|
||||
config.validate(environment)
|
||||
|
||||
_handle_legacy_libdeps(project_dir, config)
|
||||
handle_legacy_libdeps(project_dir, config)
|
||||
|
||||
results = []
|
||||
start_time = time()
|
||||
|
@ -27,7 +27,7 @@ from platformio.project.helpers import (calculate_project_hash,
|
||||
get_project_libdeps_dir)
|
||||
|
||||
|
||||
def _handle_legacy_libdeps(project_dir, config):
|
||||
def handle_legacy_libdeps(project_dir, config):
|
||||
legacy_libdeps_dir = join(project_dir, ".piolibdeps")
|
||||
if (not isdir(legacy_libdeps_dir)
|
||||
or legacy_libdeps_dir == get_project_libdeps_dir()):
|
||||
@ -46,7 +46,7 @@ def _handle_legacy_libdeps(project_dir, config):
|
||||
fg="yellow")
|
||||
|
||||
|
||||
def _autoinstall_libdeps(ctx, envname, libraries, verbose=False):
|
||||
def autoinstall_libdeps(ctx, envname, libraries, verbose=False):
|
||||
if not libraries:
|
||||
return
|
||||
libdeps_dir = join(get_project_libdeps_dir(), envname)
|
||||
@ -62,7 +62,7 @@ def _autoinstall_libdeps(ctx, envname, libraries, verbose=False):
|
||||
click.secho(str(e), fg="yellow")
|
||||
|
||||
|
||||
def _clean_build_dir(build_dir):
|
||||
def clean_build_dir(build_dir):
|
||||
# remove legacy ".pioenvs" folder
|
||||
legacy_build_dir = join(get_project_dir(), ".pioenvs")
|
||||
if isdir(legacy_build_dir) and legacy_build_dir != build_dir:
|
||||
|
@ -19,7 +19,7 @@ import click
|
||||
from platformio import exception, telemetry
|
||||
from platformio.commands.platform import \
|
||||
platform_install as cmd_platform_install
|
||||
from platformio.commands.run.helpers import _autoinstall_libdeps, print_header
|
||||
from platformio.commands.run.helpers import autoinstall_libdeps, print_header
|
||||
from platformio.commands.test.processor import (CTX_META_TEST_IS_RUNNING,
|
||||
CTX_META_TEST_RUNNING_NAME)
|
||||
from platformio.managers.platform import PlatformFactory
|
||||
@ -104,7 +104,7 @@ class EnvironmentProcessor(object):
|
||||
if "monitor" in build_targets:
|
||||
build_targets.remove("monitor")
|
||||
if "nobuild" not in build_targets and "lib_deps" in self.options:
|
||||
_autoinstall_libdeps(
|
||||
autoinstall_libdeps(
|
||||
self.cmd_ctx, self.name,
|
||||
self.config.get("env:" + self.name, "lib_deps"), self.verbose)
|
||||
|
||||
|
@ -13,23 +13,21 @@
|
||||
# limitations under the License.
|
||||
|
||||
import codecs
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from os.path import abspath, basename, expanduser, isdir, isfile, join, relpath
|
||||
|
||||
import bottle
|
||||
from click.testing import CliRunner
|
||||
|
||||
from platformio import exception, util
|
||||
from platformio.commands.run import cli as cmd_run
|
||||
from platformio import util
|
||||
from platformio.compat import WINDOWS, get_file_contents
|
||||
from platformio.proc import where_is_program
|
||||
from platformio.project.config import ProjectConfig
|
||||
from platformio.project.helpers import (get_project_lib_dir,
|
||||
get_project_libdeps_dir,
|
||||
get_project_src_dir)
|
||||
get_project_src_dir,
|
||||
load_project_ide_data)
|
||||
|
||||
|
||||
class ProjectGenerator(object):
|
||||
@ -39,57 +37,45 @@ class ProjectGenerator(object):
|
||||
self.ide = str(ide)
|
||||
self.env_name = env_name
|
||||
|
||||
self._tplvars = {}
|
||||
self._gather_tplvars()
|
||||
|
||||
@staticmethod
|
||||
def get_supported_ides():
|
||||
tpls_dir = join(util.get_source_dir(), "ide", "tpls")
|
||||
return sorted(
|
||||
[d for d in os.listdir(tpls_dir) if isdir(join(tpls_dir, d))])
|
||||
|
||||
@util.memoized()
|
||||
def get_project_env(self):
|
||||
data = {}
|
||||
config = ProjectConfig.get_instance(
|
||||
join(self.project_dir, "platformio.ini"))
|
||||
for env in config.envs():
|
||||
if self.env_name != env:
|
||||
continue
|
||||
data = config.items(env=env, as_dict=True)
|
||||
data['env_name'] = self.env_name
|
||||
return data
|
||||
def _load_tplvars(self):
|
||||
tpl_vars = {"env_name": self.env_name}
|
||||
# default env configuration
|
||||
tpl_vars.update(
|
||||
ProjectConfig.get_instance(join(
|
||||
self.project_dir, "platformio.ini")).items(env=self.env_name,
|
||||
as_dict=True))
|
||||
# build data
|
||||
tpl_vars.update(
|
||||
load_project_ide_data(self.project_dir, self.env_name) or {})
|
||||
|
||||
def get_project_build_data(self):
|
||||
data = {
|
||||
"defines": [],
|
||||
"includes": [],
|
||||
"cxx_path": None,
|
||||
"prog_path": None
|
||||
}
|
||||
envdata = self.get_project_env()
|
||||
if not envdata:
|
||||
return data
|
||||
with util.cd(self.project_dir):
|
||||
tpl_vars.update({
|
||||
"project_name": basename(self.project_dir),
|
||||
"src_files": self.get_src_files(),
|
||||
"user_home_dir": abspath(expanduser("~")),
|
||||
"project_dir": self.project_dir,
|
||||
"project_src_dir": get_project_src_dir(),
|
||||
"project_lib_dir": get_project_lib_dir(),
|
||||
"project_libdeps_dir": join(
|
||||
get_project_libdeps_dir(), self.env_name),
|
||||
"systype": util.get_systype(),
|
||||
"platformio_path": self._fix_os_path(
|
||||
sys.argv[0] if isfile(sys.argv[0])
|
||||
else where_is_program("platformio")),
|
||||
"env_pathsep": os.pathsep,
|
||||
"env_path": self._fix_os_path(os.getenv("PATH"))
|
||||
}) # yapf: disable
|
||||
return tpl_vars
|
||||
|
||||
result = CliRunner().invoke(cmd_run, [
|
||||
"--project-dir", self.project_dir, "--environment",
|
||||
envdata['env_name'], "--target", "idedata"
|
||||
])
|
||||
|
||||
if result.exit_code != 0 and not isinstance(result.exception,
|
||||
exception.ReturnErrorCode):
|
||||
raise result.exception
|
||||
if '"includes":' not in result.output:
|
||||
raise exception.PlatformioException(result.output)
|
||||
|
||||
for line in result.output.split("\n"):
|
||||
line = line.strip()
|
||||
if line.startswith('{"') and line.endswith("}"):
|
||||
data = json.loads(line)
|
||||
return data
|
||||
|
||||
def get_project_name(self):
|
||||
return basename(self.project_dir)
|
||||
@staticmethod
|
||||
def _fix_os_path(path):
|
||||
return (re.sub(r"[\\]+", '\\' * 4, path) if WINDOWS else path)
|
||||
|
||||
def get_src_files(self):
|
||||
result = []
|
||||
@ -113,6 +99,7 @@ class ProjectGenerator(object):
|
||||
return tpls
|
||||
|
||||
def generate(self):
|
||||
tpl_vars = self._load_tplvars()
|
||||
for tpl_relpath, tpl_path in self.get_tpls():
|
||||
dst_dir = self.project_dir
|
||||
if tpl_relpath:
|
||||
@ -121,11 +108,12 @@ class ProjectGenerator(object):
|
||||
os.makedirs(dst_dir)
|
||||
|
||||
file_name = basename(tpl_path)[:-4]
|
||||
contents = self._render_tpl(tpl_path)
|
||||
contents = self._render_tpl(tpl_path, tpl_vars)
|
||||
self._merge_contents(join(dst_dir, file_name), contents)
|
||||
|
||||
def _render_tpl(self, tpl_path):
|
||||
return bottle.template(get_file_contents(tpl_path), **self._tplvars)
|
||||
@staticmethod
|
||||
def _render_tpl(tpl_path, tpl_vars):
|
||||
return bottle.template(get_file_contents(tpl_path), **tpl_vars)
|
||||
|
||||
@staticmethod
|
||||
def _merge_contents(dst_path, contents):
|
||||
@ -133,28 +121,3 @@ class ProjectGenerator(object):
|
||||
return
|
||||
with codecs.open(dst_path, "w", encoding="utf8") as fp:
|
||||
fp.write(contents)
|
||||
|
||||
def _gather_tplvars(self):
|
||||
self._tplvars.update(self.get_project_env())
|
||||
self._tplvars.update(self.get_project_build_data())
|
||||
with util.cd(self.project_dir):
|
||||
self._tplvars.update({
|
||||
"project_name": self.get_project_name(),
|
||||
"src_files": self.get_src_files(),
|
||||
"user_home_dir": abspath(expanduser("~")),
|
||||
"project_dir": self.project_dir,
|
||||
"project_src_dir": get_project_src_dir(),
|
||||
"project_lib_dir": get_project_lib_dir(),
|
||||
"project_libdeps_dir": join(
|
||||
get_project_libdeps_dir(), self.env_name),
|
||||
"systype": util.get_systype(),
|
||||
"platformio_path": self._fix_os_path(
|
||||
sys.argv[0] if isfile(sys.argv[0])
|
||||
else where_is_program("platformio")),
|
||||
"env_pathsep": os.pathsep,
|
||||
"env_path": self._fix_os_path(os.getenv("PATH"))
|
||||
}) # yapf: disable
|
||||
|
||||
@staticmethod
|
||||
def _fix_os_path(path):
|
||||
return (re.sub(r"[\\]+", '\\' * 4, path) if WINDOWS else path)
|
||||
|
@ -12,13 +12,16 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
import os
|
||||
from hashlib import sha1
|
||||
from os import walk
|
||||
from os.path import (basename, dirname, expanduser, isdir, isfile, join,
|
||||
realpath, splitdrive)
|
||||
|
||||
from platformio import __version__
|
||||
from click.testing import CliRunner
|
||||
|
||||
from platformio import __version__, exception
|
||||
from platformio.compat import WINDOWS, hashlib_encode_data
|
||||
from platformio.project.config import ProjectConfig
|
||||
|
||||
@ -179,3 +182,22 @@ def calculate_project_hash():
|
||||
# A case of disk drive can differ...
|
||||
chunks_to_str = chunks_to_str.lower()
|
||||
return sha1(hashlib_encode_data(chunks_to_str)).hexdigest()
|
||||
|
||||
|
||||
def load_project_ide_data(project_dir, env_name):
|
||||
from platformio.commands.run import cli as cmd_run
|
||||
result = CliRunner().invoke(cmd_run, [
|
||||
"--project-dir", project_dir, "--environment", env_name, "--target",
|
||||
"idedata"
|
||||
])
|
||||
if result.exit_code != 0 and not isinstance(result.exception,
|
||||
exception.ReturnErrorCode):
|
||||
raise result.exception
|
||||
if '"includes":' not in result.output:
|
||||
raise exception.PlatformioException(result.output)
|
||||
|
||||
for line in result.output.split("\n"):
|
||||
line = line.strip()
|
||||
if line.startswith('{"') and line.endswith("}"):
|
||||
return json.loads(line)
|
||||
return None
|
||||
|
Reference in New Issue
Block a user