我对MSBuild.exe和环境变量有疑问。一,开发环境:
代码主要是带有一些C#的C ++。在深源树中安排了5,000多个类,340个项目和200个解决方案。树的根部和树中的其他各点都有一个解决方案。我们使用TFS并为一系列未来版本维护多个活动分支。每个开发人员都使用本地视图来修改和测试代码。一些开发人员同时在多个分支上工作。有时开发人员会同时从不同的TFS分支构建解决方案。
我们使用大约70个环境变量来定位共享头文件,库等。在VS2008中,我们使用了一个与解决方案文件具有相同基本名称的文件和.slnenv的扩展名来定义环境变量。所有变量都是相对于源树的基础定义的。此.slnenv文件由自定义VS2008 AddIn读取,该自定义VS2008 AddIn在VS2008进程空间中创建环境变量,即
MyProjectDir=$(SolutionDir)\..\..
MyRoot=$(MyProjectDir)\..\..
MyInstallDir=$(MyRoot)\Install
MySourceDir=$(MyRoot)\Source
MyUnmanagedSourceDir=$(MySourceDir)\My\Unmanaged
MyIncludeDirs=$(MyProjectDir);$(MyUnmanagedSourceDir)
此AddIn无法与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”的定义会根据项目文件存在的源根目录的距离而有所不同。到目前为止,我只在一个项目中尝试过这种方法。
我尝试修改AddIn来创建Properties而不是Environment Variables。我尝试使用ENV2.get_Properties(),但这似乎只适用于在VS2010中定义的属性,而不适用于我定义的属性。
谢谢你, 丹卡里
答案 0 :(得分:1)
通过电子邮件讨论之后,我们想出了Dan需要什么,以及以下消息可以帮助他解决问题。他同意这可能对其他SO成员有所帮助:
<啊>啊哈,我现在明白了。正如我从该主题中所理解的那样 - 你真的需要所有这些东西只用于构建步骤(include子句的路径,构建工具的路径来解析dll \ exe依赖),并且没有常规的开发人员活动依赖于它。 这很好,因为在第一次加载后我们不需要与VStudio争论不重新启动env变速器。我们只需要以某种方式编辑和实现大量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脚本 CustomBeforeMicrosoftCommonTargets 和 CustomAfterMicrosoftCommonTargets 您可以通过以下方式使用它(我认为它可以帮助您避免编辑所有proj文件或至少 - 减少编辑到非常简化的复制粘贴部分) 使用相对路径定义它以包含属性表文件
<CustomBeforeMicrosoftCommonTargets>$(MSBuildProjectFile)\ConcreteProjectCustomProperties.propz</CustomBeforeMicrosoftCommonTargets>
请注意 CustomBeforeMicrosoftCommonTargets 应该是全局范围的属性,以便所有辅助属性继承
如果你正确定义 ConcreteProjectCustomProperties.propz ,我认为你可以实现你所需要的。 “正确”是您将包含全局属性文件(具有相对或绝对路径),然后定义所有项目级属性。
NB: 另请注意,以后定义的属性不可用于早期定义的参考 您的示例定义 $(MyIncludeDirs)并引用 $(MyProjectDir),但 $(MyProjectDir)稍后声明并定义。 这可能是由于“采样”和快速搅拌代码,但如果你在生产中以相同的方式定义你的变量 - 它可能会导致细微的错误。
我希望我能正确解决您的问题,我的解释将帮助您快速将所有属性从自定义加载项移动到更简单的本机msbuild脚本;)