web-dev-qa-db-ja.com

Nugetパッケージから抽出するネイティブおよびマネージDLLの自動化

これは私を数ヶ月間狂わせており、それを達成することはまだできません。私のマネージライブラリはNugetパッケージから抽出されますが、ネイティブライブラリからは抽出されません。

他の会社が提供する管理されたネイティブライブラリがたくさんあります。 _x86_と_x64_の両方のバージョンがあります。それらをASP.NET Coreプロジェクトで使用するには、Nugetパッケージを作成する必要があります。

私のアーキテクチャは:

  • 完全な.NET Frameworkのみを対象とするように変更したASP.NET Coreクラスライブラリ。このプロジェクトは私のNugetパッケージを参照しています
  • 完全な.NET Frameworkも対象とし、クラスライブラリを参照するASP.NET Core Webサイト

もちろん、最後に、ネイティブライブラリをWebサイトの適切なランタイムフォルダーに抽出する必要があります(例:_\bin\Debug\net461\win7-x64_)。

当面の私の解決策は:

  • ネイティブライブラリをbuildフォルダ内に配置する
  • それらを$(OutputPath)にコピーするtargetsファイルを作成します(ランタイムフォルダーでもありません)。
  • いくつかのMsBuildコマンドをウェブサイトのxprojに追加して、$(USERPROFILE)\.nuget\packages\フォルダー内のターゲットファイルを取得して実行します
  • 手でコピーネイティブDLLをbinフォルダーに抽出してruntimeにコピーします

_project.json_の構成を使用して、それらをランタイムフォルダーに直接コピーしようとしました(正直に言って、この部分で試したすべてのことを覚えていません)。これは常に失敗していました。また、ターゲットファイルで_SkipUnchangedFiles="true"_を指定した場合でも、これは無視され、ビルドごとにDLLがbinフォルダーにコピーされます。

これは、DLLの抽出を実現するだけの重いプロセスです。今、私はMsBuildをすべて取り除き、より単純なソリューションを取得したいと思っています。

Nugetの新しいバージョンでは、カスタムMsBuildコマンドを追加せずにネイティブに抽出できるようになりました。 ここに書かれているように 、C#プロジェクトはtargetsファイルすら必要としません

次に、NuGetパッケージを使用する可能性のあるC++およびJavaScriptプロジェクトには、必要なアセンブリファイルとwinmdファイルを識別するための.targetsファイルが必要です。 (C#およびVisual Basicプロジェクトはこれを自動的に行います。)

私はブラウザーでタブを数か月間開いたままにして( 元のリンク )、このリソースが最近Nuget Webサイトから削除されたことに気付きました。 runtimesフォルダーを使用してネイティブDLLを自動的に抽出する方法を説明していました。しかしそれが説明されたように私は成功した結果を得ることができたことはありません。このページは削除され、 this one に置き換えられました。説明が少なく、このruntimesフォルダーについてはまったく触れていません。

私の推測では、ネイティブDLLにはruntimesフォルダーを使用し、マネージDLLにはlibフォルダーを使用する必要がありますが、100%確実ではありません。 (buildフォルダも使用する必要がありますか?)

私はいくつかのことを試しました(私は数か月の頭痛のように言ったように、試行回数を思い出せません...) thisアーキテクチャ (ここでは何がわからないのか) _build/native_およびruntimes)の下のネイティブフォルダーがあることのポイント enter image description here

また、マネージライブラリの こちら に記載されている.NETフレームワークのバージョン構造を使用しようとしました。

これ も解決策の一部のようです

アセンブリ参照を作成するとき、アーキテクチャはコンパイラによって無視されます。これはロード時間の概念です。ローダーは、アーキテクチャ固有の参照が存在する場合、それを優先します。

AnyCPUアセンブリを生成するために使用できる1つのトリックは、x86アセンブリからアーキテクチャを削除するためにcorflagsを使用することです。 EG:corflags/32BITREQ- MySDK.dll。 Corflagsは.NET SDKの一部であり、VSの開発者コマンドプロンプトにあります。

それは私がやったことであり、x86とx64の両方のDLLをAnyCPUに変換し(x64 DLLに対して何かを行うかどうかはわかりませんが、エラーは発生しませんでした)、次にNugetパッケージでいくつかの異なるアーキテクチャを試しましたが、機能していません。

