当项目使用Csc任务时,如何强制MSBuild尊重我的解决方案中的项目依赖项?

时间:2015-02-04 16:18:23

标签: c# visual-studio-2010 msbuild wildcard

背景

我目前正在使用VS2010。

MSBuild存在一个已知问题,即从IDE构建时,解决方案中的项目依赖项可以正常工作,但在通过MSBuild构建解决方案时不起作用。

(MSBuild通过Cruise Control .NET运行,如下所示:)

<cb:define buildArgs="/noconsolelogger /p:Configuration=$(configuration);Platform=$(platform) /maxcpucount /v:minimal /nologo" />
<!-- ... -->
<cb:define name="buildSolution"> 
  <msbuild>
    <executable>$(msbuildExe)</executable>
    <workingDirectory>$(localWorkingDirectory)</workingDirectory>
    <projectFile>$(solutionfile)</projectFile>
    <buildArgs>$(buildArgs)</buildArgs>
    <targets>build</targets>
    <timeout>7200</timeout>
    <logger>C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
  </msbuild>
</cb:define>

因此,我通过使用非链接项目引用解决了这个问题:

<!-- Inside ProjectB.csproj -->
<ProjectReference Include="..\ProjectA\ProjectA.vcxproj">
  <LinkLibraryDependencies>false</LinkLibraryDependencies>
  <Project>{GUID}</Project>
  <Name>ProjectA</Name>
</ProjectReference>

在这种情况下,ProjectA是一个SWIG项目,它生成要编译到ProjectB的CS源文件。我完成了这样做:

<ItemGroup>
  <Compile Include="Properties\AssemblyInfo.cs" />
  <Compile Include="..\ProjectA\generated\cs\*.cs" />
</ItemGroup>

但是,虽然这在通过IDE构建时工作正常,但在通过MSBuild构建时它不包含这些文件。我能够通过添加以下内容来实现它:

<ItemGroup>
  <CSFile Include="..\ProjectA\generated\cs\*.cs" />
</ItemGroup>
<Target Name="Build" DependsOnTargets="BeforeBuild">
  <Csc Sources="@(CSFile)" References="@(Reference)" OutputAssembly="$(OutputPath)$(AssemblyName).dll" TargetType="dll" />
</Target>

实际问题:

似乎MSBuild不再尊重项目引用,因此它通常会尝试在ProjectA之前构建ProjectB。

2 个答案:

答案 0 :(得分:1)

看起来问题不是构建顺序,而是评估通配符时。

在我的示例中,在ProjectA生成的.cs文件存在之前评估CSFile标记,因此即使ProjectA首先发生,它们也不包含在构建中。

为了避免这种情况,我必须通过MSBuild从ProjectB手动调用ProjectA,在运行时读取文件列表,然后手动将其附加到Compile集合。

在ProjectB.csproj文件的末尾,我插入了:

<Target Name="BeforeBuild">
  <!-- Force project references to build before this, because otherwise it doesn't... -->
  <MSBuild Projects="@(ProjectReference)"
           Targets="Build"
           BuildInParallel="false"
           Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration);%(_MSBuildProjectReferenceExistent.SetPlatform)"
           ContinueOnError="false" />
  <CreateItem Include="..\ProjectA\generated\$(Platform)\$(Configuration)\cs\*.cs">
    <Output ItemName="Compile" TaskParameter="Include" />
  </CreateItem>
  <CreateItem Include="..\ProjectA\generated\$(Platform)\$(Configuration)\cs\*.cs">
    <Output ItemName="GeneratedCS" TaskParameter="Include" />
  </CreateItem>
  <Message Text="Generated .cs files...%0d    @(GeneratedCS->'%(Filename)%(Extension)','%0d    ')" Importance="high" />
</Target>

这会将所有生成的.cs文件添加到项目中,并将所有名称打印到控制台。

答案 1 :(得分:0)

看起来SWIG项目根本无法由MSBuild编译,但您可以使用Visual Studio本身使用SWIG编译解决方案。请注意,您必须在Cruise Control构建服务器上安装Visual Studio + SWIG,并以某种方式让Cruise Control使用正确的Devenv Command Line Switches来呼叫devenv.exe

后台:在Visual Studio中,大多数项目文件格式都兼具:

  1. Visual Studio可以理解的项目文件,可能使用像SWIG这样的Visual Studio插件
  2. MSBuild理解的MSBuild文件。
  3. 这包括csprojvcxproj和其他许多内容。但是,某些项目类型(如安装项目(vdproj)仅支持上述(1) - 而SWIG也似乎也是如此。