Разработка софта это не только про код. Разработка софта это во многом про Toolchain(ы). Прежде чем начать исполняться исходники проходят гигантский путь и с каждым годом выходят все более и более массивные системы сборки. Современные технологии разработки софта настолько многостадийные, что понять их не просто.
Toolchain это как длинный конвейер. Есть действия, которые следуют одни за другими. После чего получается результат (артефакты). Большинство IDE(IAR, KEIL, MsVisualStudio и пр.) скрывают весь этот конвейер преобразования файлов. И программисты, которые привыкли торчать в IDE(шках) часто даже не догадываются, что в программировании существует что-то кроме *.h и *.сpp файликов. В этом плане IDE оказывают своим покупателям медвежью услугу, так как программисты привыкшие работать только в IDE имеют тенденцию становиться очень слабыми разработчиками.
По-настоящему разобраться как варятся артефакты сложно. Как же это сделать?
Надо прибегнуть к народной мудрости. Как говорит английская пословица: "картинка стоит тысячи слов". Значит надо нарисовать картинку. Схему ToolChain(а). Зачем еще нужны схемы ToolChain(ов)?
Схема может пригодиться для того чтобы ввести в курс дела новых людей. Например фирма chip maker может получить преимущество на рынке, если у нее есть качественная, понятная, доступная и разнообразная документация.
Как же нарисовать схему ToolChain(а)? Тут есть 2 варианта:
[1] Рисовать схему самому, мышкой в программе Inkscape.exe.
Плюс: Можно добиться очень высокой изобразительности и гибкости. Можно задействовать слои, линейки.
Минус: a)Ручное рисование весьма утомительно. Обязательно наступят боли в запястье. b) Использование мышки в программировании считается дурным тоном. c) Трудно подвергнуть *.svg файл версионному контролю. Конфликты при git merge *.svg так как это в сущности *.xml(ка).
[2] Составить описание графа или дерева на языке разметки графов Dot и автоматически одноименной утилитой dot.exe сгенерировать схему графа.
Плюсы: a) быстро, b) четно. c) легко перерисовать. d) легко подвергнуть версионному контролю. e) легко распределить между разными разработчиками сложной схемы.
Минус: a) Надо очень хорошо знать синтаксис и семантику языка Dot. Кластеры. Свойства вершин, свойства ребер. Способы раскраски. b) Схема может не скомпилироваться рендером, если есть ошибки в синтаксисе языка Dot. c) Cхема может отрисоваться самым неожиданным образом.
Как по мне, второй вариант выглядит намного предпочтительнее и позитивнее так как надо меньше пользоваться мышкой.
Надо установить компилятор Dot файлов. Советую брать с официального сайта https://graphviz.org/. Сейчас там версия 6.0.1. Можно конечно и из CygWin скачать Dot, но там версия устаревшая. Старый Dot может упасть в run-time из-за переполнения стека при отрисовке сложных графов. Не забываем прописать путь к dot.exe в переменную PATH.
Писать код на голом языке Dot это не эффективно. В реальных схемах слишком много повторяющихся синтаксических конструкций. Поэтому объединим Си(ишный) препроцессор (утилита cpp.exe) с языком dot. С препроцессору (cpp.exe) вообще все равно какой там язык (assembler, C++, DeviceTree). Задача утилиты cpp.exe это вставка и замена текста. Например деревья устройств в Linux тоже обрабатываются препроцессором cpp. И это всех устраивает. Поэтому будем также использовать препроцессор cpp для языка dot.
В качестве примера исследуемого сложного ToolChain(а) рассмотрим Zephyr project.
Определим только несколько полезных макросов для языка dot
#define BINARY [fillcolor = turquoise1]
#define GENERATED [fillcolor = moccasin]
#define SRC [style="filled"][fillcolor = green]
#define TOOL [shape = box][style="filled"]
#define SCRIPT [shape = box][style="filled"] [fillcolor = plum1]
#define FILE [shape = note][fillcolor = gold][style="filled"]
#define DEVICE [shape = box][fillcolor = grey][style="filled"]
Определим файл *.doti с утилитами, которые будут участвовать в ToolChain(е). *.doti - значит, что это include.
menuconfig TOOL
clang_format [label="clang-format.exe"] TOOL
eclipse [label="Eclipse.exe"] TOOL
eclipsec [label="eclipsec.exe"] TOOL
bash [label="bash.exe"] TOOL
hexdump [label="hexdump.exe"] TOOL
browser [label="chrome.exe"] TOOL
inkscape [label="Inkscape.exe"] TOOL
nrfjprog [label="nrfjprog.exe"] TOOL
Cppcheck [label="Cppcheck.exe"] TOOL
dtc [label="dtc"] TOOL
gen_defines_py [label="gen_defines.py"] SCRIPT
readelf [label="readelf.exe"]TOOL
jenkins [label="jenkins.exe"]TOOL
cpp [label="cpp.exe"]TOOL
chocolatey [label="chocolatey.exe"]TOOL
git [label="git.exe"]TOOL
buildprog [label="buildprog.py"]SCRIPT
JLinkGDBServer [label="JLinkGDBServer.exe"]TOOL
cpp_dot [label="cpp.exe"]TOOL
guiconfig TOOL
cpp_3 [label="cpp.exe (preproc)"] TOOL
linker [label="ld.exe (linker)"] TOOL
compiler [label="gcc.exe (ARM Compiler)"] TOOL
NotePadPp [label="Notepad++.exe"] TOOL
cmd [label="cmd.exe"] TOOL
GDB [label="gdb.exe"] TOOL
cMake [label="cmake.exe"] TOOL
west [label="west.py"] SCRIPT
GN [label="gn.exe"] TOOL
scripts_kconfig [label="zephyr/scripts/kconfig.py"] SCRIPT
nrfjprog [label="nrfjprog.exe"] TOOL
Python [label="Python.exe"] TOOL
make [label="make.exe"] TOOL
ninja [label="ninja.exe"] TOOL
objcopy [label="objcopy.exe"] TOOL
as [label="as.exe"]TOOL
nm [label="nm.exe"]TOOL
addr2line [label="addr2line.exe"]TOOL
dot [label="dot.exe"]TOOL
ar [label="ar.exe"]TOOL
{ rank = same; ninja; make;}
Определим *.doti файл со списком расширений файлов, которые будут участвовать в ToolChain(е)
dtsi[label="*.dtsi"] FILE SRC
DotConf[label="*.conf (Kernel configuration)"] FILE SRC
bat_file[label="*.bat"] FILE SRC
CMakeLists [label="CMakeLists.txt "] FILE SRC
sh_file[label="*.sh"] FILE SRC
ld_file[label="*.ld"] FILE SRC
mk_file[label="*.mk"] FILE SRC
h_file[label="*.h"] FILE SRC
c_file[label="*.c"] FILE SRC
dot_file[label="*.dot"] FILE SRC
doti_file[label="*.doti"] FILE SRC
yaml[label="*.yaml"] FILE SRC
Kconfig [label="Kconfig"] FILE SRC
dts[label="*.dts"] FILE SRC
zephyr_dts_pre[label="zephyr.dts.pre"] FILE
cproject [label=".cproject "] FILE
project [label=".project (description file)"] FILE
Kconfig_zephyr[label="Kconfig.zephyr"] FILE
txt_file[label="*.txt"] FILE
obj_file[label="*.o"] FILE
CMakeCache_txt [label="CMakeCache.txt "] FILE
map_file[label="*.map"] FILE
a_file[label="*.a"] FILE
elf_file[label="*.elf"] FILE
hex_file[label="*.hex"] FILE
bin_file[label="*.bin"] FILE
build_ninja [label="build.ninja"] FILE
json_file[label="*.json"] FILE
svg_file[label="*.svg "] FILE
west_yml[label="west.yml (manifest file)"] FILE
MakeFile[label="Makefile"] FILE
devicetree_generated_h[label="devicetree_generated.h"] FILE
zephyr_dts[label="zephyr.dts "] FILE
autoconfig_h [label="autoconfig.h"] FILE
s_file [label="*.S"] FILE
gn_file [label="BUILD.gn"] FILE
cmd_file [label="*.cmd"] FILE
pp_file [label="*.pp"] FILE
DotConfig [label=".config"] FILE
Определим файл со связями утилит и файлов между собой.
digraph graphname {
rankdir=TB;
splines=ortho;
#include "ToolChain_nRF5340_hardware.doti"
//overlap=scale;
//overlap=prism;
subgraph cluster_NetTop {
style=filled;
color=aliceblue;
label = "NetTop";
HostCpu
HOST_USB
subgraph cluster_Windows10 {
style=filled;
color=lightblue;
label = "Windows10";
#include "ToolChain_nRF5340_tools.doti"
#include "ToolChain_nRF5340_files.doti"
NotePadPp->bat_file[label="*.bat"][dir="both"]
NotePadPp->doti_file[label="*.doti"] [dir="both"]
NotePadPp->sh_file[label="*.sh"][dir="both"]
NotePadPp->mk_file[label="*.mk"][dir="both"]
NotePadPp->c_file[label="*.c"][dir="both"]
NotePadPp->h_file[label="*.h"][dir="both"]
bat_file->cmd[label="*.bat"]
sh_file->bash[label="*.sh"]
subgraph cluster_JVM {
style=filled;
color=lightgreen;
label = "JVM";
jenkins->bash
eclipsec
cproject->eclipse[label=".cproject"][dir="both"]
project->eclipse[label=".project"][dir="both"]
}
subgraph cluster_BuildConfig {
style=filled;
color=khaki1;
label = "Build Configuration (buildsystem)";
bash->buildprog
cmd->buildprog
Python->buildprog
json_file->buildprog [label="*.json"]
Python->west
buildprog->west[label="?"]
yaml->gen_defines_py[label="*.yaml"]
dtsi->cpp[label="*.dtsi"]
dts->cpp
cpp->zephyr_dts_pre
zephyr_dts_pre ->gen_defines_py[label="zephyr.dts.pre"]
gen_defines_py->zephyr_dts[label="zephyr.dts"]
gen_defines_py->devicetree_generated_h[label="devicetree_generated.h"]
zephyr_dts->dtc
CMakeLists->cMake[label="CMakeLists.txt"]
west->cMake
west->scripts_kconfig
cMake->CMakeCache_txt[label="CMakeCache.txt"] [dir="both"]
gn_file->GN
GN->build_ninja
cMake->build_ninja[label="build.ninja"]
cMake->MakeFile
menuconfig [label="menuconfig "]
Kconfig->menuconfig [label="Kconfig"]
Kconfig->Kconfig_zephyr
Kconfig->guiconfig[label="Kconfig"]
Kconfig->scripts_kconfig[label="Kconfig"]
DotConf->scripts_kconfig[label="*.conf"]
scripts_kconfig->autoconfig_h[label="autoconfig.h"]
scripts_kconfig->DotConfig[label="*.config"]
}//cluster_BuildConfig
ld_file->git[label="*.ld"][dir="both"]
sh_file->git[label="*.sh"][dir="both"]
h_file->git[label="*.h"][dir="both"]
c_file->git[label="*.c"][dir="both"]
mk_file->git[label="*.mk"][dir="both"]
doti_file->git[label="*.doti"][dir="both"]
cproject->git[label=".cproject"][dir="both"]
MakeFile->git[label="Makefile"][dir="both"]
project->git[label=".project"][dir="both"]
c_file->eclipse[label="*.c "]
h_file->eclipse[label="*.h"]
eclipse->c_file[label="*.c "]
eclipse->h_file[label="*.h"]
eclipse->MakeFile[dir="both"][label="Makefile"]
eclipse->mk_file[dir="both"][label="*.mk"]
subgraph cluster_BuildArtefact {
style=filled;
color=gray100;
label = "Build Artefact";
build_ninja->ninja[label="Makefile"]
ninja->cpp_3
h_file->cpp_3
c_file->cpp_3
autoconfig_h->cpp_3[label="autoconfig.h"]
devicetree_generated_h->cpp_3
pp_file->compiler
compiler->s_file [label="*.S"]
s_file->as
compiler->ar
as->obj_file
obj_file->linker [label="*.obj"] /*[tailport=s] [headport=n] */
obj_file->ar[label="*.o"]
ar->a_file[label="*.a"]
obj_file->nm[label="*.o"]
ld_file->linker [label="*.ld"]//[headport=n]
cmd_file->linker[label="*.cmd"]
a_file->linker[label="*.a"]
linker->elf_file[label="*.elf"]
linker->map_file[label="*.map"]
elf_file->addr2line[label="*.elf"]
addr2line->eclipse[label=".txt"]
elf_file -> objcopy
objcopy->bin_file
objcopy->hex_file
elf_file->readelf[label="*.elf"]
elf_file->GDB[label="*.elf"]
GDB-> JLinkGDBServer[dir="both"][label="port:2331"]
bin_file->hexdump[label="*.bin"]
hexdump->txt_file[label="*.txt"]
mk_file->make[label="*.mk"]
MakeFile->make[label="MakeFile"]
make->cpp_3
cpp_3 -> pp_file
hex_file->nrfjprog
}
subgraph cluster_BuildDoc {
style=filled;
color=beige;
label = "Build Documentation";
doti_file->cpp_dot
cpp_dot->dot_file
dot_file->dot
dot->svg_file[label="*.svg"]
svg_file->browser[label="*.svg"]
svg_file->inkscape[label="*.svg"]
}
clang_format->c_file[label="*.c"][dir="both"]
clang_format->h_file[label="*.h"][dir="both"]
h_file->Cppcheck[label="*.h"]
c_file->Cppcheck[label="*.c"]
browser->jenkins[label="8080"]
}//Win10
//NotePadPp->Monitor
}//NetTop
eclipse->Monitor
nrfjprog->HOST_USB
JLinkGDBServer->HOST_USB
subgraph cluster_Board {
style=filled;
color=lightblue;
label = "Board";
USB_CONNECTOR_BOARD
Programmator
TargetMcu
}
}
Теперь надо собрать, собственно, сам *.dot файл для утилиты рендера dot.exe, преобразовать *.dot в векторную графику *.svg и отобразить рисунок на экране монитора прямо в браузере. Вот такой микро-конвейер надо реализовать.
Тут нам как раз поможет утилита make. Вот ее код
CC=dot
RENDER="C:/Program Files/Google/Chrome/Application/chrome.exe"
#RENDER=chrome.exe
CURRENT_DIR = $(shell pwd)
$(info CURRENT_DIR= $(CURRENT_DIR) )
CURRENT_DIR := $(subst /cygdrive/c/,C:/, $(CURRENT_DIR))
$(info CURRENT_DIR=$(CURRENT_DIR) )
SOURCES_DOT += $(CURRENT_DIR)/ToolChain_nRF5340.doti
SOURCES_DOT_RES += $(CURRENT_DIR)/ToolChain_nRF5340_res.dot
SOURCES_DOT := $(subst /cygdrive/c/,C:/, $(SOURCES_DOT))
$(info SOURCES_DOT= $(SOURCES_DOT) )
ART_SVG := $(subst doti,svg, $(SOURCES_DOT))
ART_PDF := $(subst doti,pdf, $(SOURCES_DOT))
OPT +=
DOT_OPT +=-Tsvg
DOT_OPT +=-v
DOT_OPT +=-L1
#LAYOUT_ENGINE = -Kneato
#LAYOUT_ENGINE = -Kfdp
#LAYOUT_ENGINE = -Ksfdp
#LAYOUT_ENGINE = -Ktwopi
#LAYOUT_ENGINE = -Kosage
#LAYOUT_ENGINE = -Kpatchwork
LAYOUT_ENGINE = -Kdot
preproc:$(SOURCES_DOT)
$(info Preproc...)
cpp $(SOURCES_DOT) $(OPT) -E -o $(SOURCES_DOT_RES)
generate_pdf: preproc
$(info route graph...)
$(CC) -Tpdf $(LAYOUT_ENGINE) $(SOURCES_DOT_RES) -o $(ART_PDF)
generate_svg: preproc
$(info route graph...)
$(CC) $(DOT_OPT) $(SOURCES_DOT_RES) -o $(ART_SVG)
print_svg: generate_svg generate_pdf
$(info print_svg)
$(RENDER) -open $(ART_SVG)
$(RENDER) -open $(ART_PDF)
all: print_svg
$(info All)
clean:
$(info clean)
rm ToolChain_nRF5340_res.svg
rm $(SOURCES_DOT_RES)
#$(ART_SVG):$(ART_SVG)
Для любителей ninja я тоже накропал ninja скрипт
cflags = -Tsvg
cur_dir = C:\projects\code_base_workspace\code_base_firmware\docs\toolchain_nRF5340\
RENDER="C:/Program Files/Google/Chrome/Application/chrome.exe"
#RENDER=chrome.exe
rule preproc
command = cpp $in -E -o $out
rule generate_svg
command = dot $cflags $in -o $out
rule print_in_browse
command = $RENDER -open $cur_dir/$in
rule clean_temp
command = rm *_generated.svg
command = rm *_res.dot
rule svg2pdf
command = dot.exe -Tpdf $in -o $out
build clean: clean_temp
build ToolChain_nRF5340_res.dot: preproc ToolChain_nRF5340.doti
build ToolChain_nRF5340_generated.svg: generate_svg ToolChain_nRF5340_res.dot
build ToolChain_nRF5340_generated.pdf: svg2pdf ToolChain_nRF5340_res.dot
#build ToolChain_nRF5340_generated.pdf: svg2pdf ToolChain_nRF5340_generated.svg
build make_svg: print_in_browse ToolChain_nRF5340_generated.svg
build make_pdf: print_in_browse ToolChain_nRF5340_generated.pdf
default make_pdf
В результате мы собрали вот такую замечательную блок схемку.
Успех! Теперь все как на ладони. Причем даже Ctrl+F поиск есть!
Буквально пара слов про Zephyr. Видно, что Zephyr собирает проекты в два супер этапа. Сначала Zephyr собирает конфигурацию. Результат сборки конфигурации это Makefile или build.ninja плюс несколько заголовочных файлов, затем собирают сами артефакты на основе собранной ранее конфигурации. На схеме все прекрасно видно.
Вот полный *.dot код с выхода препроцессора для тех кто хочет изучить схему под увеличением
Hidden text
# 1 "C:/1_job/0_NPP_IT_ELMA/code_base_workspace/code_base_firmware/docs/toolchain_nRF5340/ToolChain_nRF5340.doti"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "C:/1_job/0_NPP_IT_ELMA/code_base_workspace/code_base_firmware/docs/toolchain_nRF5340/ToolChain_nRF5340.doti"
digraph graphname {
rankdir=TB;
splines=ortho;
# 1 "C:/1_job/0_NPP_IT_ELMA/code_base_workspace/code_base_firmware/docs/toolchain_nRF5340/ToolChain_nRF5340_hardware.doti" 1
Monitor [label="Monitor"] [shape = box][fillcolor = grey][style="filled"]
Programmator [label="Programmator"] [shape = box][fillcolor = grey][style="filled"]
TargetMcu [label="nRF5340 ARM Cortex-M33 2x"] [shape = box][fillcolor = grey][style="filled"]
HOST_USB [label="USB"] [shape = box][fillcolor = grey][style="filled"]
USB_CONNECTOR_BOARD [label="USB"] [shape = box][fillcolor = grey][style="filled"]
HostCpu [label="X86 AMD64"] [shape = box][fillcolor = grey][style="filled"]
HostCpu->HOST_USB
HOST_USB->USB_CONNECTOR_BOARD[label="USB"]
USB_CONNECTOR_BOARD->Programmator[label="USB"]
Programmator->TargetMcu[label="SWD"]
# 11 "C:/1_job/0_NPP_IT_ELMA/code_base_workspace/code_base_firmware/docs/toolchain_nRF5340/ToolChain_nRF5340.doti" 2
subgraph cluster_NetTop {
style=filled;
color=aliceblue;
label = "NetTop";
HostCpu
HOST_USB
subgraph cluster_Windows10 {
style=filled;
color=lightblue;
label = "Windows10";
# 1 "C:/1_job/0_NPP_IT_ELMA/code_base_workspace/code_base_firmware/docs/toolchain_nRF5340/ToolChain_nRF5340_tools.doti" 1
menuconfig [shape = box][style="filled"]
clang_format [label="clang-format.exe"] [shape = box][style="filled"]
eclipse [label="Eclipse.exe"] [shape = box][style="filled"]
eclipsec [label="eclipsec.exe"] [shape = box][style="filled"]
bash [label="bash.exe"] [shape = box][style="filled"]
hexdump [label="hexdump.exe"] [shape = box][style="filled"]
browser [label="chrome.exe"] [shape = box][style="filled"]
inkscape [label="Inkscape.exe"] [shape = box][style="filled"]
nrfjprog [label="nrfjprog.exe"] [shape = box][style="filled"]
Cppcheck [label="Cppcheck.exe"] [shape = box][style="filled"]
dtc [label="dtc"] [shape = box][style="filled"]
gen_defines_py [label="gen_defines.py"] [shape = box][style="filled"] [fillcolor = plum1]
readelf [label="readelf.exe"][shape = box][style="filled"]
jenkins [label="jenkins.exe"][shape = box][style="filled"]
cpp [label="cpp.exe"][shape = box][style="filled"]
chocolatey [label="chocolatey.exe"][shape = box][style="filled"]
git [label="git.exe"][shape = box][style="filled"]
buildprog [label="buildprog.py"][shape = box][style="filled"] [fillcolor = plum1]
JLinkGDBServer [label="JLinkGDBServer.exe"][shape = box][style="filled"]
cpp_dot [label="cpp.exe"][shape = box][style="filled"]
guiconfig [shape = box][style="filled"]
cpp_3 [label="cpp.exe (preproc)"] [shape = box][style="filled"]
linker [label="ld.exe (linker)"] [shape = box][style="filled"]
compiler [label="gcc.exe (ARM Compiler)"] [shape = box][style="filled"]
NotePadPp [label="Notepad++.exe"] [shape = box][style="filled"]
cmd [label="cmd.exe"] [shape = box][style="filled"]
GDB [label="gdb.exe"] [shape = box][style="filled"]
cMake [label="cmake.exe"] [shape = box][style="filled"]
west [label="west.py"] [shape = box][style="filled"] [fillcolor = plum1]
GN [label="gn.exe"] [shape = box][style="filled"]
scripts_kconfig [label="zephyr/scripts/kconfig.py"] [shape = box][style="filled"] [fillcolor = plum1]
nrfjprog [label="nrfjprog.exe"] [shape = box][style="filled"]
Python [label="Python.exe"] [shape = box][style="filled"]
make [label="make.exe"] [shape = box][style="filled"]
ninja [label="ninja.exe"] [shape = box][style="filled"]
objcopy [label="objcopy.exe"] [shape = box][style="filled"]
as [label="as.exe"][shape = box][style="filled"]
nm [label="nm.exe"][shape = box][style="filled"]
addr2line [label="addr2line.exe"][shape = box][style="filled"]
dot [label="dot.exe"][shape = box][style="filled"]
ar [label="ar.exe"][shape = box][style="filled"]
# 26 "C:/1_job/0_NPP_IT_ELMA/code_base_workspace/code_base_firmware/docs/toolchain_nRF5340/ToolChain_nRF5340.doti" 2
# 1 "C:/1_job/0_NPP_IT_ELMA/code_base_workspace/code_base_firmware/docs/toolchain_nRF5340/ToolChain_nRF5340_files.doti" 1
dtsi[label="*.dtsi"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
DotConf[label="*.conf (Kernel configuration)"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
bat_file[label="*.bat"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
CMakeLists [label="CMakeLists.txt "] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
sh_file[label="*.sh"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
ld_file[label="*.ld"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
mk_file[label="*.mk"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
h_file[label="*.h"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
c_file[label="*.c"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
dot_file[label="*.dot"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
doti_file[label="*.doti"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
yaml[label="*.yaml"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
Kconfig [label="Kconfig"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
dts[label="*.dts"] [shape = note][fillcolor = gold][style="filled"] [style="filled"][fillcolor = green]
zephyr_dts_pre[label="zephyr.dts.pre"] [shape = note][fillcolor = gold][style="filled"]
cproject [label=".cproject "] [shape = note][fillcolor = gold][style="filled"]
project [label=".project (description file)"] [shape = note][fillcolor = gold][style="filled"]
Kconfig_zephyr[label="Kconfig.zephyr"] [shape = note][fillcolor = gold][style="filled"]
txt_file[label="*.txt"] [shape = note][fillcolor = gold][style="filled"]
obj_file[label="*.o"] [shape = note][fillcolor = gold][style="filled"]
CMakeCache_txt [label="CMakeCache.txt "] [shape = note][fillcolor = gold][style="filled"]
map_file[label="*.map"] [shape = note][fillcolor = gold][style="filled"]
a_file[label="*.a"] [shape = note][fillcolor = gold][style="filled"]
elf_file[label="*.elf"] [shape = note][fillcolor = gold][style="filled"]
hex_file[label="*.hex"] [shape = note][fillcolor = gold][style="filled"]
bin_file[label="*.bin"] [shape = note][fillcolor = gold][style="filled"]
build_ninja [label="build.ninja"] [shape = note][fillcolor = gold][style="filled"]
json_file[label="*.json"] [shape = note][fillcolor = gold][style="filled"]
svg_file[label="*.svg "] [shape = note][fillcolor = gold][style="filled"]
west_yml[label="west.yml (manifest file)"] [shape = note][fillcolor = gold][style="filled"]
MakeFile[label="Makefile"] [shape = note][fillcolor = gold][style="filled"]
devicetree_generated_h[label="devicetree_generated.h"] [shape = note][fillcolor = gold][style="filled"]
zephyr_dts[label="zephyr.dts "] [shape = note][fillcolor = gold][style="filled"]
autoconfig_h [label="autoconfig.h"] [shape = note][fillcolor = gold][style="filled"]
s_file [label="*.S"] [shape = note][fillcolor = gold][style="filled"]
gn_file [label="BUILD.gn"] [shape = note][fillcolor = gold][style="filled"]
cmd_file [label="*.cmd"] [shape = note][fillcolor = gold][style="filled"]
pp_file [label="*.pp"] [shape = note][fillcolor = gold][style="filled"]
DotConfig [label=".config"] [shape = note][fillcolor = gold][style="filled"]
# 27 "C:/1_job/0_NPP_IT_ELMA/code_base_workspace/code_base_firmware/docs/toolchain_nRF5340/ToolChain_nRF5340.doti" 2
NotePadPp->bat_file[label="*.bat"][dir="both"]
NotePadPp->doti_file[label="*.doti"] [dir="both"]
NotePadPp->sh_file[label="*.sh"][dir="both"]
NotePadPp->mk_file[label="*.mk"][dir="both"]
NotePadPp->c_file[label="*.c"][dir="both"]
NotePadPp->h_file[label="*.h"][dir="both"]
bat_file->cmd[label="*.bat"]
sh_file->bash[label="*.sh"]
subgraph cluster_JVM {
style=filled;
color=lightgreen;
label = "JVM";
jenkins->bash
eclipsec
cproject->eclipse[label=".cproject"][dir="both"]
project->eclipse[label=".project"][dir="both"]
}
subgraph cluster_BuildConfig {
style=filled;
color=khaki1;
label = "Build Configuration (buildsystem)";
bash->buildprog
cmd->buildprog
Python->buildprog
json_file->buildprog [label="*.json"]
Python->west
buildprog->west[label="?"]
yaml->gen_defines_py[label="*.yaml"]
dtsi->cpp[label="*.dtsi"]
dts->cpp
cpp->zephyr_dts_pre
zephyr_dts_pre ->gen_defines_py[label="zephyr.dts.pre"]
gen_defines_py->zephyr_dts[label="zephyr.dts"]
gen_defines_py->devicetree_generated_h[label="devicetree_generated.h"]
zephyr_dts->dtc
CMakeLists->cMake[label="CMakeLists.txt"]
west->cMake
west->scripts_kconfig
cMake->CMakeCache_txt[label="CMakeCache.txt"] [dir="both"]
gn_file->GN
GN->build_ninja
cMake->build_ninja[label="build.ninja"]
cMake->MakeFile
menuconfig [label="menuconfig "]
Kconfig->menuconfig [label="Kconfig"]
Kconfig->Kconfig_zephyr
Kconfig->guiconfig[label="Kconfig"]
Kconfig->scripts_kconfig[label="Kconfig"]
DotConf->scripts_kconfig[label="*.conf"]
scripts_kconfig->autoconfig_h[label="autoconfig.h"]
scripts_kconfig->DotConfig[label="*.config"]
}
ld_file->git[label="*.ld"][dir="both"]
sh_file->git[label="*.sh"][dir="both"]
h_file->git[label="*.h"][dir="both"]
c_file->git[label="*.c"][dir="both"]
mk_file->git[label="*.mk"][dir="both"]
doti_file->git[label="*.doti"][dir="both"]
cproject->git[label=".cproject"][dir="both"]
MakeFile->git[label="Makefile"][dir="both"]
project->git[label=".project"][dir="both"]
c_file->eclipse[label="*.c "]
h_file->eclipse[label="*.h"]
eclipse->c_file[label="*.c "]
eclipse->h_file[label="*.h"]
eclipse->MakeFile[dir="both"][label="Makefile"]
eclipse->mk_file[dir="both"][label="*.mk"]
subgraph cluster_BuildArtefact {
style=filled;
color=gray100;
label = "Build Artefact";
build_ninja->ninja[label="Makefile"]
ninja->cpp_3
h_file->cpp_3
c_file->cpp_3
autoconfig_h->cpp_3[label="autoconfig.h"]
devicetree_generated_h->cpp_3
pp_file->compiler
compiler->s_file [label="*.S"]
s_file->as
compiler->ar
as->obj_file
obj_file->linker [label="*.obj"]
obj_file->ar[label="*.o"]
ar->a_file[label="*.a"]
obj_file->nm[label="*.o"]
ld_file->linker [label="*.ld"]
cmd_file->linker[label="*.cmd"]
a_file->linker[label="*.a"]
linker->elf_file[label="*.elf"]
linker->map_file[label="*.map"]
elf_file->addr2line[label="*.elf"]
addr2line->eclipse[label=".txt"]
elf_file -> objcopy
objcopy->bin_file
objcopy->hex_file
elf_file->readelf[label="*.elf"]
elf_file->GDB[label="*.elf"]
GDB-> JLinkGDBServer[dir="both"][label="port:2331"]
bin_file->hexdump[label="*.bin"]
hexdump->txt_file[label="*.txt"]
mk_file->make[label="*.mk"]
MakeFile->make[label="MakeFile"]
make->cpp_3
cpp_3 -> pp_file
hex_file->nrfjprog
}
subgraph cluster_BuildDoc {
style=filled;
color=beige;
label = "Build Documentation";
doti_file->cpp_dot
cpp_dot->dot_file
dot_file->dot
dot->svg_file[label="*.svg"]
svg_file->browser[label="*.svg"]
svg_file->inkscape[label="*.svg"]
}
clang_format->c_file[label="*.c"][dir="both"]
clang_format->h_file[label="*.h"][dir="both"]
h_file->Cppcheck[label="*.h"]
c_file->Cppcheck[label="*.c"]
browser->jenkins[label="8080"]
}
}
eclipse->Monitor
nrfjprog->HOST_USB
JLinkGDBServer->HOST_USB
subgraph cluster_Board {
style=filled;
color=lightblue;
label = "Board";
USB_CONNECTOR_BOARD
Programmator
TargetMcu
}
}
Вывод.
Как видите синергия препроцессора cpp и языка разметки Dot может оказаться очень полезна и эффективна в разработке софта и документации. Это позволяет высвободить тонну времени от ручной перерисовки. Можно также генерировать схемы электрических цепочек, графы задач из task traker(а), нейронные сети, конечные автоматы, архитектуры систем на чипе SoC. Да всё, что только угодно, что имеет графо образную природу.
Язык Dot настолько хорошо и универсален, что его следовало бы включить в университетскую программу обучения технических факультетов в качестве одной лабораторной работы по компьютерным технологиям.
Особенно советую обратить внимание на связку сpp/dot/make тем кто работает техническими писателями и схемотехниками. Это тот случай, когда программирование им тоже может быть полезно.
Ссылки про язык Dot
https://habr.com/ru/post/682346/
https://habr.com/ru/post/499170/
https://habr.com/ru/post/337078/