Тандем Cpp/Dot для Описания Сложных ToolСhain(ов)

от автора

Разработка софта это не только про код. Разработка софта это во многом про Toolchain(ы). Прежде чем начать исполняться исходники проходят гигантский путь и с каждым годом выходят все более и более массивные системы сборки. Современные технологии разработки софта настолько многостадийные, что понять их не просто.

Toolchain это как длинный конвейер. Есть действия, которые следуют одни за другими. После чего получается результат (артефакты). Большинство IDE(IAR, KEIL, MsVisualStudio и пр.) скрывают весь этот конвейер преобразования файлов. И программисты, которые привыкли торчать в IDE(шках) часто даже не догадываются, что в программировании существует что-то кроме *.h и *.с файликов. В этом плане IDE оказывают своим покупателям медвежью услугу, так как программисты привыкшие работать только в IDE имеют тенденцию становиться очень слабыми разработчиками.

По-настоящему разобраться как варятся артефакты сложно. Как же это сделать?

Надо прибегнуть к народной мудрости. Как говорит английская пословица: «картинка стоит тысячи слов». Значит надо нарисовать картинку. Схему ToolChain(а).

Зачем еще нужны схемы ToolChain(ов)?

Схема может пригодиться для того чтобы ввести в курс дела новичков. Например фирма chip maker может получить преимущество на рынке, если у нее есть качественная, понятная, доступная и разнообразная документация.

Как же нарисовать схему ToolChain(а)? Тут есть 2 варианта:

[1] Рисовать схему самому, мышкой в программе Inkscape.exe.

Плюс:

a) Можно добиться очень высокой степени изобразительности и гибкости. Можно задействовать слои, линейки. Те кто учил в художественной школе композицию тут могут оторваться по-полной.

Минусы:

a) Ручное рисование весьма утомительно. Обязательно наступят боли в запястье.

b) Использование мышки в программировании вообще считается дурным тоном.

c) Трудно подвергнуть *.svg файл версионному контролю. Конфликты при git merge *.svg так как это в сущности *.xml(ка).

[2] Составить описание графа или дерева на языке разметки графов Dot и автоматически одноименной утилитой dot.exe сгенерировать схему графа.

Плюсы:

a) Быстро.

b) Четко.

c) Легко перерисовать.

d) Легко подвергнуть версионному контролю.

e) Легко распределить между разными разработчиками сложной блок-схемы.

Минусы:

a) Надо очень хорошо знать синтаксис и семантику языка Dot: кластеры, свойства вершин, свойства ребер, способы раскраски.

b) Схема может не скомпилироваться рендером, если есть ошибки в синтаксисе языка Dot.

c) Cхема может отрисоваться самым неожиданным образом.

Как по мне, второй вариант выглядит намного предпочтительнее и позитивнее так как надо меньше пользоваться мышкой.

Какой инструментарий потребуется для авто генерации блок схем?

Если коротко то это 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++, DeviceTree, Kconfig). Задача утилиты 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"          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=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"   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.

Вот полный *.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 может оказаться очень полезна и эффективна в разработке софта и документации. Это позволяет высвободить тонну времени от ручной перерисовки. Можно также из 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/

https://habr.com/ru/post/662561/

https://habr.com/ru/post/258295/

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы пользовались языком разметки графов Dot?
50% да 7
50% нет 7
Проголосовали 14 пользователей. Воздержавшихся нет.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы составляли схемы ToolChain(а)?
21.43% да 3
78.57% нет 11
Проголосовали 14 пользователей. Воздержавшихся нет.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собирали артефакты из-под Zephyr project?
9.09% да 1
90.91% нет 10
Проголосовали 11 пользователей. Воздержавшихся нет.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собирали код из-под Ninja?
41.67% да 5
58.33% нет 7
Проголосовали 12 пользователей. Воздержавшихся нет.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собирали код из-под Makefile(ов)?
92.31% да 12
7.69% нет 1
Проголосовали 13 пользователей. Воздержавшихся нет.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собираете документацию из кода (автоматическая генерация документации)?
80% да 8
20% нет 2
Проголосовали 10 пользователей. Воздержавшихся нет.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы пользовались языком Dot в связке с препроцессором cpp?
11.11% да 1
88.89% нет 8
Проголосовали 9 пользователей. Воздержался 1 пользователь.

ссылка на оригинал статьи https://habr.com/ru/post/688542/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *