CMake lib export header files



  • Hallo zusammen,

    ich schreibe grade an einer lib mit cmake und frage mich Projekte (inklusive der eigenen example dateien im Projekt) die header files der lib inkludieren sollen.

    Projektstruktur

    - cmake
    - examples
        - example1 
        - example2
        CMakeLists.txt
    - src
        CMakeLists.txt
        foot.cpp
        foot.h
    CMakeLists.txt
    

    Jetzt weiß ich das es den Ansatz gibt, source und header files aufzusplitten in ein src und include Verzeichnis. Dann könnte ich einfach machen:

    target_include_directories(myLib PUBLIC include)
    

    Ein target, was dann meine lib linkt, muss absolut nichts mehr machen, da public dafür sorgt das diese Einstellung auf das target auch angewandt wird.

    Allerdings arbeite ich einerseits nicht gerne mit einem seperaten include directory und andererseits halte ich das nur für bedingt sinnvoll, da dort dann ja nur header files sein sollen, die auch tsatächlich zum interface gehören. Und dann einige header files im include und andere im src zu haben, ist ja noch doofer.

    Daher wollte ich mal, um Rat fragen wie ich das mit einem gemeinsamen src folder mache.
    Aktuell habe ich einfach

    target_include_directories(myLib PUBLIC src)
    

    Aber toll ist das nicht, da dann alle header files (auch interne) zum interface gehören, außerdem muss dann die Verzeichnisstruktur in meinem src folder mit angewendet werden.

    Besser wäre es, wenn ich die header files, die zum interface gehören direkt spezifieren kann (ggf. ihnen sogar einen Pfad geben kann ... z.B. MyModule/MyHeader.h, obwohl das gar nicht der echten verzeichnisstruktur entspricht).
    Diese header files sollen dann direkt genutzt werden können ohne zusätzliche Konfiguration für denjenigen, der meine lib nutzt.
    Also statt einem target_include_directories eher ein target_include_files 🙂

    Oder wie macht ihr das? Seperates include directory kann ja nicht die einzige Lösung sein, zumindest gibt es genug Empfehlungen das nicht zu haben (auch für libs).



  • Es ist aber gängige Praxis, bei einer Library ein öffentliches (public) Verzeichnis für die Headerdateien zu haben und ein privates (private) Verzeichnis für interne Daten.

    So kannst du dann einfach das öffentliche Verzeichnis mitsamt der kompilierten Library (DLL bzw. SO) den Anwendern zur Verfügung stellen.



  • Die gängige Variante ist mir bekannt.
    Trotzdem mal aus Neugier, wenn ich die gängige Variante nehme, wäre dann

    target_include_directories(myLib PUBLIC include)
    

    der richtige Weg? Damit müssen die (CMake) Nutzer dann nichts mehr machen, außer gegen meine lib linken. Habs auch schon anders gesehen, deswegen frage ich 🙂
    Hinweis: Hier geht es um Benutzung durch cmake, direkt eingebunden (z.B. durch FetchContent), nicht um installieren im System.

    Allerdings behaupte ich jetzt mal, dass man den Vorteil der gängigen Variante doch auch hätte, wenn man explizit angibt, welche header files man als Teil des Interface haben möchte (und wenn am Ende cmake nur durch geschicktes copy und paste es mir so hinbiegt als hätte ich die gängige Variante genommen). Mehraufwand ist es für den Library Schreiber auch nicht ... ob ich mir jetzt Gedanken mache, welche header files ich in ein include verzeichnis stecke oder welche ich in irgendeinem cmake command angebe, macht denke ich kaum einen Unterschied.
    Umgekehrt wären aber alle Nachteile z.B. Unübersichtlichkeit nicht da.

    Oder habe ich einen entscheidenen Vorteil vom include Verzeichnis übersehen? Für mich hört sich das nach einer trivialen Anforderung für ein build system an.

    Um genau zu sein, hat man bei cmake ja schon eine Funktionalität, die in diese Richtung geht ... bei den sources für ein target kann man angeben, ob sie private, public oder interface sein sollen. Public / Interface files, werden somit automatisch quasi weitervererbt. Damit ist die Grundfunktionalität ja eig. schon da ... fehlt nur noch, dass die include directories auch noch angepasst werden.


Log in to reply