Разработка софта это не только про код. Разработка софта это во многом про Toolchain(ы). Прежде чем начать исполняться исходники проходят гигантский путь и с каждым годом выходят все более и более массивные системы сборки. Современные технологии разработки софта настолько многостадийные, что понять их не просто.
Toolchain это как длинный конвейер. Есть действия, которые следуют одни за другими. После чего получается результат (артефакты). Большинство IDE(IAR, KEIL, MsVisualStudio и пр.) скрывают весь этот конвейер преобразования файлов. И программисты, которые привыкли торчать в IDE(шках) часто даже не догадываются, что в программировании существует что-то кроме *.h и *.с файликов. В этом плане IDE оказывают своим покупателям медвежью услугу, так как программисты привыкшие работать только в IDE имеют тенденцию становиться очень слабыми разработчиками.
По-настоящему разобраться как варятся артефакты сложно. Как же это сделать?
Надо прибегнуть к народной мудрости. Как говорит английская пословица: "картинка стоит тысячи слов". Значит надо нарисовать картинку, то есть схему ToolChain(а).
Зачем нужны эти пресловутые схемы ToolChain(ов)?
1--Например фирма chip maker может получить преимущество на рынке, если у нее есть качественная, понятная, доступная и разнообразная документация.
2--Схема ToolChain(а) позволит быстро ввести в курс дела нового сотрудника-программиста в компании.
Как же нарисовать схему ToolChain(а)? Тут есть 2 варианта:
[1] Рисовать схему самому, мышкой в программе Inkscape.exe.
Плюс:
a) Можно добиться очень высокой степени изобразительности и гибкости. Как тут.

