# --------------------------------------------------------------------------- # pda - die Anwendung # # Eigenstaendiges Projekt (P1204R0), genau wie libpda. Der entscheidende # Unterschied steht im else-Zweig unten: allein gebaut sucht die Anwendung # libpda ueber find_package -- also genau so, wie ein FREMDES Projekt sie # benutzen wuerde. # # Damit ist dieses CMakeLists.txt gleichzeitig der Beweis, dass der # Export-Mechanismus in libpda/CMakeLists.txt funktioniert. # --------------------------------------------------------------------------- cmake_minimum_required(VERSION 3.28) project(pda VERSION 0.1.0 DESCRIPTION "PDA: Kontakte, Rechner, Notizen, Dateien" LANGUAGES CXX) if(PROJECT_IS_TOP_LEVEL) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") include(ProjectDefaults) include(Warnings) include(Sanitizers) option(PDA_BUILD_TESTS "Tests bauen" ON) # Allein gebaut: libpda muss installiert und ueber CMAKE_PREFIX_PATH # auffindbar sein. # # cmake -S pda -B build/nur-app -DCMAKE_PREFIX_PATH=/pfad/zur/installation # # REQUIRED sorgt fuer einen sofortigen, verstaendlichen Abbruch statt fuer # einen Linkerfehler dreissig Zeilen spaeter. find_package(pda 0.1 REQUIRED) if(PDA_BUILD_TESTS) enable_testing() add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../third_party" third_party) endif() endif() # --------------------------------------------------------------------------- # Die Logik als interne Bibliothek. # # Warum nicht einfach alles in die Executable: ein Unit-Test muesste dann # shell.cpp erneut uebersetzen UND wuerde main.cpp mitziehen -- zwei # main()-Funktionen in einer Executable sind ein Linkerfehler. # # Das Muster dagegen ist immer dasselbe und gilt weit ueber CMake hinaus: # main.cpp bleibt duenn und macht nur Ein-/Ausgabe, alles Testbare wandert in # eine Bibliothek. Hier ist sie STATIC und wird nicht installiert -- sie ist # ein Bauhilfsmittel, kein Teil der Auslieferung. # --------------------------------------------------------------------------- add_library(pda_shell STATIC pda/shell.cpp pda/shell.hpp ) # Der Include-Root ist das PROJEKTWURZELVERZEICHNIS (also pda/), nicht # pda/pda. Nur so loest auf pda/pda/shell.hpp auf. # # PUBLIC, weil sowohl die Executable als auch der Test # inkludieren -- beide erben den Pfad, statt ihn zu wiederholen. target_include_directories(pda_shell PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") # PUBLIC bei pda::pda ist kein Versehen: shell.hpp inkludiert # im INTERFACE. Wer pda_shell linkt, braucht die Header # von libpda also ebenfalls. Waere das PRIVATE, wuerde shell.test.cpp mit # "libpda/contact.hpp: No such file" scheitern. target_link_libraries(pda_shell PUBLIC pda::pda) target_link_libraries(pda_shell PRIVATE pda_warnings) # --------------------------------------------------------------------------- # Die Executable # # Targetname "pda_app", nicht "pda": im Superprojekt gibt es bereits ein # Bibliothekstarget "pda", und zwei Targets duerfen nicht gleich heissen. # Der DATEIname wird ueber OUTPUT_NAME trotzdem "pda" -- Targetname und # Dateiname sind in CMake zwei verschiedene Dinge. # --------------------------------------------------------------------------- add_executable(pda_app pda/main.cpp) set_target_properties(pda_app PROPERTIES OUTPUT_NAME pda) target_link_libraries(pda_app PRIVATE pda_shell pda_warnings) # --------------------------------------------------------------------------- # Tests # --------------------------------------------------------------------------- if(PDA_BUILD_TESTS) if(TARGET doctest) add_executable(shell.test pda/shell.test.cpp) target_link_libraries(shell.test PRIVATE pda_shell doctest pda_warnings) doctest_discover_tests(shell.test TEST_PREFIX "doctest.") endif() add_subdirectory(tests) endif() # --------------------------------------------------------------------------- # Installation. Nur die Executable -- eine Anwendung exportiert keine Targets. # --------------------------------------------------------------------------- include(GNUInstallDirs) install(TARGETS pda_app RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")