修改 MSBuild 和 Visual Studio 中引用项目的 DefineConstants

本文关键字:引用 项目 DefineConstants Studio MSBuild Visual 修改 | 更新日期: 2023-09-27 18:31:36

我有一个解决方案,其中包含一个Windows Phone类库项目,BaseProj和几个引用该项目,项目 A,B等的WP项目。

假设项目 A 需要使用 LocationHelper 类进行编译,但项目 B 应该在没有 ID_CAP_LOCATION 能力的情况下构建,因此在构建 BaseProj 时不应包含 LocationHelper 类。

可以使用条件编译符号来实现这一点,问题是:如何根据我构建项目 A 还是 B 来构建具有适当符号的 BaseProj

经过一些研究,我想出了以下解决方案,在BaseProj.csproj中添加了

<PropertyGroup Condition=" '$(TestProperty)'==true ">
  <DefineConstants>$(DefineConstants);TEST_SYMBOL</DefineConstants>
</PropertyGroup>

在 B.csproj 中,项目参考中的一个属性:

<ProjectReference Include="..'BaseProj'BaseProj.csproj">
  <Project>{...}</Project>
  <Name>BaseProj</Name>
  <Properties>TestProperty=true</Properties>
</ProjectReference>

认为在使用 B 而不是使用 A 构建时应该添加TEST_SYMBOL。当我使用 MSBuild 构建时,这非常有效。另一方面,Visual Studio 完全忽略了这一点,这意味着当我调试和使用构建脚本进行发布构建时,我会得到不同的行为。

如何从 MSBuild Visual Studio 获得我想要的行为?

修改 MSBuild 和 Visual Studio 中引用项目的 DefineConstants

我想出了一个新的解决方案,它适用于MSBuild和Visual Studio。

首先,如果定义了条件编译符号INCLUDE_LOCATION_API,则将 BaseProj 设置为使用位置 api 进行构建。

项目 AB 设置为使用执行 powershell 脚本 pre-build.ps1 的预生成事件进行生成。(请参阅此问题)。

pre-build.ps1 将读取当前项目的清单,以确定它是否具有定位功能(ID_CAP_LOCATION),以及 BaseProj 调试和发布配置是否定义了INCLUDE_LOCATION_API。如有必要,将添加或删除INCLUDE_LOCATION_API。由于这将修改 BaseProj.csproj,因此生成脚本将退出并显示错误代码,以防止生成完成。

当我从VS构建时,如果BaseProj具有正确的配置,它将正常构建。如果配置错误,则会修改 BaseProj.csproj 并且生成失败,但下一个生成将成功。

在我的构建脚本中,我在实际构建之前执行一次 pre-build.ps1,确保项目具有正确的配置。然后执行 MSBuild 并成功生成项目。

我不会考虑这种最佳实践,但它可以完成工作,我不需要考虑在项目之间切换时应该使用什么配置。

这可以通过定义新的项目配置来完成。假设您已经拥有调试和发布配置,并且它们配置了ID_CAP_LOCATION,您可以创建新配置,例如:Debug_No_Location 和 Release_No_Location。这是在Visual Studio的Configuration Manager对话框中完成的。除了项目配置外,还要定义相应的解决方案配置,以便更轻松地从 Visual Studio 生成它。之后,从Debug_No_Location/Release_No_Location配置中删除ID_CAP_LOCATION。

请务必编辑解决方案中的所有项目,并确保中间位置和二进制文件位置与其调试/发布配置不同,否则将遇到在配置之间混合二进制文件的问题,从而使增量生成不可靠。

如果要从 VS IDE 构建两种风格(带位置和不使用),则必须在配置之间手动切换。但是,从命令行可以创建调用 MSBuild 两次的简单脚本.exe。例如:

msbuild MySolution.sln /p:Configuration=Debug
msbuild MySolution.sln /p:Configuration=Debug_No_Location