Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions platformio/project/integration/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,31 @@ def _load_tplvars(self):
# build data
tpl_vars.update(load_build_metadata(self.project_dir, self.env_name) or {})

# The VSCode launch template uses the default debug environment when
# no environment is forced. Keep its executable and toolchain paths in
# sync with that environment instead of mixing them with the default
# build environment's metadata.
debug_env_name = tpl_vars["default_debug_env_name"]
if (
self.ide == "vscode"
and not self.forced_env_name
and debug_env_name != self.env_name
):
debug_build_data = load_build_metadata(
self.project_dir, debug_env_name, build_type="debug"
)
if debug_build_data and all(
key in debug_build_data for key in ("prog_path", "cc_path")
):
tpl_vars["prog_path"] = debug_build_data["prog_path"]
tpl_vars["cc_path"] = debug_build_data["cc_path"]
else:
# If debug metadata cannot be generated (for example, before
# the selected platform is installed), use the environment
# whose metadata is available and keep the launch entry
# internally consistent.
tpl_vars["default_debug_env_name"] = self.env_name

with fs.cd(self.project_dir):
tpl_vars.update(
{
Expand Down
143 changes: 143 additions & 0 deletions tests/project/test_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
#
# 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.

# pylint: disable=protected-access,redefined-outer-name

import json
import os

import pytest

from platformio.project.config import ProjectConfig
from platformio.project.integration import generator as generator_module
from platformio.project.integration.generator import ProjectGenerator


@pytest.fixture
def project_config(tmp_path):
project_dir = tmp_path / "project"
(project_dir / "src").mkdir(parents=True)
(project_dir / "lib").mkdir()
(project_dir / "test").mkdir()
config_path = project_dir / "platformio.ini"
config_path.write_text(
"""[platformio]
default_envs = hardware

[env]
platform = test-platform
board = test-board

[env:simulation]
build_type = debug

[env:hardware]
""",
encoding="utf8",
)
return ProjectConfig(str(config_path))


def test_vscode_debug_launch_uses_metadata_for_default_debug_env(
project_config, monkeypatch
):
metadata_calls = []

def load_build_metadata(project_dir, env_name, **kwargs):
metadata_calls.append((env_name, kwargs))
return {
"hardware": {
"prog_path": os.path.join(project_dir, ".pio/build/hardware/app.elf"),
"cc_path": os.path.join(
project_dir, ".platformio/packages/toolchain-hardware/bin/cc"
),
"includes": ["hardware-include"],
},
"simulation": {
"prog_path": os.path.join(project_dir, ".pio/build/simulation/app.elf"),
"cc_path": os.path.join(
project_dir, ".platformio/packages/toolchain-simulation/bin/cc"
),
"includes": ["simulation-include"],
},
}[env_name]

monkeypatch.setattr(generator_module, "load_build_metadata", load_build_metadata)
project_generator = ProjectGenerator(project_config, None, "vscode")
template_vars = project_generator._load_tplvars()
template_vars.setdefault("svd_path", "")
launch_template = os.path.join(
project_generator.get_ide_tpls_dir(),
"vscode",
".vscode",
"launch.json.tpl",
)
rendered = project_generator.render_tpl(launch_template, template_vars)
launch = json.loads(rendered[rendered.index("{") :])

pio_launches = launch["configurations"]
assert len(pio_launches) == 3
assert all(item["projectEnvName"] == "simulation" for item in pio_launches)
assert all(
item["executable"].endswith(".pio/build/simulation/app.elf")
for item in pio_launches
)
assert all(
item["toolchainBinDir"].endswith("toolchain-simulation/bin")
for item in pio_launches
)
assert project_generator.env_name == "hardware"
assert template_vars["includes"] == ["hardware-include"]
assert metadata_calls == [
("hardware", {}),
("simulation", {"build_type": "debug"}),
]


def test_vscode_debug_launch_falls_back_to_available_metadata(
project_config, monkeypatch
):
monkeypatch.setattr(
generator_module,
"load_build_metadata",
lambda project_dir, env_name, **kwargs: (
{
"prog_path": os.path.join(project_dir, ".pio/build/hardware/app.elf"),
"cc_path": os.path.join(
project_dir, ".platformio/packages/toolchain-hardware/bin/cc"
),
}
if env_name == "hardware"
else None
),
)
project_generator = ProjectGenerator(project_config, None, "vscode")
template_vars = project_generator._load_tplvars()
template_vars.setdefault("svd_path", "")
launch_template = os.path.join(
project_generator.get_ide_tpls_dir(),
"vscode",
".vscode",
"launch.json.tpl",
)
rendered = project_generator.render_tpl(launch_template, template_vars)
launch = json.loads(rendered[rendered.index("{") :])

assert template_vars["default_debug_env_name"] == "hardware"
assert all(
item["projectEnvName"] == "hardware"
and item["executable"].endswith(".pio/build/hardware/app.elf")
and item["toolchainBinDir"].endswith("toolchain-hardware/bin")
for item in launch["configurations"]
)