
Matthias M.
Vor ungefähr einem Jahr fragte ich nach Header-Abhängigkeiten in CMake.
Mir wurde kürzlich klar, dass das Problem darin zu liegen schien, dass CMake diese Header-Dateien als extern zum Projekt. Zumindest erscheinen beim Generieren eines Code::Blocks-Projekts die Header-Dateien nicht innerhalb des Projekts (die Quelldateien tun dies). Es scheint mir daher, dass CMake diese Header als extern zum Projekt und verfolgt sie nicht in den Abhängigkeiten.
Eine schnelle Suche im CMake-Tutorial hat nur darauf hingewiesen include_directories
das scheint nicht das zu tun, was ich wünsche …
Was ist der richtige Weg, um CMake zu signalisieren, dass ein bestimmtes Verzeichnis Header enthält, die eingeschlossen werden sollen, und dass diese Header vom generierten Makefile verfolgt werden sollen?

SirDarius
Zwei Dinge müssen getan werden.
Fügen Sie zuerst das einzubindende Verzeichnis hinzu:
target_include_directories(test PRIVATE ${YOUR_DIRECTORY})
Falls Sie mit einer sehr alten CMake-Version (2.8.10 oder älter) ohne Unterstützung für target_include_directories
können Sie auch das Vermächtnis verwenden include_directories
stattdessen:
include_directories(${YOUR_DIRECTORY})
Dann müssen Sie auch die Header-Dateien zur Liste Ihrer Quelldateien für das aktuelle Ziel hinzufügen, zum Beispiel:
set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})
Auf diese Weise erscheinen die Header-Dateien als Abhängigkeiten im Makefile und beispielsweise auch im generierten Visual Studio-Projekt, falls Sie eines generieren.
So verwenden Sie diese Header-Dateien für mehrere Ziele:
set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_library(mylib libsrc.cpp ${HEADER_FILES})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})

Angew ist nicht mehr stolz auf SO
Erstens verwenden Sie include_directories()
um CMake anzuweisen, das Verzeichnis als hinzuzufügen -I
zur Kompilierungsbefehlszeile. Zweitens listen Sie die Überschriften in Ihrer auf add_executable()
oder add_library()
Anruf.
Wenn sich beispielsweise die Quellen Ihres Projekts in src
und Sie benötigen Header von include
du könntest es so machen:
include_directories(include)
add_executable(MyExec
src/main.c
src/other_source.c
include/header1.h
include/header2.h
)
Addieren include_directories("/your/path/here")
.
Dies ist ähnlich wie beim Anrufen gcc
mit -I/your/path/here/
Möglichkeit.
Stellen Sie sicher, dass Sie den Pfad in doppelte Anführungszeichen setzen. Andere Leute haben das nicht erwähnt und es hat mich 2 Tage lang feststecken lassen. Diese Antwort ist also für Leute, die CMake noch nicht kennen und sehr verwirrt sind.

Konstantin Burlachenko
CMake ähnelt eher einer Skriptsprache, wenn man es mit anderen Methoden zum Erstellen von Makefile vergleicht (z. B. make oder qmake). Es ist nicht sehr cool wie Python, aber immerhin.
Es gibt keine “richtige Weg” Wenn Sie in verschiedenen Open-Source-Projekten nachsehen, wie Leute Verzeichnisse einschließen. Aber es gibt zwei Möglichkeiten, dies zu tun.
-
Roh include_directories wird ein Verzeichnis an das aktuelle Projekt und alle anderen untergeordneten Projekte anhängen, die Sie über eine Reihe von anhängen werden add_subdirectory Befehle. Manchmal sagen die Leute, dass ein solcher Ansatz ein Vermächtnis ist.
-
Ein eleganterer Weg ist mit target_include_directories. Es ermöglicht das Anhängen eines Verzeichnisses für ein bestimmtes Projekt/Ziel ohne (möglicherweise) unnötige Vererbung oder Kollision verschiedener Include-Verzeichnisse. Erlauben Sie auch eine subtile Konfiguration und hängen Sie eine der folgenden Markierungen für diesen Befehl an.
PRIVAT – Nur für dieses angegebene Build-Ziel verwenden
ÖFFENTLICH ZUGÄNGLICH – Verwenden Sie es für ein bestimmtes Ziel und für Ziele, die mit diesem Projekt verknüpft sind
SCHNITTSTELLE — Verwenden Sie es nur für Ziele, die mit dem aktuellen Projekt verknüpft sind
PS:
-
Beide Befehle erlauben es, ein Verzeichnis als SYSTEM zu markieren, um einen Hinweis darauf zu geben, dass es nicht Ihre Sache ist, dass bestimmte Verzeichnisse Warnungen enthalten.
-
Eine ähnliche Antwort gibt es bei anderen Befehlspaaren target_compile_definitions/add_definitionen, target_compile_options/CMAKE_C_FLAGS

