Help us understand the problem. What is going on with this article?

CMake:configure_fileコマンド

More than 5 years have passed since last update.

はじめに

CMake の configure_file() コマンドを使用すると、テンプレートファイルをもとにファイルを出力できます。
テンプレートファイル内では${VAR} のようなプレースホルダを使用して、CMakeLists.txtで定義した変数の内容を使用できます。
また、単にファイルをコピーすることもできます。

本稿では、configure_file() コマンドの概要を示した後、その使用例として pkg-config 向けのファイルを生成する方法を示します。

configure_file コマンド

コマンド書式

configure_fileコマンドの書式
configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])

コマンド解説

ファイル <input> から、ファイル <output> にファイルをコピーします。コピーする際に、<input> ファイル中の変数への参照
はCMakeLists.txt中のCMake変数の値に置換されます。
<output> が相対パスの場合、現在のバイナリディレクトリからの相対パスとして扱われます。
<input> ファイルが修正されると、ビルドシステムが検知して再出力されます。

変数の置換

configure_file コマンドは、ファイル中の ${VAR} または @VAR@ の形式で参照した変数 VAR をCMake中の同名の変数で置き換えます。もし VAR が未定義なら、空で置換されます。
@ONLY
オプションを指定すると、@VAR の形式のみが置換され、${VAR} の形式は置換されずにそのまま出力されます。

ファイルの単純コピー

COPYONLY が指定されると、一切の置換は行われず、単純にファイルをコピーします。

Cプリプロセッサ向け機能

入力ファイル中の #cmakedefine VAR ... の形式の行は、#define VAR .../* #undef VAR */ のどちらかに置き換えられます。CMake変数のVARif() コマンドで false と評価される場合は、/* #undef VAR */ に、さもなければ#define VAR ...に置き換えられます。...` の部分は、通常と同様のルールで置換されます。

入力ファイル中の #cmakedefine01 VAR の形式は、VAR の値によって #define VAR 1 または #define VAR 0 に置き換えられます。

改行の指定

NEWLINE_STYLE オプションで改行方法を指定できます。

オプション 改行
UNIX または LF \n
DOS または WIN32 または CRLF \r\n

COPYONLYNEWLINE_STYLE と同時に使用してはなりません。

その他

ESCAPE_QUOTES については未調査なので、記載しません。

参考:CMake v3.0 - configure_file(7)

configure_file コマンドの使用例

pkg-config 向けのファイルを生成する

configure_file コマンドを使って、自作のライブラリを使用する際のコンパイルフラグやリンカフラグを、pkg-config で扱えるようにしてみます。

pkg-config が、読み込むファイルは libfoo.pc というファイルなので、configure_file の入力ファイル名はlibfoo.pc.inとします。

libfoo.pc.in を以下のように記述します。libfoo.pc 中に ${VAR} 形式の変数参照を残したいので、変数は@VAR@ 形式で記載します。

libfoo.pc.in
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: Foo
Description: Foo Library
Version: @foo_VERSION@
Libs: -L${libdir} -lfoo
Cflags: -I${includedir}

.pc ファイルの書式については、man pkg-config で確認してください。

CMakeLists.txt は以下のように記述します

pkg-config向けCMakeLists.txt
cmake_minimum_required(VERSION 2.8)

set(foo_VERSION 1.0.0)
add_library(foo foo.c)

configure_file(libfoo.pc.in libfoo.pc @ONLY)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libfoo.pc
    DESTINATION lib/pkgconfig)

install(TARGETS foo
    PUBLIC_HEADER DESTINATION include
    ARCHIVE DESTINATION lib)

インストール先になる libinclude はlibfoo.pc.in と記載を揃えていますが、メンテナンス性を考慮して変数として設定しても構いません。

プロジェクトをビルドし、ビルドディレクトリに以下のような libfoo.pc が出力されたことを確認してください。

libfoo.pc
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: Foo
Description: Foo Library
Version: 1.0.0
Libs: -L${libdir} -lfoo
Cflags: -I${includedir}

このプロジェクトをインストールすると、下記のコマンドで libfoo のコンパイルフラグなどが取得できます。
(当然、pkg-config を別途インストールする必要があります)

$ pkg-config libfoo --cflags --libs
-I/usr/local/include -L/usr/local/lib -lfoo

FindPkgConfig モジュール

configure_file() コマンドとは関連しませんが、FindPkgConfigモジュールの pkg_check_modules を使用すると、pkg-config コマンドを使用してコマンドラインフラグ等を取得し、CMake変数に設定できます。

FindPkgConfig
include(FindPkgConfig)

pkg_check_modules(Foo libfoo)
message(STATUS "Foo_FOUND      ${Foo_FOUND}")
message(STATUS "Foo_CFLAGS     ${Foo_CFLAGS}")
message(STATUS "Foo_LIBRARIES  ${Foo_LIBRARIES}")
message(STATUS "Foo_LDFLAGS    ${Foo_LDFLAGS}")

参考: CMake v3.0 - FindPkgConfigモジュール

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away