Можно задействовать слои, линейки. Те кто учил в художественной школе композицию тут могут оторваться по-полной.
Минусы:
a) Ручное рисование весьма утомительно. Обязательно наступят боли в запястье.
b) Использование мышки в программировании вообще считается дурным тоном.
c) Трудно подвергнуть *.svg файл версионному контролю. Конфликты при git merge *.svg так как это, в сущности, *.xml(ка).
d) Трудно вставить новый блок так как надо всё снова двигать, выравнивать.
[2] Составить описание графа или дерева на языке разметки графов Dot и автоматически одноименной утилитой dot.exe сгенерировать схему графа.
Плюсы:
a) Быстро.
b) Четко.
c) Легко перерисовать. Легко вставить новый блок.
d) Легко подвергнуть версионному контролю.
e) Легко распределить между разными разработчиками сложной блок-схемы.
Минусы:
a) Надо очень хорошо знать синтаксис и семантику языка Dot. Это кластеры, свойства вершин, свойства ребер, способы раскраски (названия цветов), свойства начала линий, свойства конца линий. Ранги узлов. Настройки авто трассировки и прочее.
b) Схема может не скомпилироваться рендером, если есть ошибки в синтаксисе языка Dot.
c) Cхема может отрисоваться (отрендериться) самым неожиданным для автора образом.
Тем не менее, как по мне, второй вариант выглядит намного предпочтительнее и позитивнее так как надо меньше пользоваться мышкой. Да и к схемам Toolchain(а) обычно не предъявляют требований высокой степени художественности. Лишь бы поскорее понять как работать с кучей разрозненных утилит.
Какой инструментарий потребуется для авто генерации блок схем?
Если коротко, то это cpp, dot, make, chrome.
Прежде всего надо накатить компилятор Dot файлов. Советую брать с официального сайта https://graphviz.org/. Сейчас там версия 6.0.1. Можно конечно и из CygWin скачать Dot, но там версия устаревшая. Старый Dot может упасть в run-time из-за переполнения стека при отрисовке сложных графов. Не забываем прописать путь к dot.exe в переменную PATH.
Писать код на голом языке Dot это не эффективно. В реальных схемах слишком много повторяющихся синтаксических конструкций. Поэтому объединим Си(ишный) препроцессор (утилита cpp.exe) с языком dot.
С препроцессору (cpp.exe) вообще все равно какой там язык (assembler, C, C++, DeviceTree, Kconfig, скрипты компоновщика *.ld). Задача утилиты cpp.exe это банальная вставка и замена текста и точка. Например деревья устройств в Linux тоже обрабатываются препроцессором cpp. И это всех более чем устраивает. Поэтому будем и мы также использовать препроцессор cpp для обработки и подготовки исходного текста на языка dot.
В качестве примера исследуемого сложного ToolChain(а) рассмотрим Zephyr project.
Определим только несколько полезных макросов для языка dot
#ifndef TOOLCHAIN_UTILS_H #define TOOLCHAIN_UTILS_H #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"] #endif /* TOOLCHAIN_UTILS_H */
Определим файл *.doti с утилитами, которые будут участвовать в ToolChain(е). *.doti - значит, что это include.
west [label="west.py"] SCRIPT scripts_kconfig [label="zephyr/scripts/kconfig.py"] SCRIPT menuconfig [label="menuconfig.py"] SCRIPT gen_defines_py [label="gen_defines.py"] SCRIPT buildprog [label="buildprog.py"]SCRIPT guiconfig [label="guiconfig.py"] SCRIPT 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 readelf [label="readelf.exe"]TOOL cpp_ld[label="cpp.exe"] TOOL jenkins [label="jenkins.exe"]TOOL cpp [label="cpp.exe"]TOOL chocolatey [label="chocolatey.exe"]TOOL git [label="git.exe"]TOOL JLinkGDBServer [label="JLinkGDBServer.exe"]TOOL cpp_dot [label="cpp.exe"] 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 GN [label="gn.exe"] TOOL 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 Kconfig_defaults[label="Kconfig.defaults"] 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 GENERATED zephyr_dts_pre[label="zephyr.dts.pre"] FILE GENERATED cproject [label=".cproject "] FILE GENERATED project [label=".project (description file)"] FILE GENERATED Kconfig_zephyr[label="Kconfig.zephyr"] FILE txt_file[label="*.txt"] FILE CMakeCache_txt [label="CMakeCache.txt"] FILE GENERATED map_file[label="*.map"] FILE GENERATED hex_file[label="*.hex"] FILE GENERATED obj_file[label="*.o"] FILE GENERATED BINARY a_file[label="*.a"] FILE GENERATED BINARY elf_file[label="*.elf"] FILE GENERATED BINARY dtb_file[label="*.dtb"] FILE GENERATED BINARY bin_file[label="*.bin"] FILE GENERATED BINARY build_ninja [label="build.ninja"] FILE GENERATED json_file[label="*.json"] FILE svg_file[label="*.svg "] FILE GENERATED west_yml[label="west.yml (manifest file)"] FILE MakeFile[label="Makefile"] FILE GENERATED devicetree_generated_h[label="devicetree_generated.h"] FILE GENERATED zephyr_dts[label="zephyr.dts"] FILE GENERATED autoconfig_h [label="autoconfig.h"] FILE GENERATED s_file [label="*.S"] FILE GENERATED gn_file [label="BUILD.gn"] FILE cmd_file [label="*.cmd"] FILE pp_file [label="*.pp"] FILE GENERATED DotConfig [label=".config"] FILE GENERATED cmake_file[label="*.cmake"] FILE defconfig_file[label="*.defconfig"] FILE
Определим файл со связями утилит и файлов между собой.
#include "ToolChain_utils.doti" digraph graphname { rankdir=TB; splines=ortho; #include "ToolChain_nRF5340_hardware.doti" subgraph cluster_NetTop { style=filled; color=aliceblue; label = "NetTop (WorkStation Computer)"; 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"] west_yml->west[label="west.yml"] 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 dtc->dtb_file[label="*.dtb"] 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 west->menuconfig [label="build -t"] Kconfig_defaults->Kconfig[label="Kconfig.defaults"] Kconfig->Kconfig_zephyr west->guiconfig[label="build -t"] Kconfig->scripts_kconfig[label="Kconfig"] DotConf->scripts_kconfig[label="*.conf"] scripts_kconfig->autoconfig_h[label="autoconfig.h"] scripts_kconfig->DotConfig[label="*.config"] DotConfig->menuconfig[label="*.config"][dir="both"] DotConfig->guiconfig[label="*.config"][dir="both"] }//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"] cMake-> project cMake-> cproject #include "ToolChain_nRF5340_build_artefacts.doti" 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=C:/cygwin64/bin/dot.exe CC_DOT="C:/Program Files/Graphviz/bin/dot.exe" RENDER="C:/Program Files/Google/Chrome/Application/chrome.exe" #RENDER=chrome.exe CURRENT_DIR = $(shell pwd) $(info CURRENT_DIR= $(CURRENT_DIR) ) CURRENT_DIR := $(subst /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 /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 +=-L10 #DOT_OPT +=-v #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_DOT) -V $(CC_DOT) -Tpdf $(LAYOUT_ENGINE) $(SOURCES_DOT_RES) -o $(ART_PDF) generate_svg: preproc $(info route graph...) $(CC_DOT) -V $(CC_DOT) $(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 я тоже накропал build.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" 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 make_svg: print_in_browse ToolChain_nRF5340_generated.svg build make_pdf: print_in_browse ToolChain_nRF5340_generated.pdf default make_pdf
В результате мы собрали вот такую замечательную блок схемку ToolChain для системы сборки Zephyr.

