首页 文章

在Linux上构建面向.NET Framework的NuGet包

提问于
浏览
14

我想创建一个NuGet包,它可以同时显式地同时针对.NET Framework 4.6.2和.Net Standard 1.5 . 这是VS 2017的缩写.csproj文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>net462;netstandard1.5</TargetFrameworks>
    ...
  </PropertyGroup>

</Project>

当我从本地Windows机器执行dotnet构建和打包命令时,NuGet包的创建完全符合预期 .

However ,当我尝试在Linux上执行相同的dotnet命令时,收到以下错误:

/opt/dotnet/sdk/1.0.4/Microsoft.Common.CurrentVersion.targets(1111,5):错误MSB3644:找不到框架“.NETFramework,Version = v4.6.2”的引用程序集 . 要解决此问题,请为此框架版本安装SDK或Targeting Pack,或者将应用程序重新定位到已安装SDK或Targeting Pack的框架版本 . 请注意,程序集将从全局程序集缓存(GAC)中解析,并将用于代替引用程序集 . 因此,您的程序集可能无法正确定位到您想要的框架 .

然后我突然意识到Linux盒子上没有任何常规的.NET Framework程序集(更不用说了 . 因此,似乎我将无法使用Linux来构建我的NuGet包 . 我搜索了一下“ Targeting Pack“,但它仅适用于Windows .

冒着听起来天真的风险,是否有人在Linux上成功构建可以针对.NET Framework的NuGet包?

1 回答

  • 16

    .NET CLI的分发不包含.NET Framework的任何引用程序集,因此其MSBuild版本无法解析所需的编译时资产 . 虽然这种情况是tracked on GitHub,但在迁移到MSBuild之前一直有效(CLI可以使用mono的引用程序集) .

    虽然可以使用一些替代方法在非Windows机器上构建您的库:

    1. Use mono 5+ to build the library.

    这可能是最稳定的路径 .

    Mono 5及更高版本包含构建.NET Standar和.NET Core应用程序所需的构建逻辑 . 在linux上,mono的msbuild可能需要作为单独的软件包安装 . 因此,而不是以下常用命令

    dotnet restore
    dotnet build
    dotnet publish -c Release
    

    你会使用mono的msbuild来做以下事情:

    msbuild /t:Restore
    msbuild
    msbuild /t:Publish /p:Configuration=Release
    

    Pack workaround for mono < 5.2:

    唯一的限制是mono(<5.2)不能生成开箱即用的NuGet包,但项目中有一个workaround involving using the NuGet.Build.Tasks.Pack NuGet package允许你通过修改项目文件来做 msbuild /t:Pack /p:Configuration=Release (特别注意 <Project> 元素上删除的 Sdk="..." 属性) ):

    <Project>
      <PropertyGroup>
        <NuGetBuildTasksPackTargets>junk-value-to-avoid-conflicts</NuGetBuildTasksPackTargets>
      </PropertyGroup>
      <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
    
      <!-- All your project's other content here -->
    
      <ItemGroup>
        <PackageReference Include="NuGet.Build.Tasks.Pack" Version="4.0.0" PrivateAssets="All" />
      </ItemGroup>
      <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
    </Project>
    

    2. Use the .NET CLI and tell MSBuild to use mono's reference assemblies.

    构建 net* 目标框架时,可以将 FrameworkPathOverride 属性设置为环境变量或csproj文件中的属性 . 它需要指向一组参考组件 - 可以在这里使用mono的参考组件 . 但有些文件包含一个特殊文件(redist list),其中包含对.NET CLI中的MSBuild版本无法遵循的其他目录的引用 . 它在许多场景中都有效:

    export FrameworkPathOverride=/usr/lib/mono/4.5/
    dotnet build -f net45
    

    这是使用和documented by the F# team .

    3. Use a NuGet package containing reference assemblies.

    在某些MyGet源上,Microsoft发布包含引用程序集的NuGet包 . 它们没有发布或"official"但是这个过程可能会在某个时间点失败 . 但他们确实做到了plan to investigate making this path official .

    首先在解决方案的目录中创建一个NuGet.Config文件,其中包含以下内容以添加提要:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
     <packageSources>
        <add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
     </packageSources>
    </configuration>
    

    然后,您可以添加项目组以将 PackageReference 添加到目标包,并添加 PropertyGroup 以设置引用程序集的路径,如下所示:

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFrameworks>netcoreapp1.1;net461</TargetFrameworks>
      </PropertyGroup>
    
      <PropertyGroup Condition=" '$(TargetFramework)' == 'net461' ">
        <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
        <FrameworkPathOverride>$(NuGetPackageFolders)microsoft.targetingpack.netframework.v4.6.1\1.0.1\lib\net461\</FrameworkPathOverride>
      </PropertyGroup>
    
      <ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
        <PackageReference Include="Microsoft.TargetingPack.NETFramework.v4.6.1" Version="1.0.1" ExcludeAssets="All" PrivateAssets="All" />
      </ItemGroup>
    
    </Project>
    

    如果使用本机资产(例如,获取Linux的 .so 文件),则可以更改不同平台的 RuntimeIdentifier ,或者在构建库时将其完全删除 .

相关问题