Project.jsonにエントリがないデフォルトのランタイムは_win7-x64_なので、念のため明示的に指定することにしました

_"runtimes": {
    "win7-x64": {}
},
_

これが、Nugetパッケージでのすべての試行に使用しているランタイム識別子です。ただし、Windowsのバージョンは気にしません。私は実際にはwin-x86またはwin-x64を使用することを好みますが、 このページ によれば無効な値のようです

Windows RID

Windows 7/Windows Server 2008 R2

  • win7-x64
  • win7-x86

Windows 8/Windows Server 2012

  • win8-x64
  • win8-x86
  • win8アーム

Windows 8.1/Windows Server 2012 R2

  • win81-x64
  • win81-x86
  • win81アーム

Windows 10/Windows Server 2016

  • win10-x64
  • win10-x86
  • win10-arm
  • win10-arm64

ただし、これは Github source がより多くのRIDを記述しているため、どのソースが正しいですか?

ご覧のように、ここには非常に多くの謎があります。これは、主にドキュメントが不足しているか、異なるドキュメント間の矛盾が原因です。

少なくとも実用的な例があるとしたら、テストを実行して、一般的な_win-x64_ RIDを試すなどの他の質問に答えるか、.NET Frameworkのバージョンに関係なく、マネージライブラリを1回含めることができるかどうかを確認します。

私の特別なコンテキストに注意してください:完全な.NET Frameworkを対象とするASP.NET Coreプロジェクトがあります

あなたの答えをありがとう、私はこの単純なことを機能させるために必死です。

23
Jérôme MEVEL

私が経験したすべての苦痛と解決策をできるだけ詳しく説明しようと思います。私の例では、ネイティブDLLの代わりに、単純なテキストファイルAAA86.txtAAA64.txtAAAany.txtを使用して、抽出プロセスを簡単に説明しています。

最初に知っておくべきこと:native NuGetのアーキテクチャを、いくつかを含むlibフォルダと混在させようとする場合管理ライブラリ、ITは機能しません

enter image description here

その場合、マネージDLLはプロジェクトの出力ディレクトリにコピーされますが、ネイティブDLLはコピーされません。

Grpc.Coreパッケージ を参照するようにアドバイスしてくれたJon Skeetに感謝します。コツは、DLL抽出を処理するtargetsファイルを作成することです。

enter image description here

ターゲットファイルには次のようなものが含まれている必要があります

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.Microsoft.com/developer/msbuild/2003">

    <ItemGroup Condition=" '$(Platform)' == 'x64' ">
        <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x64\native\AAA64.txt">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            <Link>AAA64.txt</Link>
        </Content>
    </ItemGroup>

    <ItemGroup Condition=" '$(Platform)' == 'x86' OR '$(Platform)' == 'AnyCPU' ">
        <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win-x86\native\AAA86.txt">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            <Link>AAA86.txt</Link>
        </Content>
    </ItemGroup>

</Project>

ここで、知っておく必要がある他のいくつかの事項:

1)Visual Studioは気にしません選択すると、常にダミーのRIDが使用されます。 (私の場合、Windows 10を使用している場合でも、常にwin7-x64フォルダが表示されます...)

enter image description here

2)project.jsonの-​​ プラットフォーム設定 もまったく役に立たない

{
    "buildOptions": {
        "platform": "x64"
    }
}

3)ランタイム設定winまたはwin-x64のみを設定した場合

"runtimes": {
    "win": {},
    "win-x64": {}
}

Visual Studioは代わりにwin7-x64を使用します。ただし、Windows 10マシンでwin10-x64を追加すると、これが使用されます

4)このような一般的なRIDを使用してアプリケーションをコンパイルする場合

dotnet build -c debug -r win

次に、あなたのtargetsファイルは、私が期待していたAnyCPUではなく、マシンのアーキテクチャ(私の場合はx64)を受け取ります。

5)マネージドライブラリのないネイティブライブラリのみで、アーキテクチャに従うと、ターゲットファイルなしで抽出が機能しますruntimes/RID/native

6)パッケージにネイティブライブラリのみが含まれている場合、選択したRIDは常にwin-x64になります。選択した構成に関係なく、常にwin7-x64が作成されます。パッケージにwin RIDが1つしかない場合は、正常に選択されます。

33
Jérôme MEVEL