So fügen Sie Include-Verzeichnisse mit CMake richtig hinzu

Lesezeit: 10 Minuten

So fugen Sie Include Verzeichnisse mit CMake richtig hinzu
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?

  • 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

So fugen Sie Include Verzeichnisse mit CMake richtig hinzu
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_directorieskö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})

  • Ah! Ich wusste, es muss etwas Dummes sein. Tatsächlich habe ich die Header nicht aufgelistet … Muss ich nur die Header dieser Bibliothek auflisten oder auch alle Header, von denen sie abhängen könnte (zusätzlich zur Deklaration der Abhängigkeit von der Bibliothek)? Es ist ein wachsendes Projekt und ich fürchte die Idee, einen Header hinzuzufügen alle die Abhängigkeiten, wenn ich eine in der Root-Bibliothek hinzufüge.

    – Matthias M.

    4. Dezember 2012 um 13:13 Uhr


  • Meine Frage war eher in dem Sinne, dass ich mehrere Bibliotheken habe, die voneinander abhängen: libroot, liba hängt von libroot ab, libb hängt von libroot ab. Kann ich die verwenden LIBROOT_HEADER_FILES variabel ein liba/CMakefile und libb/CMakefile dann ?

    – Matthias M.

    4. Dezember 2012 um 13:37 Uhr


  • Das ist falsch, das solltest du noch nie verwenden include_directories über target_include_directories. Ersteres setzt es rekursiv für alle Ziele in diesem Verzeichnis; wohingegen letzteres es für ein Ziel festlegt. Ersteres bricht die Vorstellung eines Zieldiagramms in CMake und verlässt sich stattdessen auf Nebeneffekte in Ihrer Dateihierarchie.

    – Andy

    10. August 2017 um 1:47 Uhr

  • Ich habe die Antwort bearbeitet, um den aktuellen Begriff des Vorziehens widerzuspiegeln target_include_directories für modernen CMake-Code. Fühlen Sie sich frei, mich zu einem Chat einzuladen, wenn Sie mit den Änderungen nicht einverstanden sind.

    – ComicSansMS

    6. Februar 2018 um 12:10 Uhr

  • @donturner Sie müssen nicht hinzufügen .h Dateien hinein add_executable. Aber es hat den netten Vorteil, dass die Dateien in angezeigt werden Visual Studio Projekte am erwarteten Standort. Makefiles nutzt das Interne cmake -E cmake_depends um Abhängigkeiten aus den Quelldateien (Header-Dateien in add_executable werden übersprungen). Es sind bekannt Themen damit der Scanner. Auch ` der Makefile-Generator-Abhängigkeits-Scanner von CMake führt nur eine ungefähre Vorverarbeitung durch. ` Berechnete Header enthalten und so etwas wird nicht funktionieren.

    – fdk1342

    1. Januar 2019 um 7:12 Uhr

1646901015 231 So fugen Sie Include Verzeichnisse mit CMake richtig hinzu
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 srcund Sie benötigen Header von includedu könntest es so machen:

include_directories(include)

add_executable(MyExec
  src/main.c
  src/other_source.c
  include/header1.h
  include/header2.h
)

  • Müssen Sie wirklich Header hinzufügen? add_executable? Ich dachte, CMake hat die Abhängigkeiten der Include-Datei automatisch herausgefunden.

    – Colin D. Bennett

    2. November 2013 um 17:40 Uhr

  • @ColinDBennett Sie müssen sie nicht aus Abhängigkeitsgründen auflisten – CMake erkennt Build-Abhängigkeiten gut, wenn Sie dies nicht tun. Wenn Sie sie jedoch auflisten, gelten sie als Teil des Projekts und werden als solche in IDEs aufgeführt (was das Thema der Frage war).

    – Angew ist nicht mehr stolz auf SO

    2. November 2013 um 18:57 Uhr

  • Zumindest für QtCreator ist es nicht notwendig, class.h hinzuzufügen, falls eine class.cpp existiert. Nur lonely.h muss zur Quelle hinzugefügt werden. Siehe Anleitung unter www.th-thielemann.de/cmake

    – Th. Thielemann

    22. Januar 2018 um 18:47 Uhr


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.

  • außer es schlägt zufällig die Hälfte der Zeit fehl. =/

    – Bad Zen

    17. März 2021 um 21:21 Uhr

So fugen Sie Include Verzeichnisse mit CMake richtig hinzu
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.

  1. 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.

  2. 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:

  1. 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.

  2. Eine ähnliche Antwort gibt es bei anderen Befehlspaaren target_compile_definitions/add_definitionen, target_compile_options/CMAKE_C_FLAGS

1646901017 66 So fugen Sie Include Verzeichnisse mit CMake richtig hinzu
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.

  • Sich daran zu erinnern, dass cmake ein „Build-System-Generator“ und kein „Build-System“ ist, das File-Glob verwendet, ist in modernem cmake (CMake mit Version 3.0 und höher) keine gute Idee, da File-Globs zur „Build“-Zeit und nicht zur „Build“-Zeit ausgewertet werden Zeit der Systemgenerierung. Siehe Link: gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1

    – Ggulgulie

    21. März 2020 um 10:34 Uhr

  • Einfach hinzufügen CONFIGURE_DEPENDS.

    – letmaik

    6. Juli 2020 um 10:33 Uhr

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

  • Sich daran zu erinnern, dass cmake ein „Build-System-Generator“ und kein „Build-System“ ist, das File-Glob verwendet, ist in modernem cmake (CMake mit Version 3.0 und höher) keine gute Idee, da File-Globs zur „Build“-Zeit und nicht zur „Build“-Zeit ausgewertet werden Zeit der Systemgenerierung. Siehe Link: gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1

    – Ggulgulie

    21. März 2020 um 10:34 Uhr

  • Einfach hinzufügen CONFIGURE_DEPENDS.

    – letmaik

    6. Juli 2020 um 10:33 Uhr

1646901018 550 So fugen Sie Include Verzeichnisse mit CMake richtig hinzu
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})

987110cookie-checkSo fügen Sie Include-Verzeichnisse mit CMake richtig hinzu

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy