「CMake パッケージガイドライン」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(→‎ヒントとヒントとテクニック‎: ビルド中の FetchContent のダウンロードを回避を翻訳して追加)
 
(同じ利用者による、間の2版が非表示)
21行目: 21行目:
 
ビルドファイルを生成するための内部特性により、CMake が好ましくない動作をすることがあります。そのため、CMake ベースのソフトウェアのために [[PKGBUILD]] を書くときにはいくつかのステップに注意する必要があります。
 
ビルドファイルを生成するための内部特性により、CMake が好ましくない動作をすることがあります。そのため、CMake ベースのソフトウェアのために [[PKGBUILD]] を書くときにはいくつかのステップに注意する必要があります。
   
=== CMake はデフォルトのコンパイラ最適化フラグを自動的にオーバーライドすることができます ===
+
=== CMake はデフォルトのコンパイラ最適化フラグを自動的にオーバーライドすることがあります ===
   
 
CMake を {{ic|1=-DCMAKE_BUILD_TYPE=Release}} オプション付きで動かしている人をよく見かけます。上流のプロジェクトでは、ビルド手順にこのオプションをうっかり入れてしまうこともありますが、これは望ましくない振る舞いを生み出します。
 
CMake を {{ic|1=-DCMAKE_BUILD_TYPE=Release}} オプション付きで動かしている人をよく見かけます。上流のプロジェクトでは、ビルド手順にこのオプションをうっかり入れてしまうこともありますが、これは望ましくない振る舞いを生み出します。
39行目: 39行目:
 
デフォルトの {{ic|None}} ビルドタイプは {{ic|CFLAGS}} と {{ic|CXXFLAGS}} にフラグを付加しないので、 {{ic|1=-DCMAKE_BUILD_TYPE=None}} オプションも使用可能です。一般的には {{ic|1=-DCMAKE_BUILD_TYPE=None}} オプションを使う方が {{ic|CMAKE_BUILD_TYPE}} を省略するよりも良いと言われています。これは {{ic|CMAKE_BUILD_TYPE}} が省略されたときにアップストリームが自動的にビルドタイプを {{ic|Release}} に設定する場合をカバーするもので、デフォルトではフラグは付加されず、ビルドタイプ {{ic|None}} に好ましくないフラグを設定するソフトウェアはまず見当たりません。
 
デフォルトの {{ic|None}} ビルドタイプは {{ic|CFLAGS}} と {{ic|CXXFLAGS}} にフラグを付加しないので、 {{ic|1=-DCMAKE_BUILD_TYPE=None}} オプションも使用可能です。一般的には {{ic|1=-DCMAKE_BUILD_TYPE=None}} オプションを使う方が {{ic|CMAKE_BUILD_TYPE}} を省略するよりも良いと言われています。これは {{ic|CMAKE_BUILD_TYPE}} が省略されたときにアップストリームが自動的にビルドタイプを {{ic|Release}} に設定する場合をカバーするもので、デフォルトではフラグは付加されず、ビルドタイプ {{ic|None}} に好ましくないフラグを設定するソフトウェアはまず見当たりません。
   
