====== Bibliotheken finden und bauen ======
Ein wichtiger Punkt im Umgang mit C und C++ Projekten aber auch in anderen Sprachen ist das finden von Bibliotheken und deren Header-Dateien im System. So könnten wir bspw. eine Bibliothek installier haben, gegen die wir unser Programm nun linken möchten. Diese Bibliothek im System zu finden gelingt in normalen GNU-Makefiles oftmals mit ''pkg-file''; CMake hat einen eingebauten Befehl: ''find_library''.
Wollen wir bspw. in unsere Hello-World Anwendung eine Routine einbauen, die JSON-parsing mithilfe von json-c übernimmt, brauchen wir die libjson-c-Bibliothek und deren Header-Dateien. Oftmals werden die Header automatisch vom Compiler gefunden, wenn sie bei der Installation im richtigen Ordner abgelegt werden, aber der Linker braucht genaue Informationen darüber, gegen welche Bibliotheken ein Programm gebaut werden soll.
===== Eine Bibliothek im System finden =====
Also finden wir die json-c Bibliothek:
find_library(JSONC_LIB NAMES json-c)
if(NOT JSONC_LIB)
message(FATAL_ERROR "Please download and install libjson-c")
endif()
Dieser Befehl sucht auf dem System nach der json-c Bilbiothek und speichert die entsprechenden Informationen in der Variable ''JSONC_LIB''. Ist diese Variable nicht gesetzt, wurde die Variable nicht gefunden. Nun können wir uns überlegen, was dann geschehen soll, bspw. kann der Übersetzungsvorgang abbrechen, mit dem Hinweis darauf, dass json-c nachinstalliert werden muss, oder aber wir übersetzen unsere Anwendung ohne Unterstützung für JSON-Dateien, falls das möglich ist.
Weitere Informationen zu ''find_library'' könnnen im [[https://cmake.org/cmake/help/latest/command/find_library.html|CMake Handbuch]] gefunden werden.
Um unsere Anwendung nun gegen die Library zu bauen, müssen wir CMake das noch mitteilen. Dazu teilen wir CMake erst mit, dass wir ein Programm bauen wollen, und danach fügen wir die Information über die Libraries hinzu.
add_executable(hello_world ${SRC_FILES})
target_link_libraries(hello_world ${JSONC_LIB})
===== Eine eigene Bibliothek bauen =====
Neben fertigen Anwendungen kann CMake auch Bibliotheken, also Sammlungen von Funktionen, bauen. Hier ist Vorgehen analog zu dem von Executable, nur geben wir hier den Befehl ''add_library'' ein, und geben an, welche Art von Bibliothek (also dynamisch (''SHARED'') oder statisch (''STATIC'') gelinkt) wir haben wollen.
add_library(hello SHARED "common.c")
Wir erhalten auf Linux eine ''libhello.so''. Wichtig ist hier, dass sich die Namen nicht doppeln dürfen, also zwei identisch benannte Libraries oder Programme können nicht in einer ''CMakeLists.txt'' gebaut werden.
===== Headerdateien =====
Größere Projekte, insbesondere Bibliotheken trennen oftmals ihren Code von den Header-Dateien; häufig auch die öffentlichen Header-Dateien von den internen. So sollen Informationen und Variablen versteckt werden, auf die ein Benutzer der Library keinen Zugriff haben soll. Auch wir können Projekte erstellen, in denen bspw. die öffentlichen Header in ''include/'' liegen, ein paar Bibliotheksdateien in ''lib/'' und alle Dateien für das Bauen unserer eigentlichen Anwendung in 'src/' zusammen mit den internen Header-Dateien.
Nun müssen wir CMake noch mitteilen, wo unsere Header-Dateien liegen, damit auch unser eigener Code die öffentlichen Header verwenden kann, bspw. um die richtigen Typdefinitionen zu verwenden. Das geht mit ''target_include_directories'':
target_include_directories(hello PUBLIC include/)
So sagen wir CMake, dass es beim Bauen der Library ''libhello.so'' die Header in ''include/'' zur Verfügung stellen soll.
===== Gebautes Installieren =====
Oftmals soll es im resultierenden Makefile auch die Möglichkeit geben, die gebauten Dateien zu installieren, also die Bibliotheken an den richtigen Ort zu legen, und die gebauten Programme auffindbar zu machen. Der ''install''-Befehl ermöglicht es uns, diese Direktiven zu geben:
file(GLOB_RECURSE INCLUDE_FILES "include/*.h")
set_target_properties(hello
PROPERTIES PUBLIC_HEADER "${INCLUDE_FILES}"
)
install(TARGETS hello_world hello)
In diesem Beispiel geschieht noch etwas mehr:
- wir suchen uns alle öffentlichen Headerdateien in ''include/'' raus
- setzen die als ''PUBLIC_HEADER'' für unsere Library ''libhello.so''
- nennen CMake unser Programm ''hello_world'' und die Library ''libhello.so'' als zu installieren
''install'' erlaubt auch das Setzen von Installationspfaden für Libraries, Programmdateien und Anderes, weitere Informationen zum ''install'' Kommando sind im [[https://cmake.org/cmake/help/latest/command/install.html|CMake-Handbuch]] einzusehen.