[...]



  • [...]



  • Morgen,
    wenn Du mit Microsoftprodukten arbeitest, schau mal nach "c++ __declspec(dllexport)" in der Suchmaschiene Deiner Wahl.



  • Im Visual Studio kannst du recht einfach dein Projekt auf mehrere Unterprojekte und damit Bibliotheken aufteilen. Musst mal auf den entsprechenden MSDN Seiten googlen. äh ich meine Bingen.



  • [...]



  • Mit einem alternativen Build-System lässt sich das auch in C++ recht angenehm plattformunabhängig gestalten.

    Mit Cmake könnte ich mir dein setup vorstellen:

    /
    - core/ (Kernfunktionalität)
    - gui/ (GUI-Anwendung)
    - cli/ (Kommandozeilen-Interface)

    Du hättest jetzt bei CMake in dem Wurzelverzeichnis eine CMakeLists.txt mit folgendem Inhalt:

    PROJECT ( MyFancyThing )
    # Version sollte man entsprechend anpassen, ich nutze meistens die älteste, mit der ich es getestet habe
    CMAKE_MINIMUM_REQUIRED ( VERSION 2.8.11 )
    
    # Unterverzeichnisse hinzufügen
    ADD_SUBDIRECTORY ( core )
    ADD_SUBDIRECTORY ( gui )
    ADD_SUBDIRECTORY ( cli )
    

    Dann hast du noch eine CMakeLists.txt in jedem der Unterverzeichnisse:

    # core/CMakeLists.txt
    
    # man könnte die Dateien auch händisch angeben, aber ich lasse mein build system
    # das gerne für mich machen
    FILE ( GLOB core_SOURCES *.cxx )
    FILE ( GLOB core_HEADERS *.hxx )
    
    ADD_LIBRARY ( core STATIC ${core_SOURCES} ${core_HEADERS} )
    # statt STATIC geht auch SHARED, dabei sind dann allerdings auch code-seitig
    # einige Feinheiten zu beachten (z.B. das oben genannte __declspec(dllexport) unter Windows)
    
    ##############################################################
    # gui/CMakeLists.txt
    
    FILE ( GLOB gui_SOURCES *.cxx )
    FILE ( GLOB gui_HEADERS *.hxx )
    
    # externe verzeichnisse zum include-path hinzufügen
    INCLUDE_DIRECTORIES ( ../core )
    
    ADD_EXECUTABLE ( MyFancyGuiApp WIN32 ${gui_SOURCES} ${gui_HEADERS} )
    # das WIN32 hier wird automatisch bei Nicht-Windows-Systemen ignoriert.
    # Unter Windows sorgt es dafür, dass beim Starten der Anwendung keine Konsole mitgestartet wird. Sollte also bei GUI-Anwendungen immer dabei sein.
    
    # gegen unsere core lib linken
    TARGET_LINK_LIBRARIES ( MyFancyGuiApp core )
    
    # optional: ein INSTALL-Target einbauen (das wird z.B. mit GNU Make für "make install" verwendet, oder wenn man CPack verwendet um sich Installer bauen zu lassen
    INSTALL ( TARGETS MyFancyGuiApp DESTINATION bin )
    
    ##############################################################
    # cli/CMakeLists.txt
    
    FILE ( GLOB cli_SOURCES *.cxx )
    FILE ( GLOB cli_HEADERS *.hxx )
    
    INCLUDE_DIRECTORIES ( ../core )
    
    ADD_EXECUTABLE ( MyFancyCliApp ${cli_SOURCES} ${cli_HEADERS} )
    TARGET_LINK_LIBRARIES ( MyFancyCliApp core )
    INSTALL ( TARGETS MyFancyCliApp DESTINATION bin )
    

    In Cmake lassen sich auch Sachen wie Doxygen zur Dokumentationserstellung, Unit Tests (z.B. CxxTest) sowie plattformabhängige Schalter einbauen.

    CMake selber ist ein Projekt-Generator. Es baut als nicht direkt deine Anwendung, sondern erstellt dir nach Bedarf ein Makefile, ein NINJA-Skript (sagt man das so?), ein Visual Studio Projekt oder was auch immer auf deinem Betriebssystem gerade cool ist.
    Einige C++ IDEs (QtCreator und KDevelop) unterstützen auch von Haus aus CMake.



  • Elementus schrieb:

    Mir ging es ja eher um meine Verständnisfragen und nicht um die konkrete Umsetzung mit Visual Studio (auch wenn ich es nachher verwenden werde). 🙂 Da die GUI Qt nutzen soll, dachte ich daran qmake zu benutzen, damit sollte das bauen dann auch gehen. Man kann sich dann mit qmake ja auch ein Visual Studio Projekt erzeugen lassen.

    Ist zwar Geschmackssache, aber ich persönlich mag qmake nicht.
    cmake hat seit Version 2.8.11 auch eine ausgezeichneten Qt5 Support.

    Ein triviales Beispiel wäre da sowas:

    PROJECT ( Foo )
    CMAKE_MINIMUM_REQUIRED ( VERSION 2.8.11 )
    
    FIND_PACKAGE ( Qt5Core )
    FIND_PACKAGE ( Qt5Gui )
    FIND_PACKAGE ( Qt5Widgets )
    
    FILE ( GLOB foo_SOURCES src/*.cxx )
    FILE ( GLOB foo_HEADERS src/*.hxx )
    
    ADD_EXECUTABLE ( Foo WIN32 ${foo_SOURCES} ${foo_HEADERS} )
    TARGET_LINK_LIBRARIES ( Foo Qt5::Core Qt5::Gui Qt5::Widgets )
    

    Theoretisch sollte auch nur Qt5Widgets und Qt5::Widgets reichen, da es die anderen beiden als Abhängigkeiten mit reinzieht, aber ich gebe sowas gerne explizit an.

    Elementus schrieb:

    __declspec(dllexport) wäre doch jetzt rein für dynamische Bibliotheken ala dll's?

    ja

    Und um nochmal auf deine anfänglichen Fragen einzugene:

    Elementus schrieb:

    Dazu programmiere ich doch ganz normal meine Klassen und Methoden, oder? Oder muss ich hier etwas spezielles beachten, wenn ich daraus eine Bibliothek bauen möchte?

    Bei einer statischen Bibliothek ja, bei einer dynamischen kommt das dllexport/dllimport Zeugs unter Windows dazu

    Elementus schrieb:

    In meiner GUI oder Komanndozeilenapplikation binde ich dann die notwendigen Header-Dateien aus der Core-Bibliothek ein und linke die Core-Bibliothek dann noch dazu?

    Ja, siehe z.B. mein CMake-Setup im obigen Post.

    Elementus schrieb:

    Sollte es sich bei der Bibliothek in meinem Fall eher um eine statische oder dynamische Bibliothek handeln?

    In diesem speziellen Fall dürfte es egal sein.
    Böse Ding mögen passieren, wenn du z.B. sowas hast:

    Lib C ist statisch und hat eine coole eigene Speicherverwaltung.
    Lib A und Lib B sind dynamisch, linken aber gegen Lib C.
    App Foo linkt gegen Lib A und Lib B.

    Jetzt holst du die in App Foo über Lib A ein Objekt aus Lib C und weil du nicht aufpasst, gibst du es mithilfe einer Funktion aus Lib B wieder frei. BÄÄM.
    Intern werden hier zwei eigenständige Instanzen von Lib C verwendet.

    Daher ist Vorsicht geboten, wenn man dynamische und statische Bibliotheken mischt.



  • Elementus schrieb:

    __declspec(dllexport) wäre doch jetzt rein für dynamische Bibliotheken ala dll's?

    Ja. Du hättest die benötigten Funktionen in einer DLL und kannst sie von Deinen Anwendungen bei Bedarf aufrufen lassen.
    Wenn das nicht Dein Ziel ist, genügt es einfach, Deine Funktionen in einer oder mehreren Quelldateien zu haben, einmal zu kompilieren, und die entstandene(n) Objektdatei(en) zu den Anwendungen, die die Funktionen nutzen sollen, hinzuzulinken.
    Selbstverständlich müssen in beiden Fällen die Funktionsprototypen in den Anwendungen bekannt sein, wofür man üblicherweise entsprechende Headerdateien benutzt.



  • [...]


  • Mod

    Der Thread scheint mir eher in die Richtung philosophischer Fragen zu Bibliotheken im Allgemeinen und zu konkreten Fragen über CMake und andere Buildsysteme im Speziellen zu driften. Ich verschiebe ihn daher mal in ein passenderes Forum.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (alle ISO-Standards) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Elementus schrieb:

    1. "CMAKE_MINIMUM_REQUIRED": Welche Version wählt man dann hier schlauerweise? Hab mir jetzt die 3.0.2 heruntergeladen und auch erstmal dies als Version eingetragen, weil es ja damit definitiv klappt. 🙂

    Ich nehme meistens die geringste getestete Version, da es häufig nicht ersichtlich ist, in welcher Version ein Feature eingeführt wurde. (In deinem Fall eben die 3.0.2)
    Speziell bei Qt5 Projekten ist man mit 2.8.11 ganz gut dabei.
    Siehe hier: http://qt-project.org/doc/qt-5/cmake-manual.html

    Elementus schrieb:

    2. "PROJECT": Sollte ich das auch in den CMakeLists.txt Dateien in den Unterordnern setzen?

    Das reicht einmal in der Haupt-CMakeLists.txt.

    Elementus schrieb:

    3: "FILE": Eure Konfiguration geht jetzt davon aus, dass alle Dateien in einem Ordner liegen, oder? Wie würde das aussehen, wenn ich dort jetzt noch Unterordner zur Strukturierung haben sollte? Ich hab in den Unterordnern der Teilprojekte noch nen src-Ordner und habe es erstmal so gesetzt:

    FILE ( GLOB core_SOURCES src/*.cpp )
    FILE ( GLOB core_HEADERS src/*.hpp )
    

    Du brauchst prinzipiell nur ein CMakeLists.txt.
    Zusätzlich benötigst du in jedem Ordner, den du mit ADD_SUBDIRECTORY eingebunden hast, eine weitere CMakeLists.txt.
    Allerdings kannst du auch in der Haupt-CMakeLists.txt beliebig tiefe Ordner-Hierarchien verwalten, ohne einmal ADD_SUBDIRECTORY zu nutzen.
    Das ist zum Teil eine Geschmacksfrage, aber auch eine Frage des Scopes:
    Gesetzte Variablen werden an Unterverzeichnisse vererbt, allerdings nicht an "Geschwister".
    Möchtest du also z.B. einen Teil deines Projektes mit C++11 kompilieren und einen anderen mit C++03, so wären Unterverzeichnisse EINE Möglichkeit das zu bewerkstelligen (vermutlich die einfachste).

    Neben GLOB gibt es übrigens auch noch GLOB_RECURSE, welches bei src/.cpp auch src//*.cpp usw. findet.

    Elementus schrieb:

    Die Philosophie von CMake scheint ja zu sein, dass ich in jedem Ordner eine CMakeLists.txt liegen habe, also auch in src/ oder wenn es später noch so etwas geben sollte wie src/bla und src/blub, dann müsste ich dort ja auch noch eine CMakeLists.txt plazieren. Wie würde das dann konkret aussehen? Ich vermute mal einfach weiter ADD_SUBDIRECTORY hinzufügen. Offen bleibt dann noch, wie ich dann in den einzelnen Unterordner noch die Dateien hinzufüge.

    Siehe oben.
    Prinzipiell kannst du dir auch simple OpenSource Projekte anschauen, die CMake verwenden, um ein ungefähres Verständnis für die Verwendung zu bekommen.
    Hier sind nur mal ein paar einfache Beispiele von mir:
    https://github.com/Drako/dbfi
    https://github.com/Drako/utf8pp
    Hier bitte nicht den Quellcode anschauen :p
    Wenn ich mal Zeit finde, werde ich auch an der Version 2 weiterschrauben...
    Aber hier ist auch ein Beispiel dabei, wie man externe Bibliotheken einbindet, die CMake selber noch nicht kennt.
    Die FindOpenCL.cmake ist allerdings auch nur kopiert. Generell findet man viel, wenn man einfach "${LIBRARY} cmake" googlet 🙂
    https://github.com/Drako/GameOfLife/tree/1.0
    Und noch ein Beispiel mit Qt5:
    https://github.com/Drako/QtPong



  • [...]


Anmelden zum Antworten