【问题标题】:MSBuild incorrectly resolves references in custom build targetMSBuild 错误地解析自定义生成目标中的引用
【发布时间】:2015-05-07 23:14:35
【问题描述】:

我必须创建一个自定义 MSBuild 目标,因为我有多个具有命名约定的 CS 文件,并且所有文件(主要是 1-3 个文件)都必须编译到一个程序集中。为简单起见,我们假设每个 DLL 有 1 个文件。这意味着有:

files/file1.cs
files/file2.cs
files/file3.cs

在输出中应该有 File1.dll, File2.dll File3.dll

所以我创建了一个自定义 MSBuild 目标,如下所示:

<ItemGroup>
    <CSFile Include="file\*.cs" Exclude="" />
</ItemGroup>

<ItemGroup>
    <Reference Include="System.dll"/>
    <Reference Include="..\libs\customdll.dll"/>
</ItemGroup>

<Target Name="CompileFiles" Inputs="@(CSFile)" Outputs="$(OutputPath) (CSFile.Filename).dll" >
    <CSC Sources="%(CSFile.Identity)" TargetType="library" OutputAssembly="$(OutputPath)%(CSFile.Filename).dll" References="@(Reference)"/>
</Target>

它在某些时候起作用了,但是现在当我想将一些 Nuget 包连接到它时(它与 NuGet 本身无关,但是当我尝试更改一些引用路径时它出现了)和

<Reference Include="..\libs\customdll.dll"/>

改为

<Reference Include="customdll"/>
  <HintPath>..\libs\customdll.dll</HintPath>
</Reference>

它根本不起作用。看起来 MSBuild 没有正确解析引用,并且只使用“包含”属性中的值。它不检查提示路径、系统路径等。此外,当我尝试将DependsOnTargets="ResolveAssemblyReferences" 添加到Target 时,我会在调用CSC 时看到引用中的完整路径(当@(Reference) 更改为@(ReferencePath) ),但令人惊讶的是,一些基本参考,如 SystemSystem.Core 等似乎被多次包含,编译器抱怨我必须删除重复项。即使我从&lt;ItemGroup&gt;&lt;Reference&gt;.. 中删除它们,错误仍然相同。

所以一般有2种错误。第一个基本上说Metadata fileSystemcould not be found,当我不使用Microsoft.CSharp中常见目标中的ResolveAssemblyReferences目标时,这基本上意味着它无法解析引用,第二个错误是当我使用它并且引用被解析时正确,但以某种方式多次包含库,但仍然无法编译。

知道如何解决这个问题吗?或者,如果没有 VisualStudio 生成的完整工作 CSPROJ,我的 MSBuild 目标应该如何按照某些标准实现 DLL 的目标。

我已经尝试过 MSBuild 工具 4.0、12.0。以及.NET4.0/.NET4.5目标框架的各种组合。

【问题讨论】:

  • Nuget 包预计会加载到“标准”C# 项目中,并基于此假设修改项目文件。在恢复 Nuget 后解开或手动提取 nuget 包(它们只是 zip 文件)。

标签: c# visual-studio msbuild


【解决方案1】:

我想到了三个想法:

1) 尝试使用 Csc 任务中的“AdditionalLibPaths”和“BaseAddress”参数。

2) 如果您说@(ReferencePath) 包含重复项,请删除它们。但不是来自Reference 项目,而是来自ReferencePath,在运行目标ResolveAssemblyReferences 之后。 试试RemoveDuplicates 任务

3) (这将是我的方法)忘记自己运行 csc。创建两个单独的文件(Main.proj 和 FileBuild.proj)并使用标准众所周知的 MSBuld 任务。 (我是从头开始写的,所以可以在这里找到一些类型:P 这只是一个概念)

Main.proj:

<ItemGroup>
  <CSFile Include="file\*.cs" />
</ItemGroup>

<Target Name="CompileFiles">
  <MSBuild Projects="FileBuild.proj" Properties="CsFile=%(CSFile.Identity)" />
</Target>

还有 FileBuild.proj

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
  <PropertyGroup>
    <OutputType>Library</OutputType>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <OutputPath>bin\</OutputPath>
    <AssemblyName>$(CsFile)</AssemblyName>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="System.dll"/>
    <Reference Include="..\libs\customdll.dll"/>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="$(CsFile)" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

当然,您必须在 FileBuild 中设置其他信息(例如将 AssemblyName 更改为仅包含不带扩展名的文件名),或者如果您确实需要输入/输出,则必须从 Main.proj 中的 MSBuild 获取输出。

【讨论】:

  • 这一切都是因为MSDN决定在寻找外部DLL时改变引用路径的优先级?我投票回滚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多