<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://wiki2.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=MDCS%E4%BB%93%E5%BA%93%E5%B8%83%E5%B1%80%E4%B8%8E%E6%9E%84%E5%BB%BA%E9%93%BE</id>
	<title>MDCS仓库布局与构建链 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://wiki2.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=MDCS%E4%BB%93%E5%BA%93%E5%B8%83%E5%B1%80%E4%B8%8E%E6%9E%84%E5%BB%BA%E9%93%BE"/>
	<link rel="alternate" type="text/html" href="https://wiki2.lessokaji.com/index.php?title=MDCS%E4%BB%93%E5%BA%93%E5%B8%83%E5%B1%80%E4%B8%8E%E6%9E%84%E5%BB%BA%E9%93%BE&amp;action=history"/>
	<updated>2026-05-16T17:14:32Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki2.lessokaji.com/index.php?title=MDCS%E4%BB%93%E5%BA%93%E5%B8%83%E5%B1%80%E4%B8%8E%E6%9E%84%E5%BB%BA%E9%93%BE&amp;diff=1039&amp;oldid=prev</id>
		<title>Artheru：​Initial bilingual draft (auto-published)</title>
		<link rel="alternate" type="text/html" href="https://wiki2.lessokaji.com/index.php?title=MDCS%E4%BB%93%E5%BA%93%E5%B8%83%E5%B1%80%E4%B8%8E%E6%9E%84%E5%BB%BA%E9%93%BE&amp;diff=1039&amp;oldid=prev"/>
		<updated>2026-05-16T14:00:17Z</updated>

		<summary type="html">&lt;p&gt;Initial bilingual draft (auto-published)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 概述 / Overview ==&lt;br /&gt;