しかし、残念ながら {{ic|1=-DCMAKE_BUILD_TYPE=None}} を使えば解決するというような単純なものではありません。{{ic|-O3}} の問題を解決するために {{ic|None}} のビルドタイプを使用する場合、別の問題に陥る可能性があります。多くのソフトウェアプロジェクトでは、CMake ファイルで {{ic|Release}} ビルドタイプに必要なコンパイラフラグを定義するのが一般的です例えば、{{ic|CMAKE_C_FLAGS_RELEASE}} と {{ic|CMAKE_CXX_FLAGS_RELEASE}} を設定するようなものです)。CMake 変数このようなソフトウェアは、これらの上流で定義されたフラグを使用せずにコンパイルすると、{{ic|None}} ビルドタイプを使用した場合、壊れたり動作がおかしくなったりする可能性があります。フラグが足りないかどうかを判断するには、CMakeファイルを見る必要がありますし{{ic|1=make VERBOSE=1}} の出力を {{ic|None}} と {{ic|Release}} ビルドタイプで比較することができます。もし、{{ic|None}} ビルドタイプで上流で定義されたフラグが見落とされた場合はどうすればいいのでしょうかなぜなら、{{ic|Release}} ビルドタイプを使用すると、望ましくない {{ic|-O3}} フラグを使用する可能性があり、{{ic|None}} ビルドタイプを使用すると、いくつかの必要な上流定義フラグを見逃す可能性があるからです。この状況を解決する標準的な方法はありませんので、ケースバイケースで分析する必要があります。もし上流が {{ic|Release}} ビルドタイプに対して {{ic|-O2}} を定義しているなら、 {{ic|1=-DCMAKE_BUILD_TYPE=Release}} を使用することができます。(後述) それ以外の場合は、CMake ファイルにパッチを当てることで解決できるかもしれません。
+
しかし、残念ながら {{ic|1=-DCMAKE_BUILD_TYPE=None}} を使えば解決するというような単純なものではありません。{{ic|-O3}} の問題を解決するために {{ic|None}} のビルドタイプを使用する場合、別の問題に陥る可能性があります。多くのソフトウェアプロジェクトでは、CMake ファイルで {{ic|Release}} ビルドタイプに必要なコンパイラフラグを定義するのが一般的です (例えば、{{ic|CMAKE_C_FLAGS_RELEASE}} と {{ic|CMAKE_CXX_FLAGS_RELEASE}} を設定するようなものです) CMake 変数)このようなソフトウェアは、これらの上流で定義されたフラグを使用せずにコンパイルすると、{{ic|None}} ビルドタイプを使用した場合、壊れたり動作がおかしくなったりする可能性があります。フラグが足りないかどうかを判断するには、CMakeファイルを見る必要がありますし {{ic|1=make VERBOSE=1}} の出力を {{ic|None}} と {{ic|Release}} ビルドタイプで比較することができます。もし、{{ic|None}} ビルドタイプで上流で定義されたフラグが見落とされた場合はどうすればいいのでしょうか?なぜなら、{{ic|Release}} ビルドタイプを使用すると、望ましくない {{ic|-O3}} フラグを使用する可能性があり、{{ic|None}} ビルドタイプを使用すると、いくつかの必要な上流定義フラグを見逃す可能性があるからです。この状況を解決する標準的な方法はありませんので、ケースバイケースで分析する必要があります。もし上流が {{ic|Release}} ビルドタイプに対して {{ic|-O2}} を定義しているなら、 {{ic|1=-DCMAKE_BUILD_TYPE=Release}} を使用することができます。(後述) それ以外の場合は、CMake ファイルにパッチを当てることで解決できるかもしれません。
   
 
いくつかのソフトウェアプロジェクトでは CMake ファイルに {{ic|-O2}} を {{ic|Release}} ビルドタイプとしてハードコードしています。
 
いくつかのソフトウェアプロジェクトでは CMake ファイルに {{ic|-O2}} を {{ic|Release}} ビルドタイプとしてハードコードしています。
   
 
{{Warning|
 
{{Warning|
* ビルドタイプが {{ic|None}} の場合、一部のソフトウェアが壊れる可能性があります。ビルドタイプが {{ic|None}} の場合、ソフトウェアが壊れたり、機能が失われたりしないかテストしてください。
+
* ビルドタイプが {{ic|None}} の場合、一部のソフトウェアが壊れる可能性があります。ビルドタイプが {{ic|None}} の場合、ソフトウェアが壊れたり、機能が失われたりしないかテストしてください。
* ソフトウェアによっては、ビルドタイプが {{ic|Release}} でないと動作しないものがあります。ソフトウェアについては、実験とテストが必要です。
+
* ソフトウェアによっては、ビルドタイプが {{ic|Release}} でないと動作しないものがあります。実験とテストが必要です。
 
}}
 
}}
   
77行目: 77行目:
 
=== バイナリから安全でない {{ic|RPATH}} 参照を削除する ===
 
=== バイナリから安全でない {{ic|RPATH}} 参照を削除する ===
   
作成されたバイナリが {{ic|RPATH}} に安全でない参照を含むことがあります。これはビルドされたパッケージに対して [[Namcap]] を実行することで確認でき、修正されるべきセキュリティ問題であることがわかります。この問題は、{{ic|1=CMAKE_SKIP_INSTALL_RPATH=YES}} を使用することで修正できる可能性が高いです。または {{ic|1=CMAKE_SKIP_RPATH=YES}} CMake のオプションです。両方を使って実験し、問題のソフトウェアで何がうまくいくかを見る必要があります両方のオプションを使うことは必要ありません。
+
作成されたバイナリが {{ic|RPATH}} に安全でない参照を含むことがあります。これはビルドされたパッケージに対して [[Namcap]] を実行することで確認でき、修正されるべきセキュリティ問題であることがわかります。この問題は、{{ic|1=CMAKE_SKIP_INSTALL_RPATH=YES}} を使用することで修正できる可能性が高いです。または {{ic|1=CMAKE_SKIP_RPATH=YES}} CMake のオプションです。両方を使って実験し、問題のソフトウェアで何がうまくいくかを見る必要があります(両方のオプションを使うことは必要ありません。)
   
 
=== 利用可能な全てのCMakeオプションの取得 ===
 
=== 利用可能な全てのCMakeオプションの取得 ===
   
ソフトウェアプロジェクトで利用可能なすべての「見える」CMakeオプションを取得するには、ソースツリーで {{ic|cmake -LAH}} を実行しますメインの {{ic|CMakeLists.txt}} ファイルがあるところです
+
ソフトウェアプロジェクトで利用可能なすべての「見える」CMakeオプションを取得するには、ソースツリーで {{ic|cmake -LAH}} を実行します(メインの {{ic|CMakeLists.txt}} ファイルがあるところです)
   
 
もし、後で参照するために出力を保存したい場合は、ファイルにリダイレクトすることができます。
 
もし、後で参照するために出力を保存したい場合は、ファイルにリダイレクトすることができます。
   
 
$ cmake -LAH >options.txt 2>&1
 
$ cmake -LAH >options.txt 2>&1
  +
  +
=== ビルド中の FetchContent のダウンロードを回避 ===
  +
  +
