当使用TransformOnBuild时,不能在T4模板中引用依赖程序集
本文关键字:引用 程序集 依赖 T4 TransformOnBuild 不能 | 更新日期: 2023-09-27 17:54:35
我们尝试在Visual Studio 2010 (SP1)中使用T4来为基于我们现有的一些c#类的另一种语言构建脚本。我的期望是:
- 模板需要加载我们现有的程序集,并使用该程序集中某个命名空间中的对象。
- 转换需要在每个开发机器和构建服务器上的每个构建上运行,而不需要任何额外的安装。
- (1)和(2)需要协同工作。
(1)相当简单:
<#@ assembly name="$(TargetDir)RequiredProject.dll" #>
<#@ import namespace="RequiredProject.RequiredNamespace" #>
使用$(TargetDir)
宏允许我使用完全限定的UNC路径引用dll(根据这里找到的指令)。
(2)有点迂回,但我认为我已经解决了:我在另一台机器上安装了所需的文本转换sdk,并将所需的。targets和。dll复制到我的解决方案中的一个文件夹中,然后更新我的。csproj文件以引用本地的。targets文件。
(3)是我遇到问题的地方。当需要在转换之前构建引用程序集时,<TransformOnBuild>true</TransformOnBuild>
属性似乎不能很好地发挥作用。每次在使用引用程序集的构建上启用转换时,都会得到以下错误:
Compiling transformation: Metadata file '$(TargetDir)RequiredProject.dll' could not be found.
但是,我使用了与(1)中使用的相同的汇编指令来引用汇编。事实上,直接转到.tt模板并保存它仍然会产生预期的输出——它只是在"构建"步骤中不起作用。我做错了什么,或者有一种方法来确保模板转换发生之后他们所依赖的程序集被构建?(或者,更简单地说,模板转换发生在最后?)
不幸的是,msbuild T4主机还不支持在程序集名称中嵌入宏或msbuild变量。
然而,它确实支持Windows环境变量"%foo%",所以尽管它意味着一些机器级别的设置,你可以得到一些跨ide和构建时间转换的工作
我的理解是Visual Studio 2013将最终解决这个问题,但这对我没有多大帮助,因为我还在使用Visual Studio 2012。经过一番努力,我终于找到了解决办法。
在具有要运行的模板的项目中,在项目属性页的Build Events选项卡上添加以下内容作为预构建步骤。
set textTransformPath="%CommonProgramFiles(x86)%'Microsoft Shared'TextTemplating'$(VisualStudioVersion)'TextTransform.exe"
if %textTransformPath%=="'Microsoft Shared'TextTemplating'$(VisualStudioVersion)'TextTransform.exe" set textTransformPath="%CommonProgramFiles%'Microsoft Shared'TextTemplating'$(VisualStudioVersion)'TextTransform.exe"
set ProjectDir=$(ProjectDir)
%textTransformPath% "%ProjectDir%StringGenerator.tt"
前两行处理在32位和64位系统上定位TextTransform.exe
的差异。第三行是关键。我需要模板中项目位置的路径,所以我设置了一个本地环境变量,等于构建的$(ProjectDir)
属性的值。在我的模板中,只需使用以下代码:
var projectDir = Environment.GetEnvironmentVariable("ProjectDir");
我的问题解决了
我创建了一个单独的解决方案,其中包含我需要的引用程序集。我让我的buildscript首先构建参考解决方案,然后转换模板,然后构建包含生成代码的解决方案。
如果您想在T4脚本中使用宏引用依赖程序集,并在构建时使文本模板成功,那么您必须使用项目属性。
在你的项目中:
<Import Project="$(ProgramFiles)'Microsoft Visual Studio'2017'Enterprise'MSBuild'Microsoft'VisualStudio'v15.0'TextTemplating'Microsoft.TextTemplating.targets" /> <PropertyGroup> <T4ProjectDir>$(ProjectDir)</T4ProjectDir> </PropertyGroup> <ItemGroup> <T4ParameterValues Include="T4ProjectDir"> <Value>$(T4ProjectDir)</Value> <Visible>false</Visible> </T4ParameterValues> </ItemGroup>
文本模板环境的路径可能不同。
然后使用$(T4ProjectDir),就像你在文本模板中使用任何其他宏一样。
或者您也可以简单地引用现有的属性:
<ItemGroup> <T4ParameterValues Include="ProjectDir"> <Value>$(ProjectDir)</Value> <Visible>false</Visible> </T4ParameterValues> </ItemGroup>