MDCS 由 7 个并列仓库组成；按依赖关系自底向上构建。本页详述各仓库职责、产物、构建顺序、引用程序集机制。&lt;br /&gt;
&lt;br /&gt;
MDCS consists of 7 sibling repositories built bottom-up by dependency. This page details responsibilities, outputs, build order, and the reference-assembly mechanism.&lt;br /&gt;
&lt;br /&gt;
== 仓库一览 / Repositories ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 仓库 / Repo !! 解决方案 / Solution !! 产物 / Output !! 角色 / Role&lt;br /&gt;
|-&lt;br /&gt;
| `D:\src\Fundamentals\` || Fundamentals.sln || FundamentalLib.dll, FundamentalLib2.dll, LessokajiProtect.dll, LessokajiLicencer.dll || 通用类型 + IPC + 日志 + 许可&lt;br /&gt;
|-&lt;br /&gt;
| `D:\src\LessokajiWeaver\` || LessokajiWeaver.sln || LessokajiWeaver.Fody.dll, LessokajiWeaverUtilities.dll || 编译期 IL 注入（Fody）&lt;br /&gt;
|-&lt;br /&gt;
| `D:\src\CycleGUI\` || CycleGUI.sln || CycleGUI.dll, libVRender.dll（C++/Vulkan）, webVRender（WASM）|| 懒协程 UI 框架&lt;br /&gt;
|-&lt;br /&gt;
| `D:\src\M2\` || M2.sln || MedullaCore.dll, OfficialPlugins/*.dll || 硬件抽象内核 + 一方插件（雷达 / 相机 / Cart）&lt;br /&gt;
|-&lt;br /&gt;
| `D:\src\Detour\` || Detour.sln || Detour.exe（.NET 4.8 GUI），DetourLite.exe（.NET 8 headless），DetourCore.dll || 定位系统&lt;br /&gt;
|-&lt;br /&gt;
| `D:\src\Clumsy\` || Clumsy.sln || ClumsyCore.dll, ClumsyDance.dll || 车载自动驾驶&lt;br /&gt;
|-&lt;br /&gt;
| `D:\src\Simple\` || Simple.sln || SimpleCore.dll, SimpleComposer.exe（Nancy HTTP）|| 车队管理&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 依赖图 / Dependency graph ==&lt;br /&gt;
&lt;br /&gt;
                 Fundamentals ◄────────── (everything)&lt;br /&gt;
                       ▲&lt;br /&gt;
                       │&lt;br /&gt;
                    CycleGUI ◄─ Detour ─── (M2, Clumsy, Simple use indirectly)&lt;br /&gt;
                       ▲           ▲&lt;br /&gt;
                       │           │&lt;br /&gt;
                       M2 ◄────── Clumsy ◄── Simple&lt;br /&gt;
                                     ▲&lt;br /&gt;
                                     └─── LessokajiWeaver (build-time only)&lt;br /&gt;
&lt;br /&gt;
== 构建顺序 / Build order ==&lt;br /&gt;
自底向上 / Bottom-up:&lt;br /&gt;
&lt;br /&gt;
# '''LessokajiWeaver''' — 构建时依赖（Fody 织入）&lt;br /&gt;
# '''Fundamentals''' — 用 Weaver&lt;br /&gt;
# '''CycleGUI''' — 用 Fundamentals；需 libVRender C++ 先构建&lt;br /&gt;
# '''M2 / MedullaCore''' — 用 Fundamentals + CycleGUI&lt;br /&gt;
# '''M2 / OfficialPlugins/\*''' — 用 MedullaCore&lt;br /&gt;
# '''Detour / DetourCore''' — 用 Fundamentals + CycleGUI&lt;br /&gt;
# '''Clumsy / ClumsyCore''' → '''ClumsyDance'''&lt;br /&gt;
# '''Simple / SimpleCore''' → '''SimpleComposer'''&lt;br /&gt;
&lt;br /&gt;
每个仓库独立 .sln；可单独 `dotnet build` / 在 IDE 打开。&lt;br /&gt;
Each repo has its own .sln; independently buildable.&lt;br /&gt;
&lt;br /&gt;
== 引用程序集机制 / Reference-assembly mechanism ==&lt;br /&gt;
=== 概念 / Concept ===&lt;br /&gt;
每个核心 DLL 同时产生一个 ''仅引用''的程序集 `Ref&amp;lt;Name&amp;gt;.dll`，通过 [[https://github.com/JetBrains/Refasmer refasmer]] 工具生成。&lt;br /&gt;
&lt;br /&gt;
Each core DLL also emits a '''reference-only assembly''' (`Ref&amp;lt;Name&amp;gt;.dll`) via refasmer.&lt;br /&gt;
&lt;br /&gt;
例如 `MedullaCore.dll` → `RefMedullaCore.dll`：后者只含 public/protected API 签名，没有方法体。&lt;br /&gt;
E.g. `MedullaCore.dll` → `RefMedullaCore.dll`: signature-only.&lt;br /&gt;
&lt;br /&gt;
=== 为什么 / Why ===&lt;br /&gt;
插件 csproj ''引用'' `Ref&amp;lt;Name&amp;gt;.dll`，不引用 impl DLL ：&lt;br /&gt;
Plugin csproj references the `Ref` assembly:&lt;br /&gt;
&lt;br /&gt;
* 插件构建不会拉入 Costura 织入的传递依赖（FodyWeavers.xml + LessokajiWeaver 等）。&lt;br /&gt;
* 公共 API 由 Ref assembly 固定 —— `internal` 成员对插件不可见，强制良好的封装。&lt;br /&gt;
* 插件 DLL 体积小、加载快。&lt;br /&gt;
&lt;br /&gt;
* No Costura transitives pulled into plugin builds.&lt;br /&gt;
* Public API frozen by the Ref assembly; `internal` hidden from plugins — enforced encapsulation.&lt;br /&gt;
* Smaller plugin DLLs, faster load.&lt;br /&gt;
&lt;br /&gt;
=== 生成 / Generation ===&lt;br /&gt;
每个核心 csproj 有 ''AfterBuild'' 目标调 refasmer，输出到 `&amp;lt;repo&amp;gt;/tools/Ref&amp;lt;Name&amp;gt;.dll`：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;Target Name=&amp;quot;GenerateRefAssembly&amp;quot; AfterTargets=&amp;quot;Build&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;Exec Command=&amp;quot;refasmer $(TargetPath) -o $(SolutionDir)tools\Ref$(AssemblyName).dll&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/Target&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
详见 `D:\src\M2\OfficialPlugins\CartActivator\CartActivator.csproj:47-54`。&lt;br /&gt;
&lt;br /&gt;
=== 更新流程 / Update flow ===&lt;br /&gt;
改动 `MedullaCore` 公共面 → 重新 build → 同时 ''rebuild Ref assembly'' → 把 ''两个 DLL''（impl + ref）都提交到仓库。&lt;br /&gt;
&lt;br /&gt;
Change `MedullaCore` public surface → build → rebuild Ref → commit '''both'''.&lt;br /&gt;
&lt;br /&gt;
【注意】 插件 csproj 用旧 `Ref` 构建 ''不会出错''，但运行时调新成员会 `MissingMethodException`。&amp;lt;br&amp;gt;&lt;br /&gt;
A plugin built against the old Ref doesn't fail to compile but throws `MissingMethodException` at runtime when calling the new member.&lt;br /&gt;
&lt;br /&gt;
== `tools/` 目录约定 / `tools/` directory convention ==&lt;br /&gt;
每个仓库根有 ''`tools/`'' 子目录，存放 ''其它仓库的 Ref assembly'' + 二进制工具（refasmer.exe 等）。插件 csproj 通过相对 HintPath 引用 ：&lt;br /&gt;
&lt;br /&gt;
Each repo root has a `tools/` subdirectory containing reference assemblies from other repos + binary tools (refasmer.exe). Plugin csproj uses relative HintPaths:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;Reference Include=&amp;quot;RefFundamentalLib&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;HintPath&amp;gt;..\tools\RefFundamentalLib.dll&amp;lt;/HintPath&amp;gt;&lt;br /&gt;
&amp;lt;/Reference&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
【发现】 `..\tools\` 是 ''仓库一致''约定 —— 每个 MDCS 插件 csproj 都这么写。不要改成 NuGet 包；现有工具链不支持。&lt;br /&gt;
The `..\tools\` HintPath pattern is repo-wide. Don't try to NuGet-ify it.&lt;br /&gt;
&lt;br /&gt;
== Costura.Fody 胖 DLL 打包 / Fat DLL packaging ==&lt;br /&gt;
插件 / 客户端 exe 用 ''Costura.Fody''把所有依赖打到一个 DLL 的 base64 资源里。最终客户只需要 1 个文件。&lt;br /&gt;
Plugins / client exes use Costura.Fody to embed all deps as base64 resources in one DLL. Customer deploys one file.&lt;br /&gt;
&lt;br /&gt;
注意 ：&lt;br /&gt;
* '''核心 DLL（MedullaCore, ClumsyCore, ...）不用 Costura'''。它们要被多个插件 ''共载''，loose DLL 必要。&lt;br /&gt;
* '''插件 / 顶层 exe 用 Costura'''。简化部署。&lt;br /&gt;
&lt;br /&gt;
Note: '''Core DLLs (MedullaCore, ClumsyCore, ...) must not use Costura''' — they need to be shared between plugins. '''Plugins / top-level exes use Costura''' for deployment simplicity.&lt;br /&gt;
&lt;br /&gt;
== LessokajiWeaver 编译期注入 / Compile-time IL injection ==&lt;br /&gt;
Fody 加上 `LessokajiWeaver.Fody.dll` 在编译后做 IL 重写。当前生效的规则 ：&lt;br /&gt;
Fody + `LessokajiWeaver.Fody.dll` rewrites IL post-compile. Active rules:&lt;br /&gt;
&lt;br /&gt;
* `[AsInitParam] / [AsUpperIO] / [AsLowerIO]` 字段 → 自动同步 DObject 的 property&lt;br /&gt;
* `[ReplaceWithCompileInfo]` 字段 → 编译时戳 + git 哈希&lt;br /&gt;
* `[Translatable] / [T(zh=, en=)]` 字段 → getter 按 `CultureInfo.CurrentUICulture` 分派&lt;br /&gt;
&lt;br /&gt;
详见 [[Special:MyLanguage/LessokajiWeaver编译后处理工具|LessokajiWeaver编译后处理工具]] 与 [[Special:MyLanguage/如何使用LessokajiWeaver的多语言功能|如何使用LessokajiWeaver的多语言功能]]。&lt;br /&gt;
&lt;br /&gt;
== 跨平台 / Cross-platform ==&lt;br /&gt;
* 多数仓库 .NET 6/8，部分 .NET Framework 4.8（旧 lidar driver / Detour.exe）。&lt;br /&gt;
* Linux 支持 ：Medulla, Detour (Lite), Clumsy, SimpleComposer 都可跑。&lt;br /&gt;
* CycleGUI 的 libVRender 在 Linux 上有 build；Windows 是主战场。&lt;br /&gt;
&lt;br /&gt;
== 仓库间集成测试 / Cross-repo integration ==&lt;br /&gt;
没有单一 mega-solution。集成测试靠：&lt;br /&gt;
There's no monolithic solution. Integration tests rely on:&lt;br /&gt;
&lt;br /&gt;
# 改动核心后重 build 所有受影响插件。&lt;br /&gt;
# 在仿真车 SimpleComposer 里跑完整任务序列。&lt;br /&gt;
# `D:\src\Fundamentals\Test\` 单元测试（DObject + DLog 等关键基础）。&lt;br /&gt;
&lt;br /&gt;
== 仓库镜像 / Repo mirror ==&lt;br /&gt;
* 内部 git：`git.lessokaji.com`（私有）。&lt;br /&gt;
* 下载站：`dl.lessokaji.com`（编译产物）。&lt;br /&gt;
* 认证 / 许可：`auth.lessokaji.com`。&lt;br /&gt;
&lt;br /&gt;
== 相关页面 / See also ==&lt;br /&gt;
* [[Special:MyLanguage/核心开发指南|核心开发指南]]&lt;br /&gt;
* [[Special:MyLanguage/MDCS跨切面约定|MDCS跨切面约定]]&lt;br /&gt;
* [[Special:MyLanguage/MDCS平台发布流程|MDCS平台发布流程]]&lt;br /&gt;
* [[Special:MyLanguage/LessokajiWeaver编译后处理工具|LessokajiWeaver编译后处理工具]]&lt;br /&gt;
* [[Special:MyLanguage/Medulla软件架构|Medulla软件架构]]&lt;br /&gt;
* [[Special:MyLanguage/Detour软件架构|Detour软件架构]]&lt;br /&gt;
* [[Special:MyLanguage/Simple软件架构|Simple软件架构]]&lt;br /&gt;
&lt;br /&gt;
[[Category:开发手册]]&lt;br /&gt;
[[Category:二次开发相关说明]]&lt;/div&gt;</summary>
		<author><name>Artheru</name></author>
	</entry>
</feed>