- Renamed build script for brief target descriptor generation

- Created new TargetService class
- Moved brief target descriptor mapping to new TargetService class
- Replaced CMake custom commands with custom targets, for TDF validation and brief target descriptor generation build scripts
- Moved BriefTargetDescriptor into separate header file
This commit is contained in:
Nav
2024-03-02 01:59:55 +00:00
parent e75ce8b403
commit 4aa8ed30de
12 changed files with 182 additions and 123 deletions

View File

@@ -46,7 +46,11 @@ if (${CMAKE_BUILD_TYPE} MATCHES "Debug")
endif() endif()
add_executable(Bloom) add_executable(Bloom)
set_target_properties(Bloom PROPERTIES OUTPUT_NAME bloom) set_target_properties(
Bloom
PROPERTIES
OUTPUT_NAME bloom
)
find_package(yaml-cpp 0.7.0 REQUIRED) find_package(yaml-cpp 0.7.0 REQUIRED)
find_package(Qt6Core REQUIRED) find_package(Qt6Core REQUIRED)
@@ -162,47 +166,56 @@ if (${ENABLE_SANITIZERS})
) )
endif() endif()
# Validate TDF files # The ValidateTargetDescriptionFiles target will invoke the TDF validation script for all TDFs in Bloom's codebase.
add_custom_command( add_custom_target(
OUTPUT ${CMAKE_BINARY_DIR}/tdf_validation_timestamp.txt ValidateTargetDescriptionFiles
COMMAND echo 'Validating target description files' COMMENT "Validating target description files"
COMMAND php COMMAND php ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/ValidateTargetDescriptionFiles.php
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/ValidateTargetDescriptionFiles.php
${CMAKE_CURRENT_SOURCE_DIR}/src/Targets/TargetDescriptionFiles/ ${CMAKE_CURRENT_SOURCE_DIR}/src/Targets/TargetDescriptionFiles/
COMMAND date > ${CMAKE_BINARY_DIR}/tdf_validation_timestamp.txt
) )
# Copy TDF files to build directory and generate TDF mapping # The GenerateBriefTargetDescriptors target will invoke the GenerateBriefTargetDescriptors.php build script to generate
set(GENERATED_TDF_MAPPING_PATH "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}_autogen/GeneratedMapping.hpp") # a BriefTargetDescriptor for all targets supported by Bloom. These descriptors are stored in an ASCII text file,
# located at ${GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH}. See the TargetService class for more on this.
#
# The script will also copy all TDFs to the build directory.
set(
GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH
"${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}_autogen/GeneratedMapping.txt"
)
target_sources( target_sources(
Bloom Bloom
PRIVATE PRIVATE
${GENERATED_TDF_MAPPING_PATH} ${GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH}
) )
target_compile_definitions( target_compile_definitions(
Bloom Bloom
PUBLIC GENERATED_TDF_MAPPING_PATH="${GENERATED_TDF_MAPPING_PATH}" PUBLIC GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH="${GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH}"
) )
add_custom_command( add_custom_target(
OUTPUT GenerateBriefTargetDescriptors
${GENERATED_TDF_MAPPING_PATH} BYPRODUCTS
${GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH}
${CMAKE_BINARY_DIR}/resources/TargetDescriptionFiles/ ${CMAKE_BINARY_DIR}/resources/TargetDescriptionFiles/
DEPENDS DEPENDS
${CMAKE_BINARY_DIR}/tdf_validation_timestamp.txt ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateBriefTargetDescriptors.php
${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateTargetDescriptionFileMapping.php COMMENT "Processing target description files"
COMMAND echo 'Processing target description files' COMMAND php ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateBriefTargetDescriptors.php
COMMAND php
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateTargetDescriptionFileMapping.php
${CMAKE_CURRENT_SOURCE_DIR}/src/Targets/TargetDescriptionFiles/ ${CMAKE_CURRENT_SOURCE_DIR}/src/Targets/TargetDescriptionFiles/
${CMAKE_CURRENT_SOURCE_DIR}/src/Targets/TargetDescription/GeneratedMapping.hpp.in ${GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH}
${GENERATED_TDF_MAPPING_PATH}
${CMAKE_BINARY_DIR}/resources/TargetDescriptionFiles/ ${CMAKE_BINARY_DIR}/resources/TargetDescriptionFiles/
) )
# TDF validation should run before we generate the brief target descriptors, which should run before compilation.
add_dependencies(GenerateBriefTargetDescriptors ValidateTargetDescriptionFiles)
add_dependencies(
Bloom
ValidateTargetDescriptionFiles
GenerateBriefTargetDescriptors
)
include(./cmake/Installing.cmake) include(./cmake/Installing.cmake)
include(./cmake/Packaging.cmake) include(./cmake/Packaging.cmake)

View File

@@ -5,9 +5,8 @@ use Targets\TargetDescriptionFiles\Services\Xml\XmlService;
use Targets\TargetDescriptionFiles\TargetFamily; use Targets\TargetDescriptionFiles\TargetFamily;
define('TDF_DIR_PATH', $argv[1] ?? null); define('TDF_DIR_PATH', $argv[1] ?? null);
define('MAPPING_TEMPLATE_PATH', $argv[2] ?? null); define('MAPPING_OUTPUT_PATH', $argv[2] ?? null);
define('MAPPING_OUTPUT_PATH', $argv[3] ?? null); define('TDF_OUTPUT_PATH', $argv[3] ?? null);
define('TDF_OUTPUT_PATH', $argv[4] ?? null);
if (empty(TDF_DIR_PATH)) { if (empty(TDF_DIR_PATH)) {
print 'Missing TDF directory path. Aborting' . PHP_EOL; print 'Missing TDF directory path. Aborting' . PHP_EOL;
@@ -19,11 +18,6 @@ if (!file_exists(TDF_DIR_PATH)) {
exit(1); exit(1);
} }
if (empty(MAPPING_TEMPLATE_PATH)) {
print 'Missing TDF mapping template path. Aborting' . PHP_EOL;
exit(1);
}
if (empty(MAPPING_OUTPUT_PATH)) { if (empty(MAPPING_OUTPUT_PATH)) {
print 'Missing TDF mapping output path. Aborting' . PHP_EOL; print 'Missing TDF mapping output path. Aborting' . PHP_EOL;
exit(1); exit(1);
@@ -50,11 +44,6 @@ $xmlService = new XmlService();
$xmlFiles = $discoveryService->findTargetDescriptionFiles(TDF_DIR_PATH); $xmlFiles = $discoveryService->findTargetDescriptionFiles(TDF_DIR_PATH);
print count($xmlFiles) . ' target descriptions files found in ' . TDF_DIR_PATH . PHP_EOL . PHP_EOL; print count($xmlFiles) . ' target descriptions files found in ' . TDF_DIR_PATH . PHP_EOL . PHP_EOL;
$targetFamilyMapping = [
TargetFamily::AVR_8->value => 'TargetFamily::AVR_8',
TargetFamily::RISC_V->value => 'TargetFamily::RISC_V',
];
const MAP_ENTRY_TEMPLATE = '{"@CONFIG_VALUE@", {"@TARGET_NAME@", "@CONFIG_VALUE@", @TARGET_FAMILY@, "@TDF_PATH@"}}'; const MAP_ENTRY_TEMPLATE = '{"@CONFIG_VALUE@", {"@TARGET_NAME@", "@CONFIG_VALUE@", @TARGET_FAMILY@, "@TDF_PATH@"}}';
$entries = []; $entries = [];
@@ -76,7 +65,10 @@ foreach ($xmlFiles as $xmlFile) {
[ [
$targetDescriptionFile->getConfigurationValue(), $targetDescriptionFile->getConfigurationValue(),
$targetDescriptionFile->getName(), $targetDescriptionFile->getName(),
$targetFamilyMapping[$targetDescriptionFile->getFamily()->value], match($targetDescriptionFile->getFamily()) {
TargetFamily::AVR_8 => 'Targets::TargetFamily::AVR_8',
TargetFamily::RISC_V => 'Targets::TargetFamily::RISC_V',
},
$relativeTdfPath, $relativeTdfPath,
], ],
MAP_ENTRY_TEMPLATE MAP_ENTRY_TEMPLATE
@@ -96,16 +88,9 @@ foreach ($xmlFiles as $xmlFile) {
} }
} }
file_put_contents( file_put_contents(MAPPING_OUTPUT_PATH, implode(',' . PHP_EOL, $entries));
MAPPING_OUTPUT_PATH,
str_replace(
'//@MAPPING_PLACEHOLDER@',
implode(',' . PHP_EOL . str_repeat(' ', 12), $entries),
file_get_contents(MAPPING_TEMPLATE_PATH)
)
);
print PHP_EOL; print PHP_EOL;
print 'Processed ' . count($xmlFiles) . ' TDFs.' . PHP_EOL; print 'Processed ' . count($xmlFiles) . ' TDFs.' . PHP_EOL;
print 'Generated TDF mapping at ' . MAPPING_OUTPUT_PATH . PHP_EOL; print 'Generated brief target descriptors at ' . MAPPING_OUTPUT_PATH . PHP_EOL;
print 'Done' . PHP_EOL; print 'Done' . PHP_EOL;

View File

@@ -14,6 +14,7 @@
#include <QUrlQuery> #include <QUrlQuery>
#include "src/Logger/Logger.hpp" #include "src/Logger/Logger.hpp"
#include "src/Services/TargetService.hpp"
#include "src/Services/PathService.hpp" #include "src/Services/PathService.hpp"
#include "src/Services/ProcessService.hpp" #include "src/Services/ProcessService.hpp"
#include "src/Helpers/BiMap.hpp" #include "src/Helpers/BiMap.hpp"
@@ -399,10 +400,10 @@ int Application::presentCapabilitiesMachine() {
auto supportedTargets = QJsonArray(); auto supportedTargets = QJsonArray();
for (const auto& [configValue, descriptor] : Targets::TargetDescription::TargetDescriptionFile::mapping()) { for (const auto& [configValue, descriptor] : Services::TargetService::briefDescriptorsByConfigValue()) {
supportedTargets.push_back(QJsonObject({ supportedTargets.push_back(QJsonObject({
{"name" , QString::fromStdString(descriptor.targetName)}, {"name" , QString::fromStdString(descriptor.name)},
{"family" , targetFamilyNames.at(descriptor.targetFamily)}, {"family" , targetFamilyNames.at(descriptor.family)},
{"configurationValue" , QString::fromStdString(configValue)}, {"configurationValue" , QString::fromStdString(configValue)},
})); }));
} }

View File

@@ -5,6 +5,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/Application.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Application.cpp
# Services # Services
${CMAKE_CURRENT_SOURCE_DIR}/Services/TargetService.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Services/TargetControllerService.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Services/TargetControllerService.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Services/PathService.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Services/PathService.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Services/ProcessService.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Services/ProcessService.cpp

View File

@@ -0,0 +1,20 @@
#include "TargetService.hpp"
namespace Services
{
using Targets::BriefTargetDescriptor;
const std::map<std::string, BriefTargetDescriptor>& TargetService::briefDescriptorsByConfigValue() {
return TargetService::descriptorsByConfigValue;
}
std::optional<BriefTargetDescriptor> TargetService::briefDescriptor(const std::string& configValue) {
const auto descriptorIt = TargetService::descriptorsByConfigValue.find(configValue);
if (descriptorIt != TargetService::descriptorsByConfigValue.end()) {
return descriptorIt->second;
}
return std::nullopt;
}
}

View File

@@ -0,0 +1,48 @@
#pragma once
#include <string>
#include <map>
#include <cstdint>
#include <optional>
#include <functional>
#include "src/Targets/BriefTargetDescriptor.hpp"
namespace Services
{
class TargetService
{
public:
/**
* Performs a lookup for the given target configuration value, to retrieve the corresponding brief target
* descriptor object.
*
* @param configValue
* The target configuration value to lookup.
*
* @return
* A BriefTargetDescriptor object, if found, otherwise, std::nullopt.
*/
static std::optional<Targets::BriefTargetDescriptor> briefDescriptor(const std::string& configValue);
/**
* Provides access to the internal mapping of the brief target descriptor objects of all targets supported by
* Bloom. See TargetService::descriptorsByConfigValue for more.
*
* @return
*/
static const std::map<std::string, Targets::BriefTargetDescriptor>& briefDescriptorsByConfigValue();
private:
/**
* This mapping contains brief target descriptor objects for every target supported by Bloom, mapped by their
* configuration value. The contents is generated by a build script and stored in an ASCII text file, located
* at GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH.
*
* See build/scripts/GenerateBriefTargetDescriptors.php and the root CMakeLists.txt for more.
*/
static const inline std::map<std::string, Targets::BriefTargetDescriptor> descriptorsByConfigValue = {
#include GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH
};
};
}

View File

@@ -375,25 +375,23 @@ namespace TargetController
}; };
} }
std::unique_ptr<Targets::Target> TargetControllerComponent::constructTargetFromBrief( std::unique_ptr<Target> TargetControllerComponent::constructTarget(const BriefTargetDescriptor& briefDescriptor) {
const TargetDescription::GeneratedMapping::BriefTargetDescriptor &targetBrief
) {
using Services::PathService; using Services::PathService;
if (targetBrief.targetFamily == TargetFamily::AVR_8) { if (briefDescriptor.family == TargetFamily::AVR_8) {
return std::make_unique<Microchip::Avr::Avr8Bit::Avr8>( return std::make_unique<Microchip::Avr::Avr8Bit::Avr8>(
this->environmentConfig.targetConfig, this->environmentConfig.targetConfig,
Microchip::Avr::Avr8Bit::TargetDescription::TargetDescriptionFile( Microchip::Avr::Avr8Bit::TargetDescription::TargetDescriptionFile(
PathService::targetDescriptionDirPath() + "/" + targetBrief.relativeTdfPath PathService::targetDescriptionDirPath() + "/" + briefDescriptor.relativeTdfPath
) )
); );
} }
if (targetBrief.targetFamily == TargetFamily::RISC_V) { if (briefDescriptor.family == TargetFamily::RISC_V) {
return std::make_unique<RiscV::RiscV>( return std::make_unique<RiscV::RiscV>(
this->environmentConfig.targetConfig, this->environmentConfig.targetConfig,
RiscV::TargetDescription::TargetDescriptionFile( RiscV::TargetDescription::TargetDescriptionFile(
PathService::targetDescriptionDirPath() + "/" + targetBrief.relativeTdfPath PathService::targetDescriptionDirPath() + "/" + briefDescriptor.relativeTdfPath
) )
); );
} }
@@ -470,10 +468,9 @@ namespace TargetController
const auto& targetName = this->environmentConfig.targetConfig.name; const auto& targetName = this->environmentConfig.targetConfig.name;
static const auto supportedDebugTools = this->getSupportedDebugTools(); static const auto supportedDebugTools = this->getSupportedDebugTools();
static const auto targetsByConfigValue = TargetDescription::TargetDescriptionFile::mapping();
const auto debugToolIt = supportedDebugTools.find(debugToolName); const auto debugToolIt = supportedDebugTools.find(debugToolName);
const auto targetBriefIt = targetsByConfigValue.find(targetName); const auto briefTargetDescriptor = Services::TargetService::briefDescriptor(targetName);
if (debugToolIt == supportedDebugTools.end()) { if (debugToolIt == supportedDebugTools.end()) {
throw Exceptions::InvalidConfig( throw Exceptions::InvalidConfig(
@@ -481,7 +478,7 @@ namespace TargetController
); );
} }
if (targetBriefIt == targetsByConfigValue.end()) { if (!briefTargetDescriptor.has_value()) {
throw Exceptions::InvalidConfig( throw Exceptions::InvalidConfig(
"Target name (\"" + targetName + "\") not recognised. Please check your configuration!" "Target name (\"" + targetName + "\") not recognised. Please check your configuration!"
); );
@@ -497,7 +494,7 @@ namespace TargetController
Logger::info("Debug tool serial: " + this->debugTool->getSerialNumber()); Logger::info("Debug tool serial: " + this->debugTool->getSerialNumber());
Logger::info("Debug tool firmware version: " + this->debugTool->getFirmwareVersionString()); Logger::info("Debug tool firmware version: " + this->debugTool->getFirmwareVersionString());
this->target = this->constructTargetFromBrief(targetBriefIt->second); this->target = this->constructTarget(*briefTargetDescriptor);
const auto& targetDescriptor = this->getTargetDescriptor(); const auto& targetDescriptor = this->getTargetDescriptor();
if (!this->target->supportsDebugTool(this->debugTool.get())) { if (!this->target->supportsDebugTool(this->debugTool.get())) {

View File

@@ -58,6 +58,7 @@
#include "Responses/Breakpoint.hpp" #include "Responses/Breakpoint.hpp"
#include "src/DebugToolDrivers/DebugTools.hpp" #include "src/DebugToolDrivers/DebugTools.hpp"
#include "src/Targets/BriefTargetDescriptor.hpp"
#include "src/Targets/Target.hpp" #include "src/Targets/Target.hpp"
#include "src/Targets/Targets.hpp" #include "src/Targets/Targets.hpp"
#include "src/Targets/TargetRegister.hpp" #include "src/Targets/TargetRegister.hpp"
@@ -248,12 +249,10 @@ namespace TargetController
/** /**
* Constructs a Target instance from a BriefTargetDescriptor object. * Constructs a Target instance from a BriefTargetDescriptor object.
* *
* @param targetBrief * @param briefDescriptor
* @return * @return
*/ */
std::unique_ptr<Targets::Target> constructTargetFromBrief( std::unique_ptr<Targets::Target> constructTarget(const Targets::BriefTargetDescriptor& briefDescriptor);
const Targets::TargetDescription::GeneratedMapping::BriefTargetDescriptor& targetBrief
);
/** /**
* Processes any pending commands in the queue. * Processes any pending commands in the queue.

View File

@@ -0,0 +1,53 @@
#pragma once
#include <string>
#include <cstdint>
#include "TargetFamily.hpp"
namespace Targets
{
/**
* The BriefTargetDescriptor struct provides limited information on a particular target.
*
* This struct serves as a starting point for constructing a Target object - it provides us with all the relevant
* information to construct a TargetDescriptionFile object, and subsequently, a Target object.
*
* At build time, we generate a BriefTargetDescriptor object for every target supported by Bloom. These objects
* can be found in the TargetService::descriptorsByConfigValue member. See the TargetService class for more.
*/
struct BriefTargetDescriptor
{
/**
* Target's market name.
*/
std::string name;
/**
* Target's configuration value.
*/
std::string configValue;
/**
* Target's family (AVR8/RISC-V)
*/
TargetFamily family;
/**
* The file path to to the target's TDF, relative to Bloom's TDF directory.
*/
std::string relativeTdfPath;
constexpr BriefTargetDescriptor(
const std::string& name,
const std::string& configValue,
TargetFamily family,
const std::string& relativeTdfPath
)
: name(name)
, configValue(configValue)
, family(family)
, relativeTdfPath(relativeTdfPath)
{}
};
}

View File

@@ -1,39 +0,0 @@
#pragma once
#include <string>
#include <map>
#include "src/Targets/TargetFamily.hpp"
namespace Targets::TargetDescription
{
struct GeneratedMapping
{
struct BriefTargetDescriptor
{
std::string targetName;
std::string configValue;
TargetFamily targetFamily;
std::string relativeTdfPath;
constexpr BriefTargetDescriptor(
const std::string& targetName,
const std::string& configValue,
TargetFamily targetFamily,
const std::string& relativeTdfPath
)
: targetName(targetName)
, configValue(configValue)
, targetFamily(targetFamily)
, relativeTdfPath(relativeTdfPath)
{}
};
/*
* The @MAPPING_PLACEHOLDER@ comment below will be replaced with the TDF mapping
*/
static const inline std::map<std::string, BriefTargetDescriptor> map = {
//@MAPPING_PLACEHOLDER@
};
};
}

View File

@@ -20,10 +20,6 @@ namespace Targets::TargetDescription
using Services::StringService; using Services::StringService;
const std::map<std::string, GeneratedMapping::BriefTargetDescriptor>& TargetDescriptionFile::mapping() {
return GeneratedMapping::map;
}
TargetDescriptionFile::TargetDescriptionFile(const std::string& xmlFilePath) { TargetDescriptionFile::TargetDescriptionFile(const std::string& xmlFilePath) {
this->init(xmlFilePath); this->init(xmlFilePath);
} }

View File

@@ -27,8 +27,6 @@
#include "src/Targets/TargetFamily.hpp" #include "src/Targets/TargetFamily.hpp"
#include "src/Targets/TargetPhysicalInterface.hpp" #include "src/Targets/TargetPhysicalInterface.hpp"
#include GENERATED_TDF_MAPPING_PATH
namespace Targets::TargetDescription namespace Targets::TargetDescription
{ {
/** /**
@@ -53,19 +51,6 @@ namespace Targets::TargetDescription
class TargetDescriptionFile class TargetDescriptionFile
{ {
public: public:
/**
* Returns a mapping of target configuration values to instances of the GeneratedMapping::BriefTargetDescriptor
* struct.
*
* The mapping is generated pre-build.
*
* The GeneratedMapping::BriefTargetDescriptor struct holds some brief info about a particular target, such as
* target name, family and TDF path. See the GeneratedMapping.hpp.in template for more.
*
* @return
*/
static const std::map<std::string, GeneratedMapping::BriefTargetDescriptor>& mapping();
/** /**
* Will construct a TargetDescriptionFile instance from the XML of a target description file, the path to which * Will construct a TargetDescriptionFile instance from the XML of a target description file, the path to which
* is given via xmlFilePath. * is given via xmlFilePath.