Replaced project configuration format from JSON to YAML
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,7 +5,7 @@ build/cmake-build-debug
|
|||||||
build/cmake-build-release
|
build/cmake-build-release
|
||||||
build/resources
|
build/resources
|
||||||
build/bin/bloom
|
build/bin/bloom
|
||||||
build/bin/bloom.json
|
build/bin/bloom.yaml
|
||||||
*.deb
|
*.deb
|
||||||
*.rpm
|
*.rpm
|
||||||
*.pkg.tar.zst
|
*.pkg.tar.zst
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ Commands:
|
|||||||
--help, -h Displays this help text.
|
--help, -h Displays this help text.
|
||||||
--version, -v Displays Bloom's version number.
|
--version, -v Displays Bloom's version number.
|
||||||
--version-machine Outputs Bloom's version number in JSON format.
|
--version-machine Outputs Bloom's version number in JSON format.
|
||||||
init Creates a new Bloom project configuration file (bloom.json), in the working directory.
|
init Creates a new Bloom project configuration file (bloom.yaml), in the working directory.
|
||||||
|
|
||||||
For more information on getting started with Bloom, please visit https://bloom.oscillate.io/docs/getting-started.
|
For more information on getting started with Bloom, please visit https://bloom.oscillate.io/docs/getting-started.
|
||||||
|
|||||||
@@ -234,22 +234,22 @@ namespace Bloom
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::loadProjectConfiguration() {
|
void Application::loadProjectConfiguration() {
|
||||||
auto jsonConfigFile = QFile(QString::fromStdString(Paths::projectConfigPath()));
|
auto configFile = QFile(QString::fromStdString(Paths::projectConfigPath()));
|
||||||
|
|
||||||
if (!jsonConfigFile.exists()) {
|
if (!configFile.exists()) {
|
||||||
throw InvalidConfig("Bloom configuration file (bloom.json) not found. Working directory: "
|
throw InvalidConfig("Bloom configuration file (bloom.yaml) not found. Working directory: "
|
||||||
+ Paths::projectDirPath());
|
+ Paths::projectDirPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!jsonConfigFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!configFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
throw InvalidConfig("Failed to load Bloom configuration file (bloom.json) Working directory: "
|
throw InvalidConfig("Failed to open Bloom configuration file (bloom.yaml) Working directory: "
|
||||||
+ Paths::projectDirPath());
|
+ Paths::projectDirPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto jsonObject = QJsonDocument::fromJson(jsonConfigFile.readAll()).object();
|
const auto configNode = YAML::Load(configFile.readAll().toStdString());
|
||||||
jsonConfigFile.close();
|
configFile.close();
|
||||||
|
|
||||||
this->projectConfig = ProjectConfig(jsonObject);
|
this->projectConfig = ProjectConfig(configNode);
|
||||||
|
|
||||||
// Validate the selected environment
|
// Validate the selected environment
|
||||||
if (!this->projectConfig->environments.contains(this->selectedEnvironmentName)) {
|
if (!this->projectConfig->environments.contains(this->selectedEnvironmentName)) {
|
||||||
@@ -337,7 +337,7 @@ namespace Bloom
|
|||||||
auto configFile = QFile(QString::fromStdString(Paths::projectConfigPath()));
|
auto configFile = QFile(QString::fromStdString(Paths::projectConfigPath()));
|
||||||
|
|
||||||
if (configFile.exists()) {
|
if (configFile.exists()) {
|
||||||
throw Exception("Bloom configuration file (bloom.json) already exists in working directory.");
|
throw Exception("Bloom configuration file (bloom.yaml) already exists in working directory.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -358,7 +358,7 @@ namespace Bloom
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!configFile.open(QIODevice::ReadWrite)) {
|
if (!configFile.open(QIODevice::ReadWrite)) {
|
||||||
throw Exception("Failed to create Bloom configuration file (bloom.json)");
|
throw Exception("Failed to create Bloom configuration file (bloom.yaml)");
|
||||||
}
|
}
|
||||||
|
|
||||||
configFile.write(templateConfigFile.readAll());
|
configFile.write(templateConfigFile.readAll());
|
||||||
@@ -366,7 +366,7 @@ namespace Bloom
|
|||||||
configFile.close();
|
configFile.close();
|
||||||
templateConfigFile.close();
|
templateConfigFile.close();
|
||||||
|
|
||||||
Logger::info("Bloom configuration file (bloom.json) created in working directory.");
|
Logger::info("Bloom configuration file (bloom.yaml) created in working directory.");
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Bloom::DebugServer
|
|||||||
EventListenerPointer eventListener = std::make_shared<EventListener>("DebugServerEventListener");
|
EventListenerPointer eventListener = std::make_shared<EventListener>("DebugServerEventListener");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project configuration for the debug server (extracted from the user project's bloom.json).
|
* Project configuration for the debug server (extracted from the user project's bloom.yaml).
|
||||||
*/
|
*/
|
||||||
DebugServerConfig debugServerConfig;
|
DebugServerConfig debugServerConfig;
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ namespace Bloom::DebugServer
|
|||||||
/**
|
/**
|
||||||
* Returns a mapping of server configuration names to lambdas/std::functions.
|
* Returns a mapping of server configuration names to lambdas/std::functions.
|
||||||
*
|
*
|
||||||
* The server configuration name is what the user will use in their project configuration (bloom.json), when
|
* The server configuration name is what the user will use in their project configuration (bloom.yaml), when
|
||||||
* selecting a debug server. It *must* be lower-case.
|
* selecting a debug server. It *must* be lower-case.
|
||||||
*
|
*
|
||||||
* The lambda should return an instance of the server implementation.
|
* The lambda should return an instance of the server implementation.
|
||||||
|
|||||||
@@ -1,18 +1,27 @@
|
|||||||
#include "GdbDebugServerConfig.hpp"
|
#include "GdbDebugServerConfig.hpp"
|
||||||
|
|
||||||
|
#include "src/Helpers/YamlUtilities.hpp"
|
||||||
|
#include "src/Logger/Logger.hpp"
|
||||||
|
|
||||||
namespace Bloom::DebugServer::Gdb
|
namespace Bloom::DebugServer::Gdb
|
||||||
{
|
{
|
||||||
GdbDebugServerConfig::GdbDebugServerConfig(const DebugServerConfig& debugServerConfig)
|
GdbDebugServerConfig::GdbDebugServerConfig(const DebugServerConfig& debugServerConfig)
|
||||||
: DebugServerConfig(debugServerConfig)
|
: DebugServerConfig(debugServerConfig)
|
||||||
{
|
{
|
||||||
if (debugServerConfig.jsonObject.contains("ipAddress")) {
|
if (debugServerConfig.debugServerNode["ipAddress"]) {
|
||||||
this->listeningAddress = debugServerConfig.jsonObject.value("ipAddress").toString().toStdString();
|
if (!YamlUtilities::isType<std::string>(debugServerConfig.debugServerNode["ipAddress"])) {
|
||||||
|
Logger::error(
|
||||||
|
"Invalid GDB debug server config parameter ('ipAddress') provided - must be a string. The "
|
||||||
|
"parameter will be ignored."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->listeningAddress = debugServerConfig.debugServerNode["ipAddress"].as<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debugServerConfig.jsonObject.contains("port")) {
|
if (debugServerConfig.debugServerNode["port"]) {
|
||||||
const auto portValue = debugServerConfig.jsonObject.value("port");
|
|
||||||
this->listeningPortNumber = static_cast<std::uint16_t>(
|
this->listeningPortNumber = static_cast<std::uint16_t>(
|
||||||
portValue.isString() ? portValue.toString().toInt(nullptr, 10) : portValue.toInt()
|
debugServerConfig.debugServerNode["port"].as<int>()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ connected AVR target, by implementing the
|
|||||||
Each server must implement the interface defined in the [`ServerInterface` class](./ServerInterface.hpp).
|
Each server must implement the interface defined in the [`ServerInterface` class](./ServerInterface.hpp).
|
||||||
|
|
||||||
At startup, the DebugServer will select the appropriate server implementation, based on the user's project
|
At startup, the DebugServer will select the appropriate server implementation, based on the user's project
|
||||||
configuration (bloom.json - see [`DebugServerConfig`](../ProjectConfig.hpp)). Each server implementation is mapped to a
|
configuration (bloom.yaml - see [`DebugServerConfig`](../ProjectConfig.hpp)). Each server implementation is mapped to a
|
||||||
config name, which is to be used in the project configuration file. For the mapping, see
|
config name, which is to be used in the project configuration file. For the mapping, see
|
||||||
`DebugServerComponent::getAvailableServersByName()`. After initialising the server (via `ServerInterface::init()`),
|
`DebugServerComponent::getAvailableServersByName()`. After initialising the server (via `ServerInterface::init()`),
|
||||||
control of the DebugServer thread will then be handed over to the server implementation (via `ServerInterface::run()`).
|
control of the DebugServer thread will then be handed over to the server implementation (via `ServerInterface::run()`).
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ namespace Bloom
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the path to the current project's configuration file (bloom.json).
|
* Returns the path to the current project's configuration file (bloom.yaml).
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static std::string projectConfigPath() {
|
static std::string projectConfigPath() {
|
||||||
return Paths::projectDirPath() + "/bloom.json";
|
return Paths::projectDirPath() + "/bloom.yaml";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,111 +1,168 @@
|
|||||||
#include "ProjectConfig.hpp"
|
#include "ProjectConfig.hpp"
|
||||||
|
|
||||||
|
#include "src/Helpers/String.hpp"
|
||||||
#include "src/Logger/Logger.hpp"
|
#include "src/Logger/Logger.hpp"
|
||||||
#include "src/Exceptions/InvalidConfig.hpp"
|
#include "src/Exceptions/InvalidConfig.hpp"
|
||||||
|
|
||||||
namespace Bloom
|
namespace Bloom
|
||||||
{
|
{
|
||||||
ProjectConfig::ProjectConfig(const QJsonObject& jsonObject) {
|
ProjectConfig::ProjectConfig(const YAML::Node& configNode) {
|
||||||
if (!jsonObject.contains("environments")) {
|
if (!configNode["environments"]) {
|
||||||
throw Exceptions::InvalidConfig(
|
throw Exceptions::InvalidConfig(
|
||||||
"No environments found - please review the bloom.json configuration file and ensure that "
|
"No environments found - please review the bloom.yaml configuration file and ensure that "
|
||||||
"no syntax errors are present."
|
"no syntax errors are present."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract all environment objects from JSON config.
|
if (!configNode["environments"].IsMap()) {
|
||||||
auto environments = jsonObject.find("environments").value().toObject();
|
throw Exceptions::InvalidConfig(
|
||||||
|
"Invalid environments configuration provided - 'environments' must be of mapping type."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& environments = configNode["environments"];
|
||||||
|
|
||||||
for (auto environmentIt = environments.begin(); environmentIt != environments.end(); environmentIt++) {
|
for (auto environmentIt = environments.begin(); environmentIt != environments.end(); environmentIt++) {
|
||||||
auto environmentName = environmentIt.key().toStdString();
|
auto environmentName = std::optional<std::string>(std::nullopt);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
environmentName = environmentIt->first.as<std::string>();
|
||||||
|
|
||||||
|
if (!String::isAscii(environmentName.value())) {
|
||||||
|
throw Exceptions::InvalidConfig(
|
||||||
|
"Environment name ('" + environmentName.value() + "') is not in ASCII form."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this->environments.insert(
|
this->environments.insert(
|
||||||
std::pair(
|
std::pair(
|
||||||
environmentName,
|
environmentName.value(),
|
||||||
EnvironmentConfig(environmentName, environmentIt.value().toObject())
|
EnvironmentConfig(environmentName.value(), environmentIt->second)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
} catch (Exceptions::InvalidConfig& exception) {
|
} catch (Exceptions::InvalidConfig& exception) {
|
||||||
Logger::error("Invalid environment config for environment '" + environmentName + "': "
|
Logger::error(
|
||||||
+ exception.getMessage() + " Environment will be ignored.");
|
"Invalid environment config for environment '" + environmentName.value() + "': "
|
||||||
|
+ exception.getMessage() + " Environment will be ignored."
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (YAML::BadConversion& exception) {
|
||||||
|
Logger::error(
|
||||||
|
"Invalid environment name provided. Environment names must be ASCII strings. Environment will be "
|
||||||
|
"ignored"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonObject.contains("debugServer")) {
|
if (configNode["debugServer"]) {
|
||||||
this->debugServerConfig = DebugServerConfig(jsonObject.find("debugServer")->toObject());
|
this->debugServerConfig = DebugServerConfig(configNode["debugServer"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonObject.contains("insight")) {
|
if (configNode["insight"]) {
|
||||||
this->insightConfig = InsightConfig(jsonObject.find("insight")->toObject());
|
this->insightConfig = InsightConfig(configNode["insight"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonObject.contains("debugLoggingEnabled")) {
|
if (configNode["debugLoggingEnabled"]) {
|
||||||
this->debugLoggingEnabled = jsonObject.find("debugLoggingEnabled").value().toBool();
|
this->debugLoggingEnabled = configNode["debugLoggingEnabled"].as<bool>(this->debugLoggingEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InsightConfig::InsightConfig(const QJsonObject& jsonObject) {
|
InsightConfig::InsightConfig(const YAML::Node& insightNode) {
|
||||||
if (jsonObject.contains("enabled")) {
|
if (insightNode["enabled"]) {
|
||||||
this->insightEnabled = jsonObject.find("enabled").value().toBool();
|
this->insightEnabled = insightNode["enabled"].as<bool>(this->insightEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EnvironmentConfig::EnvironmentConfig(std::string name, QJsonObject jsonObject) {
|
EnvironmentConfig::EnvironmentConfig(std::string name, const YAML::Node& environmentNode)
|
||||||
if (!jsonObject.contains("debugTool")) {
|
: name(std::move(name))
|
||||||
throw Exceptions::InvalidConfig("No debug tool configuration provided.");
|
{
|
||||||
|
if (!environmentNode["debugTool"]) {
|
||||||
|
throw Exceptions::InvalidConfig("Missing debug tool configuration.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!jsonObject.contains("target")) {
|
if (!environmentNode["debugTool"].IsMap()) {
|
||||||
throw Exceptions::InvalidConfig("No target configuration provided.");
|
throw Exceptions::InvalidConfig(
|
||||||
|
"Invalid debug tool configuration provided - 'debugTool' must be of mapping type."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->name = std::move(name);
|
if (!environmentNode["target"]) {
|
||||||
this->shutdownPostDebugSession = jsonObject.value(
|
throw Exceptions::InvalidConfig("Missing target configuration.");
|
||||||
"shutdownPostDebugSession"
|
|
||||||
).toBool(this->shutdownPostDebugSession);
|
|
||||||
this->debugToolConfig = DebugToolConfig(jsonObject.find("debugTool")->toObject());
|
|
||||||
this->targetConfig = TargetConfig(jsonObject.find("target")->toObject());
|
|
||||||
|
|
||||||
if (jsonObject.contains("debugServer")) {
|
|
||||||
this->debugServerConfig = DebugServerConfig(jsonObject.find("debugServer")->toObject());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonObject.contains("insight")) {
|
if (!environmentNode["target"].IsMap()) {
|
||||||
this->insightConfig = InsightConfig(jsonObject.find("insight")->toObject());
|
throw Exceptions::InvalidConfig(
|
||||||
|
"Invalid target configuration provided - 'target' must be of mapping type."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->debugToolConfig = DebugToolConfig(environmentNode["debugTool"]);
|
||||||
|
this->targetConfig = TargetConfig(environmentNode["target"]);
|
||||||
|
|
||||||
|
if (environmentNode["debugServer"]) {
|
||||||
|
if (!environmentNode["debugServer"].IsMap()) {
|
||||||
|
throw Exceptions::InvalidConfig(
|
||||||
|
"Invalid debug server configuration provided - 'debugServer' must be of mapping type."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->debugServerConfig = DebugServerConfig(environmentNode["debugServer"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (environmentNode["insight"]) {
|
||||||
|
if (!environmentNode["insight"].IsMap()) {
|
||||||
|
throw Exceptions::InvalidConfig(
|
||||||
|
"Invalid insight configuration provided - 'insight' must be of mapping type."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->insightConfig = InsightConfig(environmentNode["insight"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (environmentNode["shutdownPostDebugSession"]) {
|
||||||
|
this->shutdownPostDebugSession = environmentNode["shutdownPostDebugSession"].as<bool>(
|
||||||
|
this->shutdownPostDebugSession
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetConfig::TargetConfig(const QJsonObject& jsonObject) {
|
TargetConfig::TargetConfig(const YAML::Node& targetNode) {
|
||||||
if (!jsonObject.contains("name")) {
|
if (!targetNode["name"]) {
|
||||||
throw Exceptions::InvalidConfig("No target name found.");
|
throw Exceptions::InvalidConfig("No target name found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
this->name = jsonObject.find("name")->toString().toLower().toStdString();
|
this->name = String::asciiToLower(targetNode["name"].as<std::string>());
|
||||||
|
|
||||||
if (jsonObject.contains("variantName")) {
|
if (targetNode["variantName"]) {
|
||||||
this->variantName = jsonObject.find("variantName").value().toString().toLower().toStdString();
|
this->variantName = String::asciiToLower(targetNode["variantName"].as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
this->jsonObject = jsonObject;
|
this->targetNode = targetNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugToolConfig::DebugToolConfig(const QJsonObject& jsonObject) {
|
DebugToolConfig::DebugToolConfig(const YAML::Node& debugToolNode) {
|
||||||
if (!jsonObject.contains("name")) {
|
if (!debugToolNode["name"]) {
|
||||||
throw Exceptions::InvalidConfig("No debug tool name found.");
|
throw Exceptions::InvalidConfig("No debug tool name found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
this->name = jsonObject.find("name")->toString().toLower().toStdString();
|
this->name = String::asciiToLower(debugToolNode["name"].as<std::string>());
|
||||||
|
|
||||||
if (jsonObject.contains("releasePostDebugSession")) {
|
if (debugToolNode["releasePostDebugSession"]) {
|
||||||
this->releasePostDebugSession = jsonObject.find("releasePostDebugSession").value().toBool();
|
this->releasePostDebugSession = debugToolNode["releasePostDebugSession"].as<bool>(
|
||||||
|
this->releasePostDebugSession
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->jsonObject = jsonObject;
|
this->debugToolNode = debugToolNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugServerConfig::DebugServerConfig(const QJsonObject& jsonObject) {
|
DebugServerConfig::DebugServerConfig(const YAML::Node& debugServerNode) {
|
||||||
this->name = jsonObject.find("name")->toString().toLower().toStdString();
|
if (!debugServerNode["name"]) {
|
||||||
this->jsonObject = jsonObject;
|
throw Exceptions::InvalidConfig("No debug server name found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->name = String::asciiToLower(debugServerNode["name"].as<std::string>());
|
||||||
|
this->debugServerNode = debugServerNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,41 +3,44 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <QJsonObject>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
namespace Bloom
|
namespace Bloom
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Currently, all user configuration is stored in a JSON file (bloom.json), in the user's project directory.
|
* Currently, all user configuration is stored in a YAML file (bloom.yaml), in the user's project directory.
|
||||||
*
|
*
|
||||||
* The JSON config file should define debugging environment objects. A debugging environment object is just
|
* The YAML config file should define parameters for specific debug environments. Because a config file can define
|
||||||
* a user defined JSON object that holds parameters relating to a specific debugging environment (e.g config params
|
* multiple debug environments, each environment must be assigned a unique name that can be used to identify the
|
||||||
* for the DebugTool, Target configuration and any debug server config). Because a config file
|
* environment. This is why the 'environments' parameter is a YAML map, with the key being the environment name.
|
||||||
* can define multiple debugging environments, each object should be assigned a key in the config file. We use this
|
|
||||||
* key to allow users to select different debugging environments between debugging sessions.
|
|
||||||
*
|
*
|
||||||
* On application startup, we extract the config from this JSON file and generate an ProjectConfig object.
|
* On application startup, we extract the config from this YAML file and generate a ProjectConfig object.
|
||||||
* See Application::loadProjectConfiguration() for more on this.
|
* See Application::loadProjectConfiguration() for more on this.
|
||||||
*
|
*
|
||||||
* Some config parameters are specific to certain entities within Bloom, but have no significance across the
|
* Some config parameters are specific to certain entities within Bloom, but have no significance across the
|
||||||
* rest of the application. For example, AVR8 targets require the 'physicalInterface' and other AVR8 specific
|
* rest of the application. For example, AVR8 targets require the 'physicalInterface' and other AVR8 specific
|
||||||
* parameters. These are used to configure AVR8 targets, but have no significance across the rest of the
|
* parameters. These are used to configure AVR8 targets, but have no significance across the rest of the
|
||||||
* application. This is why some configuration structs (like TargetConfig) include a QJsonObject member, typically
|
* application. This is why some configuration structs (like TargetConfig) include a YAML::Node member.
|
||||||
* named jsonObject. When instances of these structs are passed to the appropriate entities, any configuration
|
* When instances of these structs are passed to the appropriate entities, any configuration required by those
|
||||||
* required by those entities is extracted from the jsonObject member. This means we don't have to worry about any
|
* entities is extracted from the YAML::Node member. This means we don't have to worry about any entity specific
|
||||||
* entity specific config parameters at the application level. We can simply extract what we need at an entity
|
* config parameters at the application level. We can simply extract what we need at an entity level and the rest
|
||||||
* level and the rest of the application can remain oblivious. For an example on extracting entity specific
|
* of the application can remain oblivious. For an example on extracting entity specific config, see
|
||||||
* config, see AVR8::preActivationConfigure().
|
* Avr8TargetConfig::Avr8TargetConfig() and Avr8::preActivationConfigure().
|
||||||
*
|
*
|
||||||
* For more on project configuration, see Bloom documentation at https://bloom.oscillate.io/docs/configuration
|
* For more on project configuration, see Bloom documentation at https://bloom.oscillate.io/docs/configuration
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initially, we used the JSON format for project configuration files, but this was changed in version 0.11.0.
|
||||||
|
* See https://github.com/navnavnav/Bloom/issues/50 for more.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration relating to a specific target.
|
* Configuration relating to a specific target.
|
||||||
*
|
*
|
||||||
* Please don't define any target specific configuration here, unless it applies to *all* targets across
|
* Please don't define any target specific configuration here, unless it applies to *all* targets across
|
||||||
* the application. If a target requires specific config, it should be extracted from the jsonObject member.
|
* the application. If a target requires specific config, it should be extracted from the YAML::Node (targetNode)
|
||||||
* This should be done in Target::preActivationConfigure(), to which an instance of TargetConfig is passed.
|
* member. This should be done in Target::preActivationConfigure(), to which an instance of TargetConfig is passed.
|
||||||
* See the comment above on entity specific config for more on this.
|
* See the comment above on entity specific config for more on this.
|
||||||
*/
|
*/
|
||||||
struct TargetConfig
|
struct TargetConfig
|
||||||
@@ -54,16 +57,20 @@ namespace Bloom
|
|||||||
*/
|
*/
|
||||||
std::optional<std::string> variantName;
|
std::optional<std::string> variantName;
|
||||||
|
|
||||||
QJsonObject jsonObject;
|
/**
|
||||||
|
* For extracting any target specific configuration. See Avr8TargetConfig::Avr8TargetConfig() and
|
||||||
|
* Avr8::preActivationConfigure() for an example of this.
|
||||||
|
*/
|
||||||
|
YAML::Node targetNode;
|
||||||
|
|
||||||
TargetConfig() = default;
|
TargetConfig() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains config parameters from JSON object.
|
* Obtains config parameters from YAML node.
|
||||||
*
|
*
|
||||||
* @param jsonObject
|
* @param targetNode
|
||||||
*/
|
*/
|
||||||
explicit TargetConfig(const QJsonObject& jsonObject);
|
explicit TargetConfig(const YAML::Node& targetNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +78,7 @@ namespace Bloom
|
|||||||
*
|
*
|
||||||
* As with the TargetConfig struct, please don't add any manufacture/model specific configuration here. This
|
* As with the TargetConfig struct, please don't add any manufacture/model specific configuration here. This
|
||||||
* configuration should apply to all supported debug tools. Specific configuration can be extracted from the
|
* configuration should apply to all supported debug tools. Specific configuration can be extracted from the
|
||||||
* jsonObject member, as described in the TargetConfig comment above.
|
* YAML::Node (debugToolNode) member, as described in the TargetConfig comment above.
|
||||||
*/
|
*/
|
||||||
struct DebugToolConfig
|
struct DebugToolConfig
|
||||||
{
|
{
|
||||||
@@ -89,16 +96,19 @@ namespace Bloom
|
|||||||
*/
|
*/
|
||||||
bool releasePostDebugSession = true;
|
bool releasePostDebugSession = true;
|
||||||
|
|
||||||
QJsonObject jsonObject;
|
/**
|
||||||
|
* For extracting any debug tool specific configuration.
|
||||||
|
*/
|
||||||
|
YAML::Node debugToolNode;
|
||||||
|
|
||||||
DebugToolConfig() = default;
|
DebugToolConfig() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains config parameters from JSON object.
|
* Obtains config parameters from YAML node.
|
||||||
*
|
*
|
||||||
* @param jsonObject
|
* @param debugToolNode
|
||||||
*/
|
*/
|
||||||
explicit DebugToolConfig(const QJsonObject& jsonObject);
|
explicit DebugToolConfig(const YAML::Node& debugToolNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,17 +116,25 @@ namespace Bloom
|
|||||||
*/
|
*/
|
||||||
struct DebugServerConfig
|
struct DebugServerConfig
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The name of the selected debug server.
|
||||||
|
*/
|
||||||
std::string name;
|
std::string name;
|
||||||
QJsonObject jsonObject;
|
|
||||||
|
/**
|
||||||
|
* For extracting any debug server specific configuration. See GdbDebugServerConfig::GdbDebugServerConfig() and
|
||||||
|
* GdbRspDebugServer::GdbRspDebugServer() for an example of this.
|
||||||
|
*/
|
||||||
|
YAML::Node debugServerNode;
|
||||||
|
|
||||||
DebugServerConfig() = default;
|
DebugServerConfig() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains config parameters from JSON object.
|
* Obtains config parameters from YAML node.
|
||||||
*
|
*
|
||||||
* @param jsonObject
|
* @param debugServerNode
|
||||||
*/
|
*/
|
||||||
explicit DebugServerConfig(const QJsonObject& jsonObject);
|
explicit DebugServerConfig(const YAML::Node& debugServerNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InsightConfig
|
struct InsightConfig
|
||||||
@@ -126,11 +144,11 @@ namespace Bloom
|
|||||||
InsightConfig() = default;
|
InsightConfig() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains config parameters from JSON object.
|
* Obtains config parameters from YAML node.
|
||||||
*
|
*
|
||||||
* @param jsonObject
|
* @param insightNode
|
||||||
*/
|
*/
|
||||||
explicit InsightConfig(const QJsonObject& jsonObject);
|
explicit InsightConfig(const YAML::Node& insightNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,7 +160,7 @@ namespace Bloom
|
|||||||
struct EnvironmentConfig
|
struct EnvironmentConfig
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The environment name is stored as the key to the JSON object containing the environment parameters.
|
* The environment name is stored as the key to the YAML map containing the environment parameters.
|
||||||
*
|
*
|
||||||
* Environment names must be unique.
|
* Environment names must be unique.
|
||||||
*/
|
*/
|
||||||
@@ -179,11 +197,12 @@ namespace Bloom
|
|||||||
std::optional<InsightConfig> insightConfig;
|
std::optional<InsightConfig> insightConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains config parameters from JSON object.
|
* Obtains config parameters from YAML node.
|
||||||
*
|
*
|
||||||
* @param jsonObject
|
* @param name
|
||||||
|
* @param environmentNode
|
||||||
*/
|
*/
|
||||||
EnvironmentConfig(std::string name, QJsonObject jsonObject);
|
EnvironmentConfig(std::string name, const YAML::Node& environmentNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -211,10 +230,10 @@ namespace Bloom
|
|||||||
bool debugLoggingEnabled = false;
|
bool debugLoggingEnabled = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains config parameters from JSON object.
|
* Obtains config parameters from YAML node.
|
||||||
*
|
*
|
||||||
* @param jsonObject
|
* @param configNode
|
||||||
*/
|
*/
|
||||||
explicit ProjectConfig(const QJsonObject& jsonObject);
|
explicit ProjectConfig(const YAML::Node& configNode);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ The TargetController possesses the ability to go into a suspended state. In this
|
|||||||
hardware is surrendered - Bloom will no longer be able to interact with the debug tool or target. The purpose of this
|
hardware is surrendered - Bloom will no longer be able to interact with the debug tool or target. The purpose of this
|
||||||
state is to allow other programs access to the hardware, without requiring the termination of the Bloom process. The
|
state is to allow other programs access to the hardware, without requiring the termination of the Bloom process. The
|
||||||
TargetController goes into a suspended state at the end of a debug session, if the user has enabled this via the
|
TargetController goes into a suspended state at the end of a debug session, if the user has enabled this via the
|
||||||
`releasePostDebugSession` debug tool parameter, in their project configuration file (bloom.json). See
|
`releasePostDebugSession` debug tool parameter, in their project configuration file (bloom.yaml). See
|
||||||
`TargetControllerComponent::onDebugSessionFinishedEvent()` for more.
|
`TargetControllerComponent::onDebugSessionFinishedEvent()` for more.
|
||||||
|
|
||||||
When in a suspended state, the TargetController will reject most commands. More specifically, any command that
|
When in a suspended state, the TargetController will reject most commands. More specifically, any command that
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
void Avr8::preActivationConfigure(const TargetConfig& targetConfig) {
|
void Avr8::preActivationConfigure(const TargetConfig& targetConfig) {
|
||||||
Target::preActivationConfigure(targetConfig);
|
Target::preActivationConfigure(targetConfig);
|
||||||
|
|
||||||
|
// Extract AVR8 specific target config
|
||||||
this->targetConfig = Avr8TargetConfig(targetConfig);
|
this->targetConfig = Avr8TargetConfig(targetConfig);
|
||||||
|
|
||||||
if (this->family.has_value()) {
|
if (this->family.has_value()) {
|
||||||
@@ -87,7 +88,7 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
"Failed to validate connected target - target signature mismatch.\nThe target signature"
|
"Failed to validate connected target - target signature mismatch.\nThe target signature"
|
||||||
" (\"" + targetSignature.toHex() + "\") does not match the AVR8 target description signature (\""
|
" (\"" + targetSignature.toHex() + "\") does not match the AVR8 target description signature (\""
|
||||||
+ tdSignature.toHex() + "\"). This will likely be due to an incorrect target name in the configuration"
|
+ tdSignature.toHex() + "\"). This will likely be due to an incorrect target name in the configuration"
|
||||||
+ " file (bloom.json)."
|
+ " file (bloom.yaml)."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "Avr8TargetConfig.hpp"
|
#include "Avr8TargetConfig.hpp"
|
||||||
|
|
||||||
#include "src/Logger/Logger.hpp"
|
#include "src/Helpers/String.hpp"
|
||||||
#include "src/Exceptions/InvalidConfig.hpp"
|
#include "src/Exceptions/InvalidConfig.hpp"
|
||||||
|
|
||||||
namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
||||||
@@ -8,12 +8,13 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
Avr8TargetConfig::Avr8TargetConfig(const TargetConfig& targetConfig): TargetConfig(targetConfig) {
|
Avr8TargetConfig::Avr8TargetConfig(const TargetConfig& targetConfig): TargetConfig(targetConfig) {
|
||||||
using Bloom::Exceptions::InvalidConfig;
|
using Bloom::Exceptions::InvalidConfig;
|
||||||
|
|
||||||
if (!targetConfig.jsonObject.contains("physicalInterface")) {
|
const auto& targetNode = targetConfig.targetNode;
|
||||||
|
|
||||||
|
if (!targetNode["physicalInterface"]) {
|
||||||
throw InvalidConfig("Missing physical interface config parameter for AVR8 target.");
|
throw InvalidConfig("Missing physical interface config parameter for AVR8 target.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto physicalInterfaceName = targetConfig.jsonObject.value("physicalInterface").toString().toLower()
|
const auto physicalInterfaceName = String::asciiToLower(targetNode["physicalInterface"].as<std::string>());
|
||||||
.toStdString();
|
|
||||||
|
|
||||||
static const auto physicalInterfacesByName = Avr8TargetConfig::getPhysicalInterfacesByName();
|
static const auto physicalInterfacesByName = Avr8TargetConfig::getPhysicalInterfacesByName();
|
||||||
|
|
||||||
@@ -23,26 +24,20 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
|
|
||||||
this->physicalInterface = physicalInterfacesByName.at(physicalInterfaceName);
|
this->physicalInterface = physicalInterfacesByName.at(physicalInterfaceName);
|
||||||
|
|
||||||
if (targetConfig.jsonObject.contains("updateDwenFuseBit")) {
|
if (targetNode["updateDwenFuseBit"]) {
|
||||||
this->updateDwenFuseBit = targetConfig.jsonObject.value("updateDwenFuseBit").toBool();
|
this->updateDwenFuseBit = targetNode["updateDwenFuseBit"].as<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetConfig.jsonObject.contains("cycleTargetPowerPostDwenUpdate")) {
|
if (targetNode["cycleTargetPowerPostDwenUpdate"]) {
|
||||||
this->cycleTargetPowerPostDwenUpdate = targetConfig.jsonObject.value(
|
this->cycleTargetPowerPostDwenUpdate = targetNode["cycleTargetPowerPostDwenUpdate"].as<bool>();
|
||||||
"cycleTargetPowerPostDwenUpdate"
|
|
||||||
).toBool();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetConfig.jsonObject.contains("disableDebugWirePreDisconnect")) {
|
if (targetNode["disableDebugWirePreDisconnect"]) {
|
||||||
this->disableDebugWireOnDeactivate = targetConfig.jsonObject.value(
|
this->disableDebugWireOnDeactivate = targetNode["disableDebugWirePreDisconnect"].as<bool>();
|
||||||
"disableDebugWirePreDisconnect"
|
|
||||||
).toBool();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetConfig.jsonObject.contains("targetPowerCycleDelay")) {
|
if (targetNode["targetPowerCycleDelay"]) {
|
||||||
this->targetPowerCycleDelay = std::chrono::milliseconds(targetConfig.jsonObject.value(
|
this->targetPowerCycleDelay = std::chrono::milliseconds(targetNode["targetPowerCycleDelay"].as<int>());
|
||||||
"targetPowerCycleDelay"
|
|
||||||
).toInt(static_cast<int>(this->targetPowerCycleDelay.count())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
#include "src/Helpers/Paths.hpp"
|
#include "src/Helpers/Paths.hpp"
|
||||||
#include "src/Logger/Logger.hpp"
|
#include "src/Logger/Logger.hpp"
|
||||||
@@ -46,7 +47,7 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
|||||||
if (targetName.has_value() && matchingDescriptionFiles.empty()) {
|
if (targetName.has_value() && matchingDescriptionFiles.empty()) {
|
||||||
throw Exception("Failed to resolve target description file for target \"" + targetName.value()
|
throw Exception("Failed to resolve target description file for target \"" + targetName.value()
|
||||||
+ "\" - target signature \"" + targetSignatureHex + "\" does not belong to target with name \"" +
|
+ "\" - target signature \"" + targetSignatureHex + "\" does not belong to target with name \"" +
|
||||||
targetName.value() + "\". Please review your bloom.json configuration.");
|
targetName.value() + "\". Please review your bloom.yaml configuration.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matchingDescriptionFiles.size() == 1) {
|
if (matchingDescriptionFiles.size() == 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user