
Slang 编译器子系统依赖图从 CMake 构建文件推导架构边界与风险面【免费下载链接】slangMaking it easier to work with shaders项目地址: https://gitcode.com/GitHub_Trending/sl/slang本文讲解 Slang 着色器编译器Shader Language 编译器如何以子系统级subsystem-level依赖图来描述source/目录树中各大逻辑单元之间的链接关系并给出从构建系统事实推导架构约束不变量的完整方法论。通过阅读本文你将掌握如何从CMakeLists.txt的LINK_WITH_*条款还原出 Slang 的整体分层结构、如何预判改动某个子系统会波及其他哪些子系统的风险面、以及source/core/、source/compiler-core/、source/slang/等核心模块之间必须遵守的方向性规则。文档的定位一份由构建系统驱动的架构图docs/generated/design/architecture/dependency-graph.md是 Slang 生成式设计文档体系docs/generated/design/中专门记录静态链接依赖的一页。它的源头是一份提示词规范docs/generated/design/_meta/prompts/architecture-dependency-graph.md该规范把生成这一页的全部约束固化下来包括图的粒度必须是子系统级每个节点对应一个source/subsystem/目录而不是文件级图中每一条边都必须由source/下各CMakeLists.txt中的target_link_libraries(...)等价于slang_add_target的LINK_WITH_PRIVATE/LINK_WITH_PUBLIC条款支撑禁止凭空捏造边必须列出若干值得注意的不变量Notable invariants且每条不变量都要给出构建文件或头文件依据必须说明是否存在依赖环及已知的不规则现象图与文合计体积限制在 16 KB 以内以保证文档可维护。依赖图的目标读者非常明确想要预判一次改动影响面的人——当你修改某个子系统时这张图能告诉你哪些子系统处于风险之中。文件级清单则见 docs/generated/design/architecture/module-map.md。图例与粒度为什么是子系统级而不是文件级依赖图刻意选择了粗粒度。以source/slang/为例该目录下仅 IR 相关文件就有上百个module-map.md 记录 IR passes 一族包含 163 个.cpp文件加上头文件共 326 个若把每条文件级依赖都画出来图会立刻失去可读性。子系统级图的收益在于读者只要记住十几个节点就能对全项目的构建依赖结构建立整体认知。图中的边语义有两种编译期针对某子系统的公共头文件编译compiles against the public headers of与运行时依赖depends on at runtime其事实来源统一是slang_add_target(... LINK_WITH_PRIVATE ...)/LINK_WITH_PUBLIC条款。绘制该图时必须遵守项目统一的 mermaid 语法约定节点 ID 使用 camelCase、节点名不含空格、不显式着色。依赖图全景Slang 内部子系统链接结构以下是 dependency-graph.md 呈现的完整子系统级依赖图外部依赖已从图中剔除聚焦内部结构图中所有实线边都可以在对应CMakeLists.txt中找到逐字依据汇总如下边依据文件条款compiler-core → coresource/compiler-core/CMakeLists.txtLINK_WITH_PRIVATE core实际为LINK_WITH_PRIVATE core fast_floatfast_float为外部库core-module → core、core-module → slang生成目标source/slang-core-module/CMakeLists.txtLINK_WITH_PRIVATE core slang-capability-defs slang-fiddle-outputglsl-module → coresource/slang-glsl-module/CMakeLists.txtLINK_WITH_PRIVATE coreslang → {core, prelude, compiler-core, core-module}及source/slang/内生成目标source/slang/CMakeLists.txtslang_add_target(slang ...)的LINK_WITH_PRIVATE core prelude compiler-core slang-capability-defs slang-capability-lookup slang-fiddle-output slang-lookup-tables SPIRV-Headers::SPIRV-Headers libcmark-gfmprelude实际是私有包含依赖而非静态链接slangc → core、slangc → slangsource/slangc/CMakeLists.txtLINK_WITH_PRIVATE core slang Threads::Threads外加按条件附加的 glsl-module 与 core-module-cache 依赖slang-dispatcher → coresource/slang-dispatcher/CMakeLists.txtLINK_WITH_PRIVATE中包含coreslang-wasm → {slang, core, compiler-core}及source/slang/内生成目标source/slang-wasm/CMakeLists.txtLINK_WITH_PRIVATE miniz lz4_static slang core compiler-core slang-capability-defs slang-capability-lookup slang-fiddle-output slang-lookup-tables虚线边slang -.- slang-record-replay并非由LINK_WITH_*条款支撑而是源码列表直接并入source/slang/CMakeLists.txt第 164-167 行把SLANG_RECORD_REPLAY_SYSTEM变量指向source/slang-record-replay/及其proxy/子目录传入EXTRA_SOURCE_DIRS使记录/回放源码被直接编译进slang库因此它不构成独立的链接目标。三个没有普通链接边的子系统对照 module-map.md 中的子系统清单有三个子系统在上图中没有普通LINK_WITH_*边需要单独理解source/standard-modules/它的 CMakeLists.txt 只做configure_file生成配置头、并add_subdirectory引入neural、experimental、numerics三个模块本身不声明链接目标模块产物以独立的.slang-module文件形式随编译器分发。source/slang-record-replay/没有自己的CMakeLists.txt如上所述其源码通过SLANG_RECORD_REPLAY_SYSTEM变量并入slang目标见 source/slang/CMakeLists.txt 第 164-167 行。source/slang-llvm/同样没有自己的CMakeLists.txt。slang-llvm库在源码树外构建或由根 CMakeLists.txt 第 385-401 行通过SLANG_SLANG_LLVM_FLAVOR选项控制下载预编译产物因此源码树内没有任何目标直接链接它。图中刻意不展开的生成代码目标source/slang/的构建还定义了四个生成代码目标依赖图故意不把它们当作独立子系统展示slang-fiddle-outputFIDDLE 生成的 AST/IR 支持代码由slang-fiddle工具驱动见 source/slang/CMakeLists.txt 顶部的SLANG_FIDDLE_*逻辑slang-capability-defs与slang-capability-lookup由slang-capability-generator从*.capdef生成的 capability 表分别对应生成头文件库与生成源码库slang-lookup-tables由slang-lookup-generator/slang-spirv-embed-generator生成的 SPIR-V 等查找表。这四个目标被slang与slang-wasm共同消费。同时它们也解释了图中slang-core-module → slang这条生成目标边source/slang-core-module/链接了slang-capability-defs与slang-fiddle-output即它依赖的是source/slang/拥有的生成产物而并不链接编译器库本体。外部依赖被排除在图的内部结构之外外部依赖miniz、lz4_static、Threads::Threads、unordered_dense、fast_float、SPIRV-Headers、SPIRV-Tools-opt、SPIRV-Tools-link、SPIRV、glslang、${CMAKE_DL_LIBS}等从图中剔除以保证图聚焦内部结构但规范要求以逐节点备注的方式交代最重要的几项corecoreLib私有链接miniz、lz4_static、Threads::Threads、${CMAKE_DL_LIBS}公共链接unordered_dense::unordered_dense当SLANG_ENABLE_MIMALLOC开启时额外以PUBLIC方式链接mimalloc-static并传播PUBLIC SLANG_ENABLE_MIMALLOC1编译宏使所有下游看到一致的分配器选择——配置阶段若找不到mimalloc-static目标会直接FATAL_ERROR见 source/core/CMakeLists.txt 第 16-25 行。compiler-corecompilerCore除内部core链接外私有链接fast_float用于快速浮点解析条款为LINK_WITH_PRIVATE core fast_float见 source/compiler-core/CMakeLists.txt。slang与slang-wasm依赖SPIRV-Headerswasm 目标额外使用miniz/lz4_static。slang-rt链接miniz、lz4_static、Threads、unordered_dense、${CMAKE_DL_LIBS}——注意其私有依赖列表中没有任何内部 Slang 库。不过slang-rt并非与编译器源码完全无关它的 CMakeLists.txt 通过EXTRA_SOURCE_DIRS ${slang_SOURCE_DIR}/source/core把source/core/的源码以SLANG_RT_DYNAMIC_EXPORT宏重新编译进运行时并通过INCLUDE_DIRECTORIES_PRIVATE ${slang_SOURCE_DIR}/source让这些源码能解析#include core/slang-basic.h这类直接路径包含。slang-glslang链接glslang、SPIRV、SPIRV-Tools-opt、SPIRV-Tools-link见 source/slang-glslang/CMakeLists.txt。slang-lookup-tables依赖SPIRV-Headers。值得注意的不变量架构边界的硬约束依赖图揭示的分层结构可以提炼为以下方向性规则每条都有构建文件或头文件做依据。这些不变量正是预测改动风险面的核心工具。source/core/不依赖项目内任何其他子系统。其 CMakeLists.txt 的slang_add_target(... LINK_WITH_PRIVATE miniz lz4_static Threads::Threads ${CMAKE_DL_LIBS})LINK_WITH_PUBLIC unordered_dense::unordered_dense只列出外部库。它是整个项目的基座层被其他每个子目录使用。source/compiler-core/可以依赖source/core/但绝不能依赖source/slang/。其构建块只含LINK_WITH_PRIVATE core fast_float。这一条把语言无关的编译器基础设施词法、诊断、artifact 模型、下游编译器胶水等详见 module-map.md与Slang 语言本体严格隔离。source/slang/是唯一收拢 AST / IR / emit / check 源码的子系统。具体承载这些源码的目标在非嵌入构建下就是slang库本身当SLANG_EMBED_CORE_MODULE开启时则改为slang-common-objects对象库两个库目标声明为NO_SOURCE后从对象库重链接见 source/slang/CMakeLists.txt。其他任何需要编译服务的二进制例如slangcsource/slangc/CMakeLists.txt都是链接slang库而非直接取用单个源文件。capability 子系统被拆成两个库。slang-capability-defs是生成的头文件库slang-capability-lookup是生成的源码库主slang目标两者都消费见 source/slang/CMakeLists.txt。核心模块是可选链接的。在slang-embedded-core-module与slang-no-embedded-core-module之间的选择由 CMake 选项SLANG_EMBED_CORE_MODULE控制并以生成器表达式体现在 source/slang/CMakeLists.txt 中。当该选项关闭且SLANG_LIB_TYPE为SHARED时同一文件还会添加generate_core_module_cache目标它运行slang-core-module-cache工具把刚链接好的库与generate_core_module产出的无时间戳归档core_module_archive_without_timestamp见 source/slang-core-module/CMakeLists.txt合成为带时间戳前缀的slang-core-module.bin放在库旁边。这是对 tools/ 下某个目标的构建顺序依赖而非链接边且它把库文件在磁盘上的时间戳纳入缓存有效性判断。slang-rt不依赖编译器。它的LINK_WITH_PRIVATE列表中不含任何编译器内部库运行时与 CPU 目标的发射产物一起分发。slang-glslang的导出面由一个文件约束而不是由编译器的可见性设置约束。CXX_VISIBILITY_PRESET hidden与-Wl,--exclude-libs,ALL分别隐藏 shim 自身与静态链接依赖的非导出符号但都不能决定最终导出清单slang-glslang.version-script才是导出名的唯一事实来源见 source/slang-glslang/CMakeLists.txt。ELF 直接消费该文件Mach-O 没有 version-script 概念因此同一 CMake 文件在配置期解析脚本的global:块并推导出-exported_symbols_listld64 会给 C 符号加下划线前缀例如glslang_compile变成_glslang_compile。推导而非手工维护第二份清单正是为了两种格式不漂移解析逻辑被设计为宁可大声失败提取不到任何名字、或去掉name;条目后还有残余非空白字符说明有条目格式不符合预期会被静默丢弃时都会message(FATAL_ERROR)。对贡献者的实际含义记录在 shim 自身的头注释里——新增导出入口必须同时加到 version-script 与 C 中否则在 ELF 和 macOS 上都不会被导出。include/中的公共头文件不得包含source/中的私有头文件。这不是构建系统约束而是项目规则见 CLAUDE.md遵守它才能让下游用户只消费include/slang.h即可使用编译器。循环与已知不规则现象在逐目录的 CMake 文件中没有观察到任何链接级依赖环。依赖图是有向无环的这本身就是架构健康度的重要信号。不过有两个已知的不规则现象值得留意slang库向上反向引用工具树的头文件。source/slang/CMakeLists.txt 把${slang_SOURCE_DIR}/tools加进INCLUDE_DIRECTORIES_PRIVATE这使得slang-language-server.cpp能够编译#include platform/performance-counter.h来自 tools/platform/。这条路径没有伴随任何链接边——头文件只被用于其内联定义——但它意味着tools/platform/不能随意搬移而不触碰编译器库。slang-common-objects间接层。在SLANG_EMBED_CORE_MODULE开启的某些模式下同一批源文件先被编译进一个对象库再被同时重链接进slang-without-embedded-core-module与主slang库见 source/slang/CMakeLists.txt。这是构建系统的便利设计用于在用户面向的slang之外额外产出一个无内嵌核心模块的编译器生成器供slang-bootstrap使用。质量红线如何保证这张图始终可信因为依赖图是从构建文件机械推导的规范为其设定了明确的质检清单这些红线同样值得任何维护者遵守每个节点都必须对应source/下的一个目录或 module-map.md 中的一个小节标题每条边都必须由某个CMakeLists.txt的条款背书——regenerate.py show doc可以列出目标文档的 watched paths即当前提交下需要盯防的实际文件mermaid 图遵循项目约定camelCase ID、节点名无空格、不显式着色、标签中的特殊字符用引号转义文档体积上限 16 KB通用契约docs/generated/design/_meta/prompts/_common.md还要求页面必须带 YAML front-mattergenerated、model、generated_at、source_commit、watched_paths_digest、warning且正文中严禁出现裸{{/{%GitHub Pages 的 Jekyll 会对全文执行 Liquid未闭合的标签曾导致整个站点构建中断五天。阅读路径建议需要每个子系统的文件级清单与职责说明见 docs/generated/design/architecture/module-map.md需要更高层的整体架构导览见 docs/generated/design/architecture/overview.md需要运行时数据流而非构建期依赖视角从 docs/generated/design/pipeline/overview.md 开始沿着编译管线阅读需要生成式文档体系的通用规则front-matter、Liquid 安全、标识符扫描等见 docs/generated/design/_meta/prompts/_common.md。【免费下载链接】slangMaking it easier to work with shaders项目地址: https://gitcode.com/GitHub_Trending/sl/slang创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考