Успех! Теперь все как на ладони. Причем при просмотре *.svg из браузера даже Ctrl+F поиск есть! Супер!
Буквально пара слов про Zephyr. Видно, что Zephyr собирает проекты в два супер этапа. Сначала Zephyr собирает конфигурацию. Результат сборки конфигурации это Makefile или build.ninja плюс несколько заголовочных файлов *.h, затем собирают сами артефакты на основе собранной ранее конфигурации. На схеме все прекрасно видно. Рулит всем внутри фактически CMake. Но есть Python скрипты west, которые запускают CMake.
Вот полный *.dot код с выхода препроцессора для тех, кто хочет изучить схему под увеличением
Hidden text
digraph graphname { rankdir=TB; splines=ortho; 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 Core)"] [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"] subgraph cluster_NetTop { style=filled; color=aliceblue; label = "NetTop (WorkStation Computer)"; HostCpu HOST_USB subgraph cluster_Windows10 { style=filled; color=lightblue; label = "Windows10"; west [label="west.py"] [shape = box][style="filled"] [fillcolor = plum1] scripts_kconfig [label="zephyr/scripts/kconfig.py"] [shape = box][style="filled"] [fillcolor = plum1] menuconfig [label="menuconfig.py"] [shape = box][style="filled"] [fillcolor = plum1] gen_defines_py [label="zephyr/scripts/dts/gen_defines.py"] [shape = box][style="filled"] [fillcolor = plum1] buildprog [label="buildprog.py"][shape = box][style="filled"] [fillcolor = plum1] guiconfig [label="guiconfig.py"] [shape = box][style="filled"] [fillcolor = plum1] 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"] fdtdump [label="fdtdump.exe"] [shape = box][style="filled"] dtc [label="dtc"] [shape = box][style="filled"] cpp_ld[label="cpp.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"] JLinkGDBServer [label="JLinkGDBServer.exe"][shape = box][style="filled"] cpp_dot [label="cpp.exe"] [shape = box][style="filled"] cpp_3 [label="cpp.exe (preproc)"] [shape = box][style="filled"] compiler [label="arm-zephyr-eabi-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"] GN [label="gn.exe"] [shape = box][style="filled"] 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"] [fillcolor = deepskyblue] linker [label="ld.exe (linker)"] [shape = box][style="filled"] [fillcolor = deepskyblue] as [label="as.exe"] [shape = box][style="filled"] [fillcolor = deepskyblue] nm [label="nm.exe"] [shape = box][style="filled"] [fillcolor = deepskyblue] ar [label="ar.exe"] [shape = box][style="filled"] [fillcolor = deepskyblue] readelf [label="readelf.exe"] [shape = box][style="filled"] [fillcolor = deepskyblue] gprof [label="gprof.exe"] [shape = box][style="filled"] [fillcolor = deepskyblue] addr2line [label="addr2line.exe"] [shape = box][style="filled"] [fillcolor = deepskyblue] dot [label="dot.exe"][shape = box][style="filled"] 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] Kconfig_defaults[label="Kconfig.defaults"] [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] overlay_file[label="*.overlay"] [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] devicetree_h[label="devicetree.h"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] devicetree_fixups_h[label="devicetree_fixups.h"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] devicetree_unfixed_h[label="devicetree_unfixed.h"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] zephyr_dts_pre[label="zephyr.dts.pre"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] cproject [label=".cproject "] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] project [label=".project (description file)"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] Kconfig_zephyr[label="Kconfig.zephyr"] [shape = note][fillcolor = gold][style="filled"] txt_file[label="*.txt"] [shape = note][fillcolor = gold][style="filled"] CMakeCache_txt [label="CMakeCache.txt"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] map_file[label="*.map"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] hex_file[label="*.hex"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] obj_file[label="*.o"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] [fillcolor = turquoise1] a_file[label="*.a"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] [fillcolor = turquoise1] elf_file[label="*.elf"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] [fillcolor = turquoise1] dtb_file[label="*.dtb"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] [fillcolor = turquoise1] bin_file[label="*.bin"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] [fillcolor = turquoise1] build_ninja [label="build.ninja"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] json_file[label="*.json"] [shape = note][fillcolor = gold][style="filled"] svg_file[label="*.svg "] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] west_yml[label="west.yml (manifest file)"] [shape = note][fillcolor = gold][style="filled"] MakeFile[label="Makefile"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] devicetree_generated_h[label="devicetree_generated.h"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] zephyr_dts[label="zephyr.dts"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] autoconfig_h [label="autoconfig.h"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] s_file [label="*.S"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] 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"] [fillcolor = moccasin] DotConfig [label=".config"] [shape = note][fillcolor = gold][style="filled"] [fillcolor = moccasin] cmake_file[label="*.cmake"] [shape = note][fillcolor = gold][style="filled"] defconfig_file[label="*.defconfig"] [shape = note][fillcolor = gold][style="filled"] 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"] west_yml->west[label="west.yml"] Python->west buildprog->west[label="?"] dtsi->cpp[label="*.dtsi"] dts->cpp[label="*.dts"] overlay_file->cpp[label="*.overlay"] cpp->zephyr_dts_pre[label="zephyr.dts.pre"] yaml->gen_defines_py[label="*.yaml"] zephyr_dts_pre->gen_defines_py[label="zephyr.dts.pre"] zephyr_dts->dtc[label="zephyr.dts"] dtc->dtb_file[label="*.dtb"] CMakeLists->cMake[label="CMakeLists.txt"] west->cMake cMake->gen_defines_py gen_defines_py->zephyr_dts[label="zephyr.dts"] gen_defines_py->devicetree_unfixed_h[label="devicetree_unfixed.h"] gen_defines_py->devicetree_generated_h[label="devicetree_generated.h"] cMake->CMakeCache_txt[label="CMakeCache.txt"] [dir="both"] gn_file->GN GN->build_ninja[label="build.ninja"] cMake->build_ninja[label="build.ninja"] cMake->MakeFile[label="MakeFile"] west->menuconfig [label="build -t"] Kconfig_defaults->Kconfig[label="Kconfig.defaults"] Kconfig->Kconfig_zephyr west->guiconfig[label="build -t"] Kconfig->scripts_kconfig[label="Kconfig"] DotConf->scripts_kconfig[label="*.conf"] cMake->scripts_kconfig scripts_kconfig->autoconfig_h[label="autoconfig.h"] scripts_kconfig->DotConfig[label="*.config"] DotConfig->menuconfig[label="*.config"][dir="both"] DotConfig->guiconfig[label="*.config"][dir="both"] DotConfig->cMake[label="*.config"] autoconfig_h->cMake[label="autoconfig.h"] devicetree_unfixed_h->devicetree_h[label="devicetree_unfixed.h"] devicetree_fixups_h->devicetree_h[label="devicetree_fixups.h"] dtb_file->fdtdump[label="*.dtb"] } 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"] cMake-> project cMake-> cproject 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 [label="*.S"] compiler->ar as->obj_file [label="*.obj"] obj_file->ar[label="*.o"] ar->a_file[label="*.a"] obj_file->nm[label="*.o"] ld_file->cpp_ld[label="*.ld"] cpp_ld->cmd_file[label="*.cmd"] obj_file->linker [label="*.obj"] 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 } }
ShowRoom схем ToolChain(ов)
Вот классическая схема ToolChain для сборки прошивок под микроконтроллер nrf5340.

А это схема ToolChain(а) при разработке топологии для электронной платы

Это схема метаморфоза файлов для черчения

Вывод
Как видите синергия препроцессора cpp и языка разметки Graphviz может оказаться очень полезна и эффективна в разработке софта и всяческой документации. Это позволяет высвободить тонну времени от ручной перерисовки. Можно также из Graphviz генерировать архитектуры систем на чипе SoC, схемы электрических цепочек, графы задач из task tracker(а), нейронные сети, конечные автоматы, схемы метро. Да всё, что только душе угодно, что имеет графо образную природу.
Язык Graphviz настолько хорош и универсален, что его следовало бы включить в университетскую программу обучения в технических факультетах в качестве одной лабораторной работы по компьютерным технологиям.
Особенно советую обратить внимание на связку сpp.exe/dot.exe/make.exe тем кто работает техническими писателями и схемотехниками. Это тот самый случай, когда программирование на Graphviz может принести пользу.
Ссылки про язык Dot
https://habr.com/ru/post/682346/
https://habr.com/ru/post/499170/
https://habr.com/ru/post/337078/
