Skip to content

MS_NuGetPackageDevelopment

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

NuGetパッケージの開発と公開

概要

  • NuGet パッケージを作成してみたくなったので調査。

補足(本ページの前提と、現在の方式/最新化): 本ページは
nuget.exe + 手書きの .nuspec を前提としている。
SDK スタイル プロジェクトでは、この手順はほぼ不要になった。

【本ページの方式(.NET Framework / packages.config 時代)】
   nuget spec           → .nuspec を生成
   .nuspec を手で編集   → メタデータ・依存・files を記述
   nuget pack           → .nupkg
   nuget push

【現在の方式(SDK スタイル)】
   .csproj にメタデータを書く(.nuspec 不要)
   dotnet pack          → .nupkg(依存も自動)
   dotnet nuget push
<!-- .csproj だけで完結する -->
<PropertyGroup>
  <TargetFrameworks>net48;netstandard2.0;net8.0</TargetFrameworks>
  <GeneratePackageOnBuild>true</GeneratePackageOnBuild>

  <PackageId>Contoso.Utility.UsefulStuff</PackageId>
  <Version>1.8.3</Version>
  <Authors>Dejana Tesic, Rajeev Dey</Authors>
  <Description>Core utility functions for web applications</Description>
  <PackageTags>web;utility;http;json;url;parsing</PackageTags>
  <PackageLicenseExpression>MIT</PackageLicenseExpression>
  <PackageProjectUrl>https://github.com/contoso/UsefulStuff</PackageProjectUrl>
  <PackageIcon>icon.png</PackageIcon>
  <PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>

.csprojPackageReferenceTargetFrameworks から
dependencieslib\<tfm> が自動生成される
ため、
後述の「Dependencies」や
複数の Target Frameworks のサポート」で
原文が苦労している部分は、自動で正しく組み上がる

本ページは、.nuspec の意味を理解するため、および
既存の packages.config 系プロジェクトを保守するため
資料として読むのが妥当である。

Nuget でできること。

追加できるファイル

パッケージの色々

その他

  • 複数の Target Frameworks のサポート
  • appSettings など、*.config の編集

補足(現在は使えない/推奨されない機能): 上記のうち、
PackageReference 方式では動かないものがある。

機能 packages.config PackageReference
アセンブリ参照(lib\
content\ によるファイル配置 ×contentFiles を使う)
install.ps1 / uninstall.ps1 × 実行されない
*.config の変換web.config.transform ×
build\*.props / *.targets
アナライザー(analyzers\

*.config の編集や PowerShell スクリプトによるプロジェクト改変は、
現在は行えない
Program.cs に 1 行書いてもらう設計にするのが定石)。
原文が挙げる「テンプレートの拡張」も、現在は
dotnet new テンプレート パッケージpackageType="Template"
として別の仕組みで提供する。

.NET Framework プロジェクト以外

Native Package(C++)

C++ の、Native Package も作成できる模様。

基本的な手順

Nuget のサイトにサインイン

  • NuGet Gallery | Home
    https://www.nuget.org/

  • Microsoft アカウントでサインアップ可能。

    • 連携するのはメールアドレスで、同時にユーザ名の入力が必要。
    • サインアップ後、サインインが可能になる。
    • ローカル・ログオン用のパスワードはアカウント編集画面から設定可能。
  • 以下はサインアップ・サインイン後のアカウント編集画面

補足(最新化): 現在、nuget.org は
Microsoft アカウント(または Microsoft Entra ID)でのみサインイン可能で、
ローカル パスワードによるログオンは廃止されている。
「ローカル・ログオン用のパスワード」の設定項目は現存しない。

Nuget のサイトから Nuget.exe を取得

に遷移。

  • Windows x86 Commandline
    nuget.exe - recommended latest vn.n.n

をクリックして、nuget.exe を Download。

補足(現在は dotnet CLI で足りる/最新化): nuget.exe が要るのは、
packages.config 形式を扱う場合に限られる。

用途 コマンド
パッケージ作成 dotnet pack
公開 dotnet nuget push
復元 dotnet restore
ソース管理 dotnet nuget add source
packages.config の復元 nuget restorenuget.exe が必要)

dotnet CLI は .NET SDK に同梱されているため、
追加のダウンロードは不要である(dotnetコマンド)。

nuspec ファイルの生成

nuspec ファイルとは?

  • パッケージのメタデータを含む XML 形式のマニフェスト(公約文書)。
  • マニフェスト(公約文書)は常にパッケージに含まれる。
  • パッケージを構築し、消費者に情報を提供するために使用される。

補足: SDK スタイルで dotnet pack を使う場合も、
.nuspec は内部的に生成されて .nupkg に含まれる
(手で書く必要が無くなっただけで、無くなったわけではない)。
.nupkg を ZIP として展開すれば中身を確認できる。

nuspec ファイルの出力準備

  • nuget.exe へのパスを通しておくか、
    プロジェクトファイル(*.csproj)のあるフォルダに nuget.exe を配置する。
  • AssemblyInfo の属性値を使用するので、これに属性を記入しておく。
    • 規定値
[assembly: AssemblyTitle("Public")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("xxxxxxxxxx")]
[assembly: AssemblyProduct("Public")]
[assembly: AssemblyCopyright("Copyright (C) 2007,2016 xxxxxxxxxx")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
  • 以下を追加(ただ、実際にやっている人は少なそう)
[assembly: AssemblyMetadata("ProjectUrl", "http・・・")]
[assembly: AssemblyMetadata("LicenseUrl", "http・・・")]

補足(SDK スタイルでは AssemblyInfo.cs 自体が不要): SDK スタイルでは
AssemblyInfo.cs は自動生成されるため、手で書かない
(書くと「重複する属性」でビルド エラーになる)。
.csproj のプロパティが、そのままアセンブリ属性と
パッケージ メタデータの両方になる。

.csproj プロパティ 対応するアセンブリ属性
<Product> AssemblyProduct
<Company> AssemblyCompany
<Copyright> AssemblyCopyright
<Description> AssemblyDescriptionパッケージの description
<Version> AssemblyInformationalVersionパッケージの version

詳細は .NETアセンブリのバージョン情報 を参照。

nuget.exe から nuspec ファイルを出力

  • プロジェクトファイル(*.csproj)から生成する。
    • プロジェクトファイル(*.csproj)のあるフォルダで [nuget spec] コマンドを実行する。
nuget spec
  • *.nuspec ファイルが生成される(何故か、AssemblyInfo の属性値が反映されなかった)。
<?xml version="1.0"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2017</copyright>
    <tags>Tag1 Tag2</tags>
  </metadata>
</package>

補足($id$ などが残る理由): 原文の
「何故か、AssemblyInfo の属性値が反映されなかった」は仕様通りである。

$id$ $version$ $title$ $author$ $description$
置換トークンであり、
nuget pack.csproj に対して実行した時点で
AssemblyInfo から値が埋め込まれる

nuget spec の時点では展開されない。

nuget pack Foo.csproj    # ← ここでトークンが解決される
nuget pack Foo.nuspec    # ← .csproj を見ないので解決されない(要注意)

つまり .nuspec を直接 pack すると、トークンが未解決のままになる。
原文が後述の「nuspec ファイルを使用」で
.nuspec を指定する手順を挙げているが、
その場合はトークンを実際の値に置き換えておく必要がある

  • DLL ファイル(*.dll)から生成する。
    • DLL ファイル(*.dll)を指定して [nuget spec] コマンドを実行する。
nuget spec [*.dllファイルパス]
  • *.nuspec ファイルが生成される(こちらも、AssemblyInfo の属性値が反映されていない)。
<?xml version="1.0"?>
<package >
  <metadata>
    <id>Public.dll</id>
    <version>1.0.0</version>
    <authors>(Windowsにログインしたユーザ名)</authors>
    <owners>(Windowsにログインしたユーザ名)</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package description</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2017</copyright>
    <tags>Tag1 Tag2</tags>
    <dependencies>
      <dependency id="SampleDependency" version="1.0" />
    </dependencies>
  </metadata>
</package>

nuspec ファイルの編集

  • 生成された nuspec ファイルを修正する。
  • それぞれの項目については下記を参照。

以下、ザックリとした説明。

id

例 : Oracle.DataAccess(.dll) とか、Microsoft.AspNet.Identity(.dll) とか。

  • 一意
  • 名前空間っぽくする。
  • 社名などを使うと良い。
  • サンプルのパッケージは、*.Sample を足す。

補足(ID の付け方は事故防止にも効く): 「社名などを使う」
という原文の助言は、現在ではセキュリティ上も重要である。

MyCompany.* という前置きを決めておくことで、
NuGetプライベート・リポジトリ で述べた
packageSourceMapping による
「この前置きのパッケージは社内ソースからのみ取得する」
という設定が可能になる(依存関係かく乱への対策)。

なお、nuget.org にはID 前置きの予約(ID Prefix Reservation)
という制度があり、承認されると
「予約済み ID」のチェック マークが表示される。

title

description

パッケージのザックリとした説明。

authors、owners

移行メモ(正誤): 原文の説明は NuGet における意味と逆である。
nuget.org における定義は次の通り。

要素 意味
authors パッケージの作者.nuspec に書かれた文字列がそのまま表示される
owners nuget.org 上の所有アカウント。公開・更新・削除の権限を持つ

owners.nuspec からは設定できない(無視される)。
所有者は nuget.org 側で管理され、
公開したアカウントが自動的に owner になる。

このため、現在は
.nuspec / .csproj に書くのは authors だけでよい。

projectUrl、licenseUrl、iconUrl

各種 URL を設定する。

  • projectUrl
  • licenseUrl
  • iconUrl

補足(licenseUrl / iconUrl は非推奨/最新化): この 2 つは
URL 指定が非推奨になり、パッケージへの埋め込みに変わった。

理由
licenseUrl license(SPDX 式 or ファイル) リンク切れ・後からの差し替えを防ぐ
iconUrl icon(同梱ファイル) 外部依存・オフライン対応
<!-- SDK スタイル(.csproj) -->
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<!-- あるいは独自ライセンスをファイルで同梱 -->
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>

<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>

<ItemGroup>
  <None Include="icon.png" Pack="true" PackagePath="\" />
  <None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>

PackageReadmeFile(README の同梱)は比較的新しい機能で、
nuget.org のパッケージ ページに README がそのまま表示される
現在は指定しておくのが望ましい。

version

  • 依存関係を解決する際に使用されるパッケージバージョン。

  • パッケージを単一のアセンブリに限定するためのもの。

  • 基本的には、以下の 3 つを使用して
    「n.n.n」(Major.Minor.Patch)と構成する。

    • メジャーバージョン
    • マイナーバージョン
    • 下位互換性のあるバグ修正
  • 注 :

    • アセンブリバージョンではなく、パッケージバージョン
    • 故に、アセンブリバージョンと一致させる必要はない。
  • 参考

補足(版番号の関係): 「アセンブリバージョンと一致させる必要はない」
という原文の指摘は重要で、実際に性質が異なる

用途 変えると何が起きるか
PackageVersion NuGet の依存解決 利用側が Version= で指定する値
AssemblyVersion CLR のバインド bindingRedirect が必要になる
AssemblyFileVersion ファイル プロパティの表示 影響なし
InformationalVersion 表示用(1.2.0-beta+sha 影響なし

ライブラリ作者の定石は、

PackageVersion       1.2.3   (毎回上げる)
AssemblyVersion      1.0.0.0 (メジャー版でだけ上げる)
AssemblyFileVersion  1.2.3.0 (毎回上げる)

AssemblyVersion を固定気味にすることで、
.NET Framework 利用者の bindingRedirect 地獄を避けられる
(詳細は .NETアセンブリのバージョン情報)。

.NET Framework アセンブリへの参照の追加

<frameworkAssemblies> 
  <frameworkAssembly assemblyName="System.Web" /> 
</frameworkAssemblies>

補足: これは GAC にある .NET Framework の
アセンブリへの参照を、利用側プロジェクトに追加させる
指定である。
.NET Core 以降では GAC が無いため意味を持たない
netstandard / net8.0 向けには書かない)。

他の Nuget パッケージへの依存関係の追加

<dependencies> 
  <dependency id="jQuery" /> 
</dependencies>

バージョンを指定可能。範囲指定も可能。

補足(範囲指定の記法): 実務でよく使う書き方を整理しておく。

記法 意味 用途
1.0 1.0 以上(= [1.0, ) 既定。これが基本
[1.0] 1.0 のみ(完全一致) 厳密に固定したい場合
[1.0, 2.0) 1.0 以上 2.0 未満 メジャー版を跨がせない
(1.0, ) 1.0 より大きい 特定版を除外
1.0.* 浮動バージョン 開発中のみ推奨

重要: NuGet の 1.0 は「1.0 ちょうど」ではなく
「1.0 以上」を意味する(最小バージョンの指定)。
このため、依存の版は実際には利用側の解決結果で決まる

(最も高い最小バージョンが選ばれる)。

ライブラリ作者の指針:

  • 下限だけを指定する1.0)のが原則。
    上限を切ると、利用側が更新できなくなり衝突の原因になる。
  • [1.0] のような完全固定は避ける
    (複数のライブラリが別々に固定すると解決不能になる)。

アセンブリの追加(*.dll)

targetを設定して、
アセンブリ(*.dll)を同梱する。

<files> 
  <file src="bin\Release\*.*" target="lib\net45" /> 
</files>

補足: lib\<TFM> というフォルダ名がそのまま対象の判定に使われる。
TFM の一覧は ターゲット フレームワークのバージョン を参照。
SDK スタイルでは <TargetFrameworks> から自動で振り分けられる

参考

https://learn.microsoft.com/ja-jp/nuget/create-packages/creating-a-package

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
    <!-- The identifier that must be unique within the hosting gallery -->
    <!-- ホスティングギャラリー内で一意でなければならないID -->
    <id>Contoso.Utility.UsefulStuff</id>

    <!-- The package version number that is used when resolving dependencies -->
    <!-- 依存関係を解決するときに使用されるパッケージのバージョン番号 -->
    <version>1.8.3.331</version>

    <!-- Authors contain text that appears directly on the gallery -->
    <!-- Authorsには、ギャラリーに直接表示されるテキストが含まれています -->
    <authors>Dejana Tesic, Rajeev Dey</authors>

    <!-- Owners are typically nuget.org identities that allow gallery users to easily find other packages by the same owners.  -->
    <!-- ownersは通常、ギャラリーのユーザーが同じownerによる他のパッケージを簡単に見つけることを可能にするnuget.org IDです。 -->
    <owners>dejanatc, rjdey</owners>

    <!-- License and project URLs provide links for the gallery -->
    <!-- licenseUrlとprojectUrlはギャラリーにリンクを提供します -->
    <licenseUrl>http://opensource.org/licenses/MS-PL</licenseUrl>
    <projectUrl>http://github.com/contoso/UsefulStuff</projectUrl>

    <!-- The icon is used in Visual Studio's package manager UI -->
    <!-- このアイコンは、Visual Studioのパッケージ・マネージャUIで使用されます -->
    <iconUrl>http://github.com/contoso/UsefulStuff/nuget_icon.png</iconUrl>

    <!-- If true, this value prompts the user to accept the license when installing the package. -->
    <!-- trueの場合、この値は、パッケージのインストール時にライセンスを受け入れるようにユーザーに指示します。 -->
    <requireLicenseAcceptance>false</requireLicenseAcceptance>

    <!-- Any details about this particular release -->
    <!-- このリリースに関する詳細 -->
    <releaseNotes>Bug fixes and performance improvements</releaseNotes>

    <!-- The description can be used in package manager UI. Note that the nuget.org gallery uses information you add in the portal. -->
    <!-- descriptionは、パッケージ・マネージャのUIで使用できます。 nuget.orgギャラリーでは、ポータルに追加した情報が使用されます。 -->
    <description>Core utility functions for web applications</description>

    <!-- Copyright information -->
    <!-- 著作権情報 -->
    <copyright>Copyright ©2016 Contoso Corporation</copyright>

    <!-- Tags appear in the gallery and can be used for tag searches -->
    <!-- tagsはギャラリーに表示され、tag検索に使用できます -->
    <tags>web utility http json url parsing</tags>

    <!-- Dependencies are automatically installed when the package is installed -->
    <!-- dependencyは、パッケージのインストール時に自動的に(他のパッケージが)インストールされます。 -->
    <dependencies>
      <dependency id="Newtonsoft.Json" version="9.0" />
    </dependencies>
  </metadata>

  <!-- A readme.txt will be displayed when the package is installed -->
  <!-- パッケージのインストール時に readme.txt が表示されます -->
  <files>
    <file src="readme.txt" target="" />
  </files>
</package>

パッケージ(nupkg ファイル)の作成

プロジェクト・ファイルを使用

  • 以下のコマンドでパッケージを作成する。
nuget pack [*.csprojファイルパス]
  • カレントでやれば、*.csproj ファイルのパス指定は不要。
nuget pack
  • リリースビルドを選択する場合、
nuget pack -Prop Configuration=Release

移行メモ(誤字): 原文の「リリースビル」は
リリースビルドの脱字と判断し修正した。

nuspec ファイルを使用

  • 高度な設定」を行う場合は nuspec ファイルを作成・指定して実行する。
nuget pack [*.nuspecファイルパス]

nupkg ファイルの内容確認方法

  • .nupkg、.symbols.nupkg」は ZIP ファイルなので、
    拡張子を「*.zip」にすれば、解凍して実際に含まれるファイルを確認可能。

  • 同梱されているアセンブリの詳細については、
    .NETアセンブリのtargetFrameworkを確認する方法
    に記述されている方法で確認できる。

補足(現在の作成方法): SDK スタイルでは次の 1 コマンドで済む。

dotnet pack -c Release
# → bin/Release/Foo.1.0.0.nupkg(+ .snupkg)

# 中身の確認(NuGet Package Explorer、または unzip)
unzip -l bin/Release/Foo.1.0.0.nupkg

GUI で確認するなら NuGet Package Explorer が便利で、
メタデータ・依存関係・lib\<tfm> の構成を一覧できる。

NuGet への登録

コマンドラインから

  • Access Key を取得する。
    Account ページに遷移して API Keys を取得する。

  • 以下のコマンドで NuGet へ登録する。

    • 方法1(url の v1 は、バージョン指定?)
nuget push -source http://packages.nuget.org/v1/ [*.nupkgファイルパス] [access key]
  • 方法2(URL は不要?)
nuget setapikey [access key] 
nuget push [*.nupkgファイルパス] 

補足(現在のエンドポイントとキー運用/最新化): 原文の v1
旧 API(廃止済み)である。現在は v3 を使う。

dotnet nuget push bin/Release/Foo.1.0.0.nupkg \
  --source https://api.nuget.org/v3/index.json \
  --api-key $NUGET_API_KEY

API キーの運用:

項目 推奨
有効期限 最長 365 日(無期限にはできない)
スコープ パッケージ ID の範囲を絞るMyCompany.*
権限 **「新規と更新」か「更新のみ」**を選ぶ
保管 CI のシークレット。コミットしない

なお、nuget.org は Trusted Publishing(OIDC 連携)に対応しており、
GitHub Actions から API キー無しで公開することもできる。
長期キーを持たずに済むため、こちらの方が安全である。

Web サイトから

NuGet Gallery でアップロードする場合、API Keys は不要。

公開前に(ローカルで)テスト実行する。

  • 以下が参考になる。

  • ざっくり、

    • Nuget パッケージ・マネージャーの設定で、
      パッケージ ソース(ローカル PC のフォルダ)を追加する。
    • ソリューションの Nuget パッケージの管理を開き、
      追加したパッケージ ソースを選択して「参照」の検索窓から検索する。

ソリューションのNugetパッケージの管理

  • 検索された Nuget パッケージを選択してインストールする。
  • packages フォルダには以下のようにインストールされる。
Touryo.Public.2.0.0
 ├ lib
 |  └ net46
 |      ├ Public.dll
 |      └ Public.XML
 └ Touryo.Public.2.0.0.nupkg
  • なお、依存関係も自動的に反映されるようで、
    このプロジェクトの packages.config で使用しているパッケージも同時にインストールされた。

補足(ローカル テストの落とし穴): ローカル フォルダをソースにして
検証する際、グローバル パッケージ フォルダのキャッシュに注意する。

同じ版番号で .nupkg を作り直しても、
  %USERPROFILE%\.nuget\packages\foo\1.0.0\ が残っていると
  そちらが使われ、変更が反映されない

対処:

# 該当版のキャッシュを消す
rm -rf ~/.nuget/packages/foo/1.0.0

# あるいは、検証のたびに版を上げる(プレリリース サフィックスが便利)
dotnet pack -p:VersionSuffix=local.$(date +%H%M%S)

版を上げながら検証する方が確実で、
NuGetパッケージのプレリリース版
CI 採番と同じ考え方である。

バージョンアップする。

nuspec ファイルの version を書き換えて同じように nupkg をアップロード。

高度な設定

パッケージにファイルを含める

パッケージに含めるファイル

  • ターゲットプロジェクトに挿入するコンテンツとソースコード
  • PowerShell スクリプト(インストールスクリプト、NuGet 2.x でのみサポート)
  • プロジェクト内の既存の構成ファイルおよびソースコードファイルへの変換

作業ディレクトリのフォルダ構造レイアウトの規則

# フォルダ 説明 パッケージのインストール時の動作
1 tools Package Manager Console パッケージ・マネージャコンソールからアクセスできる Powershell スクリプトとプログラム 内容はプロジェクトフォルダにコピーされ、tools フォルダは PATH 環境変数に追加される。
2 lib アセンブリファイル(.dll)、ドキュメント(.xml)ファイル、およびシンボル(.pdb)ファイル アセンブリは参照として追加される。.xml と .pdb はプロジェクトフォルダにコピーされる。
3 content 任意のファイル コンテンツはプロジェクトルートにコピーされる。
4 build MSBuild .targets と .props ファイル プロジェクトファイル(NuGet 2.x)または project.lock.json(NuGet 3.x)に自動的に挿入される。

補足(現在のフォルダ規則/最新化): 上表に加えて、
現在は次のフォルダも使われる。

フォルダ 用途
analyzers\dotnet\cs Roslyn アナライザー / ソース ジェネレーター
contentFiles\any\<tfm> content の後継(PackageReference 用)
runtimes\<rid>\native RID 別のネイティブ ライブラリ
ref\<tfm> 参照専用アセンブリ(コンパイル時のみ)
buildTransitive\ 推移的に伝播する .props / .targets

content は PackageReference では機能しないため、
ファイルを配りたい場合は contentFiles を使う。
ただし、そもそもファイルを配る設計自体が現在は好まれない
(更新時に利用側の変更を上書きしてしまうため)。

パッケージへのインクルード

nuspec ファイルの <metadata> 要素と同じ階層に、
<files> か <contentFiles> 要素を追加することで、ファイルをインクルード出来る。

  • アセンブリ・ファイル

    • ファイルは *.nupkg ファイルを作成するときに自動的にインクルードされる。
    • <files> 要素を使用し、自動動作を回避、インクルード・ファイルを明示的に制御できる。
  • コンテンツ・ファイル

    • contentFiles 要素を使用する。

補足(SDK スタイルでの同梱): .csproj では
Pack / PackagePath 属性で個別に指定する。

<ItemGroup>
  <None Include="README.md"      Pack="true" PackagePath="\" />
  <None Include="build\Foo.props" Pack="true" PackagePath="build\" />
  <None Include="runtimes\**"     Pack="true" PackagePath="runtimes\" />
</ItemGroup>

複数の Target Frameworks のサポート

https://learn.microsoft.com/ja-jp/nuget/create-packages/multiple-target-frameworks-project-file

パッケージにファイルを含める」の方法で、
複数バージョンを同梱するだけでいい。

設定

以下は、nuspec ファイルの設定例

<files>
  <file src="bin\Release\net46\MyAssembly.dll" target="lib\net46" />
  <file src="bin\Release\net461\MyAssembly.dll" target="lib\net461" />    
  <file src="bin\Release\uap\MyAssembly.dll" target="lib\uap" />    
  <file src="bin\Release\netcore\MyAssembly.dll" target="lib\netcore" />
</files>

結果

パッケージのインストール後の packages フォルダの lib フォルダは以下のようになる。

  • lib{framework name}[{version}]
  • 例:
\lib
    \net46
        \MyAssembly.dll
    \net461
        \MyAssembly.dll
    \uap
        \MyAssembly.dll
    \netcore
        \MyAssembly.dll

補足(SDK スタイルなら 1 行): 同じことが TargetFrameworks
指定だけで実現できる(ターゲット フレームワークのバージョン)。

<TargetFrameworks>net48;netstandard2.0;net8.0</TargetFrameworks>

dotnet packlib\net48 / lib\netstandard2.0 / lib\net8.0
自動生成
し、後述の dependenciesgroup も自動で切ってくれる。

なお、原文の例にある netcore
ターゲット フレームワークのバージョン
注意されている通り Windows ストア アプリを指し、
.NET Core ではない(.NET Core は netcoreapp / net5.0 以降)。

参考

Dapper の nuspec ファイルが参考になる。

<files>
  <file src="Dapper NET45\bin\Release\Dapper.dll" target="lib\net45" />
  <file src="Dapper NET45\bin\Release\Dapper.pdb" target="lib\net45" />
  <file src="Dapper NET45\bin\Release\Dapper.xml" target="lib\net45" />
  
  <file src="Dapper NET40\bin\Release\Dapper.dll" target="lib\net40" />
  <file src="Dapper NET40\bin\Release\Dapper.pdb" target="lib\net40" />
  <file src="Dapper NET40\bin\Release\Dapper.xml" target="lib\net40" />
  
  <file src="Dapper NET35\bin\Release\Dapper.dll" target="lib\net35" />
  <file src="Dapper NET35\bin\Release\Dapper.pdb" target="lib\net35" />
  <file src="Dapper NET35\bin\Release\Dapper.xml" target="lib\net35" />
</files>

.NET Standard.NET Core の Dependencies

dependencies > group > targetFramework="netstandard2.0" 等とする。

<dependencies>
  <group>
    <dependency id="DotNetZip" version="1.12.0" />
    <dependency id="log4net" version="2.0.8" />
    <dependency id="Newtonsoft.Json" version="11.0.2" />
  </group>
  <group targetFramework="netstandard2.0">
    <dependency id="log4net" version="2.0.8" />
    <dependency id="Microsoft.Extensions.Configuration" version="2.2.0" />
    <dependency id="Microsoft.Extensions.Configuration.Binder" version="2.2.0" />
    <dependency id="Microsoft.Extensions.Configuration.FileExtensions" version="2.2.0" />
    <dependency id="Microsoft.Extensions.Configuration.Json" version="2.2.0" />
    <dependency id="Newtonsoft.Json" version="11.0.2" />
    <dependency id="System.Data.Odbc" version="4.5.0" />
    <dependency id="System.Data.SqlClient" version="4.5.1" />
  </group>
</dependencies>

補足(group を切ることの意味): これが
NuGetでインストールすると依存関係が増えすぎる問題
主要な対処であり、NU1701 の解消にも直結する。

【group を切らない】
   net48 のプロジェクトにも
   Microsoft.Extensions.Configuration(netstandard 用)が付いてくる
     → NU1701 警告、または不要な依存の氾濫

【group を切る】
   net48   → DotNetZip, log4net, Newtonsoft.Json
   netstandard2.0 → Microsoft.Extensions.* ほか
     → 各ターゲットに必要なものだけが付く

**targetFramework 無しの <group> は「その他すべて」**を意味する
(フォールバック)。上の例では .NET Framework 側がこれにあたる。

SDK スタイルでは、.csproj の条件付き PackageReference から
自動で group が生成されるため、手で書く必要はない。

<ItemGroup Condition="'$(TargetFramework)'=='net48'">
  <PackageReference Include="DotNetZip" Version="1.12.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
  <PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
</ItemGroup>

様々なパッケージ

Localized Package(ローカライズ)

https://learn.microsoft.com/ja-jp/nuget/create-packages/creating-localized-packages

以下の 2 つの方法がある。

  • Localized resource assembly(Localized satellite assembly)を同梱する。

    • ワイルドカードを使用する方法。
    • xxxx.resources.dll を個別に同梱することもできる。
  • 個別に Localized satellite packages を作成する。
    (Microsoft.Owin.ja や Microsoft.AspNet.Mvc.ja 的な)

補足: 後者(サテライト パッケージを分ける)方式は、
必要な言語だけを取得できる利点があるが、
版の同期を保つ運用が要る。
言語数が少なければ同梱で十分である。

package type

NuGet 3.5 以降で設定可能。

  • Dependency(既定値)
    上記の説明はコレ。

  • DotnetCliTool
    .NET Core プロジェクトにのみインストールできる .NET Core CLI ツール

  • カスタムタイプパッケージ
    Dependency と DotnetCliTool 以外のタイプは、
    Visual Studio の NuGet Package Manager によって認識されない。

補足(現在のパッケージ種別/最新化): DotnetCliTool は廃止され、
DotnetTool(.NET Core 2.1 以降のグローバル / ローカル ツール)に
置き換わっている。

packageType 用途 現況
Dependency 通常のライブラリ 既定
DotnetTool dotnet tool install で入れる CLI ツール 現行
Template dotnet new テンプレート 現行
DotnetCliTool 旧方式(.csproj に書いて復元) 廃止
<!-- CLI ツールとして公開する -->
<PropertyGroup>
  <PackAsTool>true</PackAsTool>
  <ToolCommandName>myctl</ToolCommandName>
</PropertyGroup>
dotnet tool install -g MyCompany.MyTool
myctl --help

注意

依存関係

Dependencies タグ

NuGet サイトに表示されるのは、*.nuspec ファイルの Dependencies タグに明記したもの。

移行メモ(誤記): 原文の「*.nspec ファイル」は
.nuspec の誤記、
「Dependenciesタグ明記したもの」は**「タグに明記したもの」**の
助詞の脱字と判断し修正した。

自動的に追加される NuGet パッケージ

しかし、NuGet から追加された時には、

  • package.config によるのか、
  • バイナリ解析によるのか、

不明だが自動的に依存関係にある NuGet パッケージが追加される。

補足(原文の疑問への回答): バイナリ解析ではない
追加されるのは、

  1. .nuspecdependencies に書かれたパッケージ、および
  2. そのパッケージ自身の dependencies(=推移的依存)

であり、.nuspec の記述だけを辿って解決される

あなたが入れたもの         Foo 1.0
  Foo の .nuspec が言う     → A 1.0, B 2.0
    A の .nuspec が言う     → C 1.0
  …これらがすべて packages.config に平坦に並ぶ

packages.config 方式では推移的依存まで全部書かれるため、
「自動的に追加された」ように見える。
PackageReference では書かれない(復元時に解決される)ため、
この現象自体が起きない
NuGetでインストールすると依存関係が増えすぎる問題)。

なお、dotnet pack で作る場合は
.csprojPackageReference がそのまま dependencies になるため、
「意図しない依存が入る」のは
PrivateAssets="all" の付け忘れが原因であることが多い。

一度登録すると通常消せない。

  • バージョン番号を上げてアップロードすることでアップデートする。
  • 必要に応じて、
    • 旧バージョンを非表示にすることはできる。
    • 別途、運営に連絡して削除することもできる。

補足(削除できない理由): nuget.org は
**「一度公開した版は永続する」**という方針を取っている
(依存する既存プロジェクトのビルドを壊さないため)。

操作 効果
Unlist(一覧から外す) 検索・一覧に出なくなるが、版を明示すれば取得できる
削除(運営に依頼) 原則として受け付けられない(法的問題等の例外のみ)

このため、

の 3 点が特に重要になる。
API キーや接続文字列を誤って同梱した場合、
unlist しても取得可能なままなので、鍵の失効が必須である。

参考

nuspec ファイルの定義例

著名なパッケージを参考にする。

Open棟梁のパッケージを参考にする。

nuspec ファイルのメタデータ要素

この nuspec.xsd を Visual Studio で確認すると Scheme の詳細が解るらしい。

必要なメタデータ要素(最小要件)

# 要素 説明
1 id 大文字と小文字を区別しない、nuget.org などのパッケージ・ギャラリー内で一意なパッケージ識別子。
ID には URL に有効でないスペースや文字を含めない。
2 version major.minor.patch パターンのパッケージのバージョン。
バージョン番号には、プレリリースパッケージに記載されているリリース前のサフィックスが含まれている場合がある。
3 description nuget.org でパッケージのページを表示したときに表示される概要説明文
4 authors パッケージ著者のカンマ区切りのリスト。

オプションのメタデータ要素(必要に応じて追加)

  • 単項目
# 要素名 説明
1 title パッケージには、一般的には UI で使用される、パッケージの人間にとって使いやすいタイトルが nuget.org や Visual Studio のパッケージ・マネージャで表示される。
指定しない場合、パッケージ ID が代わりに使用される。
2 owners nuget.org でプロファイル名を使用しているパッケージ作成者のカンマ区切りのリスト。
これらは nuget.org の NuGet Gallery に表示され、同じ著者によるパッケージの相互参照に使用されている。
3 projectUrl パッケージのホームページの URL。
多くの場合、UI 表示と nuget.org に表示される。
4 licenseUrl パッケージのライセンスの URL。
nuget.org と同様に UI 表示にも表示されることがよくある。
5 iconUrl UI 表示でパッケージのアイコンとして使用する透過背景を持つ 64x64 画像の URL。
6 requireLicenseAcceptance パッケージをインストールする前に、パッケージライセンスを受け入れるようにクライアントに指示する必要があるかどうかを指定するブール値。
7 developmentDependency (2.8+)パッケージが開発専用依存としてマークされるかどうかを指定するブール値。
パッケージが他のパッケージへの依存として含まれないようにする。
8 summary Visual Studio から検索して表示される一覧表示用のパッケージの短い説明。
省略された場合、description の切り詰められたバージョンが使用される。
9 releaseNotes (1.5+)このパッケージのリリースで行われた変更の説明。
パッケージ説明の代わりに Visual Studio パッケージ・マネージャの [更新] タブなどの UI でよく使用される。
10 copyright (1.5+)パッケージの著作権詳細。
11 language パッケージのロケール ID。
ローカライズされたパッケージの作成を参照。
12 tags パッケージを記述するタグとキーワードのスペース区切りリストで、
検索とフィルタリングのメカニズムを通じたパッケージの発見可能性を支援する。
13 serviceable (3.3+)内部 NuGet 専用
14 minClientVersion (2.5+)このパッケージをインストールできる NuGet クライアントの最小バージョンを指定する。
このバージョンは、nuget.exe と Visual Studio Package Manager によって適用される。
これは、パッケージが NuGet クライアントの特定のバージョンで追加された .nuspec ファイルの特定の機能に依存する場合に使用される。
例えば、developmentDependency 属性を使用するパッケージは、minClientVersion に「2.8」を指定する。
同様に、contentFiles 要素を使用するパッケージ(次のセクションを参照)は、minClientVersion を "3.3" に設定する。
また、2.5 より前の NuGet クライアントはこのフラグを認識しないため、minClientVersion で使用する値に関係なく、常にパッケージのインストールを拒否する。
  • 複数項目
# 要素名 説明
1 packageTypes (3.3+)伝統的な依存パッケージ以外のパッケージのタイプを指定する 0 個以上の <packageType> 要素の集合。
各 packageType には name と version の属性がある。パッケージタイプの設定を参照。
2 dependencies パッケージの依存関係を指定する 0 個以上の <dependency> 要素の集合。
各依存関係には、id、version、include(3.x+)、および exclude(3.x+)の属性がある。
下記の依存関係を参照。
3 frameworkAssemblies (1.2+)このパッケージに必要な .NET Framework アセンブリ参照を識別する 0 個以上の <frameworkAssembly> 要素のコレクション。
パッケージを使用するプロジェクトに参照が確実に追加される。
各 frameworkAssembly には assemblyName 属性と targetFramework 属性がある。
下記のフレームワークアセンブリ参照 GAC の指定を参照。
4 references (1.5+)プロジェクトの参照として追加される、パッケージの lib フォルダ内のアセンブリを命名する 0 個以上の <reference> 要素のコレクション。
各参照にはファイル属性がある。
<references> は、<reference> 要素を含む targetFramework 属性を持つ <group> 要素も含むことができる。
省略すると、lib のすべての参照が含まれる。
下記の明示的アセンブリ参照の指定を参照。
5 contentFiles (3.3+)コンシューマプロジェクトに含めるコンテンツファイルを識別する <files> 要素のコレクション。
これらのファイルは、プロジェクトシステム内でどのように使用されるべきかを記述する一連の属性で指定される。
下記のパッケージに含めるファイルの指定を参照。

補足(現在追加された要素): 上表以降に追加され、
現在は指定が推奨されるものを補っておく。

要素 .csproj プロパティ 内容
license PackageLicenseExpression / PackageLicenseFile licenseUrl の後継(SPDX 式)
icon PackageIcon iconUrl の後継(同梱)
readme PackageReadmeFile nuget.org に README を表示
repository RepositoryUrl / RepositoryType ソースの所在(Source Link と連動)

Microsoft Learn

パッケージ作成

移行メモ(誤字): 原文の「高度なタクス」は
高度なタスクの誤記と判断し修正した。

NuGet.org の概要

※ Organizations on NuGet.org | The NuGet Blog
  https://devblogs.microsoft.com/nuget/organizations-on-nuget-org/

NuGetパッケージ関連

Open 棟梁 Wiki

NuGet導入、NuGet登録(OTR_NuGetIntroduction.md

Open棟梁のバージョン番号付与ポリシー(OTR_VersioningPolicy.md

OssCons...TestClassLibrary1

OSS コンソーシアム 開発基盤部で登録したテスト用ライブラリ


Tags: 移行, .NET開発, デプロイ, NuGet

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally