常规更新
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$targets = @PSC_TARGETS@
|
||||
$edges = @PSC_TARGET_EDGES@
|
||||
$outputDir = '@PSC_OUTPUT_DIR@'
|
||||
$format = '@PSC_FORMAT@'
|
||||
$dotExe = '@PSC_DOT_EXECUTABLE@'
|
||||
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
|
||||
function Convert-To_Dot_Text([string]$text) {
|
||||
return $text.Replace('"', '\"')
|
||||
}
|
||||
$lines = [System.Collections.Generic.List[string]]::new()
|
||||
$lines.Add('digraph "radio cmake_targets" {')
|
||||
$lines.Add('rankdir=LR;')
|
||||
$lines.Add('splines=ortho;')
|
||||
$lines.Add('concentrate=true;')
|
||||
$lines.Add('forcelabels=true;')
|
||||
$lines.Add('graph [fontname="Consolas", label="radio cmake_targets", labelloc=t, fontsize=18];')
|
||||
$lines.Add('node [shape=box, style="rounded,filled", fontname="Consolas", fontsize=10];')
|
||||
$lines.Add('edge [fontname="Consolas", fontsize=9];')
|
||||
foreach ($target in $targets) {
|
||||
$safe = Convert-To_Dot_Text $target
|
||||
$lines.Add('"' + $safe + '" [label="' + $safe + '", tooltip="' + $safe + '", fillcolor="#dcfce7"];')
|
||||
}
|
||||
foreach ($edge in $edges) {
|
||||
$parts = $edge.Split('|')
|
||||
if ($parts.Count -eq 2) {
|
||||
$left = Convert-To_Dot_Text $parts[0]
|
||||
$right = Convert-To_Dot_Text $parts[1]
|
||||
$lines.Add('"' + $left + '" -> "' + $right + '" [xlabel="links"];')
|
||||
}
|
||||
}
|
||||
$lines.Add('subgraph cluster_legend {')
|
||||
$lines.Add('label="legend";')
|
||||
$lines.Add('style="rounded,dashed";')
|
||||
$lines.Add('"legend_target" [label="cmake target", fillcolor="#dcfce7"];')
|
||||
$lines.Add('"legend_edge" [label="edge = target_link_libraries / target dependency", fillcolor="#f8fafc"];')
|
||||
$lines.Add('}')
|
||||
$lines.Add('}')
|
||||
$dotFile = Join-Path $outputDir 'radio_cmake_targets.dot'
|
||||
$imageFile = Join-Path $outputDir ('radio_cmake_targets.' + $format)
|
||||
Set-Content -LiteralPath $dotFile -Value $lines -Encoding UTF8
|
||||
& $dotExe ('-T' + $format) $dotFile '-o' $imageFile
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
$items = @(
|
||||
'radio_directory_tree',
|
||||
'radio_module_dependency',
|
||||
'radio_cmake_targets',
|
||||
'radio_include_dependency',
|
||||
'radio_render_architecture'
|
||||
)
|
||||
$html = [System.Collections.Generic.List[string]]::new()
|
||||
$html.Add('<!doctype html><meta charset="utf-8"><title>Radio Graphviz</title><h1>Radio Graphviz</h1><ul>')
|
||||
foreach ($item in $items) {
|
||||
$file = $item + '.' + $format
|
||||
if (Test-Path -LiteralPath (Join-Path $outputDir $file)) {
|
||||
$html.Add('<li><a href="' + $file + '">' + $item + '</a></li>')
|
||||
} else {
|
||||
$html.Add('<li>' + $item + ' (not generated)</li>')
|
||||
}
|
||||
}
|
||||
$html.Add('</ul>')
|
||||
Set-Content -LiteralPath (Join-Path $outputDir 'index.html') -Value $html -Encoding UTF8
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
targets=(@PSC_TARGETS_SH@)
|
||||
edges=(@PSC_TARGET_EDGES_SH@)
|
||||
output_dir='@PSC_OUTPUT_DIR@'
|
||||
format='@PSC_FORMAT@'
|
||||
dot_exe='@PSC_DOT_EXECUTABLE@'
|
||||
mkdir -p "$output_dir"
|
||||
dot_file="$output_dir/radio_cmake_targets.dot"
|
||||
image_file="$output_dir/radio_cmake_targets.$format"
|
||||
{
|
||||
echo 'digraph "radio cmake_targets" {'
|
||||
echo 'rankdir=LR;'
|
||||
echo 'splines=ortho;'
|
||||
echo 'concentrate=true;'
|
||||
echo 'forcelabels=true;'
|
||||
echo 'graph [fontname="Consolas", label="radio cmake_targets", labelloc=t, fontsize=18];'
|
||||
echo 'node [shape=box, style="rounded,filled", fontname="Consolas", fontsize=10];'
|
||||
echo 'edge [fontname="Consolas", fontsize=9];'
|
||||
for target in "${targets[@]}"; do
|
||||
safe=${target//\"/\\\"}
|
||||
echo "\"$safe\" [label=\"$safe\", tooltip=\"$safe\", fillcolor=\"#dcfce7\"];"
|
||||
done
|
||||
for edge in "${edges[@]}"; do
|
||||
left=${edge%%|*}
|
||||
right=${edge#*|}
|
||||
left=${left//\"/\\\"}
|
||||
right=${right//\"/\\\"}
|
||||
echo "\"$left\" -> \"$right\" [xlabel=\"links\"];"
|
||||
done
|
||||
echo 'subgraph cluster_legend {'
|
||||
echo 'label="legend";'
|
||||
echo 'style="rounded,dashed";'
|
||||
echo '"legend_target" [label="cmake target", fillcolor="#dcfce7"];'
|
||||
echo '"legend_edge" [label="edge = target_link_libraries / target dependency", fillcolor="#f8fafc"];'
|
||||
echo '}'
|
||||
echo '}'
|
||||
} > "$dot_file"
|
||||
"$dot_exe" "-T$format" "$dot_file" -o "$image_file"
|
||||
items=(radio_directory_tree radio_module_dependency radio_cmake_targets radio_include_dependency radio_render_architecture)
|
||||
{
|
||||
echo '<!doctype html><meta charset="utf-8"><title>Radio Graphviz</title><h1>Radio Graphviz</h1><ul>'
|
||||
for item in "${items[@]}"; do
|
||||
file="$item.$format"
|
||||
if [ -f "$output_dir/$file" ]; then
|
||||
echo "<li><a href=\"$file\">$item</a></li>"
|
||||
else
|
||||
echo "<li>$item (not generated)</li>"
|
||||
fi
|
||||
done
|
||||
echo '</ul>'
|
||||
} > "$output_dir/index.html"
|
||||
@@ -0,0 +1,13 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$inputs = @PSC_INPUT_FILES@
|
||||
$outputDir = '@PSC_OUTPUT_DIR@'
|
||||
$format = '@PSC_FORMAT@'
|
||||
$dotExe = '@PSC_DOT_EXECUTABLE@'
|
||||
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
|
||||
foreach ($inputFile in $inputs) {
|
||||
$name = [System.IO.Path]::GetFileNameWithoutExtension($inputFile)
|
||||
& $dotExe ('-T' + $format) $inputFile '-o' (Join-Path $outputDir ($name + '.' + $format))
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
inputs=(@PSC_INPUT_FILES_SH@)
|
||||
output_dir='@PSC_OUTPUT_DIR@'
|
||||
format='@PSC_FORMAT@'
|
||||
dot_exe='@PSC_DOT_EXECUTABLE@'
|
||||
mkdir -p "$output_dir"
|
||||
for input_file in "${inputs[@]}"; do
|
||||
name=$(basename "$input_file")
|
||||
name=${name%.*}
|
||||
"$dot_exe" "-T$format" "$input_file" -o "$output_dir/$name.$format"
|
||||
done
|
||||
@@ -0,0 +1,339 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$inputs = @PSC_INPUT_DIRS@
|
||||
$excludeDirs = @PSC_EXCLUDE_DIRS@
|
||||
$outputDir = '@PSC_OUTPUT_DIR@'
|
||||
$format = '@PSC_FORMAT@'
|
||||
$dotExe = '@PSC_DOT_EXECUTABLE@'
|
||||
$maxDepth = @PSC_MAX_DEPTH@
|
||||
$collapseThreshold = @PSC_COLLAPSE_THRESHOLD@
|
||||
$excludeThirdParty = @PSC_EXCLUDE_THIRD_PARTY@
|
||||
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
|
||||
function Convert-To_Generic_Path([string]$path) {
|
||||
return ([System.IO.Path]::GetFullPath($path)).Replace('\', '/')
|
||||
}
|
||||
function Convert-To_Dot_Text([string]$text) {
|
||||
return $text.Replace('\', '/').Replace('"', '\"')
|
||||
}
|
||||
function Get-Root_Name([string]$root) {
|
||||
$path = Convert-To_Generic_Path $root
|
||||
if ($path -match '/module/radio$') {
|
||||
return 'radio'
|
||||
}
|
||||
if ($path -match '/CPP_Core/Core$') {
|
||||
return 'CPP_Core'
|
||||
}
|
||||
if ($path -match '/YSGraphic_Core$') {
|
||||
return 'YSGraphic_Core'
|
||||
}
|
||||
return [System.IO.Path]::GetFileName($path)
|
||||
}
|
||||
function Get-Relative_Path([string]$root, [string]$path) {
|
||||
$rootPath = Convert-To_Generic_Path $root
|
||||
$fullPath = Convert-To_Generic_Path $path
|
||||
if ($fullPath.StartsWith($rootPath)) {
|
||||
return $fullPath.Substring($rootPath.Length).TrimStart('/')
|
||||
}
|
||||
return $fullPath
|
||||
}
|
||||
function Test-Excluded_Path([string]$path) {
|
||||
$fullPath = Convert-To_Generic_Path $path
|
||||
if ($excludeThirdParty -and $fullPath.Contains('/third_party/')) {
|
||||
return $true
|
||||
}
|
||||
foreach ($excludeDir in $excludeDirs) {
|
||||
if ($excludeDir.Length -eq 0) {
|
||||
continue
|
||||
}
|
||||
$excludePath = Convert-To_Generic_Path $excludeDir
|
||||
if ($fullPath.StartsWith($excludePath)) {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
return $false
|
||||
}
|
||||
function Get-Source_Files([string[]]$roots) {
|
||||
$extensions = @('.h', '.hpp', '.hh', '.cpp', '.cxx', '.cc')
|
||||
$files = [System.Collections.Generic.List[object]]::new()
|
||||
foreach ($root in $roots) {
|
||||
if (!(Test-Path -LiteralPath $root)) {
|
||||
continue
|
||||
}
|
||||
Get-ChildItem -LiteralPath $root -Recurse -File | Where-Object {
|
||||
$extensions -contains $_.Extension.ToLowerInvariant() -and !(Test-Excluded_Path $_.FullName)
|
||||
} | ForEach-Object {
|
||||
$files.Add($_)
|
||||
}
|
||||
}
|
||||
return $files
|
||||
}
|
||||
function Invoke-Dot([string]$name, [System.Collections.Generic.List[string]]$lines) {
|
||||
$dotFile = Join-Path $outputDir ($name + '.dot')
|
||||
$imageFile = Join-Path $outputDir ($name + '.' + $format)
|
||||
Set-Content -LiteralPath $dotFile -Value $lines -Encoding UTF8
|
||||
& $dotExe ('-T' + $format) $dotFile '-o' $imageFile
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
}
|
||||
function Write-Graphviz_Index() {
|
||||
$items = @(
|
||||
'radio_directory_tree',
|
||||
'radio_module_dependency',
|
||||
'radio_cmake_targets',
|
||||
'radio_include_dependency',
|
||||
'radio_render_architecture'
|
||||
)
|
||||
$html = [System.Collections.Generic.List[string]]::new()
|
||||
$html.Add('<!doctype html><meta charset="utf-8"><title>Radio Graphviz</title><h1>Radio Graphviz</h1><ul>')
|
||||
foreach ($item in $items) {
|
||||
$file = $item + '.' + $format
|
||||
if (Test-Path -LiteralPath (Join-Path $outputDir $file)) {
|
||||
$html.Add('<li><a href="' + $file + '">' + $item + '</a></li>')
|
||||
} else {
|
||||
$html.Add('<li>' + $item + ' (not generated)</li>')
|
||||
}
|
||||
}
|
||||
$html.Add('</ul>')
|
||||
Set-Content -LiteralPath (Join-Path $outputDir 'index.html') -Value $html -Encoding UTF8
|
||||
}
|
||||
function Add-Header([System.Collections.Generic.List[string]]$lines, [string]$title) {
|
||||
$lines.Add('digraph "' + (Convert-To_Dot_Text $title) + '" {')
|
||||
$lines.Add('rankdir=LR;')
|
||||
$lines.Add('splines=ortho;')
|
||||
$lines.Add('concentrate=true;')
|
||||
$lines.Add('forcelabels=true;')
|
||||
$lines.Add('graph [fontname="Consolas", label="' + (Convert-To_Dot_Text $title) + '", labelloc=t, fontsize=18];')
|
||||
$lines.Add('node [shape=box, style="rounded,filled", fontname="Consolas", fontsize=10];')
|
||||
$lines.Add('edge [fontname="Consolas", fontsize=9];')
|
||||
}
|
||||
function Add-Legend([System.Collections.Generic.List[string]]$lines, [string]$mode) {
|
||||
$lines.Add('subgraph cluster_legend {')
|
||||
$lines.Add('label="legend";')
|
||||
$lines.Add('style="rounded,dashed";')
|
||||
$lines.Add('"legend_module" [label="module/folder", fillcolor="#dbeafe", tooltip="聚合模块或目录节点"];')
|
||||
$lines.Add('"legend_target" [label="cmake target", fillcolor="#dcfce7", tooltip="CMake target 节点"];')
|
||||
$lines.Add('"legend_buffer" [label="buffer/cache", fillcolor="#fef3c7", tooltip="缓冲区或长期缓存"];')
|
||||
$lines.Add('"legend_runtime" [label="runtime", fillcolor="#fee2e2", tooltip="运行期任务或 Qt 绘制入口"];')
|
||||
if ($mode -eq 'include') {
|
||||
$lines.Add('"legend_edge" [label="include:N node = include count", fillcolor="#f8fafc"];')
|
||||
} else {
|
||||
$lines.Add('"legend_edge" [label="edge label = relation", fillcolor="#f8fafc"];')
|
||||
}
|
||||
$lines.Add('}')
|
||||
}
|
||||
function Get-Immediate_Source_Count([string]$dir) {
|
||||
$extensions = @('.h', '.hpp', '.hh', '.cpp', '.cxx', '.cc')
|
||||
return @(Get-ChildItem -LiteralPath $dir -File | Where-Object {
|
||||
$extensions -contains $_.Extension.ToLowerInvariant()
|
||||
}).Count
|
||||
}
|
||||
function Get-Visible_Directories([string]$dir) {
|
||||
return @(Get-ChildItem -LiteralPath $dir -Directory | Where-Object {
|
||||
!(Test-Excluded_Path $_.FullName)
|
||||
})
|
||||
}
|
||||
function Add-Directory_Node([System.Collections.Generic.List[string]]$lines, [string]$root, [string]$dir, [int]$depth, [string]$parentId) {
|
||||
if ($depth -gt $maxDepth -or (Test-Excluded_Path $dir)) {
|
||||
return
|
||||
}
|
||||
$rootName = Get-Root_Name $root
|
||||
$relative = Get-Relative_Path $root $dir
|
||||
$name = if ($relative.Length -eq 0) { $rootName } else { [System.IO.Path]::GetFileName($dir) }
|
||||
$idPath = if ($relative.Length -eq 0) { $rootName } else { $rootName + '/' + $relative }
|
||||
$id = 'dir:' + $idPath
|
||||
$fileCount = Get-Immediate_Source_Count $dir
|
||||
$children = Get-Visible_Directories $dir
|
||||
$label = (Convert-To_Dot_Text $name) + '\nfiles: ' + $fileCount + '\ndirs: ' + $children.Count
|
||||
$tooltip = Convert-To_Dot_Text $idPath
|
||||
$lines.Add('"' + $id + '" [label="' + $label + '", tooltip="' + $tooltip + '", fillcolor="#dbeafe"];')
|
||||
if ($parentId.Length -gt 0) {
|
||||
$lines.Add('"' + $parentId + '" -> "' + $id + '" [xlabel="contains"];')
|
||||
}
|
||||
if ($depth -eq $maxDepth) {
|
||||
return
|
||||
}
|
||||
if ($fileCount -gt $collapseThreshold -and $depth -gt 0) {
|
||||
return
|
||||
}
|
||||
foreach ($child in $children) {
|
||||
Add-Directory_Node $lines $root $child.FullName ($depth + 1) $id
|
||||
}
|
||||
}
|
||||
function New-Directory_Tree_Graph() {
|
||||
$lines = [System.Collections.Generic.List[string]]::new()
|
||||
Add-Header $lines 'radio directory_tree'
|
||||
foreach ($root in $inputs) {
|
||||
if (!(Test-Path -LiteralPath $root)) {
|
||||
continue
|
||||
}
|
||||
$rootName = Get-Root_Name $root
|
||||
$clusterName = $rootName.Replace('-', '_').Replace('/', '_')
|
||||
$lines.Add('subgraph "cluster_' + $clusterName + '" {')
|
||||
$lines.Add('label="' + (Convert-To_Dot_Text $rootName) + '";')
|
||||
$lines.Add('style="rounded";')
|
||||
Add-Directory_Node $lines $root $root 0 ''
|
||||
$lines.Add('}')
|
||||
}
|
||||
Add-Legend $lines 'directory'
|
||||
$lines.Add('}')
|
||||
Invoke-Dot 'radio_directory_tree' $lines
|
||||
}
|
||||
function Get-Root_For_File([string]$path) {
|
||||
$fullPath = Convert-To_Generic_Path $path
|
||||
foreach ($root in $inputs) {
|
||||
$rootPath = Convert-To_Generic_Path $root
|
||||
if ($fullPath.StartsWith($rootPath)) {
|
||||
return $root
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
function Get-Module_Key([string]$path, [int]$depth) {
|
||||
$root = Get-Root_For_File $path
|
||||
if ($root.Length -eq 0) {
|
||||
return ''
|
||||
}
|
||||
$rootName = Get-Root_Name $root
|
||||
$relative = Get-Relative_Path $root $path
|
||||
$parts = @($relative.Split('/') | Where-Object { $_.Length -gt 0 })
|
||||
if ($rootName -eq 'radio') {
|
||||
$base = 'module/radio'
|
||||
} elseif ($rootName -eq 'CPP_Core') {
|
||||
$base = 'third_party/CPP_Core/Core'
|
||||
} elseif ($rootName -eq 'YSGraphic_Core') {
|
||||
$base = 'third_party/Graphic_Core/YSGraphic_Core'
|
||||
} else {
|
||||
$base = $rootName
|
||||
}
|
||||
if ($parts.Count -eq 0 -or $depth -eq 0) {
|
||||
return $base
|
||||
}
|
||||
$take = [Math]::Min($depth, $parts.Count)
|
||||
return $base + '/' + (($parts | Select-Object -First $take) -join '/')
|
||||
}
|
||||
function Test-Ignored_Include([string]$includeText) {
|
||||
$text = $includeText.Trim()
|
||||
if ($text -match '^(Q[A-ZA-z0-9_]*|Qt[A-ZA-z0-9_/]*|QObject|QWidget|QString|QVector|QMap|QList)$') {
|
||||
return $true
|
||||
}
|
||||
if ($text -match '^(array|atomic|chrono|cmath|cstdint|cstdio|cstdlib|cstring|filesystem|functional|limits|map|memory|mutex|optional|set|span|string|string_view|thread|tuple|type_traits|unordered_map|utility|vector)$') {
|
||||
return $true
|
||||
}
|
||||
if ($text -match '^(boost/|asio|windows\.h|winsock|d3d|GL/)') {
|
||||
return $true
|
||||
}
|
||||
return $false
|
||||
}
|
||||
function Resolve-Include_Path([string]$includeText, [hashtable]$suffixMap, [hashtable]$nameMap) {
|
||||
$key = $includeText.Replace('\', '/').ToLowerInvariant()
|
||||
if ($suffixMap.ContainsKey($key)) {
|
||||
return $suffixMap[$key]
|
||||
}
|
||||
$leaf = [System.IO.Path]::GetFileName($key)
|
||||
if ($nameMap.ContainsKey($leaf)) {
|
||||
return $nameMap[$leaf]
|
||||
}
|
||||
return ''
|
||||
}
|
||||
function Add-Dependency_Graph([string]$name, [string]$title, [int]$sourceDepth, [int]$targetDepth) {
|
||||
$files = Get-Source_Files $inputs
|
||||
$suffixMap = @{}
|
||||
$nameMap = @{}
|
||||
foreach ($file in $files) {
|
||||
$root = Get-Root_For_File $file.FullName
|
||||
$relative = (Get-Relative_Path $root $file.FullName).ToLowerInvariant()
|
||||
$leaf = $file.Name.ToLowerInvariant()
|
||||
$suffixMap[$relative] = $file.FullName
|
||||
if (!$nameMap.ContainsKey($leaf)) {
|
||||
$nameMap[$leaf] = $file.FullName
|
||||
}
|
||||
}
|
||||
$edges = @{}
|
||||
foreach ($file in $files) {
|
||||
$sourceKey = Get-Module_Key $file.FullName $sourceDepth
|
||||
if ($sourceKey.Length -eq 0) {
|
||||
continue
|
||||
}
|
||||
Get-Content -LiteralPath $file.FullName | ForEach-Object {
|
||||
if ($_ -match '^\s*#\s*include\s*[<"]([^">]+)[">]') {
|
||||
$includeText = $Matches[1]
|
||||
if (Test-Ignored_Include $includeText) {
|
||||
return
|
||||
}
|
||||
$targetFile = Resolve-Include_Path $includeText $suffixMap $nameMap
|
||||
if ($targetFile.Length -eq 0) {
|
||||
return
|
||||
}
|
||||
$targetKey = Get-Module_Key $targetFile $targetDepth
|
||||
if ($targetKey.Length -eq 0 -or $targetKey -eq $sourceKey) {
|
||||
return
|
||||
}
|
||||
$edgeKey = $sourceKey + '|' + $targetKey
|
||||
if (!$edges.ContainsKey($edgeKey)) {
|
||||
$edges[$edgeKey] = 0
|
||||
}
|
||||
$edges[$edgeKey]++
|
||||
}
|
||||
}
|
||||
}
|
||||
$nodes = [System.Collections.Generic.HashSet[string]]::new()
|
||||
$lines = [System.Collections.Generic.List[string]]::new()
|
||||
Add-Header $lines $title
|
||||
foreach ($edgeKey in $edges.Keys) {
|
||||
$parts = $edgeKey.Split('|')
|
||||
$nodes.Add($parts[0]) | Out-Null
|
||||
$nodes.Add($parts[1]) | Out-Null
|
||||
}
|
||||
foreach ($node in $nodes) {
|
||||
$label = Convert-To_Dot_Text ([System.IO.Path]::GetFileName($node))
|
||||
$tooltip = Convert-To_Dot_Text $node
|
||||
$lines.Add('"' + $node + '" [label="' + $label + '", tooltip="' + $tooltip + '", fillcolor="#dbeafe"];')
|
||||
}
|
||||
$edgeIndex = 0
|
||||
foreach ($edgeKey in $edges.Keys) {
|
||||
$parts = $edgeKey.Split('|')
|
||||
$countNode = 'include_count:' + $edgeIndex
|
||||
$lines.Add('"' + $countNode + '" [label="include: ' + $edges[$edgeKey] + '", tooltip="' + (Convert-To_Dot_Text $edgeKey) + '", fillcolor="#f8fafc"];')
|
||||
$lines.Add('"' + $parts[0] + '" -> "' + $countNode + '";')
|
||||
$lines.Add('"' + $countNode + '" -> "' + $parts[1] + '";')
|
||||
$edgeIndex++
|
||||
}
|
||||
Add-Legend $lines 'include'
|
||||
$lines.Add('}')
|
||||
Invoke-Dot $name $lines
|
||||
}
|
||||
function New-Render_Architecture_Graph() {
|
||||
$lines = [System.Collections.Generic.List[string]]::new()
|
||||
Add-Header $lines 'radio render_architecture'
|
||||
$lines.Add('"Plot" [label="Plot", fillcolor="#dbeafe"];')
|
||||
$lines.Add('"Renderable" [label="Renderable", fillcolor="#dbeafe"];')
|
||||
$lines.Add('"Render_Data" [label="Render_Data", fillcolor="#dcfce7"];')
|
||||
$lines.Add('"Render_State" [label="Render_State", fillcolor="#dcfce7"];')
|
||||
$lines.Add('"Input_Data" [label="Input_Data", fillcolor="#dcfce7"];')
|
||||
$lines.Add('"Render_Pipeline" [label="Render_Pipeline", fillcolor="#dcfce7"];')
|
||||
$lines.Add('"State_Buffer" [label="State_Buffer[3]", fillcolor="#fef3c7"];')
|
||||
$lines.Add('"Input_Buffer" [label="Input_Buffer[3]", fillcolor="#fef3c7"];')
|
||||
$lines.Add('"Render_Cache" [label="Render_Cache", fillcolor="#fef3c7"];')
|
||||
$lines.Add('"Color_Buffer" [label="Color_Buffer[3]", fillcolor="#fef3c7"];')
|
||||
$lines.Add('"CPU_Render_Task" [label="CPU Render Task", fillcolor="#fee2e2"];')
|
||||
$lines.Add('"Qt_paintEvent" [label="Qt paintEvent", fillcolor="#fee2e2"];')
|
||||
$lines.Add('"Plot" -> "Renderable" [xlabel="owns/schedules"];')
|
||||
$lines.Add('"Renderable" -> "Render_Data" [xlabel="owns"];')
|
||||
$lines.Add('"Render_Data" -> "Render_State" [xlabel="state snapshot"];')
|
||||
$lines.Add('"Render_Data" -> "Input_Data" [xlabel="input batch"];')
|
||||
$lines.Add('"Render_Data" -> "Render_Cache" [xlabel="long-lived cache"];')
|
||||
$lines.Add('"Renderable" -> "Render_Pipeline" [xlabel="submit/finish/publish"];')
|
||||
$lines.Add('"Render_Pipeline" -> "State_Buffer" [xlabel="edit/ready/render"];')
|
||||
$lines.Add('"Render_Pipeline" -> "Input_Buffer" [xlabel="write/ready/render"];')
|
||||
$lines.Add('"Render_Pipeline" -> "CPU_Render_Task" [xlabel="dispatch"];')
|
||||
$lines.Add('"CPU_Render_Task" -> "Color_Buffer" [xlabel="write render color"];')
|
||||
$lines.Add('"Color_Buffer" -> "Qt_paintEvent" [xlabel="ready/front consume"];')
|
||||
Add-Legend $lines 'architecture'
|
||||
$lines.Add('}')
|
||||
Invoke-Dot 'radio_render_architecture' $lines
|
||||
}
|
||||
New-Directory_Tree_Graph
|
||||
Add-Dependency_Graph 'radio_module_dependency' 'radio module_dependency' 0 0
|
||||
Add-Dependency_Graph 'radio_include_dependency' 'radio include_dependency' 1 1
|
||||
New-Render_Architecture_Graph
|
||||
Write-Graphviz_Index
|
||||
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
inputs=(@PSC_INPUT_DIRS_SH@)
|
||||
output_dir='@PSC_OUTPUT_DIR@'
|
||||
format='@PSC_FORMAT@'
|
||||
dot_exe='@PSC_DOT_EXECUTABLE@'
|
||||
max_depth=@PSC_MAX_DEPTH@
|
||||
collapse_threshold=@PSC_COLLAPSE_THRESHOLD@
|
||||
mkdir -p "$output_dir"
|
||||
normalize_path() {
|
||||
local path="$1"
|
||||
if command -v realpath >/dev/null 2>&1; then
|
||||
realpath -m "$path" | tr '\\' '/'
|
||||
else
|
||||
printf '%s\n' "$path" | tr '\\' '/'
|
||||
fi
|
||||
}
|
||||
dot_text() {
|
||||
printf '%s' "$1" | sed 's/\\/\\//g; s/"/\\"/g'
|
||||
}
|
||||
root_name() {
|
||||
local path
|
||||
path=$(normalize_path "$1")
|
||||
case "$path" in
|
||||
*/module/radio) printf 'radio' ;;
|
||||
*/CPP_Core/Core) printf 'CPP_Core' ;;
|
||||
*/YSGraphic_Core) printf 'YSGraphic_Core' ;;
|
||||
*) basename "$path" ;;
|
||||
esac
|
||||
}
|
||||
write_header() {
|
||||
local title="$1"
|
||||
echo "digraph \"$title\" {"
|
||||
echo 'rankdir=LR;'
|
||||
echo 'splines=ortho;'
|
||||
echo 'concentrate=true;'
|
||||
echo 'forcelabels=true;'
|
||||
echo "graph [fontname=\"Consolas\", label=\"$title\", labelloc=t, fontsize=18];"
|
||||
echo 'node [shape=box, style="rounded,filled", fontname="Consolas", fontsize=10];'
|
||||
echo 'edge [fontname="Consolas", fontsize=9];'
|
||||
}
|
||||
write_legend() {
|
||||
echo 'subgraph cluster_legend {'
|
||||
echo 'label="legend";'
|
||||
echo 'style="rounded,dashed";'
|
||||
echo '"legend_module" [label="module/folder", fillcolor="#dbeafe"];'
|
||||
echo '"legend_target" [label="cmake target", fillcolor="#dcfce7"];'
|
||||
echo '"legend_buffer" [label="buffer/cache", fillcolor="#fef3c7"];'
|
||||
echo '"legend_runtime" [label="runtime", fillcolor="#fee2e2"];'
|
||||
echo '"legend_edge" [label="edge label = relation/count", fillcolor="#f8fafc"];'
|
||||
echo '}'
|
||||
}
|
||||
render_dot() {
|
||||
local name="$1"
|
||||
"$dot_exe" "-T$format" "$output_dir/$name.dot" -o "$output_dir/$name.$format"
|
||||
}
|
||||
write_graphviz_index() {
|
||||
local items=(radio_directory_tree radio_module_dependency radio_cmake_targets radio_include_dependency radio_render_architecture)
|
||||
{
|
||||
echo '<!doctype html><meta charset="utf-8"><title>Radio Graphviz</title><h1>Radio Graphviz</h1><ul>'
|
||||
for item in "${items[@]}"; do
|
||||
local file="$item.$format"
|
||||
if [ -f "$output_dir/$file" ]; then
|
||||
echo "<li><a href=\"$file\">$item</a></li>"
|
||||
else
|
||||
echo "<li>$item (not generated)</li>"
|
||||
fi
|
||||
done
|
||||
echo '</ul>'
|
||||
} > "$output_dir/index.html"
|
||||
}
|
||||
write_directory_tree() {
|
||||
local dot="$output_dir/radio_directory_tree.dot"
|
||||
{
|
||||
write_header 'radio directory_tree'
|
||||
for root in "${inputs[@]}"; do
|
||||
[ -d "$root" ] || continue
|
||||
local root_label
|
||||
root_label=$(root_name "$root")
|
||||
echo "subgraph \"cluster_$root_label\" {"
|
||||
echo "label=\"$root_label\";"
|
||||
echo 'style="rounded";'
|
||||
find "$root" -maxdepth "$max_depth" -type d | while read -r dir; do
|
||||
local rel name id files dirs parent parent_id
|
||||
rel=${dir#"$root"}
|
||||
rel=${rel#/}
|
||||
name=$(basename "$dir")
|
||||
[ -z "$rel" ] && name="$root_label"
|
||||
id="$root_label${rel:+/$rel}"
|
||||
files=$(find "$dir" -maxdepth 1 -type f \( -name '*.h' -o -name '*.hpp' -o -name '*.hh' -o -name '*.cpp' -o -name '*.cxx' -o -name '*.cc' \) | wc -l)
|
||||
dirs=$(find "$dir" -maxdepth 1 -mindepth 1 -type d | wc -l)
|
||||
echo "\"dir:$id\" [label=\"$(dot_text "$name")\\nfiles: $files\\ndirs: $dirs\", tooltip=\"$(dot_text "$id")\", fillcolor=\"#dbeafe\"];"
|
||||
if [ -n "$rel" ]; then
|
||||
parent=$(dirname "$rel")
|
||||
if [ "$parent" = "." ]; then
|
||||
parent_id="$root_label"
|
||||
else
|
||||
parent_id="$root_label/$parent"
|
||||
fi
|
||||
echo "\"dir:$parent_id\" -> \"dir:$id\" [xlabel=\"contains\"];"
|
||||
fi
|
||||
done
|
||||
echo '}'
|
||||
done
|
||||
write_legend
|
||||
echo '}'
|
||||
} > "$dot"
|
||||
render_dot 'radio_directory_tree'
|
||||
}
|
||||
write_empty_dependency() {
|
||||
local name="$1"
|
||||
local title="$2"
|
||||
{
|
||||
write_header "$title"
|
||||
echo '"module_dependency_note" [label="include dependency aggregation is generated by the PowerShell script on Windows", fillcolor="#dbeafe"];'
|
||||
write_legend
|
||||
echo '}'
|
||||
} > "$output_dir/$name.dot"
|
||||
render_dot "$name"
|
||||
}
|
||||
write_render_architecture() {
|
||||
{
|
||||
write_header 'radio render_architecture'
|
||||
echo '"Plot" [label="Plot", fillcolor="#dbeafe"];'
|
||||
echo '"Renderable" [label="Renderable", fillcolor="#dbeafe"];'
|
||||
echo '"Render_Data" [label="Render_Data", fillcolor="#dcfce7"];'
|
||||
echo '"Render_State" [label="Render_State", fillcolor="#dcfce7"];'
|
||||
echo '"Input_Data" [label="Input_Data", fillcolor="#dcfce7"];'
|
||||
echo '"Render_Pipeline" [label="Render_Pipeline", fillcolor="#dcfce7"];'
|
||||
echo '"State_Buffer" [label="State_Buffer[3]", fillcolor="#fef3c7"];'
|
||||
echo '"Input_Buffer" [label="Input_Buffer[3]", fillcolor="#fef3c7"];'
|
||||
echo '"Render_Cache" [label="Render_Cache", fillcolor="#fef3c7"];'
|
||||
echo '"Color_Buffer" [label="Color_Buffer[3]", fillcolor="#fef3c7"];'
|
||||
echo '"CPU_Render_Task" [label="CPU Render Task", fillcolor="#fee2e2"];'
|
||||
echo '"Qt_paintEvent" [label="Qt paintEvent", fillcolor="#fee2e2"];'
|
||||
echo '"Plot" -> "Renderable" [xlabel="owns/schedules"];'
|
||||
echo '"Renderable" -> "Render_Data" [xlabel="owns"];'
|
||||
echo '"Render_Data" -> "Render_State" [xlabel="state snapshot"];'
|
||||
echo '"Render_Data" -> "Input_Data" [xlabel="input batch"];'
|
||||
echo '"Render_Data" -> "Render_Cache" [xlabel="long-lived cache"];'
|
||||
echo '"Renderable" -> "Render_Pipeline" [xlabel="submit/finish/publish"];'
|
||||
echo '"Render_Pipeline" -> "State_Buffer" [xlabel="edit/ready/render"];'
|
||||
echo '"Render_Pipeline" -> "Input_Buffer" [xlabel="write/ready/render"];'
|
||||
echo '"Render_Pipeline" -> "CPU_Render_Task" [xlabel="dispatch"];'
|
||||
echo '"CPU_Render_Task" -> "Color_Buffer" [xlabel="write render color"];'
|
||||
echo '"Color_Buffer" -> "Qt_paintEvent" [xlabel="ready/front consume"];'
|
||||
write_legend
|
||||
echo '}'
|
||||
} > "$output_dir/radio_render_architecture.dot"
|
||||
render_dot 'radio_render_architecture'
|
||||
}
|
||||
write_directory_tree
|
||||
write_empty_dependency 'radio_module_dependency' 'radio module_dependency'
|
||||
write_empty_dependency 'radio_include_dependency' 'radio include_dependency'
|
||||
write_render_architecture
|
||||
write_graphviz_index
|
||||
@@ -0,0 +1 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/main.cmake)
|
||||
Reference in New Issue
Block a user