CMake パッケージガイドライン
32ビット – CLR – クロス – Eclipse – Electron – Free Pascal – GNOME – Go – Haskell – Java – KDE – カーネル – Lisp – MinGW – Node.js – ノンフリー – OCaml – Perl – PHP – Python – R – Ruby – Rust – VCS – ウェブ – Wine
この文書は cmake を使うソフトウェアの PKGBUILD を書くための標準とガイドラインをカバーしています。
目次
はじめに
CMake は、ソフトウェアをビルド、テスト、パッケージ化するために設計された、オープンソースでクロスプラットフォームのツールファミリーです。CMake は、プラットフォームやコンパイラに依存しないシンプルな設定ファイルを使ってソフトウェアのコンパイルプロセスを制御し、選択したコンパイラ環境で使用できるネイティブな makefile と workspaces を生成するために使用されます。
典型的な使用方法
典型的な使い方は、cmake
コマンドを実行し、その後に building コマンドを実行することです。cmake
コマンドは通常、いくつかのパラメータを設定し、必要な依存関係をチェックしてビルドファイルを作成し、ソフトウェアを make
や ninja
といった他のツールでビルドできる状態にします。
CMakeの好ましくない動作について
ビルドファイルを生成するための内部特性により、CMake が好ましくない動作をすることがあります。そのため、CMake ベースのソフトウェアのために PKGBUILD を書くときにはいくつかのステップに注意する必要があります。
CMake はデフォルトのコンパイラ最適化フラグを自動的にオーバーライドすることができます
CMake を -DCMAKE_BUILD_TYPE=Release
オプション付きで動かしている人をよく見かけます。上流のプロジェクトでは、ビルド手順にこのオプションをうっかり入れてしまうこともありますが、これは望ましくない振る舞いを生み出します。
それぞれのビルドタイプは CMake に自動的に CFLAGS
と CXXFLAGS
にフラグのセットを追加させます。一般的な Release
ビルドタイプを使うときは、自動的に -O3
[1] コンパイラ最適化フラグを追加し、これは現在 Arch Linux のデフォルトフラグである -O2
よりも優先されます。(設定ファイル makepkg configuration file で定義されています) これは Arch Linux が目標とする最適化レベルから逸脱しているので望ましくありません。
-O3
に関する注意事項
-O3
を使用したからといって、ソフトウェアのパフォーマンスが向上することを保証するものではなく、時にはプログラムの動作が遅くなることもあります。また、状況によってはソフトウェアを壊してしまうこともあります。Arch Linux の開発者がターゲット最適化レベルとして -O2
を選択したのには理由があり、私たちはそれに従うべきでしょう。あなたが何をしているかを正確に分かっている場合、またはアップストリームが -O3
が必要であると明示的・暗示的に言っている場合以外は、私たちのパッケージで使用するのは避けるべきです。
自動最適化フラグオーバーライドの修正
100%保証された方法で修正することは、CMake の柔軟性により、簡単な問題ではありません。すべてのケースに適用できる標準的な解決策は存在しないことに注意してください。ここでは、考えられる解決策と、守るべきポイントについて説明します。
CMake のデフォルトのビルドタイプは None
であり、デフォルトでは CFLAGS
と CXXFLAGS
にフラグを付加しないため、 CMAKE_BUILD_TYPE
オプションを使用しないだけでもデフォルトが None
となり動作することがあります。しかし、多くのソフトウェアプロジェクトでは、ビルドタイプを自動的に Release
に設定するため、このオプションを省略しても問題が解決する保証はないことに注意してください。コマンドラインで CMAKE_BUILD_TYPE
が設定されていない場合、CMake ファイルで (または他のタイプで) 設定します。
デフォルトの None
ビルドタイプは CFLAGS
と CXXFLAGS
にフラグを付加しないので、 -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_RELEASE
と CMAKE_CXX_FLAGS_RELEASE
を設定するようなものです)。CMake 変数)。このようなソフトウェアは、これらの上流で定義されたフラグを使用せずにコンパイルすると、None
ビルドタイプを使用した場合、壊れたり動作がおかしくなったりする可能性があります。フラグが足りないかどうかを判断するには、CMakeファイルを見る必要がありますし、make VERBOSE=1
の出力を None
と Release
ビルドタイプで比較することができます。もし、None
ビルドタイプで上流で定義されたフラグが見落とされた場合はどうすればいいのでしょうか?なぜなら、Release
ビルドタイプを使用すると、望ましくない -O3
フラグを使用する可能性があり、None
ビルドタイプを使用すると、いくつかの必要な上流定義フラグを見逃す可能性があるからです。この状況を解決する標準的な方法はありませんので、ケースバイケースで分析する必要があります。もし上流が Release
ビルドタイプに対して -O2
を定義しているなら、 -DCMAKE_BUILD_TYPE=Release
を使用することができます。(後述)。それ以外の場合は、CMake ファイルにパッチを当てることで解決できるかもしれません。
いくつかのソフトウェアプロジェクトでは CMake ファイルに -O2
を 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.
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.