CMake は、ビルド時に追加のリソースまたはサブプロジェクトを取得できるようにする [https://cmake.org/cmake/help/latest/module/FetchContent.html FetchContent] モジュールを提供します。ただし、理想的には、すべてのソースは {{ic|sources}} 配列で指定されているため、ビルド前に [[makepkg]] によってフェッチされる必要があります。これは、オプション [https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_SOURCE_DIR_%3CuppercaseName%3E FETCHCONTENT_SOURCE_DIR_<uppercaseName>] を使用して実行できます。これにより、ファイルへのパスを指定できます。それ以外の場合は取得されます。さらに、[https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_FULLY_DISCONNECTED FETCHCONTENT_FULLY_DISCONNECTED=ON] を使用すると、{{ic|FetchContent}} 宣言を見逃しても、ビルド中にすべてのダウンロードをスキップすることができます。
  +
  +
==== 例 ====
  +
  +
プロジェクトがリソース {{ic|foo}} を取得すると仮定します。
  +
  +
{{hc|CMakeLists.txt|<nowiki>
  +
FetchContent_Declare(
  +
foo
  +
URL https://example.com/foo.tar.gz
  +
URL_HASH SHA256=cf051bf611a94884ba5e4c2d03932d14e83875c5b77f0fdf55c404cad0e4a6e6
  +
)
  +
FetchContent_MakeAvailable(foo)
  +
</nowiki>}}
  +
  +
次に、ビルド中にダウンロードする代わりに、このリソースを {{ic|sources}} 配列に追加し、ビルド ファイルの生成時に宣言できます。
  +
  +
{{hc|PKGBUILD|<nowiki>
  +
sources=(
  +
...
  +
"https://example.com/foo.tar.gz"
  +
)
  +
  +
sha256sums=(
  +
...
  +
"cf051bf611a94884ba5e4c2d03932d14e83875c5b77f0fdf55c404cad0e4a6e6"
  +
)
  +
</nowiki>}}
  +
  +
$ cmake -B build -S "$pkgname-$pkgver" -DFETCHCONTENT_FULLY_DISCONNECTED=ON -DFETCHCONTENT_SOURCE_DIR_FOO="$srcdir/foo"
   
 
== テンプレート ==
 
== テンプレート ==

2023年10月30日 (月) 03:47時点における最新版

この文書は cmake を使うソフトウェアの PKGBUILD を書くための標準とガイドラインをカバーしています。

はじめに

CMake web page より

CMake は、ソフトウェアをビルド、テスト、パッケージ化するために設計された、オープンソースでクロスプラットフォームのツールファミリーです。CMake は、プラットフォームやコンパイラに依存しないシンプルな設定ファイルを使ってソフトウェアのコンパイルプロセスを制御し、選択したコンパイラ環境で使用できるネイティブな makefile と workspaces を生成するために使用されます。

典型的な使用方法

典型的な使い方は、cmake コマンドを実行し、その後に building コマンドを実行することです。cmake コマンドは通常、いくつかのパラメータを設定し、必要な依存関係をチェックしてビルドファイルを作成し、ソフトウェアを makeninja といった他のツールでビルドできる状態にします。

CMakeの好ましくない動作について

ビルドファイルを生成するための内部特性により、CMake が好ましくない動作をすることがあります。そのため、CMake ベースのソフトウェアのために PKGBUILD を書くときにはいくつかのステップに注意する必要があります。

CMake はデフォルトのコンパイラ最適化フラグを自動的にオーバーライドすることがあります

CMake を -DCMAKE_BUILD_TYPE=Release オプション付きで動かしている人をよく見かけます。上流のプロジェクトでは、ビルド手順にこのオプションをうっかり入れてしまうこともありますが、これは望ましくない振る舞いを生み出します。

それぞれのビルドタイプは CMake に自動的に CFLAGSCXXFLAGS にフラグのセットを追加させます。一般的な Release ビルドタイプを使うときは、自動的に -O3 [1] コンパイラ最適化フラグを追加し、これは現在 Arch Linux のデフォルトフラグである -O2 よりも優先されます。(設定ファイル makepkg configuration file で定義されています) これは Arch Linux が目標とする最適化レベルから逸脱しているので望ましくありません。

-O3 に関する注意事項

-O3 を使用したからといって、ソフトウェアのパフォーマンスが向上することを保証するものではなく、時にはプログラムの動作が遅くなることもあります。また、状況によってはソフトウェアを壊してしまうこともあります。Arch Linux の開発者がターゲット最適化レベルとして -O2 を選択したのには理由があり、私たちはそれに従うべきでしょう。あなたが何をしているかを正確に分かっている場合、またはアップストリームが -O3 が必要であると明示的・暗示的に言っている場合以外は、私たちのパッケージで使用するのは避けるべきです。

自動最適化フラグオーバーライドの修正

100%保証された方法で修正することは、CMake の柔軟性により、簡単な問題ではありません。すべてのケースに適用できる標準的な解決策は存在しないことに注意してください。ここでは、考えられる解決策と、守るべきポイントについて説明します。

CMake のデフォルトのビルドタイプは None であり、デフォルトでは CFLAGSCXXFLAGS にフラグを付加しないため、 CMAKE_BUILD_TYPE オプションを使用しないだけでもデフォルトが None となり動作することがあります。しかし、多くのソフトウェアプロジェクトでは、ビルドタイプを自動的に Release に設定するため、このオプションを省略しても問題が解決する保証はないことに注意してください。コマンドラインで CMAKE_BUILD_TYPE が設定されていない場合、CMake ファイルで (または他のタイプで) 設定します。

デフォルトの None ビルドタイプは CFLAGSCXXFLAGS にフラグを付加しないので、 -DCMAKE_BUILD_TYPE=None オプションも使用可能です。一般的には -DCMAKE_BUILD_TYPE=None オプションを使う方が CMAKE_BUILD_TYPE を省略するよりも良いと言われています。これは CMAKE_BUILD_TYPE が省略されたときにアップストリームが自動的にビルドタイプを Release に設定する場合をカバーするもので、デフォルトではフラグは付加されず、ビルドタイプ None に好ましくないフラグを設定するソフトウェアはまず見当たりません。

しかし、残念ながら -DCMAKE_BUILD_TYPE=None を使えば解決するというような単純なものではありません。-O3 の問題を解決するために None のビルドタイプを使用する場合、別の問題に陥る可能性があります。多くのソフトウェアプロジェクトでは、CMake ファイルで Release ビルドタイプに必要なコンパイラフラグを定義するのが一般的です (例えば、CMAKE_C_FLAGS_RELEASECMAKE_CXX_FLAGS_RELEASE を設定するようなものです) CMake 変数)このようなソフトウェアは、これらの上流で定義されたフラグを使用せずにコンパイルすると、None ビルドタイプを使用した場合、壊れたり動作がおかしくなったりする可能性があります。フラグが足りないかどうかを判断するには、CMakeファイルを見る必要がありますし make VERBOSE=1 の出力を NoneRelease ビルドタイプで比較することができます。もし、None ビルドタイプで上流で定義されたフラグが見落とされた場合はどうすればいいのでしょうか?なぜなら、Release ビルドタイプを使用すると、望ましくない -O3 フラグを使用する可能性があり、None ビルドタイプを使用すると、いくつかの必要な上流定義フラグを見逃す可能性があるからです。この状況を解決する標準的な方法はありませんので、ケースバイケースで分析する必要があります。もし上流が Release ビルドタイプに対して -O2 を定義しているなら、 -DCMAKE_BUILD_TYPE=Release を使用することができます。(後述) それ以外の場合は、CMake ファイルにパッチを当てることで解決できるかもしれません。

