Как стать автором
Обновить

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

Уровень сложностиПростой
Время на прочтение19 мин
Количество просмотров3.5K

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

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

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

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

Зачем нужны эти пресловутые схемы ToolChain(ов)?

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

2--Схема ToolChain(а) позволит быстро ввести в курс дела нового сотрудника-программиста в компании.

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

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

Плюс:

a) Можно добиться очень высокой степени изобразительности и гибкости. Как тут.

Схем ToolChain нарисованная от руки
Схем ToolChain нарисованная от руки

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

Минусы:

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.

Автоматически сгенерированная схема ToolChain(а)
Автоматически сгенерированная схема ToolChain(а)

Успех! Теперь все как на ладони. Причем при просмотре *.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/

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

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

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы пользовались языком разметки графов Graphviz?
44.19% да19
55.81% нет24
Проголосовали 43 пользователя. Воздержался 1 пользователь.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы составляли схемы ToolChain(а)?
7.5% да3
92.5% нет37
Проголосовали 40 пользователей. Воздержались 2 пользователя.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собирали артефакты из-под Zephyr Project?
8.11% да3
91.89% нет34
Проголосовали 37 пользователей. Воздержался 1 пользователь.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собирали код из-под Ninja?
43.9% да18
56.1% нет23
Проголосовал 41 пользователь. Воздержавшихся нет.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собирали код из-под Makefile(ов)?
86.36% да38
13.64% нет6
Проголосовали 44 пользователя. Воздержавшихся нет.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собираете документацию из кода (автоматическая генерация документации)?
62.16% да23
37.84% нет14
Проголосовали 37 пользователей. Воздержались 2 пользователя.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы пользовались языком Dot в связке с препроцессором cpp?
3.03% да1
96.97% нет32
Проголосовали 33 пользователя. Воздержались 4 пользователя.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы используете деревья устройств (*.dts файлы) для описания аппаратной части PCB при сборке прошивок MCU?
0% да0
100% нет6
Проголосовали 6 пользователей. Воздержались 2 пользователя.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы пользовались программой Inkscape?
57.14% да4
42.86% нет3
Проголосовали 7 пользователей. Воздержавшихся нет.
Теги:
Хабы:
Всего голосов 11: ↑8 и ↓3+7
Комментарии8

Публикации

Истории

Работа

Программист С
37 вакансий

Ближайшие события

15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань