次の方法で共有


メンテナー ガイド

このドキュメントでは、vcpkg に投稿するときに従うポリシー、ガイドライン、ベスト プラクティスについて説明します。

これは、次と同じ役割を果たすことを目的としています。

キュレーションされたレジストリ設計の目標

ポートを同時にインストールしなければならない

キュレーションされたレジストリに含まれるポートは、レジストリ内の他のすべてのポートが存在する場合に正常にビルドされる必要があります。 ポートの組み合わせ全体は、vcpkg の自動 CI によって定期的にテストされます。

ポートでは、次の操作を行わないでください。

例外は次の場合に行われます。

  • 公式な役割で別のポートを置き換えるポート。 後続プロジェクト。
  • プラットフォームの重複がないポート。 たとえば、Windows をサポートしていない Linux プロジェクトに対する Windows 専用の置き換えです。
  • このポリシーの前に存在し、ユーザーと共同作成者の数が証明可能なほど多いポート。

このポリシーに準拠していないポートは、キュレーションされたレジストリに受け入れることはできません。

ヒント

ポートをキュレーションされたレジストリに含めることができない場合は、 カスタム レジストリを発行 するか、 オーバーレイ ポートを使用することを検討してください。

ポートは、少なくとも 1 つの公式トリプレットでテストする必要があります

キュレーションされたレジストリ内のすべてのポートは、少なくとも1つの公式トリプレットでCI環境においてテストされる必要があります。

例外は次の場合に行われます。

  • 次のような一時的な状況:
    • CI インフラストラクチャを更新しないと、ポートはビルドされません。
    • アップストリームの依存関係が最近破壊的変更されたため、ポートはビルドされません。状況を解決するための作業が進行中です。
  • このポリシーより前に存在し、利用者と貢献者の数が非常に多いポート。

少なくとも 1 つの公式トリプレットでテストできない新しいポートは、キュレーションされたレジストリには受け入れられません。 このポリシーに準拠しなくなり、一時的に除外されない既存のポートは、レジストリから除外されます。

ヒント

ポートをキュレーションされたレジストリに含めることができない場合は、 カスタム レジストリを発行 するか、 オーバーレイ ポートを使用することを検討してください。

パッケージ化されたプロジェクトは安定し、積極的に維持する必要がある

キュレーションされたレジストリにパッケージ化されたプロジェクトは、アクティブなメンテナンス中である必要があります。 非アクティブなプロジェクトのポートは一覧から削除される可能性があります。

次の場合、プロジェクトは非アクティブと見なされます。

  • そのメンテナーは、プロジェクトを放棄したと宣言しました。
  • アーカイブされているか、投稿を受け入れなくなりました。
  • メンテナーは応答しないか、到達できません。
  • 意味のある変更は長い間行われません。

成熟していて安定していると見なされ、頻繁に変更を受け取らない基本プロジェクトでは例外が発生します。 たとえば、 zlibと指定します。

パッケージ化されたプロジェクトは成熟している必要がある

キュレーションされたレジストリにパッケージ化されたプロジェクトは成熟している必要があり、vcpkg のユーザーによる使用を意図している必要があります。 個人使用を目的としたプロジェクトは、 カスタム レジストリに発行する必要があります。

次のいずれかのステートメントが当てはまる場合、プロジェクトはキュレーションされたレジストリに十分に成熟したと見なされます。

  • プロジェクトには、少なくとも 6 か月前のリリースがあります。
  • このプロジェクトでは、少なくとも 6 か月間のアクティブなパブリック開発を示します。
  • このプロジェクトは、以前の要件を満たす別のプロジェクトの公式コンポーネントです。 たとえば、新しい Boost ライブラリや Qt コンポーネントなどです。
  • プロジェクトは、他の観点からの以前の要件と同等の成熟度を示しています。

プロジェクトの未成熟性のいくつかの指標は次のとおりです。

  • プロジェクトは検索エンジンに表示されません。
  • プロジェクトの名前は頻繁に変更されます。
  • 他のライブラリとの競合。

ヒント

ポートをキュレーションされたレジストリに含めることができない場合は、 カスタム レジストリを発行 するか、 オーバーレイ ポートを使用することを検討してください。

PR 構造体

ポートごとに個別のプル要求を行う

小さいプル要求 (PR) を確認する方が簡単です。 プル要求では、1 つのポートに変更を加える必要があります。 これにより、継続的インテグレーション (CI) の結果の待機時間も短縮されます。

場合によっては、PR を 1 つのポートに制限できない場合があります。 たとえば、ポートを変更する場合、ダウンストリーム コンシューマーを更新または修正する必要があります。

変更されていないファイルの簡単な変更を回避する

再フォーマット、変数の名前変更、入力ミスの修正など、変更されていないポートに簡単な変更を加えないでください。 ポートのインストールの出力に影響を与えない変更は、簡単と見なされます。 単純な変更では、コンピューティング時間が消費されます。それ以外の場合は使用率が高くなります。

固有のポート名を使用する

ポートの名前は、その内容を示す必要があります。

検索エンジンまたは Repology などの特殊なパッケージ ブラウザーでポートの名前を検索すると、対応するプロジェクトにつながる必要があります。

短い名前または一般的な単語の名前が付いたポートでは、曖昧さの解消が必要です。 これは、キュレーションされたレジストリ内のポートの名前にのみ適用されます。パッケージ化されたプロジェクトの名前とその内容は、このポリシーに準拠する必要はありません。

ポートの名前に厳密な関連付けを持つプロジェクトをパッケージ化するポートに対して例外が行われます。 例えば: libpngopenssl、またはzlib

このポリシーに準拠するために、あいまいな名前を持つ新しいポートでは、次のようなプレフィックスを使用できます。

  • リポジトリの所有者、ユーザー名、または組織。 例: google-cloud-cpp。 GitHub プロジェクトのポートの場合、GitHub 所有者は許容される明確なプレフィックス <github owner>-<repository name>です。
  • パッケージが属するスイートの名前: boost-dll。 パッケージがそのようなスイートの公式コンポーネントである場合にのみ。

例: あいまいなポート名

ipという名前のポートは、次の理由であいまいと見なされます。

  • 名前が短すぎます。
  • 名前は一般的な単語であり、
  • 名前はどの単一のプロジェクトにも強く関連付けられません。

名前があいまいかどうかを判断するには、C++ およびオープン ソース プロジェクトで使用される次の一般的なプレフィックスとサフィックスをポート名から削除します。

  • cpp
  • free
  • lib
  • open
  • 数字

たとえば、 ip-cpplibipip5は、同じ ip 語幹に縮小されるため、あいまいです。

ポート名の変更を制限する

ユーザーの混乱を避けるために、ポートの名前を変更できるのは、最後の名前が変更されてから 1 年後までです。

GitHub ドラフト PR を使用する

GitHub Draft PR は、まだマージする準備ができていない作業に関する CI または人間のフィードバックを得るための優れた方法です。 ほとんどの新しい PR は下書きとして開き、CI が通過したら通常の PR に変換する必要があります。

GitHub ドラフト PR の詳細については、「 ドラフトプルリクエストの紹介」を参照してください。

vcpkg チームは、レビュー プロセス中に PR をドラフトに変換できます。 通常、PR をレビューの準備完了としてマークするタイミングを示すコードまたはコメントに変更を加える要求がある場合。

非アクティブな PR を閉じる

vcpkg チームは、60 日を超えるアクティビティがないプル要求 (PR) を閉じる場合があります。

レビュー可能な状態のプル要求の場合、カウントダウンは、vcpkg 保守担当者が最後に変更を要求した時点から始まるか、説明を要求します。 共同作成者が 60 日以内にアクティビティを行わない場合、PR は古いと見なされ、チームの判断で終了される可能性があります。

PR は、次の場合にレビュー可能な状態になります。

  • 失敗した PR チェックがない場合、または投稿者がヘルプを求めるか、失敗の理由を正当化する場合。
  • vcpkg メンテナーからの変更や明確化の要求が保留されているものはありません。
  • マージの競合はありません。

PR が 60 日を超え、レビュー可能な状態でない場合は、レビューなしで閉じることがあります。

ポートファイル

非推奨のヘルパー関数を回避する

現時点では、次のヘルパーは非推奨となっています。

  • vcpkg_extract_source_archive_ex() は、サポートされているオーバーロードの vcpkg_extract_source_archive() に置き換える必要がある (ARCHIVE を使用)
  • vcpkg_extract_source_archive()のないARCHIVEの非推奨のオーバーロードは、ARCHIVEでサポートされているオーバーロードに置き換える必要があります。
  • vcpkg_apply_patches() は、"extract" ヘルパーの PATCHES 引数に置き換える必要があります (例: vcpkg_from_github())
  • vcpkg_build_msbuild()vcpkg_install_msbuild() に置き換える必要があります。
  • vcpkg_copy_tool_dependencies()vcpkg_copy_tools() に置き換える必要があります。
  • vcpkg_configure_cmake 削除後に vcpkg_cmake_configure() に置き換える必要があります PREFER_NINJA
  • vcpkg_build_cmakevcpkg_cmake_build() に置き換える必要があります。
  • vcpkg_install_cmakevcpkg_cmake_install() に置き換える必要があります。
  • vcpkg_fixup_cmake_targetsvcpkg_cmake_config_fixup に置き換える必要があります。

一部の置換ヘルパー関数は、コンシューマーが特定のバージョンで動作をピン留めし、特定のバージョンでヘルパーの動作をロックできるようにするための "ツール ポート" にあります。 次のように、ツール ポートをポートの "dependencies"に追加する必要があります。

{
  "name": "vcpkg-cmake",
  "host": true
},
{
  "name": "vcpkg-cmake-config",
  "host": true
}

ポートファイル内の過剰なコメントを避ける

理想的には、ポートファイルは短く、単純で、可能な限り宣言型にする必要があります。 PR を送信する前に、 create コマンドによって導入されたボイラー プレートコメントを削除します。

16 進数の文字列に小文字を使用する

vcpkg の機能の多くは、16 進数の文字列の比較に依存しています。 例としては、SHA512 ハッシュ、Git コミット ID、ツリー オブジェクト ハッシュなどがありますが、これらに限定されません。

内部的には、vcpkg は、大文字と小文字が区別されない値の比較で小文字の正規化を使用します。 ただし、vcpkg のインフラストラクチャ上に構築されたツールでは、同じ考慮事項が発生しない場合があります。 このため、16 進数の文字列が必要です

次のシナリオでは、一貫性を保つために小文字にする必要があります。

  • vcpkg ヘルパー関数の SHA512 パラメーター。
  • vcpkg ヘルパー関数の REF パラメーター (値が 16 進数の文字列の場合)。
  • git-tree内の オブジェクト。
  • sha512 ファイル内のscripts/vcpkg-tools.json オブジェクト。
  • 16 進文字列の大文字と小文字が重要でないその他の場所。

ポートはパスに依存してはなりません

ポートは、既にインストールされているポートに基づいて動作を変更し、その結果としてインストールする内容が変わるようなことはあってはなりません。 次に例を示します。

> vcpkg install a
> vcpkg install b
> vcpkg remove a

そして

> vcpkg install b

bによってインストールされたファイルは、aの以前のインストールによる影響に関係なく、同じである必要があります。 つまり、ポートは、何らかのアクションを実行する前に、別のポートによってインストールされたツリーに何かが提供されているかどうかを検出しようとしないでください。 このような "パス依存" 動作の具体的で一般的な原因については、以下の「機能を定義する場合、依存関係を明示的に制御する」で説明します。

一意のポート属性ルール

vcpkg システム全体では、ユーザーが同時に使用する必要がある 2 つのポートが同じファイルを提供する可能性はありません。 ポートが別のファイルによって既に提供されているファイルをインストールしようとすると、インストールは失敗します。 たとえば、ポートでヘッダーに非常に一般的な名前を使用する場合は、それらのヘッダーを includeではなくサブディレクトリに配置する必要があります。

このプロパティは、レジストリにすべてのポートをインストールしようとする継続的インテグレーション実行によって定期的にチェックされます。これは、2 つのポートが同じファイルを提供する場合、 FILE_CONFLICTS で失敗します。

非公式の名前空間に CMake エクスポートを追加する

vcpkg の中心的な設計の理想は、ユーザーに対して "ロックイン" を作成しないことです。 ビルド システムでは、システムのライブラリに依存することと、vcpkg のライブラリに依存することに違いはありません。 そのため、CMake エクスポートまたはターゲットを既存のライブラリに "わかりやすい名前" で追加することは避け、アップストリームは vcpkg と競合することなく独自の公式の CMake エクスポートを追加できます。

そのため、ポートがエクスポートする CMake 構成のうち、アップストリーム ライブラリにないものには、プレフィックスとして unofficial- を付ける必要があります。 追加のターゲットは、 unofficial::<port>:: 名前空間に存在する必要があります。

これは、ユーザーに次の情報が表示されることを意味します。

  • vcpkg に特有のパッケージを取得する方法としての find_package(unofficial-<port> CONFIG)
  • unofficial::<port>::<target> そのポートからエクスポートされたターゲットとして。

例 :

  • brotliunofficial-brotli パッケージを作成し、ターゲット unofficial::brotli::brotliを生成します。

各ポートは、フォルダー copyright${CURRENT_PACKAGES_DIR}/share/${PORT} という名前のファイルを提供する必要があります。 パッケージのライセンス コンテンツをソース ファイル内で使用できる場合は、 vcpkg_install_copyright()の呼び出しによってこのファイルを作成する必要があります。 vcpkg_install_copyright また、必要に応じて複数の著作権ファイルをバンドルします。

vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")

このファイルを手動で作成する古い方法は、CMake の組み込みの file コマンドです。 これは、新しいポートでの vcpkg_install_copyright を優先することはお勧めしませんが、引き続き許可されます。

file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)

アップストリーム ソース ファイル内のライセンス コンテンツがテキスト形式 (PDF ファイルなど) にない場合は、 copyright ユーザーがライセンス要件を見つける方法に関する説明を含める必要があります。 可能であれば、これを示す元のソース ファイルへのリンクも含める必要があるため、ユーザーは最新かどうかを確認できます。

file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/copyright" [[As of 2023-07-25, according to
https://github.com/GPUOpen-LibrariesAndSDKs/display-library/blob/master/Public-Documents/README.md#end-user-license-agreement
this software is bound by the "SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT" PDF located at
https://github.com/GPUOpen-LibrariesAndSDKs/display-library/blob/master/Public-Documents/ADL%20SDK%20EULA.pdf
]])

ポートのバージョン制約

ポート内のバージョン制約は、プロジェクトの独立した進化を妨げる可能性があるため、通常は避ける必要があります。 このような制約の追加は、特定の以前のバージョンとの互換性がない実証済みなど、適切に文書化された正当な理由がある場合にのみ許容されます。 これらの制約は、独立したプロジェクトとの同等性を維持するためだけに使用しないでください。

MAYBE_UNUSED_VARIABLES内の変数は、少なくとも 1 つの構成に適用する必要があります

CMake 構成手順中に警告を無音にするために新しい変数を MAYBE_UNUSED_VARIABLES に追加する場合は、新しい変数が適用されたときのケースを説明するコメントを追加する必要があります。 どの構成にも変数が適用されない場合、基になるバグ (たとえば、スペルミスの変数名) が存在する可能性が非常に高く、追加してもビルドに実際の影響はありません。

vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
  FEATURES
    windowsfeature WINDOWS_OPTION
)

vcpkg_configure_cmake(
  SOURCE_PATH "${SOURCE_PATH}"
  OPTIONS
    ${FEATURE_OPTIONS}
  MAYBE_UNUSED_VARIABLES
    # Applies only on Windows
    WINDOWS_OPTION
)

機能

機能を使用して代替手段を実装しない

特徴は追加機能として扱う必要があります。 port[featureA]をインストールし、port[featureB]をインストールする場合は、port[featureA,featureB]をインストールする必要があります。 さらに、2 つ目のポートが [featureA] に依存し、3 つ目のポートが [featureB]に依存している場合は、2 番目と 3 番目のポートの両方をインストールすると、依存関係が満たされている必要があります。

この状況のライブラリでは、vcpkg で表される使用可能なオプションのいずれかを選択する必要があり、別の設定を必要とするユーザーは、現時点でオーバーレイ ポートを使用する必要があります。

旧バージョンとの互換性を保つために、現在は受け入れられない既存の例:

  • libgit2 libzipopen62541はすべて、TLS または暗号化バックエンドを選択するための機能を備えています。 curl には異なる暗号化バックエンド オプションがありますが、実行時に選択できます。つまり、上記のテネットが維持されます。
  • darknet には、依存関係に使用する opencv のバージョンを制御する opencv2opencv3機能があります。

機能はプレビュー機能またはベータ版の機能を利用する場合があります

上記にかかわらず、プレビュー機能がプレビュー以外の機能 (API の削除なしなど) を中断しない可能性が高いプレビュー ブランチなどがある場合は、この設定をモデル化できます。

例 :

  • (フォーム azure-Xxxの) Azure SDK には、 public-preview 機能があります。
  • imgui には、公開番号付きリリースごとに添付されたマージ コミットを使用するプレビュー ドッキング ブランチを使用する experimental-docking 機能があります。

既定の機能では API を追加できません

アップストリーム ビルド システムによって既定で有効になっている機能は、その機能を default-features エントリに追加する必要があることを意味するものではありません。 default-featuresの目的は、アップストリームによって行われた決定をモデル化するのではなく、クラシック モードのユーザーに利便性を提供することです。

既定の機能は、ライブラリを使用していることを知らないお客様に対して、ライブラリの合理的に機能的なビルドが確実にインストールされるようにするためのものです。 ライブラリを使用していることを知らない場合は、機能を一覧表示することはできません。 たとえば、 libarchive は、圧縮アルゴリズムを有効にする機能を既存の汎用インターフェイスに公開します。そのような機能を使用せずにビルドされた場合、ライブラリにはユーティリティがない可能性があります。

既定の機能の無効化は複雑であるため、機能を既定でオンにする必要があるかどうかを慎重に検討する必要があります。

"推移的" コンシューマーとして既定の機能を無効にする場合は、次のものが必要です。

  • すべてのお客様は、 "default-features": false を使用して既定の機能を明示的に無効にするか、コマンド ラインの機能リストに [core] を含めます。
  • vcpkg install コマンド ラインに推移的な依存関係の名前を付けるか、最上位レベルのマニフェストで直接依存関係として名前を付ける

vcpkg のキュレーション レジストリでは、機能によって追加の API、実行可能ファイル、またはその他のバイナリが追加される場合は、既定でオフになっている必要があります。 不明な場合は、機能を既定としてマークしないでください。

発行済みインターフェイスの代替機能を制御するために機能を使用しない

ポートのコンシューマーがそのポートのコア機能のみに依存している場合、機能をオンにしても問題が生じることはほぼ避けなければなりません。 これは、代替手段がコンシューマーによって直接制御されるのではなく、 /std:c++17 / -std=c++17などのコンパイラ設定によって制御される場合にさらに重要になります。

旧バージョンとの互換性を保つために、現在は受け入れられない既存の例:

  • redis-plus-plus[cxx17] はポリフィルを制御しますが、設定をインストール済みのツリーにベイクしません。
  • ace[wchar]は、const wchar_t*ではなくconst char*を受け入れるようにすべての API を変更します。

インストールされたツリーに置き換えが組み込まれている場合、機能によりポリフィルがエイリアスで置き換えられる場合があります

上記にかかわらず、ポートは、次の場合に限り、機能を備えたポリフィルを削除できます。

  1. この機能をオンにすると、ポリフィルがポリフィルされたエンティティのエイリアスに変更されます
  2. ポリフィルの状態はインストールされたヘッダーに組み込まれているため、ABI の不一致による "不可能な" ランタイムエラーが発生する可能性は低い。
  3. ポートのコンシューマーは、たとえば、ポリフィルされた typedef を使用するかどうかにかかわらず、両方のモードで機能するコードを書くことができます。

例:

  • abseil[cxx17]absl::string_viewを置換またはstd::string_viewに変更します。パッチはベーキング要件を実装します。

基になる代替手段を公開することが重要な場合は、ビルド時にメッセージを提供して、プライベート オーバーレイにポートをコピーする方法をユーザーに指示することをお勧めします。

set(USING_DOG 0)
message(STATUS "This version of LibContoso uses the Kittens backend. To use the Dog backend instead, create an overlay port of this with USING_DOG set to 1 and the `kittens` dependency replaced with `dog`.")
message(STATUS "This recipe is at ${CMAKE_CURRENT_LIST_DIR}")
message(STATUS "See the overlay ports documentation at https://github.com/microsoft/vcpkg/blob/master/docs/specifications/ports-overlay.md")

ビルド手法

ベンダーの依存関係を使用しない

ライブラリの埋め込みコピーは使用しないでください。 更新および保守できるように、すべての依存関係を分割して個別にパッケージ化する必要があります。

ベンダーの依存関係では、信頼性が高く、一貫性があり、保守可能なパッケージ管理システムを提供するという vcpkg の目標と競合するいくつかの課題が発生します。

更新の難しさ: ライブラリの埋め込みコピーにより、アップストリーム プロジェクトからのセキュリティ パッチを含む更新プログラムの追跡と適用が困難になります。 これにより、潜在的なセキュリティ リスクと、エコシステム内の古い依存関係が発生します。

シンボルの競合: 複数のパッケージに同じライブラリの異なるバージョンが含まれている場合、ベンダーの依存関係によってシンボルの競合が発生する可能性があります。

たとえば、パッケージ A ベンダー ライブラリ X (バージョン 1) とパッケージ B ベンダー ライブラリ X (バージョン 2) の場合、両方のパッケージをリンクしているアプリケーションで、シンボルの競合が原因で実行時エラーまたは未定義の動作が発生する可能性があります。

vcpkg は依存関係を個別にパッケージ化することで、すべてのパッケージでライブラリの単一バージョンが使用され、このような競合を排除します。

ライセンスコンプライアンス: ベンダーの依存関係は、組み込みライブラリのライセンスを隠し、使用条件に違反したり、互換性の問題を引き起こしたりする可能性があります。

メンテナンスの負担の増加: ベンダーの依存関係をアップストリーム バージョンと同期させるには、手作業が必要であり、パッケージ間で重複する作業につながることがよくあります。

CMake の使用を優先する

複数のビルドシステムが使用可能な場合は、CMake を使用することをお選び下さいます。 さらに、必要に応じて、 file(GLOB) ディレクティブを使用して代替ビルドシステムを CMake に書き換える方が簡単で保守しやすくなります。

例: abseil

静的バイナリまたは共有バイナリを選択する

CMake ライブラリをビルドするときに、 vcpkg_cmake_configure() は、ユーザーの要求されたバリアントに基づいて、 BUILD_SHARED_LIBS の正しい値を渡します。

string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" ...)を使用して、代替構成パラメーターを計算できます。

# portfile.cmake

string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" KEYSTONE_BUILD_STATIC)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" KEYSTONE_BUILD_SHARED)

vcpkg_cmake_configure(
    SOURCE_PATH ${SOURCE_PATH}
    OPTIONS
        -DKEYSTONE_BUILD_STATIC=${KEYSTONE_BUILD_STATIC}
        -DKEYSTONE_BUILD_SHARED=${KEYSTONE_BUILD_SHARED}
)

ライブラリでビルド バリアントを選択するための構成オプションが提供されていない場合は、ビルドに修正プログラムを適用する必要があります。 ビルドにパッチを適用する場合は、常にポートの将来の保守性を最大限に高める必要があります。 通常、これは、目の前の問題を解決するためにタッチする必要がある行の数を最小限にすることを意味します。

例: 不要なバリアントを構築しないように CMake ライブラリにパッチを適用する

たとえば、CMake ベースのライブラリにパッチを適用する場合、不要なターゲットに EXCLUDE_FROM_ALL を追加し、 install(TARGETS ...) 呼び出しを if(BUILD_SHARED_LIBS)でラップするだけで十分な場合があります。 これは、不要なバリアントに言及するすべての行を折り返したり削除したりするよりも短くなります。

次の内容を含むプロジェクト CMakeLists.txt の場合:

add_library(contoso SHARED contoso.c)
add_library(contoso_static STATIC contoso.c)

install(TARGETS contoso contoso_static EXPORT ContosoTargets)

install(EXPORT ContosoTargets
  FILE ContosoTargets
  NAMESPACE contoso::
  DESTINATION share/contoso)

install(TARGETS)行にのみ修正プログラムを適用する必要があります。

add_library(contoso SHARED contoso.c)
add_library(contoso_static STATIC contoso.c)

if(BUILD_SHARED_LIBS)
  set_target_properties(contoso_static PROPERTIES EXCLUDE_FROM_ALL 1)
  install(TARGETS contoso EXPORT ContosoTargets)
else()
  set_target_properties(contoso PROPERTIES EXCLUDE_FROM_ALL 1)
  install(TARGETS contoso_static EXPORT ContosoTargets)
endif()

install(EXPORT ContosoTargets
  FILE ContosoTargets
  NAMESPACE contoso::
  DESTINATION share/contoso)

機能を定義する場合は、依存関係を明示的に制御します

オプションの依存関係をキャプチャする機能を定義する場合は、機能が明示的に有効になっていないときに依存関係が誤って使用されないようにします。

set(CMAKE_DISABLE_FIND_PACKAGE_ZLIB ON)
set(CMAKE_REQUIRE_FIND_PACKAGE_ZLIB OFF)
if ("zlib" IN_LIST FEATURES)
  set(CMAKE_DISABLE_FIND_PACKAGE_ZLIB OFF)
  set(CMAKE_REQUIRE_FIND_PACKAGE_ZLIB ON)
endif()

vcpkg_cmake_configure(
  SOURCE_PATH ${SOURCE_PATH}
  OPTIONS
    -DCMAKE_DISABLE_FIND_PACKAGE_ZLIB=${CMAKE_DISABLE_FIND_PACKAGE_ZLIB}
    -DCMAKE_REQUIRE_FIND_PACKAGE_ZLIB=${CMAKE_REQUIRE_FIND_PACKAGE_ZLIB}
)

vcpkg_check_features()を使用する次のスニペットは同等です。

vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
  FEATURES
    "zlib"    CMAKE_REQUIRE_FIND_PACKAGE_ZLIB
  INVERTED_FEATURES
    "zlib"    CMAKE_DISABLE_FIND_PACKAGE_ZLIB
)

vcpkg_cmake_configure(
    SOURCE_PATH ${SOURCE_PATH}
    OPTIONS
      ${FEATURE_OPTIONS}
)

スニペットの ZLIB では大文字と小文字が区別されます。 詳細については、 CMAKE_DISABLE_FIND_PACKAGE_<PackageName>CMAKE_REQUIRE_FIND_PACKAGE_<PackageName> のドキュメントを参照してください。

次のいずれかの場合、lib は競合すると見なされます。

  • main を定義する
  • malloc の定義
  • 他のライブラリでも宣言されているシンボルを定義する

競合するライブラリは通常、設計上の意図によるものであり、欠陥とは見なされません。 一部のビルド システムは lib ディレクトリ内のすべてにリンクするため、 manual-linkという名前のサブディレクトリに移動する必要があります。

事前構築済みバイナリのインストール

他のポートのバージョン変更を妨げない限り、事前構築された (バイナリのみの) アーティファクトをインストールするポートは許容されますが、使用はあまり推奨されません。 ソースからのビルドは、コンパイラまたはフラグを変更するすべての vcpkg の設定を尊重するため、推奨されます。