Seyed Hussein Mirzaki
Ich hatte das gleiche Problem.
Mein Projektverzeichnis sah so aus:
--project
---Classes
----Application
-----.h and .c files
----OtherFolders
--main.cpp
Und was ich verwendet habe, um die Dateien in all diesen Ordnern einzuschließen:
file(GLOB source_files CONFIGURE_DEPENDS
"*.h"
"*.cpp"
"Classes/*/*.cpp"
"Classes/*/*.h"
)
add_executable(Server ${source_files})
Und es hat total funktioniert.
Struktur des Projekts
.
├── CMakeLists.txt
├── external //We simulate that code is provided by an "external" library outside of src
│ ├── CMakeLists.txt
│ ├── conversion.cpp
│ ├── conversion.hpp
│ └── README.md
├── src
│ ├── CMakeLists.txt
│ ├── evolution //propagates the system in a time step
│ │ ├── CMakeLists.txt
│ │ ├── evolution.cpp
│ │ └── evolution.hpp
│ ├── initial //produces the initial state
│ │ ├── CMakeLists.txt
│ │ ├── initial.cpp
│ │ └── initial.hpp
│ ├── io //contains a function to print a row
│ │ ├── CMakeLists.txt
│ │ ├── io.cpp
│ │ └── io.hpp
│ ├── main.cpp //the main function
│ └── parser //parses the command-line input
│ ├── CMakeLists.txt
│ ├── parser.cpp
│ └── parser.hpp
└── tests //contains two unit tests using the Catch2 library
├── catch.hpp
├── CMakeLists.txt
└── test.cpp
Wie es geht
1. Die CMakeLists.txt der obersten Ebene ist Rezept 1, Wiederverwendung von Code mit Funktionen und Makros, sehr ähnlich
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(recipe-07 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(GNUInstallDirs)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
# defines targets and sources
add_subdirectory(src)
# contains an "external" library we will link to
add_subdirectory(external)
# enable testing and define tests
enable_testing()
add_subdirectory(tests)
2.Ziele und Quellen sind in src/CMakeLists.txt definiert (außer dem Konvertierungsziel)
add_executable(automata main.cpp)
add_subdirectory(evolution)
add_subdirectory(initial)
add_subdirectory(io)
add_subdirectory(parser)
target_link_libraries(automata
PRIVATE
conversion
evolution
initial
io
parser
)
3.Die Konvertierungsbibliothek ist in external/CMakeLists.txt definiert
add_library(conversion "")
target_sources(conversion
PRIVATE
${CMAKE_CURRENT_LIST_DIR}/conversion.cpp
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/conversion.hpp
)
target_include_directories(conversion
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
4.Die Datei src/CMakeLists.txt fügt weitere Unterverzeichnisse hinzu, die wiederum CMakeLists.txt-Dateien enthalten. Sie sind alle ähnlich aufgebaut; src/evolution/CMakeLists.txt enthält Folgendes:
add_library(evolution "")
target_sources(evolution
PRIVATE
evolution.cpp
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/evolution.hpp
)
target_include_directories(evolution
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
5. Die Komponententests werden in tests/CMakeLists.txt registriert
add_executable(cpp_test test.cpp)
target_link_libraries(cpp_test evolution)
add_test(
NAME
test_evolution
COMMAND
$<TARGET_FILE:cpp_test>
)
Wie man es ausführt
$ mkdir -p build
$ cd build
$ cmake ..
$ cmake --build .
Beziehen auf: https://github.com/sun1211/cmake_with_add_subdirectory

Bryan Jyh Herng Chong
Das hat bei mir funktioniert:
set(SOURCE main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE})
# target_include_directories must be added AFTER add_executable
target_include_directories(${PROJECT_NAME} PUBLIC ${INTERNAL_INCLUDES})
9871100cookie-checkSo fügen Sie Include-Verzeichnisse mit CMake richtig hinzuyes
Die an dieser Frage vorgenommenen Änderungen machen sie verwirrend. Die ursprüngliche Frage und Antworten waren, wie man Header-Dateien in einer IDE verfolgt. Dies unterscheidet sich deutlich von einem generierten Makefile mit fehlenden Header-Dateiabhängigkeiten und der Lösung dieses Problems.
– fdk1342
1. Januar 2019 um 17:39 Uhr
@Fred: Ich habe keine Ahnung, wovon du sprichst. Wie die Edit-Revision deutlich zeigt, hat der letzte Satz immer war dort. An dieser Frage wurden nur kosmetische Änderungen vorgenommen, und es wurde kein Wort hinzugefügt (oder entfernt).
– Matthias M.
1. Januar 2019 um 17:45 Uhr
Dann ist das mein Missverständnis. Es sah für mich so aus, als wäre ein ganzer Absatz hinzugefügt worden. stackoverflow.com/questions/13703647/… sagt, dass das gemeinsame Verständnis war, wie die Header-Datei in der IDE aufgelistet wird. Dies hätte sich auf die bezogen
.cbp
Projektdatei. Wenn der cmake-Abhängigkeitsscanner eine Header-Datei nicht korrekt als Abhängigkeit für ein Makefile identifiziert, gibt es Möglichkeiten, dies zu beheben, aber in einigen Fällen wird er falsch angezeigt, da er keinen vollständigen Präprozessor enthält.– fdk1342
1. Januar 2019 um 18:28 Uhr