CMakeのfind_fileコマンドで開発効率アップ!ライブラリやヘッダーファイルを楽々検索


find_file()コマンドは、指定された名前のファイルのフルパスを検索するために使用されます。このコマンドは、CMakeの"Commands"モジュールの一部であり、プロジェクトに必要なライブラリやヘッダーファイルなどのファイルを自動的に検出するのに役立ちます。

構文

find_file(<VAR> NAMES name1 [name2 ...]
         PATHS path1 [path2 ...]
         [OPTIONS option1 [option2 ...]])

引数

  • OPTIONS: オプション
  • PATHS: 検索対象のディレクトリパス。複数指定可能
  • NAMES: 検索対象のファイル名。複数指定可能
  • <VAR>: 検索結果を格納する変数名

オプション

  • DOC: 検索対象のファイルに関するドキュメント
  • REQUIRED: ファイルが見つからない場合、エラーを発生させる
  • QUIET: 検索結果を出力しない
  • NO_CMAKE_PATH: CMake固有の検索パスを使用しない
  • NO_DEFAULT_PATH: デフォルトの検索パスを使用しない

find_file(MY_HEADER_FILE foo.h
         PATHS /usr/include
         DOC "My header file")

この例では、/usr/includeディレクトリ内でfoo.hという名前のヘッダーファイルを検索し、そのフルパスをMY_HEADER_FILE変数に格納します。

  • find_file()コマンドは、キャッシュを使用して検索結果を保存します。つまり、同じファイルが何度も検索された場合、キャッシュから結果が読み込まれます。
  • ファイルが見つかった場合、そのファイルのフルパスがVAR変数に格納されます。ファイルが見つからない場合、VAR変数は空になります。
  • find_file()コマンドは、再帰的に検索しません。つまり、サブディレクトリは検索されません。
  • CMakeの"Commands"モジュールは、プロジェクトのビルドプロセスを自動化するために使用できる機能が豊富です。
  • CMakeには、find_path()コマンドなど、ファイル検索に関連する他のコマンドもいくつかあります。


cmake_minimum_required(VERSION 3.17)
project(myproject)

find_file(MY_HEADER_FILE foo.h
         PATHS /usr/include
         DOC "My header file")

if(MY_HEADER_FILE)
  message(STATUS "Found header file: ${MY_HEADER_FILE}")
else()
  message(FATAL_ERROR "Header file not found: foo.h")
endif()

例2: ライブラリの検索

この例では、libfoo.soという名前のライブラリを検索し、そのフルパスをMY_LIBRARY_FILE変数に格納します。

cmake_minimum_required(VERSION 3.17)
project(myproject)

find_file(MY_LIBRARY_FILE NAMES libfoo.so
         PATHS /usr/lib /usr/local/lib
         DOC "My library file")

if(MY_LIBRARY_FILE)
  message(STATUS "Found library file: ${MY_LIBRARY_FILE}")
else()
  message(FATAL_ERROR "Library file not found: libfoo.so")
endif()

例3: オプションの指定

この例では、find_file()コマンドにオプションを指定して、検索条件を絞り込みます。

cmake_minimum_required(VERSION 3.17)
project(myproject)

find_file(MY_HEADER_FILE foo.h
         PATHS /usr/include
         NO_DEFAULT_PATH
         NO_CMAKE_PATH
         DOC "My header file")

if(MY_HEADER_FILE)
  message(STATUS "Found header file: ${MY_HEADER_FILE}")
else()
  message(STATUS "Header file not found: foo.h")
endif()
  • ファイルが見つからない場合、message()コマンドを使用してエラーメッセージを出力しています。
  • ファイルが見つかった場合、message()コマンドを使用してそのフルパスを出力しています。
  • if()ステートメントを使用して、ファイルが見つかったかどうかを確認しています。
  • 各例では、find_file()コマンドを使用してファイルを検索し、その結果をMY_*という名前の変数に格納しています。
  • 上記の例は、CMakeのバージョン3.17以降で使用できます。
  • 上記の例はあくまでも一例であり、状況に応じてさまざまなオプションを指定することができます。


手動によるファイルの指定

最も単純な代替方法は、手動でファイルのパスを指定することです。これは、ファイルの場所がわかっている場合や、CMakeの検索機能を使用しない方が効率的な場合に有効です。

set(MY_HEADER_FILE "/usr/include/foo.h")
set(MY_LIBRARY_FILE "/usr/lib/libfoo.so")

pkg_config モジュールを使用する

pkg_configモジュールは、Unix系システムでパッケージ管理を容易にするために使用されるツールです。 pkg_configモジュールを使用すると、find_file()コマンドよりも簡単にライブラリやヘッダーファイルを検索することができます。

find_package(PkgConfig REQUIRED)
pkg_check_modules(MY_LIBRARY_MODULE libfoo)

target_link_libraries(myproject ${MY_LIBRARY_MODULE})

外部スクリプトを使用する

複雑な検索条件が必要な場合は、外部スクリプトを使用してファイルを検索することができます。 この方法は、柔軟性が高いですが、設定とメンテナンスの手間がかかります。

カスタムモジュールを作成する

独自の検索ロジックが必要な場合は、カスタムモジュールを作成することができます。 この方法は、高度な制御が必要な場合に有効ですが、開発とメンテナンスの手間がかかります。

CMakeLists.txtファイルを直接編集する

最終手段として、CMakeLists.txtファイルを直接編集して、必要なファイルパスを指定することができます。 これは、他の方法がうまくいかない場合や、一時的な解決策が必要な場合にのみ使用してください。

選択の指針

どの代替方法を選択するかは、状況によって異なります。 以下の点を考慮して選択してください。

  • 移植性
  • 開発とメンテナンスの手間
  • 検索条件の複雑さ
  • ファイルの場所がわかっているかどうか