如何在MSBuild中为DLL添加外部.cs文件并支持增量构建?
解决方案:实现动态添加文件的增量构建并保留DLL包含逻辑
针对你遇到的问题——动态添加的.cs文件在增量构建时跳过编译后无法纳入DLL,结合你的场景(自定义Target在NuGet包中全局运行,无需项目额外代码),可以通过以下几种方式解决:
方案一:在项目评估阶段添加Compile项(优先推荐)
如果$(_TargetFolder)的路径在项目加载时即可确定(比如是NuGet包内的固定路径、项目目录下的已知文件夹),直接在NuGet包的.props文件中添加Compile项,而非在Target中动态添加:
<ItemGroup Condition=" '$(Generate)' != '' "> <Compile Include="$(_TargetFolder)\**\*.cs" /> </ItemGroup>
原理说明
这种方式会在项目评估阶段就将目标文件夹的.cs文件纳入编译列表,MSBuild的默认增量编译机制会自动跟踪每个文件的变更:
- 未修改的文件不会重新编译,对应的
.obj文件会被复用 - 链接阶段(C#编译器的
csc.exe会完成编译+链接)会自动将所有有效的.obj文件合并到最终DLL中,无需额外操作
方案二:为自定义Target添加增量构建标记
如果$(_TargetFolder)是构建过程中动态生成的(比如依赖其他Target生成文件),则需要为你的自定义Target添加输入输出规则,确保仅在文件变更时重新执行,同时让MSBuild持续跟踪这些文件的编译产物:
<Target Name="AddGenFolderFilesToCompile" BeforeTargets="CoreCompile" Condition=" '$(Generate)' != '' " Inputs="$(_TargetFolder)\**\*.cs" Outputs="$(IntermediateOutputPath)GenFolderFiles.Tracker"> <ItemGroup> <Compile Include="$(_TargetFolder)\**\*.cs" /> </ItemGroup> <!-- 创建跟踪文件,标记Target执行状态 --> <Touch Files="$(IntermediateOutputPath)GenFolderFiles.Tracker" AlwaysCreate="true" /> </Target>
原理说明
Inputs指定目标文件夹下的所有.cs文件,只有当这些文件有变更时,Target才会重新执行Outputs使用一个全局跟踪文件,确保MSBuild能识别Target的执行状态- 即使Target跳过执行,MSBuild在后续构建中仍会保留之前添加的Compile项跟踪,复用已生成的
.obj文件,确保DLL包含未修改的文件内容
替代方案:预编译独立DLL
如果上述增量构建方案无法满足需求,可以将目标文件夹的.cs文件单独编译成一个DLL,再让主项目引用这个DLL:
- 在NuGet包中添加一个专用的项目文件(比如
GenFiles.csproj),配置为编译$(_TargetFolder)下的.cs文件 - 在NuGet包的.targets文件中,添加对该项目的构建依赖,并让主项目引用生成的DLL
这种方式的优势是:
- 可以独立控制这些文件的增量构建,主项目无需参与其编译过程
- 主项目仅需引用预编译的DLL,大幅降低整体构建时间
内容的提问来源于stack exchange,提问作者Daniel Patrício
相关产品推荐
相关产品推荐

