- Began refactoring TDF build scripts
- Separated TDF validation and mapping generation - Moving away from the JSON mapping file, to a generated header file containing the TDF mapping. - Other bits of tidying
This commit is contained in:
@@ -2,10 +2,13 @@ cmake_minimum_required(VERSION 3.22)
|
|||||||
|
|
||||||
project(Bloom LANGUAGES CXX VERSION 1.0.0)
|
project(Bloom LANGUAGES CXX VERSION 1.0.0)
|
||||||
set(CMAKE_PROJECT_HOMEPAGE_URL "https://bloom.oscillate.io")
|
set(CMAKE_PROJECT_HOMEPAGE_URL "https://bloom.oscillate.io")
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
|
set(AUTOGEN_BUILD_DIR ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}_autogen/)
|
||||||
|
file(MAKE_DIRECTORY ${AUTOGEN_BUILD_DIR})
|
||||||
|
|
||||||
set(CMAKE_VERBOSE_MAKEFILE off)
|
set(CMAKE_VERBOSE_MAKEFILE off)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
|
||||||
set(ENABLE_SANITIZERS off)
|
set(ENABLE_SANITIZERS off)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
@@ -78,12 +81,6 @@ target_link_libraries(Bloom Qt6::Core)
|
|||||||
target_link_libraries(Bloom Qt6::Xml)
|
target_link_libraries(Bloom Qt6::Xml)
|
||||||
target_link_libraries(Bloom Qt6::Network)
|
target_link_libraries(Bloom Qt6::Network)
|
||||||
|
|
||||||
target_sources(
|
|
||||||
Bloom
|
|
||||||
PRIVATE
|
|
||||||
${CMAKE_BINARY_DIR}/resources/TargetDescriptionFiles/AVR/Mapping.json
|
|
||||||
)
|
|
||||||
|
|
||||||
qt_add_resources(
|
qt_add_resources(
|
||||||
Bloom
|
Bloom
|
||||||
"ApplicationResources"
|
"ApplicationResources"
|
||||||
@@ -166,15 +163,46 @@ if (${ENABLE_SANITIZERS})
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Copy AVR8 TDFs to build directory and construct JSON mapping of AVR8 target signatures to TDF paths.
|
# 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
|
||||||
|
${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")
|
||||||
|
|
||||||
|
target_sources(
|
||||||
|
Bloom
|
||||||
|
PRIVATE
|
||||||
|
${GENERATED_TDF_MAPPING_PATH}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(
|
||||||
|
Bloom
|
||||||
|
PUBLIC GENERATED_TDF_MAPPING_PATH="${GENERATED_TDF_MAPPING_PATH}"
|
||||||
|
)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT
|
OUTPUT
|
||||||
${CMAKE_BINARY_DIR}/resources/TargetDescriptionFiles/AVR/Mapping.json
|
${GENERATED_TDF_MAPPING_PATH}
|
||||||
|
${CMAKE_BINARY_DIR}/resources/TargetDescriptionFiles/
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/Avr8TargetDescriptionFiles.php
|
${CMAKE_BINARY_DIR}/tdf_validation_timestamp.txt
|
||||||
COMMAND echo 'Processing AVR target description files.'
|
${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateTargetDescriptionFileMapping.php
|
||||||
COMMAND
|
COMMAND echo 'Processing target description files'
|
||||||
php ${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/Avr8TargetDescriptionFiles.php ${CMAKE_BINARY_DIR}
|
COMMAND php
|
||||||
|
ARGS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/build/scripts/GenerateTargetDescriptionFileMapping.php
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Targets/TargetDescriptionFiles/
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/Targets/TargetDescription/GeneratedMapping.hpp.in
|
||||||
|
${GENERATED_TDF_MAPPING_PATH}
|
||||||
|
${CMAKE_BINARY_DIR}/resources/TargetDescriptionFiles/
|
||||||
)
|
)
|
||||||
|
|
||||||
include(./cmake/Installing.cmake)
|
include(./cmake/Installing.cmake)
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*
|
|
||||||
* Copies AVR8 target description files to AVR_TDF_DEST_FILE_PATH, in preparation for a build, and creates a JSON
|
|
||||||
* mapping of target signatures to file paths (relative to Bloom's resource directory).
|
|
||||||
* The JSON mapping is compiled as a Qt resource and used for looking-up target description file paths, by target ID.
|
|
||||||
*
|
|
||||||
* This script should be run as part of the build process.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Bloom\BuildScripts;
|
|
||||||
|
|
||||||
$buildPath = $argv[1] ?? null;
|
|
||||||
if (empty($buildPath)) {
|
|
||||||
print "Missing build path. Aborting\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once __DIR__ . "/TargetDescriptionFiles/Factory.php";
|
|
||||||
|
|
||||||
define("AVR_TDF_DEST_FILE_PATH", $buildPath . "/resources/TargetDescriptionFiles/AVR");
|
|
||||||
define("AVR_TDF_DEST_RELATIVE_FILE_PATH", "TargetDescriptionFiles/AVR");
|
|
||||||
define("AVR_TDF_MAPPING_FILE_PATH", AVR_TDF_DEST_FILE_PATH . "/Mapping.json");
|
|
||||||
|
|
||||||
// Empty destination directory
|
|
||||||
if (file_exists(AVR_TDF_DEST_FILE_PATH)) {
|
|
||||||
// There is no PHP function to delete a non-empty directory and I can't be arsed to write one. Bite me
|
|
||||||
exec("rm -r " . AVR_TDF_DEST_FILE_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_exists(AVR_TDF_MAPPING_FILE_PATH)) {
|
|
||||||
unlink(AVR_TDF_MAPPING_FILE_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
mkdir(AVR_TDF_DEST_FILE_PATH, 0700, true);
|
|
||||||
|
|
||||||
print "Loading AVR8 TDFs\n\n";
|
|
||||||
|
|
||||||
$tdfMapping = [];
|
|
||||||
$avrTdfs = TargetDescriptionFiles\Factory::loadAvr8Tdfs();
|
|
||||||
|
|
||||||
print "Processing " . count($avrTdfs) . " AVR8 TDFs...\n\n";
|
|
||||||
|
|
||||||
foreach ($avrTdfs as $avrTdf) {
|
|
||||||
print "Processing AVR8 TDF for target " . $avrTdf->targetName . "\n";
|
|
||||||
|
|
||||||
$strippedTargetName = str_replace([' '] , '_', $avrTdf->targetName);
|
|
||||||
$id = strtolower($strippedTargetName);
|
|
||||||
|
|
||||||
if (in_array($id, $tdfMapping)) {
|
|
||||||
print "\033[31m" . "\n";
|
|
||||||
print "FATAL ERROR: duplicate AVR8 target ID detected: " . $id . "\n\n"
|
|
||||||
. "TDF Path: " . realpath($avrTdf->filePath);
|
|
||||||
print "\033[0m" . "\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty(($validationFailures = $avrTdf->validate()))) {
|
|
||||||
print "\033[31m" . "\n";
|
|
||||||
print "FATAL ERROR: AVR8 TDF failed validation - failure reasons:" . "\n"
|
|
||||||
. implode("\n", $validationFailures) . "\n\n" . "TDF Path: "
|
|
||||||
. realpath($avrTdf->filePath);
|
|
||||||
print "\033[0m" . "\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$destinationFilePath = AVR_TDF_DEST_FILE_PATH;
|
|
||||||
$relativeDestinationFilePath = AVR_TDF_DEST_RELATIVE_FILE_PATH;
|
|
||||||
|
|
||||||
if (!empty($avrTdf->targetArchitecture)) {
|
|
||||||
// Group by architecture
|
|
||||||
$destinationFilePath .= "/" . strtoupper($avrTdf->targetArchitecture);
|
|
||||||
$relativeDestinationFilePath .= "/" . strtoupper($avrTdf->targetArchitecture);
|
|
||||||
}
|
|
||||||
|
|
||||||
$avrFamily = $avrTdf->getFamily();
|
|
||||||
if (!empty($avrFamily)) {
|
|
||||||
// Group by family
|
|
||||||
$destinationFilePath .= "/" . str_replace([' '] , '_', strtoupper($avrFamily));
|
|
||||||
$relativeDestinationFilePath .= "/" . str_replace([' '] , '_', strtoupper($avrFamily));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists($destinationFilePath)) {
|
|
||||||
mkdir($destinationFilePath, 0700, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$destinationFilePath .= "/" . strtoupper($strippedTargetName) . ".xml";
|
|
||||||
$relativeDestinationFilePath .= "/" . strtoupper($strippedTargetName) . ".xml";
|
|
||||||
|
|
||||||
// Copy TDF to build location
|
|
||||||
if (copy($avrTdf->filePath, $destinationFilePath) === false) {
|
|
||||||
print "FATAL ERROR: Failed to copy TDF file to " . $destinationFilePath . "\n";
|
|
||||||
print "Aborting\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$tdfMapping[$id] = [
|
|
||||||
'name' => $strippedTargetName,
|
|
||||||
'signature' => $avrTdf->getSignature()->toHex(),
|
|
||||||
'tdfPath' => $relativeDestinationFilePath,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_put_contents(AVR_TDF_MAPPING_FILE_PATH, json_encode($tdfMapping, JSON_PRETTY_PRINT)) === false) {
|
|
||||||
print "FATAL ERROR: Failed to create JSON mapping of target IDs to target description file paths\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
print "\n";
|
|
||||||
print "Created JSON mapping of target IDs to target description file paths: " . AVR_TDF_MAPPING_FILE_PATH . "\n\n";
|
|
||||||
print "Processed " . count($avrTdfs) . " files.\n";
|
|
||||||
print "Done\n";
|
|
||||||
96
build/scripts/GenerateTargetDescriptionFileMapping.php
Normal file
96
build/scripts/GenerateTargetDescriptionFileMapping.php
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bloom\BuildScripts;
|
||||||
|
|
||||||
|
use Bloom\BuildScripts\TargetDescriptionFiles\TargetDescriptionFile;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (empty(TDF_DIR_PATH)) {
|
||||||
|
print 'Missing TDF directory path. Aborting' . PHP_EOL;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty(TDF_OUTPUT_PATH)) {
|
||||||
|
print 'Missing TDF output path. Aborting' . PHP_EOL;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists(dirname(MAPPING_OUTPUT_PATH))) {
|
||||||
|
mkdir(dirname(MAPPING_OUTPUT_PATH), 0700);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/TargetDescriptionFiles/Factory.php';
|
||||||
|
require_once __DIR__ . '/TargetDescriptionFiles/AVR8/Avr8TargetDescriptionFile.php';
|
||||||
|
|
||||||
|
$xmlFiles = TargetDescriptionFiles\Factory::findXmlFiles(TDF_DIR_PATH);
|
||||||
|
print count($xmlFiles) . ' target descriptions files found in ' . TDF_DIR_PATH . PHP_EOL . PHP_EOL;
|
||||||
|
|
||||||
|
$targetFamiliesByArch = [
|
||||||
|
TargetDescriptionFile::ARCHITECTURE_AVR8 => 'TargetFamily::AVR8',
|
||||||
|
];
|
||||||
|
|
||||||
|
const MAP_ENTRY_TEMPLATE = '{"@CONFIG_VALUE@", {"@TARGET_NAME@", "@CONFIG_VALUE@", @TARGET_FAMILY@, "@TDF_PATH@"}}';
|
||||||
|
|
||||||
|
$entries = [];
|
||||||
|
|
||||||
|
foreach ($xmlFiles as $xmlFile) {
|
||||||
|
$xmlFilePath = $xmlFile->getPathname();
|
||||||
|
|
||||||
|
print 'Processing ' . $xmlFilePath . PHP_EOL;
|
||||||
|
$targetDescriptionFile = TargetDescriptionFiles\Factory::loadTdfFromFile($xmlFilePath);
|
||||||
|
|
||||||
|
$relativeTdfPath = $targetDescriptionFile->targetArchitecture . '/'
|
||||||
|
. strtoupper($targetDescriptionFile->targetName) . '.xml';
|
||||||
|
|
||||||
|
$entries[] = str_replace(
|
||||||
|
['@CONFIG_VALUE@', '@TARGET_NAME@', '@TARGET_FAMILY@', '@TDF_PATH@'],
|
||||||
|
[
|
||||||
|
$targetDescriptionFile->configurationValue,
|
||||||
|
$targetDescriptionFile->targetName,
|
||||||
|
$targetFamiliesByArch[$targetDescriptionFile->targetArchitecture],
|
||||||
|
$relativeTdfPath,
|
||||||
|
],
|
||||||
|
MAP_ENTRY_TEMPLATE
|
||||||
|
);
|
||||||
|
|
||||||
|
$tdfDestinationPath = TDF_OUTPUT_PATH . '/' . $relativeTdfPath;
|
||||||
|
|
||||||
|
$tdfDestinationDirPath = dirname($tdfDestinationPath);
|
||||||
|
if (!file_exists($tdfDestinationDirPath)) {
|
||||||
|
mkdir($tdfDestinationDirPath, 0700, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!copy($targetDescriptionFile->filePath, $tdfDestinationPath)) {
|
||||||
|
print 'FATAL ERROR: Failed to copy TDF file to ' . $tdfDestinationPath . PHP_EOL;
|
||||||
|
print 'Aborting' . PHP_EOL;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents(
|
||||||
|
MAPPING_OUTPUT_PATH,
|
||||||
|
str_replace(
|
||||||
|
'//@MAPPING_PLACEHOLDER@',
|
||||||
|
implode(',' . PHP_EOL . str_repeat(' ', 12), $entries),
|
||||||
|
file_get_contents(MAPPING_TEMPLATE_PATH)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
print PHP_EOL;
|
||||||
|
print 'Processed ' . count($xmlFiles) . ' TDFs.' . PHP_EOL;
|
||||||
|
print 'Generated TDF mapping at ' . MAPPING_OUTPUT_PATH . PHP_EOL;
|
||||||
|
print 'Done' . PHP_EOL;
|
||||||
@@ -8,9 +8,6 @@ require_once __DIR__ . "/AVR8/Avr8TargetDescriptionFile.php";
|
|||||||
|
|
||||||
class Factory
|
class Factory
|
||||||
{
|
{
|
||||||
private const TDF_PATH = __DIR__ . '/../../../src/Targets/TargetDescriptionFiles';
|
|
||||||
private const AVR8_TDF_PATH = self::TDF_PATH . '/AVR8';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a target description file with the appropriate class.
|
* Loads a target description file with the appropriate class.
|
||||||
*
|
*
|
||||||
@@ -22,36 +19,19 @@ class Factory
|
|||||||
$tdf = new TargetDescriptionFile($filePath);
|
$tdf = new TargetDescriptionFile($filePath);
|
||||||
|
|
||||||
if ($tdf->targetArchitecture == TargetDescriptionFile::ARCHITECTURE_AVR8) {
|
if ($tdf->targetArchitecture == TargetDescriptionFile::ARCHITECTURE_AVR8) {
|
||||||
$tdf = new Avr8TargetDescriptionFile($filePath);
|
return new Avr8TargetDescriptionFile($filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $tdf;
|
return $tdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all AVR8 target description files.
|
* Recursively finds all XML files within a given directory.
|
||||||
*
|
|
||||||
* @return Avr8TargetDescriptionFile[]
|
|
||||||
*/
|
|
||||||
public static function loadAvr8Tdfs(): array
|
|
||||||
{
|
|
||||||
/** @var Avr8TargetDescriptionFile[] $output */
|
|
||||||
$output = [];
|
|
||||||
|
|
||||||
foreach (self::loadXmlFiles(self::AVR8_TDF_PATH) as $xmlFile) {
|
|
||||||
$output[] = new Avr8TargetDescriptionFile($xmlFile->getPathname());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively loads all XML files from a given directory.
|
|
||||||
*
|
*
|
||||||
* @param string $dirPath
|
* @param string $dirPath
|
||||||
* @return \SplFileInfo[]
|
* @return \SplFileInfo[]
|
||||||
*/
|
*/
|
||||||
private static function loadXmlFiles(string $dirPath): array
|
public static function findXmlFiles(string $dirPath): array
|
||||||
{
|
{
|
||||||
$output = [];
|
$output = [];
|
||||||
|
|
||||||
@@ -61,7 +41,7 @@ class Factory
|
|||||||
$output[] = clone $entry;
|
$output[] = clone $entry;
|
||||||
|
|
||||||
} else if ($entry->isDir() && !$entry->isDot()) {
|
} else if ($entry->isDir() && !$entry->isDot()) {
|
||||||
$output = array_merge($output, self::loadXmlFiles($entry->getPathname()));
|
$output = array_merge($output, self::findXmlFiles($entry->getPathname()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class TargetDescriptionFile
|
|||||||
public ?SimpleXMLElement $xml = null;
|
public ?SimpleXMLElement $xml = null;
|
||||||
|
|
||||||
public ?string $targetName = null;
|
public ?string $targetName = null;
|
||||||
|
public ?string $configurationValue = null;
|
||||||
public ?string $targetArchitecture = null;
|
public ?string $targetArchitecture = null;
|
||||||
|
|
||||||
/** @var string[] */
|
/** @var string[] */
|
||||||
@@ -71,6 +72,7 @@ class TargetDescriptionFile
|
|||||||
|
|
||||||
if (!empty($this->deviceAttributesByName['name'])) {
|
if (!empty($this->deviceAttributesByName['name'])) {
|
||||||
$this->targetName = $device['name'];
|
$this->targetName = $device['name'];
|
||||||
|
$this->configurationValue = strtolower($device['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($this->deviceAttributesByName['architecture'])) {
|
if (!empty($this->deviceAttributesByName['architecture'])) {
|
||||||
@@ -480,6 +482,10 @@ class TargetDescriptionFile
|
|||||||
$failures[] = 'Target name not found';
|
$failures[] = 'Target name not found';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (str_contains($this->targetName, ' ')) {
|
||||||
|
$failures[] = 'Target name cannot contain whitespaces';
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($this->targetArchitecture)) {
|
if (empty($this->targetArchitecture)) {
|
||||||
$failures[] = 'Target architecture not found';
|
$failures[] = 'Target architecture not found';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Bloom\BuildScripts;
|
|
||||||
|
|
||||||
require_once __DIR__ . "/TargetDescriptionFiles/Factory.php";
|
|
||||||
|
|
||||||
print "Loading AVR8 target description files.\n";
|
|
||||||
$avr8Tdfs = TargetDescriptionFiles\Factory::loadAvr8Tdfs();
|
|
||||||
$failedValidationCount = 0;
|
|
||||||
|
|
||||||
foreach ($avr8Tdfs as $targetDescriptionFile) {
|
|
||||||
$validationFailures = $targetDescriptionFile->validate();
|
|
||||||
|
|
||||||
if (!empty($validationFailures)) {
|
|
||||||
$failedValidationCount++;
|
|
||||||
|
|
||||||
print "\033[31m";
|
|
||||||
print "Validation for " . $targetDescriptionFile->filePath . " failed.\n";
|
|
||||||
print count($validationFailures) . " error(s) found:\n";
|
|
||||||
print implode("\n", $validationFailures);
|
|
||||||
print "\n\n";
|
|
||||||
print "\033[0m";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
print "\033[32m";
|
|
||||||
print "Validation for " . $targetDescriptionFile->filePath . " passed.\n";
|
|
||||||
print "\033[0m";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print "\n\n";
|
|
||||||
print "Validated " . count($avr8Tdfs) . " TDFs. ";
|
|
||||||
print (($failedValidationCount > 0) ? "\033[31m" : "\033[32m");
|
|
||||||
print $failedValidationCount . " failure(s)." . "\033[0m" . "\n";
|
|
||||||
print "Done\n";
|
|
||||||
58
build/scripts/ValidateTargetDescriptionFiles.php
Normal file
58
build/scripts/ValidateTargetDescriptionFiles.php
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bloom\BuildScripts;
|
||||||
|
|
||||||
|
define('TDF_DIR_PATH', $argv[1] ?? null);
|
||||||
|
|
||||||
|
if (empty(TDF_DIR_PATH)) {
|
||||||
|
print 'Missing TDF directory path. Aborting\n';
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/TargetDescriptionFiles/Factory.php';
|
||||||
|
|
||||||
|
$xmlFiles = TargetDescriptionFiles\Factory::findXmlFiles(TDF_DIR_PATH);
|
||||||
|
print count($xmlFiles) . ' target descriptions files found in ' . TDF_DIR_PATH . PHP_EOL . PHP_EOL;
|
||||||
|
|
||||||
|
$processedTargetConfigValues = [];
|
||||||
|
$failedValidationCount = 0;
|
||||||
|
|
||||||
|
foreach ($xmlFiles as $xmlFile) {
|
||||||
|
$xmlFilePath = $xmlFile->getPathname();
|
||||||
|
|
||||||
|
print 'Processing ' . $xmlFilePath . PHP_EOL;
|
||||||
|
$targetDescriptionFile = TargetDescriptionFiles\Factory::loadTdfFromFile($xmlFilePath);
|
||||||
|
|
||||||
|
$validationFailures = $targetDescriptionFile->validate();
|
||||||
|
if (in_array($targetDescriptionFile->configurationValue, $processedTargetConfigValues)) {
|
||||||
|
$validationFailures[] = 'Duplicate target configuration value ("'
|
||||||
|
. $targetDescriptionFile->configurationValue . '")';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($validationFailures)) {
|
||||||
|
$failedValidationCount++;
|
||||||
|
|
||||||
|
print "\033[31m";
|
||||||
|
print 'Validation for ' . $xmlFilePath . ' failed' . PHP_EOL;
|
||||||
|
print count($validationFailures) . ' error(s) found:' . PHP_EOL;
|
||||||
|
print implode(PHP_EOL, $validationFailures);
|
||||||
|
print PHP_EOL . PHP_EOL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
print "\033[32m";
|
||||||
|
print 'Validation for ' . $xmlFilePath . ' passed' . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
print "\033[0m";
|
||||||
|
|
||||||
|
$processedTargetConfigValues[] = $targetDescriptionFile->configurationValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
print 'Validated ' . count($xmlFiles) . ' TDFs' . PHP_EOL;
|
||||||
|
print (($failedValidationCount > 0) ? "\033[31m" : "\033[32m");
|
||||||
|
print $failedValidationCount . ' failure(s)' . "\033[0m" . PHP_EOL;
|
||||||
|
print 'Done' . PHP_EOL;
|
||||||
|
|
||||||
|
if ($failedValidationCount > 0) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
39
src/Targets/TargetDescription/GeneratedMapping.hpp.in
Normal file
39
src/Targets/TargetDescription/GeneratedMapping.hpp.in
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#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@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -11,6 +11,18 @@ namespace Targets::TargetDescription
|
|||||||
{
|
{
|
||||||
using namespace Exceptions;
|
using namespace Exceptions;
|
||||||
|
|
||||||
|
const std::map<std::string, GeneratedMapping::BriefTargetDescriptor>& TargetDescriptionFile::mapping() {
|
||||||
|
return GeneratedMapping::map;
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetDescriptionFile::TargetDescriptionFile(const QString& xmlFilePath) {
|
||||||
|
this->init(xmlFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetDescriptionFile::TargetDescriptionFile(const QDomDocument& xml) {
|
||||||
|
this->init(xml);
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& TargetDescriptionFile::getTargetName() const {
|
const std::string& TargetDescriptionFile::getTargetName() const {
|
||||||
return this->targetName;
|
return this->targetName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include "Pinout.hpp"
|
#include "Pinout.hpp"
|
||||||
#include "Interface.hpp"
|
#include "Interface.hpp"
|
||||||
|
|
||||||
|
#include GENERATED_TDF_MAPPING_PATH
|
||||||
|
|
||||||
namespace Targets::TargetDescription
|
namespace Targets::TargetDescription
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -36,24 +38,33 @@ 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.
|
||||||
*
|
*
|
||||||
* @param xmlFilePath
|
* @param xmlFilePath
|
||||||
*/
|
*/
|
||||||
explicit TargetDescriptionFile(const QString& xmlFilePath) {
|
explicit TargetDescriptionFile(const QString& xmlFilePath);
|
||||||
this->init(xmlFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will construct a TargetDescriptionFile instance from pre-loaded XML.
|
* Will construct a TargetDescriptionFile instance from pre-loaded XML.
|
||||||
*
|
*
|
||||||
* @param xml
|
* @param xml
|
||||||
*/
|
*/
|
||||||
explicit TargetDescriptionFile(const QDomDocument& xml) {
|
explicit TargetDescriptionFile(const QDomDocument& xml);
|
||||||
this->init(xml);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the target name extracted from the TDF.
|
* Returns the target name extracted from the TDF.
|
||||||
|
|||||||
Reference in New Issue
Block a user