关于msbuild:Build for .NET 4和.NET 4.5 – 参考NuGet包怎么样?

Build for .NET 4 and .NET 4.5 - what about referenced NuGet packages?

我有一个脚本可以构建一个项目,输出.NET 4.0程序集。

该项目包括Nuget的NLOG。因此项目文件中的引用如下所示:

1
2
3
4
5
6
7
<Reference Include="NLog">
  <HintPath>..\packages
Log.2.0.1.2\lib
Log
et40
Log.dll</HintPath>
</Reference>

我的packages.config如下所示:

1
2
3
<packages>
  <package id="NLog" version="2.0.1.2" targetFramework="net40" />
</packages>

这个项目将在nuget上发布,现在我想更新构建脚本,以便它也构建.NET 4.5程序集。

现在,我知道我可以将/p:TargetFrameworkVersion="4.5"传递给msbuild,并使其以.NET 4.5为目标-但这仍将构建.NET 4.0 nlog程序集。

如何使用目标框架的nuget依赖项的正确版本进行构建?


不久前这里也有同样的要求,没有找到"纯"的Nuget解决方案。我怀疑有。唯一的选择似乎是维护不同的项目文件(或其中的一部分),这绝对是对大量代码库的禁止。

相反,我所做的只是在所有项目中以4.5为目标,并有一个相当简单的msbuild脚本,用于创建项目的副本及其所有nuget配置,用于以其他版本的.NET为目标。基本上,它只是枚举所有.csproj文件,从net45->net40字符串中进行查找/替换,并以不同的名称保存它们。包配置/目标/解决方案文件的IDEM。

以下是几乎完整的msbuild目标:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<Target Name="MakeNet40Projects">
  <ItemGroup>
    <SourceProjs Include="$(MyProjectDir)*\*\*.csproj" Exclude="$(MyProjectDir)\*\*\*.Net40.csproj"/>
      ...
    <SourceConfigs Include="$(MyProjectDir)*\*\packages.config"/>
      ...
    <DestProjs Include="%(SourceProjs.RootDir)%(SourceProjs.Directory)%(SourceProjs.FileName).Net40.csproj"/>
    <DestConfigs Include="%(SourceConfigs.RootDir)%(SourceConfigs.Directory)%(SourceConfigs.FileName).Net40.config"/>
  </ItemGroup>
  <PropertyGroup>
    <OldPackages>packages.config</OldPackages>
    <NewPackages>packages.Net40.config</NewPackages>
    <OldTargets>NuGet.targets</OldTargets>
    <NewTargets>NuGet.Net40.targets</NewTargets>
    <OldProj>\.csproj</OldProj>
    <NewProj>.Net40.csproj</NewProj>
  </PropertyGroup>

  <Copy SourceFiles="@(SourceProjs)" DestinationFiles="@(DestProjs)"/>
  <FileUpdate Files="@(DestProjs)" Regex="[Nn][Ee][Tt]45" ReplacementText="net40" Encoding="utf-8"/>
  <FileUpdate Files="@(DestProjs)" Regex="$(OldPackages)" ReplacementText="$(NewPackages)" Encoding="utf-8"/>
  <FileUpdate Files="@(DestProjs)" Regex="$(OldTargets)" ReplacementText="$(NewTargets)" Encoding="utf-8"/>
  <FileUpdate Files="@(DestProjs)" Regex="$(OldProj)" ReplacementText="$(NewProj)" Encoding="utf-8"/>

  <Copy SourceFiles="@(SourceConfigs)" DestinationFiles="@(DestConfigs)"/>
  <FileUpdate Files="@(DestConfigs)" Regex="[Nn][Ee][Tt]45" ReplacementText="net40" Encoding="utf-8"/>

  <Copy SourceFiles="$(MsBuildThisFileDirectory)\.nuget\$(OldTargets)" DestinationFiles="$(MsBuildThisFileDirectory)\.nuget\$(NewTargets)"/>
  <FileUpdate Files="$(MsBuildThisFileDirectory)\.nuget\$(NewTargets)" Regex="$(OldPackages)" ReplacementText="$(NewPackages)" Encoding="utf-8"/>

  <Copy SourceFiles="$(MsBuildThisFileDirectory)\my.sln" DestinationFiles="$(MsBuildThisFileDirectory)\my.Net40.sln"/>
  <FileUpdate Files="$(MsBuildThisFileDirectory)\my.Net40.sln" Regex="$(OldProj)" ReplacementText="$(NewProj)" Encoding="utf-8"/>
  <FileUpdate Files="$(MsBuildThisFileDirectory)\my.Net40.sln" Regex="NuGet\.targets" ReplacementText="$(NewTargets)" Encoding="utf-8"/>
</Target>

运行完这个之后,每个项目都有一个.net40.csproj,一个.net40.sln,一个解决方案的nuget.net40.targets和packages.net40.config文件,都可以构建了。到目前为止,一切都很好。

不过,小问题是:packages.config在nuget.exe中被硬编码为字符串,因此它不会在命令行上接受packages.net40.config。它是"算法"的一部分,决定传递给-install算法的路径是实际的包配置还是包ID。lol。我对此提出了一个问题,但没有答案。不管怎样,我不打算让这破坏了乐趣,所以我在源代码中做了一个单行调整,让它接受以.config结尾的任何内容,构建它并使用nuget.exe。