From 4aa8ed30de2a6a5ef8d4b9d27db928fa1ee88abc Mon Sep 17 00:00:00 2001 From: Nav Date: Sat, 2 Mar 2024 01:59:55 +0000 Subject: [PATCH] - 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 --- CMakeLists.txt | 61 +++++++++++-------- ...php => GenerateBriefTargetDescriptors.php} | 31 +++------- src/Application.cpp | 7 ++- src/CMakeLists.txt | 1 + src/Services/TargetService.cpp | 20 ++++++ src/Services/TargetService.hpp | 48 +++++++++++++++ .../TargetControllerComponent.cpp | 19 +++--- .../TargetControllerComponent.hpp | 7 +-- src/Targets/BriefTargetDescriptor.hpp | 53 ++++++++++++++++ .../TargetDescription/GeneratedMapping.hpp.in | 39 ------------ .../TargetDescriptionFile.cpp | 4 -- .../TargetDescriptionFile.hpp | 15 ----- 12 files changed, 182 insertions(+), 123 deletions(-) rename build/scripts/{GenerateTargetDescriptionFileMapping.php => GenerateBriefTargetDescriptors.php} (78%) create mode 100644 src/Services/TargetService.cpp create mode 100644 src/Services/TargetService.hpp create mode 100644 src/Targets/BriefTargetDescriptor.hpp delete mode 100644 src/Targets/TargetDescription/GeneratedMapping.hpp.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 26927be8..c1a6f370 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,11 @@ if (${CMAKE_BUILD_TYPE} MATCHES "Debug") endif() 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(Qt6Core REQUIRED) @@ -162,47 +166,56 @@ if (${ENABLE_SANITIZERS}) ) endif() -# Validate TDF files -add_custom_command( - OUTPUT ${CMAKE_BINARY_DIR}/tdf_validation_timestamp.txt - COMMAND echo 'Validating target description files' - COMMAND php - ARGS - ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/ValidateTargetDescriptionFiles.php +# The ValidateTargetDescriptionFiles target will invoke the TDF validation script for all TDFs in Bloom's codebase. +add_custom_target( + ValidateTargetDescriptionFiles + COMMENT "Validating target description files" + COMMAND php ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/ValidateTargetDescriptionFiles.php ${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 -set(GENERATED_TDF_MAPPING_PATH "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}_autogen/GeneratedMapping.hpp") +# The GenerateBriefTargetDescriptors target will invoke the GenerateBriefTargetDescriptors.php build script to generate +# 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( Bloom PRIVATE - ${GENERATED_TDF_MAPPING_PATH} + ${GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH} ) target_compile_definitions( 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( - OUTPUT - ${GENERATED_TDF_MAPPING_PATH} +add_custom_target( + GenerateBriefTargetDescriptors + BYPRODUCTS + ${GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH} ${CMAKE_BINARY_DIR}/resources/TargetDescriptionFiles/ DEPENDS - ${CMAKE_BINARY_DIR}/tdf_validation_timestamp.txt - ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateTargetDescriptionFileMapping.php - COMMAND echo 'Processing target description files' - COMMAND php - ARGS - ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateTargetDescriptionFileMapping.php + ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateBriefTargetDescriptors.php + COMMENT "Processing target description files" + COMMAND php ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateBriefTargetDescriptors.php ${CMAKE_CURRENT_SOURCE_DIR}/src/Targets/TargetDescriptionFiles/ - ${CMAKE_CURRENT_SOURCE_DIR}/src/Targets/TargetDescription/GeneratedMapping.hpp.in - ${GENERATED_TDF_MAPPING_PATH} + ${GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH} ${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/Packaging.cmake) diff --git a/build/scripts/GenerateTargetDescriptionFileMapping.php b/build/scripts/GenerateBriefTargetDescriptors.php similarity index 78% rename from build/scripts/GenerateTargetDescriptionFileMapping.php rename to build/scripts/GenerateBriefTargetDescriptors.php index 77beb1c2..68aa9f59 100644 --- a/build/scripts/GenerateTargetDescriptionFileMapping.php +++ b/build/scripts/GenerateBriefTargetDescriptors.php @@ -5,9 +5,8 @@ use Targets\TargetDescriptionFiles\Services\Xml\XmlService; use Targets\TargetDescriptionFiles\TargetFamily; define('TDF_DIR_PATH', $argv[1] ?? null); -define('MAPPING_TEMPLATE_PATH', $argv[2] ?? null); -define('MAPPING_OUTPUT_PATH', $argv[3] ?? null); -define('TDF_OUTPUT_PATH', $argv[4] ?? null); +define('MAPPING_OUTPUT_PATH', $argv[2] ?? null); +define('TDF_OUTPUT_PATH', $argv[3] ?? null); if (empty(TDF_DIR_PATH)) { print 'Missing TDF directory path. Aborting' . PHP_EOL; @@ -19,11 +18,6 @@ if (!file_exists(TDF_DIR_PATH)) { exit(1); } -if (empty(MAPPING_TEMPLATE_PATH)) { - print 'Missing TDF mapping template path. Aborting' . PHP_EOL; - exit(1); -} - if (empty(MAPPING_OUTPUT_PATH)) { print 'Missing TDF mapping output path. Aborting' . PHP_EOL; exit(1); @@ -50,11 +44,6 @@ $xmlService = new XmlService(); $xmlFiles = $discoveryService->findTargetDescriptionFiles(TDF_DIR_PATH); 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@"}}'; $entries = []; @@ -76,7 +65,10 @@ foreach ($xmlFiles as $xmlFile) { [ $targetDescriptionFile->getConfigurationValue(), $targetDescriptionFile->getName(), - $targetFamilyMapping[$targetDescriptionFile->getFamily()->value], + match($targetDescriptionFile->getFamily()) { + TargetFamily::AVR_8 => 'Targets::TargetFamily::AVR_8', + TargetFamily::RISC_V => 'Targets::TargetFamily::RISC_V', + }, $relativeTdfPath, ], MAP_ENTRY_TEMPLATE @@ -96,16 +88,9 @@ foreach ($xmlFiles as $xmlFile) { } } -file_put_contents( - MAPPING_OUTPUT_PATH, - str_replace( - '//@MAPPING_PLACEHOLDER@', - implode(',' . PHP_EOL . str_repeat(' ', 12), $entries), - file_get_contents(MAPPING_TEMPLATE_PATH) - ) -); +file_put_contents(MAPPING_OUTPUT_PATH, implode(',' . PHP_EOL, $entries)); print 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; diff --git a/src/Application.cpp b/src/Application.cpp index de3d4e5a..2dae5803 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -14,6 +14,7 @@ #include #include "src/Logger/Logger.hpp" +#include "src/Services/TargetService.hpp" #include "src/Services/PathService.hpp" #include "src/Services/ProcessService.hpp" #include "src/Helpers/BiMap.hpp" @@ -399,10 +400,10 @@ int Application::presentCapabilitiesMachine() { auto supportedTargets = QJsonArray(); - for (const auto& [configValue, descriptor] : Targets::TargetDescription::TargetDescriptionFile::mapping()) { + for (const auto& [configValue, descriptor] : Services::TargetService::briefDescriptorsByConfigValue()) { supportedTargets.push_back(QJsonObject({ - {"name" , QString::fromStdString(descriptor.targetName)}, - {"family" , targetFamilyNames.at(descriptor.targetFamily)}, + {"name" , QString::fromStdString(descriptor.name)}, + {"family" , targetFamilyNames.at(descriptor.family)}, {"configurationValue" , QString::fromStdString(configValue)}, })); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e04c5310..a784a823 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,7 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/Application.cpp # Services + ${CMAKE_CURRENT_SOURCE_DIR}/Services/TargetService.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Services/TargetControllerService.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Services/PathService.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Services/ProcessService.cpp diff --git a/src/Services/TargetService.cpp b/src/Services/TargetService.cpp new file mode 100644 index 00000000..4e5d96a9 --- /dev/null +++ b/src/Services/TargetService.cpp @@ -0,0 +1,20 @@ +#include "TargetService.hpp" + +namespace Services +{ + using Targets::BriefTargetDescriptor; + + const std::map& TargetService::briefDescriptorsByConfigValue() { + return TargetService::descriptorsByConfigValue; + } + + std::optional TargetService::briefDescriptor(const std::string& configValue) { + const auto descriptorIt = TargetService::descriptorsByConfigValue.find(configValue); + + if (descriptorIt != TargetService::descriptorsByConfigValue.end()) { + return descriptorIt->second; + } + + return std::nullopt; + } +} diff --git a/src/Services/TargetService.hpp b/src/Services/TargetService.hpp new file mode 100644 index 00000000..f84450bd --- /dev/null +++ b/src/Services/TargetService.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include +#include + +#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 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& 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 descriptorsByConfigValue = { +#include GENERATED_BRIEF_TARGET_DESCRIPTOR_MAPPING_PATH + }; + }; +} diff --git a/src/TargetController/TargetControllerComponent.cpp b/src/TargetController/TargetControllerComponent.cpp index 57b3c0a0..328cf7e3 100644 --- a/src/TargetController/TargetControllerComponent.cpp +++ b/src/TargetController/TargetControllerComponent.cpp @@ -375,25 +375,23 @@ namespace TargetController }; } - std::unique_ptr TargetControllerComponent::constructTargetFromBrief( - const TargetDescription::GeneratedMapping::BriefTargetDescriptor &targetBrief - ) { + std::unique_ptr TargetControllerComponent::constructTarget(const BriefTargetDescriptor& briefDescriptor) { using Services::PathService; - if (targetBrief.targetFamily == TargetFamily::AVR_8) { + if (briefDescriptor.family == TargetFamily::AVR_8) { return std::make_unique( this->environmentConfig.targetConfig, 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( this->environmentConfig.targetConfig, RiscV::TargetDescription::TargetDescriptionFile( - PathService::targetDescriptionDirPath() + "/" + targetBrief.relativeTdfPath + PathService::targetDescriptionDirPath() + "/" + briefDescriptor.relativeTdfPath ) ); } @@ -470,10 +468,9 @@ namespace TargetController const auto& targetName = this->environmentConfig.targetConfig.name; static const auto supportedDebugTools = this->getSupportedDebugTools(); - static const auto targetsByConfigValue = TargetDescription::TargetDescriptionFile::mapping(); const auto debugToolIt = supportedDebugTools.find(debugToolName); - const auto targetBriefIt = targetsByConfigValue.find(targetName); + const auto briefTargetDescriptor = Services::TargetService::briefDescriptor(targetName); if (debugToolIt == supportedDebugTools.end()) { throw Exceptions::InvalidConfig( @@ -481,7 +478,7 @@ namespace TargetController ); } - if (targetBriefIt == targetsByConfigValue.end()) { + if (!briefTargetDescriptor.has_value()) { throw Exceptions::InvalidConfig( "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 firmware version: " + this->debugTool->getFirmwareVersionString()); - this->target = this->constructTargetFromBrief(targetBriefIt->second); + this->target = this->constructTarget(*briefTargetDescriptor); const auto& targetDescriptor = this->getTargetDescriptor(); if (!this->target->supportsDebugTool(this->debugTool.get())) { diff --git a/src/TargetController/TargetControllerComponent.hpp b/src/TargetController/TargetControllerComponent.hpp index 06db0d87..b2b36855 100644 --- a/src/TargetController/TargetControllerComponent.hpp +++ b/src/TargetController/TargetControllerComponent.hpp @@ -58,6 +58,7 @@ #include "Responses/Breakpoint.hpp" #include "src/DebugToolDrivers/DebugTools.hpp" +#include "src/Targets/BriefTargetDescriptor.hpp" #include "src/Targets/Target.hpp" #include "src/Targets/Targets.hpp" #include "src/Targets/TargetRegister.hpp" @@ -248,12 +249,10 @@ namespace TargetController /** * Constructs a Target instance from a BriefTargetDescriptor object. * - * @param targetBrief + * @param briefDescriptor * @return */ - std::unique_ptr constructTargetFromBrief( - const Targets::TargetDescription::GeneratedMapping::BriefTargetDescriptor& targetBrief - ); + std::unique_ptr constructTarget(const Targets::BriefTargetDescriptor& briefDescriptor); /** * Processes any pending commands in the queue. diff --git a/src/Targets/BriefTargetDescriptor.hpp b/src/Targets/BriefTargetDescriptor.hpp new file mode 100644 index 00000000..4f3e1322 --- /dev/null +++ b/src/Targets/BriefTargetDescriptor.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include + +#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) + {} + }; +} diff --git a/src/Targets/TargetDescription/GeneratedMapping.hpp.in b/src/Targets/TargetDescription/GeneratedMapping.hpp.in deleted file mode 100644 index 196837a1..00000000 --- a/src/Targets/TargetDescription/GeneratedMapping.hpp.in +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include - -#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 map = { - //@MAPPING_PLACEHOLDER@ - }; - }; -} diff --git a/src/Targets/TargetDescription/TargetDescriptionFile.cpp b/src/Targets/TargetDescription/TargetDescriptionFile.cpp index 3987f70c..edd5b321 100644 --- a/src/Targets/TargetDescription/TargetDescriptionFile.cpp +++ b/src/Targets/TargetDescription/TargetDescriptionFile.cpp @@ -20,10 +20,6 @@ namespace Targets::TargetDescription using Services::StringService; - const std::map& TargetDescriptionFile::mapping() { - return GeneratedMapping::map; - } - TargetDescriptionFile::TargetDescriptionFile(const std::string& xmlFilePath) { this->init(xmlFilePath); } diff --git a/src/Targets/TargetDescription/TargetDescriptionFile.hpp b/src/Targets/TargetDescription/TargetDescriptionFile.hpp index 6f87e957..05e67733 100644 --- a/src/Targets/TargetDescription/TargetDescriptionFile.hpp +++ b/src/Targets/TargetDescription/TargetDescriptionFile.hpp @@ -27,8 +27,6 @@ #include "src/Targets/TargetFamily.hpp" #include "src/Targets/TargetPhysicalInterface.hpp" -#include GENERATED_TDF_MAPPING_PATH - namespace Targets::TargetDescription { /** @@ -53,19 +51,6 @@ namespace Targets::TargetDescription class TargetDescriptionFile { 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& mapping(); - /** * Will construct a TargetDescriptionFile instance from the XML of a target description file, the path to which * is given via xmlFilePath.