Verwenden von vorkompilierten Headern mit CMake

Lesezeit: 5 Minuten

Verwenden von vorkompilierten Headern mit CMake
Klebrig

Ich habe ein paar (alte) Beiträge im Internet gesehen, in denen es darum ging, Unterstützung für vorkompilierte Header in CMake zu hacken. Sie scheinen alle ein bisschen überall zu sein und jeder hat seine eigene Art, dies zu tun. Wie geht das derzeit am besten?

1641816927 73 Verwenden von vorkompilierten Headern mit CMake
sakra

Da ist ein CMake-Modul eines Drittanbieters namens ‘Cotire’ die die Verwendung vorkompilierter Header für CMake-basierte Build-Systeme automatisiert und auch Unity-Builds unterstützt.

  • Ich habe eine Reihe von Makros erstellt, die die Cotire-Funktionalität umschließen (vorkompilierte Header und Unity-Builds). Hier zur einfacheren Bedienung

    – onqtam

    29. Februar ’16 um 5:24

  • @onqtam wie ist das einfacher, es ist so riesig, dass ich nicht einmal sehe, wie man einfach vorkompiliert mit cmake und gcc arbeitet

    – Pavel P

    7. Juni ’17 um 1:54

  • CMake 3.16 führte integrierte Unterstützung für vorkompilierte Header ein. Siehe meine Antwort stackoverflow.com/a/59514029/2799037 Keine Notwendigkeit für Module von Drittanbietern mehr!

    – usr1234567

    28. Dez. 19 um 19:05

Verwenden von vorkompilierten Headern mit CMake
larsmoa

Ich verwende das folgende Makro, um vorkompilierte Header zu generieren und zu verwenden:

MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
  IF(MSVC)
    GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
    SET(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${PrecompiledBasename}.pch")
    SET(Sources ${${SourcesVar}})

    SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
                                PROPERTIES COMPILE_FLAGS "/Yc"${PrecompiledHeader}" /Fp"${PrecompiledBinary}""
                                           OBJECT_OUTPUTS "${PrecompiledBinary}")
    SET_SOURCE_FILES_PROPERTIES(${Sources}
                                PROPERTIES COMPILE_FLAGS "/Yu"${PrecompiledHeader}" /FI"${PrecompiledHeader}" /Fp"${PrecompiledBinary}""
                                           OBJECT_DEPENDS "${PrecompiledBinary}")  
    # Add precompiled header to SourcesVar
    LIST(APPEND ${SourcesVar} ${PrecompiledSource})
  ENDIF(MSVC)
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)

Nehmen wir an, Sie haben eine Variable ${MySources} mit all Ihren Quelldateien, der Code, den Sie verwenden möchten, wäre einfach

ADD_MSVC_PRECOMPILED_HEADER("precompiled.h" "precompiled.cpp" MySources)
ADD_LIBRARY(MyLibrary ${MySources})

Der Code würde auch auf Nicht-MSVC-Plattformen gut funktionieren. Ziemlich ordentlich 🙂

  • Dieses Makro hat 1 Fehler. Wenn der Generator nicht MSVC-basiert ist, wird die vorkompilierte Quelle nicht zur Liste der Quellen hinzugefügt. Meine Modifikation verschiebt also einfach die list( APPEND ... ) außerhalb der Schließung endif(). Vollständigen Code sehen Sie hier: pastebin.com/84dm5rXZ

    – void.pointer

    30. Okt ’11 um 19:05

  • @RobertDailey: Dies ist eigentlich beabsichtigt – ich möchte die vorkompilierte Quelldatei nicht kompilieren, wenn keine vorkompilierten Header verwendet werden – sie sollte sowieso keine Symbole definieren.

    – larsmoa

    31. Okt ’11 um 6:54

  • @Iarsam Bitte korrigiere die /Yu und /FI Argumente, das sollten sie sein ${PrecompiledHeader} und nicht ${PrecompiledBinary}.

    – Mourad

    28. Juni ’13 um 13:34


  • Können Sie erklären, warum wir die Flags “/Fp” und “/FI” benötigen? Gemäß msdn.microsoft.com/en-us/library/z0atkd6c.aspx Die Verwendung von “/Fp” ist nicht obligatorisch. Wenn ich jedoch diese Flags aus Ihrem Makro ausschneide, wird kein PC festgelegt.

    – Vram Vardanian

    14. April ’15 um 15:56 Uhr


  • Beachten Sie jedoch, dass das Argument zu /Yu sehr wörtlich genommen wird. Z.B /YuC:/foo/bar.h wird dich zwingen, entweder die /FpC:/foo/bar.h Flagge oder Put #include <C:/foo/bar.h> am Anfang aller Ihrer .cpp-Dateien als erste Include-Anweisung. MSVC führt einen String-Vergleich der #include Argumente, es prüft nicht, ob es auf dieselbe Datei verweist wie die, die an übergeben wurde /Yu. Ergo, #include <bar.h> funktioniert nicht und gibt den Fehler C2857 aus.

    – Manuzor

    19. September ’15 um 12:05

1641816927 451 Verwenden von vorkompilierten Headern mit CMake
janisozaur

CMake hat gerade Unterstützung für PCHs (vorkompilierte Header) erhalten, dies sollte in der kommenden Version 3.16 am 01.10.2019 verfügbar sein:

