web-dev-qa-db-ja.com

ヘッダーとソースファイルの再帰的なCMake検索

私はCMakeを初めて使用するので、次の問題で誰かが手伝ってくれるかどうか尋ねたいと思います。

C++のソースファイルとヘッダーファイルがそれぞれのフォルダーにあるので、それらを再帰的に検索するCMakeテキストファイルを作成します。

現在、私はこのようにしています:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(CarDetectorDAISY)

file(GLOB_RECURSE SRCS *.cpp)
file(GLOB_RECURSE HDRS *.h)

ADD_EXECUTABLE(stereo_framework  ${SRCS} ${HDRS})
TARGET_LINK_LIBRARIES(stereo_framework) 

これは私のCarDetectorDAISY.slnソリューションファイルを作成し、それをビルドしようとすると、ヘッダーファイルが見つからないというエラーが表示されます(そのようなファイルまたはディレクトリはありません)。

誰かが私を助けてくれると本当にありがたいです。ありがとう。

19
Sanchit

おそらく1つ以上の _include_directories_ 呼び出しがありません。 _add_executable_呼び出しでファイルのリストにヘッダーを追加しても、実際にはコンパイラの検索パスに追加されません。これは、IDEでプロジェクトのフォルダー構造にのみ追加される便利な機能です。

したがって、ルートに/my_lib/foo.hがあり、それをソースファイルに次のように含めたいとします。

_#include "my_lib/foo.h"
_

次に、CMakeLists.txtで次のことを行う必要があります。

_include_directories(${CMAKE_SOURCE_DIR})
_

もしあなたが代わりにしたいなら

_#include "foo.h"
_

次に、CMakeLists.txtで、

_include_directories(${CMAKE_SOURCE_DIR}/my_lib)
_


file(GLOB...) はソースのリストを収集するための推奨される方法ではありません-各ファイルをCMakeLists.txtに明示的に追加するだけです。これにより、後でソースファイルを追加または削除した場合、CMakeLists.txtが変更され、次回ビルドしようとするとCMakeが自動的に再実行されます。 fileのドキュメントから:

ソースツリーからソースファイルのリストを収集するためにGLOBを使用することはお勧めしません。ソースが追加または削除されたときにCMakeLists.txtファイルが変更されていない場合、生成されたビルドシステムは、CMakeに再生成を依頼するタイミングを認識できません。

23
Fraser

私の答えはほとんどハックですが、すべてのディレクトリを手動で追加したくない場合に便利です。

このマクロは、すべてのサブディレクトリ(およびそのサブディレクトリなど)を再帰的にスキャンします。ディレクトリにヘッダー(.h)ファイルが含まれている場合、return_listにそのパスが追加されます。このリストはtarget_include_directoriesで使用できます。

MARO(HEADER_DIRECTORIES return_list)
    FILE(GLOB_RECURSE new_list *.h)
    SET(dir_list "")
    FOREACH(file_path ${new_list})
        GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
        SET(dir_list ${dir_list} ${dir_path})
    ENDFOREACH()
    LIST(REMOVE_DUPLICATES dir_list)
    SET(${return_list} ${dir_list})
ENDMACRO()

使用法:

HEADER_DIRECTORIES(header_dir_list)

list(LENGTH header_dir_list header_dir_list_count)
message(STATUS "[INFO] Found ${header_dir_list_count} header directories.")

target_include_directories(
    my_program
    PUBLIC
    ${header_dir_list} # Recursive
)

マクロクレジット: Christoph

Cmake 3.10でテスト済み

1
gberthiaume

フレーザーの答えの1つのポイントをさらに明確にするために:

ヘッダーをADD_EXECUTABLEに渡してはいけません。

その理由は、たとえばLinuxで意図されているコンパイルコマンドが次のとおりであるためです。

gcc main.c mylib.c

ではなく:

gcc main.c mylib.c mylib.h

次に、Cプリプロセッサはmylib.cを解析し、#include "mylib.h"を確認して、それらのファイルの検索パスを使用します。

代わりにinclude_directoriesを使用して、代わりにcppプリプロセッサー検索パスを変更します。これは正しいアプローチです。 GCCでは、これは-Iフラグをコマンドラインに追加することを意味します。

gcc -Inew/path/to/search/for/headers main.c mylib.c