ファイルからnuget packageを作る


nuget packageをソリューションとかプロジェクト関係なしに作ろうとしたら結構苦労したのでメモ

DLLと周辺の必要ファイルをnugetで参照したい

社内資産として使いまわしたいDLLやらそれに付随するファイル群があって、ローカルのnugetサーバで管理したいなぁなんて思って作り始めました。
ちょっと試した感じだと、ネットワークドライブでマウントできる場所ならnuget package置いとくだけで勝手にバージョンとか良い感じに扱ってくれて幸せになれそうです。
これは使いたい。

nuget.package形式とPackageReference形式

現状ではソリューション毎にnugetのファイル配置形式が選べます。
従来のソリューション毎にpackageの中身を配置するのがnuget.package形式で、
マシン毎にpackageの中身を配置して複数ソリューションがそれを見に行くのがPackageReference形式です。

色々触ってみて、支障がなければPackageReference形式に切り替えた方が幸せになれそうな印象です。
contentFilesタグを使うためにはPackageReferenceである必要があるみたいです。

もう途中からnuget.package形式の方は追うことを諦めました。

便利ツール「NuGetPackageExplorer」

NuGetPackageExplorerを使って作りました。
やっぱりGUIの方が楽に感じてしまいます。
Chocoでインストールが便利ですかね。

適当なファイルを準備

とりあえず中身すっからかんの適当なファイルを準備しました。
直接参照するDLLはNugetPackageのLibフォルダに入れるだけでいい感じに扱ってくれますがそこからさらに必要とされるファイル群で躓いたのでそれらをイメージしてます。

NuGetPackageExplorerの使い方

パッケージ作成

起動したら「Create a new package」します。

ファイルの配置

右ペインに「contentFiles」フォルダを作成します。

contentFilesの構造はフォーマットがあるので好き勝手に作ってはだめです。
詳しくはここをチェック

抜粋すると

パッケージ プロジェクトでは、次のパターンを使ってコンテンツを構成する必要があります。

/contentFiles/{codeLanguage}/{TxM}/{any?}
codeLanguages には、cs、vb、fs、any、または指定された $(ProjectLanguage) に相当する小文字表現を指定できます。
TxM は、NuGet がサポートする任意の有効なターゲット フレームワーク モニカーです (「ターゲット フレームワーク」を参照)。
この構文の末尾に、任意のフォルダー構造を追加できます。
例 :

Language- and framework-agnostic:
    /contentFiles/any/any/config.xml
net45 content for all languages
    /contentFiles/any/net45/config.xml
C#-specific content for net45 and up
    /contentFiles/cs/net45/sample.cs

空のフォルダーでは、. を使って、言語と TxM の特定の組み合わせにコンテンツを提供しないようにすることができます。次はその例です。

/contentFiles/vb/any/code.vb
/contentFiles/cs/any/.

だそうです。

今回は使う先が限定的だったので手抜きして/contentFiles/any/any/以下に配置します。

こんな感じに配置してみました。

metadataの編集

左ペインでmetadataを編集します

必要な依存関係などはここで設定できます。
contentFIlesをコピーさせるにはcontentFilesタグでどうしたいかを記述する必要があります。
今回のケースは何でもかんでもそのままの構造でコピーしておいて!で済むので以下のような記述になります

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>MyPackage</id>
    <version>1.0.0</version>
    <title></title>
    <authors>abcdef</authors>
    <owners></owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>My package description.</description>
    <contentFiles>
      <files include="**/*" buildAction="None" copyToOutput="true" flatten="false" />
    </contentFiles>
  </metadata>
</package>

packageの保存

File→Save Asで保存します。
パッケージIDとファイル名がそろってないとまずそうです。

VisualStudioでパッケージソースの追加

VisualStudio起動してツール->オプション->Nugetパッケージマネージャー->パッケージソース
で作ったpackageを保存したディレクトリを追加します。

NugetPackageをインストールしてみる

適当なプロジェクトにNugetで追加してみます

今回はcontentFilesを使ってるのでPackageReference形式にします。

こんな感じに参照が追加されました

インストールされたファイルの確認

PackageReference形式にすると設定変えてなければC:\Users\username\.nuget\packages以下に配置されます。

配置状況を確認するとPackageと同じように配置されているのがわかります。

ビルドしてコピー状況の確認


というわけで成功です!

作り直すときの注意

作り直すときどこを参照してるのかを意識しないとハマります。
特にバージョン変更しないのにpakageの中身を変更するときに注意してください。(そんなことしちゃいけませんねw)
初回インストールのバージョンのパッケージはパッケージソースで設定した先からコピーして持ってきますが、
既にインストール済みのバージョンの場合はローカルのC:\Users\username\.nuget\packages以下に配置されたファイルを見ます。
よって実験しながら試すときはバージョン上げていって変更していくか、ローカルのファイルを削除してからNugetインストールするか、しないといつまでたっても変更が反映されません。