https://gitlab.kitware.com/cmake/cmake/merge_requests/3553

  target_precompile_headers(<target>
    <INTERFACE|PUBLIC|PRIVATE> [header1...]
    [<INTERFACE|PUBLIC|PRIVATE> [header2...] ...])

Es gibt eine anhaltende Diskussion über die Unterstützung der gemeinsamen Nutzung von PCHs zwischen Zielen: https://gitlab.kitware.com/cmake/cmake/issues/19659

Es gibt einige zusätzliche Kontexte (Motivation, Zahlen) unter https://blog.qt.io/blog/2019/08/01/precompiled-headers-and-unity-jumbo-builds-in-upcoming-cmake/

  • Hier ist der Link zur offiziellen CMake-Dokumentation: cmake.org/cmake/help/latest/command/…

    – Alex Che

    8. Mai ’20 um 15:38 Uhr

  • Es gibt einen Beitrag vom MSVC-Team, um herauszufinden, welche Header in PCH aufgenommen werden sollen: devblogs.microsoft.com/cppblog/…

    – janisozaur

    9. Mai ’20 um 18:04

  • Für Obj-C und/oder Obj-C++ Sprachen, verwenden Sie Syntax wie target_precompile_headers(MyTarget PUBLIC "$<$<COMPILE_LANGUAGE:OBJC,OBJCXX>:${CMAKE_CURRENT_LIST_DIR}/src/MyPrefixHeader.pch>") – Wenn Ihr Header C/C++ nicht unterstützt, oder fügen Sie einfach Unterstützung hinzu (indem Sie eine beliebige einschließen #import in #ifdef __OBJC__ Schecks).

    – Top-Master

    29. Juni ’21 um 19:20


  • Habe versucht es zu benutzen. Irgendwie bekomme ich es nicht hin. Fehlermeldungen erhalten wie Cannot specify precompile headers for target "xxx," which is not built by this project. Höchstwahrscheinlich, weil die CMakeLists.txt an anderer Stelle enthalten ist. Vielleicht hat jemand ein Beispiel, wie man dies in einer Multiprojektumgebung verwenden kann?

    – Jörg S

    20. Okt ’21 um 11:18


1641816927 251 Verwenden von vorkompilierten Headern mit CMake
Dave Hillier

Hier ist ein Code-Snippet, mit dem Sie vorkompilierte Header für Ihr Projekt verwenden können. Fügen Sie Folgendes zu Ihrer CMakeLists.txt-Datei hinzu und ersetzen Sie myprecompiledheaders und myproject_SOURCE_FILES wie angemessen:

if (MSVC)

    set_source_files_properties(myprecompiledheaders.cpp
        PROPERTIES
        COMPILE_FLAGS "/Ycmyprecompiledheaders.h"
        )
    foreach( src_file ${myproject_SOURCE_FILES} )
        set_source_files_properties(
            ${src_file}
            PROPERTIES
            COMPILE_FLAGS "/Yumyprecompiledheaders.h"
            )
    endforeach( src_file ${myproject_SOURCE_FILES} )
    list(APPEND myproject_SOURCE_FILES myprecompiledheaders.cpp)
endif (MSVC)

Am Ende habe ich eine angepasste Version des Larsm-Makros verwendet. Die Verwendung von $(IntDir) für den pch-Pfad hält vorkompilierte Header für Debug- und Release-Builds getrennt.

MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
  IF(MSVC)
    GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
    SET(PrecompiledBinary "$(IntDir)/${PrecompiledBasename}.pch")
    SET(Sources ${${SourcesVar}})

    SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
                                PROPERTIES COMPILE_FLAGS "/Yc"${PrecompiledHeader}" /Fp"${PrecompiledBinary}""
                                           OBJECT_OUTPUTS "${PrecompiledBinary}")
    SET_SOURCE_FILES_PROPERTIES(${Sources}
                                PROPERTIES COMPILE_FLAGS "/Yu"${PrecompiledHeader}" /FI"${PrecompiledHeader}" /Fp"${PrecompiledBinary}""
                                           OBJECT_DEPENDS "${PrecompiledBinary}")  
    # Add precompiled header to SourcesVar
    LIST(APPEND ${SourcesVar} ${PrecompiledSource})
  ENDIF(MSVC)
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)

ADD_MSVC_PRECOMPILED_HEADER("stdafx.h" "stdafx.cpp" MY_SRCS)
ADD_EXECUTABLE(MyApp ${MY_SRCS})

Angepasst von Dave, aber effizienter (setzt Zieleigenschaften, nicht für jede Datei):

if (MSVC)
   set_target_properties(abc PROPERTIES COMPILE_FLAGS "/Yustd.h")
   set_source_files_properties(std.cpp PROPERTIES COMPILE_FLAGS "/Ycstd.h")
endif(MSVC)

1641816927 189 Verwenden von vorkompilierten Headern mit CMake
Roman Kruglov

Wenn Sie das Rad nicht neu erfinden möchten, verwenden Sie einfach Cotire, wie die Top-Antwort vorschlägt, oder eine einfachere – cmake-vorkompilierter-Header Hier. Um es zu verwenden, fügen Sie einfach das Modul ein und rufen Sie auf:

include( cmake-precompiled-header/PrecompiledHeader.cmake )
add_precompiled_header( targetName StdAfx.h FORCEINCLUDE SOURCE_CXX StdAfx.cpp )

.

300980cookie-checkVerwenden von vorkompilierten Headern mit CMake

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

Privacy policy