次のすべての条件を満たすポートは拒否されます。

  1. ソースからビルドするのではなく、事前構築済みのバイナリをインストールし、
  2. これらのバイナリには、キュレーションされたレジストリ内の他のポートによって提供される (または実行時に必要な) 依存関係があります。
  3. インストールされた成果物は、vcpkg の公開済みリンク ドメインに入ります。つまり、ダウンストリーム ポートまたはユーザー プロジェクトがリンクする必要があるライブラリ/ヘッダー/CMake または pkg-config メタデータをインストールします。

根拠: この組み合わせにより、依存関係グラフの ABI が、アップストリームの事前構築済み作成時に使用されたバージョンに効果的にロックされます。 vcpkg は、事前構築済みライブラリにリンクしているコンシューマーに対して微妙な ODR/ABI 破損を危険にさらすことなく、 zlibopenssl、または同様の依存関係を安全に更新することはできません。また、ユーザーは重要なセキュリティ パッチを見逃す可能性があります。

"公開されたリンク ドメインを入力します" は、通常、次のいずれかを意味します。

  • ユーザーがリンクすることを目的とした.lib.a.so.dylib、またはインポートライブラリをインストールする。
  • 他の vcpkg ポートからシンボル、型、またはマクロを参照する (直接またはインライン/テンプレート コードを介して) ヘッダーを配布する。
  • 他の vcpkg ポートで find_dependency() / Requires: を呼び出す CMake 構成/pkg-config ファイルのインストール。

許可されている (ただし推奨されない) シナリオ:

  • ビルド時に使用されるホスト専用ヘルパー ツール (実行可能ファイル) で、出力は消費されますが、依存関係をプライベートにバンドルするか、ユビキタス システム ランタイム ライブラリのみに依存している場合は、依存ポートによってリンクされません。
  • すべての OSS 依存関係を静的にリンクし、インストールされているヘッダーまたはエクスポートされたインターフェイスを介してシンボルや型を公開しない完全に自己完結型の事前構築済みライブラリ (コンシューマーは推移的な ABI を観察したり依存したりすることはできません)。
  • ユーザーコードにリンクされていないデータのみ、ファームウェア、およびアセットパッケージ。

禁止されている例:

  • 特定のlibfooバージョンに対してコンパイルされた、lib/libfoo.lib<zlib.h>をインストールし、zlibを含むヘッダーを持つ事前構築済みのlib/libfoo.lib。その後、コンシューマーは互換性を期待してにリンクします。
  • バイナリが以前の OpenSSL リリースに対してコンパイルされている間に find_dependency(OpenSSL) を呼び出す CMake パッケージ ファイルをインストールする事前構築済み SDK。

軽減策/代替手段:

  • アップストリーム スクリプトを使用してソースからのビルドを提供するか、薄いCMakeラッパーを追加します。
  • ソース ベースのリリースまたは再現可能なビルド命令を公開するようにアップストリームに依頼します。 portfile.cmake または vcpkg.jsonのコメントでアップストリームの問題/PR をリンクします。
  • これらの規則を満たすことができない組織固有の事前構築済みには、 オーバーレイ ポート またはプライベート レジストリを使用します。

バージョン管理

"version" フィールドの一般的な規則に従う

新しいポートを作成するときは、パッケージ作成者が使用するバージョン管理規則に従ってください。 ポートを更新する場合は、アップストリームで特に断りがない限り、引き続き同じ規則を使用します。 規則の詳細については、 バージョン管理に関するドキュメントを参照してください

アップストリームがしばらくリリースを公開していない場合は、最新の変更を取得するために、ポートのバージョン管理スキームを version-date に変更しないでください。 これらのコミットには、運用環境の準備ができていない変更が含まれる場合があります。 代わりに、アップストリーム リポジトリに新しいリリースを発行するよう依頼してください。

変更されたポートのマニフェスト ファイルの "port-version" フィールドを更新します

vcpkg は、このフィールドを使用して、特定のポートが古く、ポートの動作が変更されるたびに変更する必要があるかどうかを判断します。

この規則では、アップストリーム バージョンを変更しないポートへの変更に "port-version" フィールドを使用し、アップストリーム バージョンへの更新が行われたときに "port-version" をゼロにリセットします。

例:

  • Zlib のパッケージバージョンは現在1.2.1です。明示的な"port-version"はなく、これは"port-version"0に相当します。
  • 間違った著作権ファイルがデプロイされていることを発見し、ポートファイル内で修正しました。
  • マニフェスト ファイルの "port-version" フィールドを 1に更新する必要があります。

詳細については、 バージョン管理のドキュメント を参照してください。

変更されたポートの versions/ でバージョン ファイルを更新する

vcpkg は、一連のメタデータ ファイルを使用してバージョン管理機能を強化します。 これらのファイルは、次の場所にあります。

  • ${VCPKG_ROOT}/versions/baseline.json、(このファイルはすべてのポートに共通です)、
  • ${VCPKG_ROOT}/versions/${first-letter-of-portname}-/${portname}.json (ポートごとに 1 つ)。

たとえば、関連するファイル zlib 次のようになります。

  • ${VCPKG_ROOT}/versions/baseline.json
  • ${VCPKG_ROOT}/versions/z-/zlib.json

ポートを更新するたびに、そのバージョン ファイルも更新される予定です。

これらのファイルを更新するには、次のような x-add-version コマンドを実行することをお勧めします。

vcpkg x-add-version zlib

複数のポートを同時に更新する場合は、代わりに次のコマンドを実行できます。

vcpkg x-add-version --all

変更されたすべてのポートのファイルを一度に更新します。

詳細については、バージョン管理のリファレンスレジストリの に関する記事を参照してください。

パッチを適用すること

vcpkg はパッケージ ソリューションであり、デプロイするコンポーネントの最終的な所有者ではありません。 場合によっては、コンポーネントとプラットフォームの互換性、またはコンポーネントの互換性を向上させるために、パッチを適用する必要があります。

  • パッチのうち、以下を回避したいと考えています。
    • アップストリームは同意しないでしょう
    • 脆弱性やクラッシュを引き起こす
    • アップストリーム バージョンの更新プログラム全体を維持することは不可能です
    • は、vcpkg リポジトリ自体とライセンスの絡み合いを引き起こすのに十分な大きさです

アップストリーム関連パッチについてアップストリーム所有者に通知する

アップストリームでパッチが役に立つ可能性がある場合は、アップストリームにパッチの内容を通知する必要があります。 (依存関係の取り外しなど、アップストリームに関係のない vcpkg 固有の動作を適用するパッチでは、通知する必要がありません)。

アップストリームがパッチと一致しない状況を回避するために、そのようなパッチの適用を少なくとも 30 日間待ちます。

変更が正しいという確信が高い場合は、この待機期間をスキップします。 信頼度の高いパッチの例としては、次のようなものがありますが、これらに限定されません。

  • アップストリームでのパッチの受け入れ (アップストリームがマージした pull request から特定の変更をバックポートするなど)。
  • 不足している #includeを追加する。
  • 小規模で明白な製品コードの修正 (初期化されていない変数の初期化など)。
  • テストや例など、ビルドの無関係な vcpkg コンポーネントを無効にします。

修正プログラムの適用よりもオプションを優先する

設定に直接パッチを適用するよりも vcpkg_configure_xyz() する呼び出しでオプションを設定することをお勧めします。

修正プログラムの適用を回避できる一般的なオプション:

  • [MSBUILD] <PropertyGroup> プロジェクト ファイル内の設定は、 /p: パラメーターを使用してオーバーライドできます
  • [CMAKE] CMake スクリプトでの find_package(XYz) の呼び出しは -DCMAKE_DISABLE_FIND_PACKAGE_XYz=ON によって無効にすることができます。
  • [CMAKE]キャッシュ変数 ( set(VAR "value" CACHE STRING "Documentation") または option(VAR "Documentation" "Default Value") として宣言) は、コマンド ラインで -DVAR:STRING=Fooとして渡すだけでオーバーライドできます。 注目すべき例外の 1 つは、 FORCE パラメーターが set()に渡される場合です。 詳細については、 CMake set のドキュメントを参照してください。

承認されたパッチをダウンロードすることを、ポートへのチェックインよりも優先する

承認されたパッチ ファイルまたはマージされたパッチ ファイルをアップストリームから取得できる場合は、ポート ファイルの一部として取得するのではなく、それらをダウンロードして適用する必要があります。 このプロセスは、次の理由で優先されます。

  • アップストリームがパッチの変更を受け入れたことを確認します
  • onus をアップストリームにシフトすることで、レビュー プロセスを簡略化します。
  • パッチを使用していないユーザーの vcpkg リポジトリ のサイズを小さくします
  • vcpkg リポジトリとのライセンスの競合を回避します

SHA の競合を回避するには、安定したエンドポイントからパッチをダウンロードする必要があります。 プル要求からパッチ ファイルをダウンロードする場合、または GitHub と GitLab からコミットする場合は、 ?full_index=1 パラメーターをダウンロード URL に追加する必要があります。

例 :

  • https://github.com/google/farmhash/pull/40.diff?full_index=1
  • https://github.com/linux-audit/audit-userspace/commit/f8e9bc5914d715cdacb2edc938ab339d5094d017.patch?full_index=1
  • https://gitlab.kitware.com/paraview/paraview/-/merge_requests/6375.diff?full_index=1

VCPKG_<VARIABLE>値のオーバーライドよりも修正プログラムの適用を優先する

VCPKG_<VARIABLE>プレフィックスが付いた一部の変数には、同等のCMAKE_<VARIABLE>があります。 ただし、そのすべてが内部パッケージ ビルド (実装: Windows ツールチェーンを参照) に渡されるわけではありません。

次の例を確認してください。

set(VCPKG_C_FLAGS "-O2 ${VCPKG_C_FLAGS}")
set(VCPKG_CXX_FLAGS "-O2 ${VCPKG_CXX_FLAGS}")

vcpkgの組み込みツールチェーンを使用すると、VCPKG_<LANG>_FLAGSの値が適切なCMAKE_LANG_FLAGS変数に転送されるため、これは機能します。 ただし、 vcpkgの変数を認識していないカスタム ツールチェーンは、それらを転送しません。

このため、 CMAKE_<LANG>_FLAGS設定するときにビルドシステムに直接パッチを適用することをお勧めしています。

パッチを最小限に抑える

ライブラリに変更を加える場合は、最終的な差分を最小限に抑えるように努めます。 つまり、リージョンに影響を与える変更を行うときは、アップストリームのソース コードを再フォーマットしないでください。 条件付きを無効にする場合は、条件のすべての行を削除するよりも、条件に AND FALSE または && 0 を追加することをお勧めします。 大きなリージョンを無効にする必要がある場合は、パッチ内のすべての行を削除するのではなく、リージョンの周りに if(0) または #if 0 を追加する方が短くなります。

ポートが古く、ポートを新しいリリースバージョンに更新すると同じ問題が解決する場合は、パッチを追加しないでください。 vcpkg では、古いバージョンにパッチを適用するよりも、ポートの更新が優先されます。

これにより、vcpkg リポジトリのサイズを減らしながら、将来のコード バージョンにパッチが適用される可能性が向上します。

パッチに機能を実装しない

vcpkg で修正プログラムを適用する目的は、コンパイラ、ライブラリ、プラットフォームとの互換性を有効にすることです。 適切なオープン ソースの手順に従う代わりに新機能を実装する (問題/PR などを送信する) ためのものではありません。

既定ではテスト/ドキュメント/例をビルドしないでください

新しいポートを送信するときは、 BUILD_TESTSWITH_TESTSPOCO_ENABLE_SAMPLES などのオプションを確認し、追加のバイナリが無効になっていることを確認します。 これにより、平均ユーザーのビルド時間と依存関係が最小限に抑えられます。

必要に応じて、テストのビルドを可能にする test 機能を追加できますが、これは Default-Features リストに含めてはなりません。

ライブラリの既存のユーザーが vcpkg に切り替えるようにする

追加しないでください CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS

ライブラリの作成者が既に使用している場合を除き、この CMake 機能は C++ テンプレートと十分に対話せず、特定のコンパイラ機能を中断するため、使用しないでください。 .def ファイルを提供せず、__declspec() 宣言を使用しないライブラリは、単に Windows の共有ビルドをサポートしていないため、次のようにマークする必要があります。

if(VCPKG_TARGET_IS_WINDOWS)
    vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
endif()

アップストリームによって指定された名前の外部にあるバイナリの名前を変更しないでください

つまり、アップストリーム ライブラリの名前がリリースとデバッグで異なる場合 (libx と libxd)、デバッグ ライブラリの名前を libx に変更しないでください。 逆に、アップストリーム ライブラリがリリースとデバッグで同じ名前を持つ場合は、新しい名前を導入しないでください。

重要な注意事項:

  • 多くの場合、静的バリアントと共有バリアントの名前を共通スキームに変更する必要があります。 これにより、コンシューマーは共通名を使用し、ダウンストリーム リンケージを無視できます。 これは、一度に 1 つしか使用できないため、安全です。

ライブラリで CMake 統合ファイル (foo-config.cmake) が生成される場合は、単に出力アーカイブ/LIB で file(RENAME) を呼び出すのではなく、CMake ビルド自体に修正プログラムを適用して名前を変更する必要があります。

最後に、Windows 上の DLL ファイルは、生成された LIB を壊すので、ビルド後に名前を変更しないでください。

マニフェスト

マニフェスト ファイルを書式設定する必要があります。 すべてのマニフェスト ファイルを書式設定するには、次のコマンドを使用します。

> vcpkg format-manifest --all

三つ子

現時点では、コミュニティ以外のトリプレットを追加する要求は受け付けていません。 コミュニティから完全なトリプレット状態への昇格は、主にハードウェアがこのようなトリプレットをテストするための予算に基づいており、実際に使用するものが完全にテストされる可能性を最大化するために vcpkg によって送信されたメトリックによって駆動されます。

以下の場合、コミュニティトリプレットを追加します。

  • 人々が実際にそのコミュニティ トリプレットを使用することが実証されています。
  • 私たちは、そのような三重項が壊れていることを知らない。

たとえば、 https://github.com/microsoft/vcpkg/pull/29034 にトリプレットを追加しませんでした。これは、作成者が実際にそのようなものを使用することを示すのではなく、単に "セットを完了" しようとしていただけであり、結果を再配置可能にするために patchlf ソリューションが作成されるまで linux-dynamic を追加しませんでした。

便利な実装に関する注意事項

ポートファイルはスクリプト モードで実行されます

portfile.cmakeCMakeLists.txtは共通の構文とコア CMake 言語コンストラクト ("Scripting Commands") を共有していますが、ポートファイルは "スクリプト モード" で実行されますが、CMakeLists.txt ファイルは "プロジェクト モード" で実行されます。 これら 2 つのモードの最も重要な違いは、"スクリプト モード" には "Toolchain"、"Language"、"Target" という概念が含まれていないということです。 これらのコンストラクト ( CMAKE_CXX_COMPILERCMAKE_EXECUTABLE_SUFFIXCMAKE_SYSTEM_NAME など) に依存するスクリプト コマンドを含む動作は正しくありません。

Portfile はトリプレット ファイルで設定された変数に直接アクセスできますが、 CMakeLists.txtにはアクセスできません (ただし、多くの場合、変換が行われますが、 VCPKG_LIBRARY_LINKAGEBUILD_SHARED_LIBS)。

ポートファイルによって呼び出されるポートファイルとプロジェクト ビルドは、異なるプロセスで実行されます。 概念的に言えば

+----------------------------+       +------------------------------------+
| CMake.exe                  |       | CMake.exe                          |
+----------------------------+       +------------------------------------+
| Triplet file               | ====> | Toolchain file                     |
| (x64-windows.cmake)        |       | (scripts/buildsystems/vcpkg.cmake) |
+----------------------------+       +------------------------------------+
| Portfile                   | ====> | CMakeLists.txt                     |
| (ports/foo/portfile.cmake) |       | (buildtrees/../CMakeLists.txt)     |
+----------------------------+       +------------------------------------+

ポートファイル内のホストを特定するために、標準の CMake 変数は問題ありません (CMAKE_HOST_WIN32)。

ポートファイル内のターゲットを決定するには、vcpkg triplet 変数を使用する必要があります (VCPKG_CMAKE_SYSTEM_NAME)。

使用可能な設定の完全な列挙については、 triplet のドキュメント も参照してください。