MSBuild处理循环依赖项

时间:2012-03-17 20:58:04

标签: c# .net-4.0 msbuild

我是MSBuild的新手。刚刚开始尝试它,两天前,现在我只是测试它。我遇到了这个错误的问题:

"c:\Users\martinslot\Documents\Visual Studio 2010\Projects\MultifileAssembly\SpecializedBuild.xml" (BuildNumberUtil target) (1) ->
  c:\Users\martinslot\Documents\Visual Studio 2010\Projects\MultifileAssembly\SpecializedBuild.xml(4,34): error MSB4006: There is a circular dependency in t
he target dependency graph involving target "BuildNumberUtil".

我的MSBuild脚本如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Target Name="BuildNumberUtil" DependsOnTargets="BuildStringUtil" >
    <Message Text="=============Building modules for NumberUtil============="/>

    <Csc TargetType="Module" Sources="NumberUtil/DoubleUtil.cs; NumberUtil/IntegerUtil.cs" AddModules="/StringUtil/StringUtil"/>
    <Copy SourceFiles="@(NetModules)" DestinationFolder="../Output/Specialized"/>

  </Target>

  <Target Name="BuildStringUtil" DependsOnTargets="BuildNumberUtil" >
    <Message Text="=============Building modules for StringUtil============="/>

    <Csc TargetType="Module" Sources="StringUtil/StringUtil.cs;" AddModules="/NumberUtil/IntegerUtil;/NumberUtil/DoubleUtil"/>
    <Copy SourceFiles="@(NetModules)" DestinationFolder="/Output/Specialized"/>

  </Target>
</Project>

我理解这个问题,实际上我创建了这个小例子,看看MSBuild是否理解并能以某种方式纠正问题。我该如何解决这个问题?

我的问题是两个目标编译依赖于彼此的模块。这里有人有解决方案如何处理MSBuild的这类问题?也许我正在以错误的方式构建它?

3 个答案:

答案 0 :(得分:5)

您根本无法构建具有循环依赖关系的项目。你怎么能?你先建立哪个?这可能有一些深奥的,错综复杂的,不正确的方式,但为什么呢?循环依赖通常表示设计缺陷。修复设计,您不再有循环依赖问题。

答案 1 :(得分:1)

可以在MSBuild和Visual Studio的范围内构建循环模块;但是,这样做的情况非常有限,这样做是有效的。

如果您计划在代码中使用Xaml,那么执行此操作的一个关键方法是删除Sources标记的Csc方面并生成您自己的.response文件它实际上指向您要注入的代码。在Csc代码属性中,您可以在ResponseFiles属性中自行指定此文件。

.response文件中,您可以将应用程序分解为其程序集和netmodule组件,确保始终首先包含核心程序集的文件。通常,Csc标记的属性会直接转换为Csc.exe命令行参数。参数名称并不总是匹配。为了解决问题,最好在引用文件时使用完整的非相对路径(例如,下面的部分.response):

"X:\Projects\Code\C#\Solution Name\InternalName\ProjectName - InternalName\SearchContexts\StringSearchType.cs"
"X:\Projects\Code\C#\Solution Name\InternalName\ProjectName - InternalName\UI\Themes\Themes.cs"
/target:module /out:bin\x86\Debug\InternalName.UI.dll
"X:\Projects\Code\C#\Solution Name\InternalName\ProjectName - InternalName\UI\EditDatabaseImageControl.xaml.cs"
"X:\Projects\Code\C#\Solution Name\InternalName\ProjectName - InternalName\obj\x86\Debug\UI\EditDatabaseImageControl.g.cs"

你会注意到这最终会将你的多组目标合并为一组,并且我自己也包含了xaml生成的代码。这是部分删除Sources方面的部分原因,因为MSBuild任务的Xaml Page生成器部分会自动将信息注入@(编译)集。由于存在调试/发布配置,因此在您定义要使用的响应文件的区域中,我创建了两个版本的响应(因为我使用的是T4模板):

ResponseFiles="$(CompilerResponseFile);InternalName.$(Configuration).response"

如果您打算在代码中包含多个平台,则可能需要C * P响应文件,其中C是配置数(Debug | Release),P是平台数(x86,x64,AnyCpu) )。通过使用生成器,这种解决方案可能只是一种理智的方法。

简短版本:只要您可以保证您只需一步编译就可以创建循环模块。为确保您保持使用Xaml构建步骤为您提供的构建功能,最好的办法是从正常的C#项目开始,并从.Targets创建自己的$(MSBuildToolsPath)\Microsoft.CSharp.targets文件。底部附近的<Import ...标记。您还可能需要辅助csproj用于设计目的,因为使用此变通方法会丢失大部分智能感知(或使用csproj Condition属性,其中目标由您设置的某个标志选择)。您还会注意到某些Xaml编辑器似乎不喜欢绑定到netmodule命名空间,因此如果您绑定到netmodule中的类型,您可能必须在代码隐藏中执行它们(我还没有测试过这方面的解决方法,因为有通常是围绕静态命名空间绑定的方法)

出于某种原因,.baml编译器隐含地理解了.xaml编译的Csc文件,我无法弄清楚它是从哪一个导出的命令参数,或者它只是隐含在设计中。如果我不得不猜测它们是由与您在包含文件列表中包含的内容相关联的g.cs文件推断的。

答案 2 :(得分:0)

观察到Web应用程序(ASP.NET标准Web应用程序或ASP.NET MVC应用程序)发生了这种情况,并且要解决此问题,请在&#34; .csproj&#34;中删除以下行。文件。

<PropertyGroup>
  <BuildDependsOn>
    $(BuildDependsOn);
    Package
  </BuildDependsOn>
</PropertyGroup>