いくつかのソフトウェアプロジェクトでは CMake ファイルに -O2Release ビルドタイプとしてハードコードしています。

警告:
  • ビルドタイプが None の場合、一部のソフトウェアが壊れる可能性があります。ビルドタイプが None の場合、ソフトウェアが壊れたり、機能が失われたりしてないかテストしてください。
  • ソフトウェアによっては、ビルドタイプが Release でないと動作しないものがあります。実験とテストが必要です。

修正内容の確認

ビルドツールの冗長モードを有効にすることで、CMakeで修正内容が正しく使用されているかどうかを確認することができます。例えば、make を使っている場合。(CMakeのデフォルトです) に VERBOSE=1 を追加することで実行できます (make VERBOSE=1 のように。) これにより、実行中のコンパイラコマンドを make が出力するようになります。これで makepkg を実行し、コンパイラが -D_FORTIFY_SOURCE=2-O2 フラグを使っているか出力を確認することができます。各コマンドラインで複数の最適化フラグが表示されている場合、その行の最後のフラグがコンパイラによって使用されます(-O2 が有効になるためには、最後の最適化フラグが必要です。)

Prefix とライブラリのインストール先

Arch Linux 標準の /usr Prefix は -DCMAKE_INSTALL_PREFIX=/usr CMake のオプションで指定できます。多くのソフトウェアがデフォルトでファイルを /usr/local という Prefix にインストールするため、これは通常必要です。

一部のアップストリームプロジェクトは、ライブラリを /usr/lib64 ディレクトリにインストールするように CMake ファイルを設定します。この場合、-DCMAKE_INSTALL_LIBDIR=lib CMake オプションを使用して、ライブラリのインストールディレクトリを /usr/lib に正しく設定できます。

ヒントとヒントとテクニック‎

ディレクトリの指定

CMake バージョン 3.13 以降、ビルドディレクトリを自動的に作成する -B オプションが用意されています。これにより、分離された mkdir によるビルドディレクトリの作成が不要になりました。(または install) コマンドを使用します。-S オプションはソースディレクトリ (CMakeLists.txt ファイルを検索する場所) を指定し、 cmake を実行する前にソースツリーに cd する必要をなくしました。この2つのオプションを組み合わせると、ビルドとソースのディレクトリを指定する便利な方法となります。例えば、foo という名前のプログラムをビルドする場合。

