MSBuild:避免重复构建任何 CPU 项目引用

Posted

技术标签:

【中文标题】MSBuild:避免重复构建任何 CPU 项目引用【英文标题】:MSBuild: Avoiding repeatedly building Any CPU project references 【发布时间】:2020-01-02 22:57:24 【问题描述】:

我们有一个包含大约 150 个项目的视觉工作室解决方案。其中 5 个是可执行文件,另外 95 个是可执行文件引用的库或测试项目等。

我们的自动化 CI 通过 MSBuild 为 x86 和 x64 构建解决方案。但是,由于库总是构建 Any CPU,因此应该可以构建完整的解决方案 Any CPU,然后为每个平台再次构建可执行文件。

在 Visual Studio 中,我在配置管理器中有 3 个解决方案平台,x86/x64 平台仅构建 5 个可执行文件。在VS中,如果我先构建Any CPU,然后我可以构建其他平台。

但是,我无法通过 msbuild 让这个构建工作。构建 Any CPU 后,我构建了 x86,它无法解析项目引用。也就是说,库二进制文件的 /reference: 参数没有传递到 csc.exe,因此 csc 失败,因为它找不到二进制文件所依赖的任何类型。

如何让它与 MSBuild 一起使用? Visual Studio 如何知道在 bin\Any CPU 中查找,而 MSBuild 却不知道?

【问题讨论】:

嗨,it can't resolve Project References. 是什么意思?我在我的机器上进行了测试,但是构建可以成功,但会出现 MSB3270 mismatch 之类的警告...... @Lance Li-MSFT。当我查看在 msbuild 期间发出的 csc 命令时,项目二进制文件没有 /reference: 参数。并且可执行的 csproj 没有构建,因为它找不到它所依赖的各种类型。 【参考方案1】:

构建 Any CPU 后,我构建 x86,但无法解析项目 参考。也就是说,/reference: 库二进制文件的参数 没有传递到 csc.exe,因此 csc 失败,因为它找不到 二进制文件所依赖的任何类型。

我无法重现此问题。每次如果 CoreCompile 目标执行,它会将引用的 projectName.dll 传递给我机器中的 csc.exe。为此,请确保您使用这种格式的引用来引用项目 dll:

   <ProjectReference Include="..\ClassLibraryOne\ClassLibraryOne.csproj">
      <Project>xxx</Project>
      <Name>ClassLibraryOne</Name>
    </ProjectReference>

并确保您没有将 Condition="'$(Platform)' == 'AnyCPU'" 之类的条件添加到 ProjectReference 元素中。

Visual Studio 如何知道在 bin\Any CPU 中查找,但 MSBuild 知道 不是吗?

这是因为配置管理器。假设我有这样的配置设置:

我在解决方案中有一个可执行文件和两个库项目。可执行文件依赖于这两个库。

1.在vs中,当我将switch box设置为Any CPU构建解决方案时,它实际上构建了平台Any CPU的三个项目。

2.在vs中,当我构建switch box设置为x86的解决方案时,它实际上构建了平台Any CPU的两个库项目,并构建了x86平台的可执行文件。

3.当我在 msbuild 命令行中使用 Any CPU 构建解决方案时,它的工作原理与 #1 相同。

4.当我用x86构建executable project时,它实际上是在x86平台上构建了三个项目。这是VS和命令行最大的区别。

为了区别,你应该知道VS中的开关框代表Solution Platform而不是Project Platform。所以在VS中,当我将开关框设置为x86时,它知道对于x86解决方案平台,它应该在Any CPU中构建库,在X86中构建可执行文件。

但是,当您在命令行中构建项目时,例如:msbuild xx.csproj /p:xxx=x86。它只指定项目平台x86。而且由于 msbuild 可以发现这个项目依赖于两个库项目,它也会在 x86 中构建库项目。 (有关解决方案配置和平台的信息存储在 xx.sln 文件中,而不是任何 xx,csproj 文件中

如何让它与 MSBuild 一起使用?

因为它在您第一次构建解决方案 Any CPU 然后在五个项目 X86 时在 VS 中工作。我认为您可以修改配置管理器。根据您的要求,您应该确保解决方案平台和项目平台之间的关系是:

1.
For solution: Debug Any CPU
For Library projects: Debug Any CPU
For executable projects: Debug Any CPU

2.
For solution: Debug x86
For Library projects: Debug Any CPU
For executable projects: Debug x86

3.
For solution: Debug x64
For Library projects: Debug Any CPU
For executable projects: Debug x64

不要忘记在发布模式下检查设置。那么我认为它会满足您的需求:as the libraries are always built Any CPU, it should be possible to build the full solution Any CPU, and then build the executables again for each platform.。您应该始终使用解决方案文件而不是项目文件进行构建:

msbuild xx.sln /p:Platform="Any CPU" ...
msbuild xx.sln /p:Platform=x86 ...
msbuild xx.sln /p:Platform=x64 ...

因为 Any CPU 平台的库将在您首次使用 Any CPU 构建时构建。在第二次和第三次时,msbuild 只会编译和构建每个平台的可执行项目。它会跳过再次构建库以节省时间。

希望对你有所帮助,如果我有什么误解,请随时纠正我:)

【讨论】:

以上是关于MSBuild:避免重复构建任何 CPU 项目引用的主要内容,如果未能解决你的问题,请参考以下文章

CMake + MSBuild 项目显示重复条目

当项目以 3.5 为目标时,Msbuild 4.0 是不是引用 System.Core 4.0?

VS/MSBUILD:复制子项目的输出文件,不添加对exe的引用

如何使用msbuild首先构建依赖项目

使用 msbuild (CLI) 编译时程序集引用损坏

为啥 Visual Studio 2010 (msbuild?) 构建速度不快?