CMake パッケージガイドライン

提供: ArchWiki
2022年2月22日 (火) 22:16時点におけるKgx (トーク | 投稿記録)による版 (→‎Fixing the automatic optimization flag override: 翻訳)
ナビゲーションに移動 検索に移動

この文書は 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 でないと動作しないものがあります。ソフトウェアについては、実験とテストが必要です。

Verifying the fixes

You can verify if the fixes are being correctly used by CMake by enabling the verbose mode of the build tool. For example, when using make (which is the CMake default), this can be done by adding VERBOSE=1 to it (like make VERBOSE=1). This will enable make to output the compiler commands that are being executed. You can then run makepkg and examine the output to see if the compiler is using the -D_FORTIFY_SOURCE=2 and -O2 flags. If multiple optimization flags are being displayed in each command line, the last flag in the line will be the one used by the compiler (it means that -O2 needs to be the last optimization flag in order to be effective).

Prefix and library install directories

The standard Arch Linux /usr prefix can be specified by the -DCMAKE_INSTALL_PREFIX=/usr CMake option. This is usually needed because a lot of software defaults to install files into the /usr/local prefix.

Some upstream projects set their CMake files to install libraries into the /usr/lib64 directory. If this is the case, you can correctly set the library installation directory to /usr/lib by using the -DCMAKE_INSTALL_LIBDIR=lib CMake option.

Tips and tricks

Specifying directories

Since CMake version 3.13, there is a -B option that automatically creates the build directory. This avoids the creation of the build directory by a separated mkdir (or install) command. The -S option specifies the source directory (where to search for a CMakeLists.txt file) and avoids the need of cd'ing into the source tree before executing cmake. Combined together, these two options are a convenient way to specify the build and the source directories. For example, for building a program named foo:

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

Reducing possible unneeded output

The -Wno-dev CMake option will suppress the output of some warnings that are meant only for the upstream project developers who write the CMakeLists.txt files. Removing these warnings makes the CMake output smoother and reduces the burden on examining it. As a general rule, these warnings usually can be safely ignored by packagers.

Removing insecure RPATH references from binaries

Sometimes the resulting binaries can contain insecure references in RPATH. This can be verified by running Namcap on the built package and consists in a security issue that should be fixed. There is a good chance to fix this by using the CMAKE_SKIP_INSTALL_RPATH=YES or CMAKE_SKIP_RPATH=YES CMake options. You need to experiment with both and see what will work in the software in question (using both options is not needed).

Getting all available CMake options

For getting all "visible" CMake options that are available for a software project, execute cmake -LAH in the source tree (where the main CMakeLists.txt file is located).

If you want to save the output for later reference, you can redirect it to a file:

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

Template

Here is a general template for the build() function that serves as a starting point for CMake-based packages. Supposing the package is named foo, it is C and C++ based and that it does not define any required compiler flags for the Release build type in the CMake files.

ノート: The check function will only work if projects use enable_testing() and/or add_test() functionality in 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
}

Do not forget to place cmake in makedepends.

Example packages

See also