PKGBUILD
build() {
    cmake -B build -S "foo-${pkgver}" [other_cmake_options]
    cmake --build build
}

不要な出力の可能性を低減する

-Wno-dev を使用します。CMake オプションは、CMakeLists.txt ファイルを書いた上流プロジェクトの開発者のみを対象とした警告の出力を抑止します。これらの警告を削除することで、CMake の出力がスムーズになり、それを調べる負担が軽減されます。一般的なルールとして、これらの警告は通常パッケージャが安全に無視できるものです。

バイナリから安全でない RPATH 参照を削除する

作成されたバイナリが RPATH に安全でない参照を含むことがあります。これはビルドされたパッケージに対して Namcap を実行することで確認でき、修正されるべきセキュリティ問題であることがわかります。この問題は、CMAKE_SKIP_INSTALL_RPATH=YES を使用することで修正できる可能性が高いです。または CMAKE_SKIP_RPATH=YES CMake のオプションです。両方を使って実験し、問題のソフトウェアで何がうまくいくかを見る必要があります(両方のオプションを使うことは必要ありません。)

利用可能な全てのCMakeオプションの取得

ソフトウェアプロジェクトで利用可能なすべての「見える」CMakeオプションを取得するには、ソースツリーで cmake -LAH を実行します(メインの CMakeLists.txt ファイルがあるところです)。

もし、後で参照するために出力を保存したい場合は、ファイルにリダイレクトすることができます。

$ cmake -LAH >options.txt 2>&1

ビルド中の FetchContent のダウンロードを回避

CMake は、ビルド時に追加のリソースまたはサブプロジェクトを取得できるようにする FetchContent モジュールを提供します。ただし、理想的には、すべてのソースは sources 配列で指定されているため、ビルド前に makepkg によってフェッチされる必要があります。これは、オプション FETCHCONTENT_SOURCE_DIR_<uppercaseName> を使用して実行できます。これにより、ファイルへのパスを指定できます。それ以外の場合は取得されます。さらに、FETCHCONTENT_FULLY_DISCONNECTED=ON を使用すると、FetchContent 宣言を見逃しても、ビルド中にすべてのダウンロードをスキップすることができます。

プロジェクトがリソース foo を取得すると仮定します。

CMakeLists.txt
FetchContent_Declare(
    foo
    URL https://example.com/foo.tar.gz
    URL_HASH SHA256=cf051bf611a94884ba5e4c2d03932d14e83875c5b77f0fdf55c404cad0e4a6e6
)
FetchContent_MakeAvailable(foo)

次に、ビルド中にダウンロードする代わりに、このリソースを sources 配列に追加し、ビルド ファイルの生成時に宣言できます。

PKGBUILD
sources=(
    ...
    "https://example.com/foo.tar.gz"
)

sha256sums=(
    ...
    "cf051bf611a94884ba5e4c2d03932d14e83875c5b77f0fdf55c404cad0e4a6e6"
)
$ cmake -B build -S "$pkgname-$pkgver" -DFETCHCONTENT_FULLY_DISCONNECTED=ON -DFETCHCONTENT_SOURCE_DIR_FOO="$srcdir/foo"

テンプレート

ここでは、CMake ベースのパッケージの出発点となる build() 関数の一般的なテンプレートについて説明します。パッケージの名前は foo で、C および C++ ベースであり、CMake ファイルの中で Release ビルドタイプに必要なコンパイラフラグを定義していないと仮定します。

ノート: このチェック機能は enable_testing()add_test()CMakeFiles.txt

で使われている場合のみ働きます。

PKGBUILD
build() {
    cmake -B build -S "foo-${pkgver}" \
        -DCMAKE_BUILD_TYPE='None' \
        -DCMAKE_INSTALL_PREFIX='/usr' \
        -Wno-dev
    cmake --build build
}

check() {
    cd build
    ctest --output-on-failure
}

package() {
    DESTDIR="$pkgdir" cmake --install build
}

cmakemakedepends に配置することを忘れないでください。

パッケージの例

参照