MSBuild doesn't pick up references of the refe

2019-01-14 13:07发布

问题:

I bumped into a strange situation with MSBuild just now. There's a solution which has three projects: LibX, LibY and Exe. Exe references LibX. LibX in its turn references LibY, has some content files, and also references to a third-party library (several pre-built assemblies installed in both GAC and local lib folder). The third-party library is marked as "Copy Local" ("private") and appears in the output of the LibX project, as the LibY's output and LibX's content files do. Now, Exe project's output has LibX project output, content files of the LibX project, LibY project output (coming from LibX), but NO third-party library's assemblies.

Now I worked this around by referencing the third-party library directly in Exe project, but I don't feel this is a "right" solution.

Anyone had this problem before?

回答1:

Yes, I've had that problem, too. Though I'd love to say otherwise, I believe you must include all transitive dependencies as references in your build file.



回答2:

There is a difference in behavior when building with MSBuild (i.e. command line, TFS Build and other tools) compared to building with Visual Studio. The secondary references are not included in the references variable sent into MSBuild compile tasks.

There are several extension points provided by MSBuild to change how references are to be resolved. I have successfully used AfterResolveReference to fix this issue for some of my projects - I have posted more info about the background on my blog.

The workaround is to add the following code into you vbproj or csproj files

  <Target Name="AfterResolveReferences">
    <!-- Redefine referencepath to add dependencyies-->
    <ItemGroup>
     <ReferencePath Include="@(ReferenceDependencyPaths)">
     </ReferencePath>
    </ItemGroup> 
  </Target>

Microsoft has stated that this is a won't fix on Connect



回答3:

You can actually go into the Microsoft.CSharp.targets or Microsoft.VisualBasic.targets file (located in the framework directory, usually C:\Windows\Microsoft.NET\Framework\v3.5) and modify the csc or vbc task parameters to include additional reference dependencies. In the file (VB targets, line 166; C# targets, line 164) change:\

References="@(ReferencePath)"

to

References="@(ReferencePath);@(ReferenceDependencyPaths)"

This might cause other issues depending on how complicated things are and it may play tricks with the Visual Studio inproc compiler, but it's the only way to do it in MSBuild that I've found.



回答4:

josant's answer almost worked for me; I kept getting an error in Visual Studio when I tried that:

A problem occurred while trying to set the "References" parameter for the IDE's in-process compiler. Error HRESULT E_FAIL has been returned from a call to a COM component

The solution to my problem was to put a condition on the ItemGroup, like this:

<Target Name="AfterResolveReferences">
  <!-- Redefine referencepath to add dependencies-->
  <ItemGroup Condition=" '$(BuildingInsideVisualStudio)' != 'true' ">
    <ReferencePath Include="@(ReferenceDependencyPaths)"></ReferencePath>
  </ItemGroup>
</Target>

That caused Visual Studio to ignore the reference change completely, and the build works fine locally and on the build server.



回答5:

I've combined Alex Yakunin's solution with one that will also copy native dll's.



回答6:

The AfterResolveReferences method fails if you've got a directed graph not a tree with a "trying to deploy different copies of the dll" error. (cf. How to configure msbuild/MSVC to deploy dependent files of dependent assemblies)