it-swarm.com.de

Rekursive CMake-Suche nach Header- und Quelldateien

Ich bin neu bei CMake und möchte fragen, ob jemand bei dem folgenden Problem helfen kann. 

Ich habe C++ - Quell- und Header-Dateien in ihren jeweiligen Ordnern und jetzt möchte ich eine CMake-Textdatei erstellen, die rekursiv danach sucht. 

Derzeit mache ich das auf diese Weise: 

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) 

Dadurch wird meine CarDetectorDAISY.sln solution-Datei erstellt. Wenn ich versuche, sie zu erstellen, zeigt sie Einen Fehler an, dass Header-Dateien nicht gefunden werden (keine solche Datei oder ein solches Verzeichnis). 

Es wäre wirklich dankbar, wenn mir jemand helfen kann. Vielen Dank.

16
Sanchit

Vermutlich fehlen Ihnen ein oder mehrere include_directories Anrufe. Das Hinzufügen von Headern zur Liste der Dateien im Aufruf add_executable fügt den Suchpfad des Compilers nicht wirklich hinzu. Dies ist eine praktische Funktion, bei der sie nur der Ordnerstruktur des Projekts in IDEs hinzugefügt werden.

Sagen Sie also in Ihrem Root-Verzeichnis, dass Sie /my_lib/foo.h haben, und möchten dies in eine Quelldatei aufnehmen

#include "my_lib/foo.h"

Dann müssen Sie in Ihrer CMakeLists.txt Folgendes tun:

include_directories(${CMAKE_SOURCE_DIR})

Wenn, möchten Sie stattdessen nur tun

#include "foo.h"

dann in der CMakeLists.txt tun

include_directories(${CMAKE_SOURCE_DIR}/my_lib)


Ich sollte erwähnen, dass file(GLOB...) nicht der empfohlene Weg ist, um Ihre Quellenliste zu sammeln - Sie sollten wirklich jede Datei explizit in der CMakeLists.txt hinzufügen. Wenn Sie eine Quelldatei später hinzufügen oder entfernen, wird die Datei CMakeLists.txt geändert, und CMake wird beim nächsten Versuch automatisch erneut ausgeführt. Aus den Dokumenten für file:

Es wird nicht empfohlen, GLOB zu verwenden, um eine Liste der Quelldateien aus dem Quellbaum zu sammeln. Wenn sich keine CMakeLists.txt-Datei ändert, wenn eine Quelle hinzugefügt oder entfernt wird, kann das generierte Build-System nicht wissen, wann CMake aufgefordert wird, eine erneute Generierung durchzuführen.

21
Fraser

Meine Antwort ist meistens ein Hack, aber ich finde es nützlich, wenn Sie nicht alle Verzeichnisse manuell hinzufügen möchten.

Dieses Makro durchsucht rekursiv alle Unterverzeichnisse (und deren Unterverzeichnisse usw.). Wenn ein Verzeichnis eine Headerdatei (.h) enthält, wird der Pfad an return_list Angehängt. Diese Liste kann dann mit target_include_directories Verwendet werden.

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()

Verwendungszweck:

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
)

Makrokredit: Christoph

Getestet mit Cmake 3.10

1
gberthiaume

Um nur einen Punkt in Frasers Antwort näher zu erläutern:

Header sollten nicht an ADD_EXECUTABLE übergeben werden.

Der Grund ist, dass der beabsichtigte Kompilierungsbefehl zum Beispiel unter Linux einfach ist:

gcc main.c mylib.c

und nicht:

gcc main.c mylib.c mylib.h

Der C-Vorprozessor analysiert dann mylib.c und sieht einen #include "mylib.h" und verwendet seinen Suchpfad für diese Dateien.

Wenn Sie stattdessen include_directories verwenden, ändern wir stattdessen den cpp-Präprozessor-Suchpfad. Dies ist der richtige Ansatz. In GCC bedeutet dies, dass der Befehlszeile das Flag -I hinzugefügt wird:

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