3

我对 MSBuild.exe 和环境变量有疑问。一、开发环境:

代码主要是 C++ 和一些 C#。有超过 5,000 个类、340 个项目和 200 个解决方案排列在一个深度源代码树中。在树的根部和树中的各个其他点都有一个解决方案。我们使用 TFS 并为一系列未来版本维护多个活动分支。每个开发人员都使用本地视图来修改和测试代码。一些开发人员同时在多个分支上工作。有时开发人员会同时从不同的 TFS 分支构建解决方案。

我们使用大约 70 个环境变量来定位共享头文件、库等。在 VS2008 中,我们使用与解决方案文件具有相同基本名称的文件和 .slnenv 的扩展名来定义环境变量。所有变量都是相对于源树的基础定义的。这个 .slnenv 文件由自定义的 VS2008 AddIn 读取,该插件在 VS2008 进程空间中创建环境变量,即

  MyProjectDir=$(SolutionDir)\..\..
  MyRoot=$(MyProjectDir)\..\..
  MyInstallDir=$(MyRoot)\Install
  MySourceDir=$(MyRoot)\Source
  MyUnmanagedSourceDir=$(MySourceDir)\My\Unmanaged
  MyIncludeDirs=$(MyProjectDir);$(MyUnmanagedSourceDir)

此插件无法与 VS2010 一起正常工作,因为 MSBuild 不继承加载解决方案后创建的环境变量。

我的问题是如何将这些环境变量添加到 MSBuild?我发现了两种可行的方法,但不如我们一直使用的 AddIn 方便。

VS2010 可以通过命令脚本启动,该脚本首先在进程空间中设置环境变量,然后启动 VS2010。MSBuild 确实继承了这些环境变量。这是不能令人满意的,因为脚本需要针对可以加载解决方案的各个点进行定制。

我尝试的第二种方法是将环境变量定义为属性表和 .vcxproj 文件中的属性。我们有一个所有 .vcxproj 文件都加载的基本属性表。在该属性表中:

  <PropertyGroup>
    <MyRoot>$(MyProjectDir)\..\..</MyRoot>
    <MyInstallDir>$(MyRoot)\Install</MyInstallDir>
    <MySourceDir>$(MyRoot)\Source</MySourceDir>
    <MyUnmanagedSourceDir>$(MySourceDir)\My\Unmanaged</MyUnmanagedSourceDir>
    <MyIncludeDirs>$(MyProjectDir);$(MyUnmanagedSourceDir)</MyIncludeDirs>
  </PropertyGroup>

然后我可以在每个 .vcxproj 文件中定义基本目录:

  <PropertyGroup>
    <MyProjectDir>..\..</MyProjectDir>
  </PropertyGroup>

此方法使用相对路径名,其中 AddIn 将所有环境变量解析为绝对路径名。我宁愿不必编辑 340 个 .vcxproj 文件,其中“MyProjectDir”的定义会根据项目文件离源根目录的距离而有所不同。到目前为止,我只在一个项目中尝试过这种方法。

我试图修改插件以创建属性而不是环境变量。我尝试使用 ENV2.get_Properties(),但这似乎只适用于 VS2010 中定义的属性,不适用于我定义的属性。

谢谢你,丹·卡里

4

1 回答 1

1

在通过电子邮件讨论后,我们知道 Dan​​ 需要什么,下面的消息可以帮助他解决问题。他同意这可能对其他 SO 成员有所帮助:

啊哈,我现在明白了。

正如我从该主题中所理解的那样 - 您确实只需要构建步骤的所有内容(包含子句的路径,用于解决 dll\exe 依赖关系的构建工具的路径),并且没有常规的开发人员活动依赖于它。这很好,因为我们不需要在第一次加载后与 VStudio 争论不重新初始化环境变量。我们只需要以某种方式为大量 proj 文件编辑和实施您的解决方案;)任务变得更加容易:D

小免责声明 - 我正在路上写这篇文章,并且无法访问完全成熟的开发环境来检查和防弹所有进一步的建议,所以请提前为我将犯的任何错误道歉;)

我想提请您注意一些 msbuild 功能:http: //msdn.microsoft.com/en-us/library/ms164309.aspx

您有预定义的属性,可用于所有脚本和项目,看起来这将帮助您解决第一个问题 - 绝对路径而不是相对路径。这是链接的一小部分摘录,以供进一步参考

$(MSBuildProjectDirectory) - 
The absolute path of the directory where the project file is located, for example, C:\MyCompany\MyProduct.

$(MSBuildProjectFile) - 
The complete file name of the project file, including the file name extension, for example, 
MyApp.proj.

$(MSBuildProjectExtension)
The file name extension of the project file, including the period, for example, .proj.

$(MSBuildProjectFullPath)
The absolute path and complete file name of the project file, for example, C:\MyCompany\MyProduct\MyApp.proj.

$(MSBuildProjectName)
The file name of the project file without the file name extension, for example, MyApp.

所以你应该能够在你的属性表中使用这个定义的属性。现在,使用 msbuild 4.0 工具集(由根脚本元素上的属性ToolsVersion=""定义的工具集)有一个有趣的技巧 Microsoft.Common.Targets定义了 2 个变量以在其之前或之后有条件地导入自定义 msbuild 脚本 CustomBeforeMicrosoftCommonTargetsCustomAfterMicrosoftCommonTargets 你可以使用它以下方式(我认为这可能会帮助您避免编辑所有 proj 文件或至少 - 将编辑减少到非常简化的复制粘贴部分)使用相对路径定义它以包含您的属性表文件

<CustomBeforeMicrosoftCommonTargets>$(MSBuildProjectFile)\ConcreteProjectCustomProperties.propz</CustomBeforeMicrosoftCommonTargets>

请注意,CustomBeforeMicrosoftCommonTargets应该是全局范围的属性,由所有辅助对象继承

如果你正确定义你的ConcreteProjectCustomProperties.propz我认为你可以实现你所需要的。“正确”是您将在其中包含您的全局属性文件(具有相对或绝对路径),然后定义所有项目级属性。

注意:还请注意,稍后定义的属性不可用于参考早期定义您的示例定义$(MyIncludeDirs)参考$(MyProjectDir),但$(MyProjectDir)稍后声明和定义。这可能是由于“示例”和快速搅动该代码,但如果您在生产中以相同的方式定义您的变量 - 它可能会导致细微的错误。

我希望我能正确解决您的问题,并且我的解释将帮助您快速将所有属性从自定义加载项移动到更简单的原生 msbuild 脚本;)

于 2012-09-29T06:23:20.837 回答