cmake einfaches Konfigurationsdateibeispiel

Lesezeit: 5 Minuten

Benutzer-Avatar
J. Doe

Jetzt habe ich eine Bibliothek, die ich selbst erstellt habe und die ich in einem anderen CMake-C++-Projekt verwenden möchte. Es existiert in meinem Computer so.

${MY_LIB_PATH}\include
${MY_LIB_PATH}\lib\x86\debug\lib-files
${MY_LIB_PATH}\lib\x86\release\lib-files
${MY_LIB_PATH}\lib\x64\debug\lib-files
${MY_LIB_PATH}\lib\x64\release\lib-files

Wie würde eine grundlegende Konfigurationsdatei aussehen, die CMake find_package kennst du die? Ich hatte erwartet, dass es sehr einfach sein würde, weil es einfach nicht viele Informationen zu liefern hat. Aber diese Seite tut mir nur weh.

Entschuldigung, ich habe beschlossen, den Quellcode zu kopieren, damit ich nicht wirklich weiß, welche Antwort akzeptiert werden sollte.

  • Hast Du Dir angesehen Dies?

    – Arnav Borborah

    16. April 2018 um 12:42 Uhr

Benutzer-Avatar
Stefan Newell

Schreiben Sie nicht selbst eine Konfiguration; Verwenden Sie CMakes export Befehl. Es ist zu breit, um es hier in seiner Gesamtheit zu behandeln, aber hier ist ein modifiziertes Beispiel aus einem meiner Projekte:

install(TARGETS
        your_target
    EXPORT YourPackageConfig
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
export(TARGETS
        your_target
    NAMESPACE YourPackage::
    FILE "${CMAKE_CURRENT_BINARY_DIR}/YourPackageConfig.cmake"
)
install(EXPORT
        YourPackageConfig
    DESTINATION "${CMAKE_INSTALL_DATADIR}/YourPackage/cmake"
    NAMESPACE YourPackage::
)

Dadurch wird die Konfigurationsdatei für Sie erstellt, sodass andere Projekte sie über verwenden können find_package.

find_package(YourPackage REQUIRED)
target_link_libraries(foo YouprPackage::your_target)

Dies behandelt die IMPORTED Ziele automatisch und lässt Sie auch Compiler-Flags einbetten, Pfade, Bibliotheksabhängigkeiten und sogar welche Dateien Teil Ihrer Schnittstelle sind (im Grunde alles, was unter die INTERFACE Eigenschaften).

  • Bist du sicher, dass das funktioniert? Das Handbuch des Exportbefehls sagt: “Die von diesem Befehl erstellte Datei ist spezifisch für den Build-Baum und sollte niemals installiert werden”. Und tatsächlich, wenn ich dies versuche, erhalte ich eine Fehlermeldung, die besagt: “Die Datei … wurde durch den Befehl export() generiert. Sie kann möglicherweise nicht mit dem Befehl install() installiert werden”.

    – Georg P.

    31. Januar 2019 um 9:35 Uhr

  • Ach ja, mein Fehler. Aber wofür wird YourPackageConfig.cmake dann überhaupt verwendet?

    – Georg P.

    31. Januar 2019 um 13:25 Uhr

  • Dieses Snippet erstellt zwei Dateien mit dem Namen YourPackageConfig.cmake, nur an verschiedenen Orten. Der erstellt von export lässt andere Pakete Ihre Artefakte verwenden, ohne sie zuerst installieren zu müssen, obwohl ich dies nie außerhalb eines kurzen Tests verwendet habe; ich finde make && make install viel sauberer und entspricht der häufigeren Verwendung aller Pakete, an denen ich arbeite.

    – Stephen Newell

    31. Januar 2019 um 13:32 Uhr

  • Sollte nicht der Exportpfad sein ${CMAKE_INSTALL_DATADIR}/cmake/YourPackage? Denn für den Standardfall einer systemweiten Installation würde dies eingefügt werden /usr/share/cmake/YourPackage, wo es von cmake gefunden wird. Das macht zB pybind11.

    – MaxNoe

    12. November 2020 um 14:33 Uhr

  • @Eslam – Am besten stellen Sie eine neue Frage, um Ihr Problem in den Blick zu bekommen.

    – Stephen Newell

    vor 16 Stunden

Fügen Sie eine “${libname}-config.cmake” in das Stammverzeichnis der Bibliothek ein.

Fügen Sie dann ein IMPORTIERTES Ziel in dieser Datei hinzu.

Es gibt ein Beispiel für libprotobuf.

add_library(libprotobuf STATIC IMPORTED GLOBAL)

set_target_properties(libprotobuf PROPERTIES 
    IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/prebuilt/android/${ANDROID_ABI}/libprotobuf.a"
    IMPORTED_LINK_INTERFACE_LIBRARIES "${ZLIB_LIBRARIES};${CMAKE_THREAD_LIBS_INIT}"
    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/src")

Setzen Sie die Env- oder CMake-Variable “${libname}_DIR” auf “${MY_LIB_PATH}”.

Benutze es.

find_package(${libname})
#.......
target_link_libraries(main ${libname})

  • Warum sind diese Art von Ratschlägen nicht in offiziellen Dokumenten? Warum müssen sie so schrecklich sein (Dokumente)? Thx btw – einfach und funktioniert. Außerdem schlage ich vor, CMAKE_CURRENT_LIST_DIR anstelle von CMAKE_CURRENT_SOURCE_DIR zu verwenden, um dieses Unterprojekt verschiebbar zu machen.

    – Tehada

    4. August 2020 um 14:24 Uhr


Benutzer-Avatar
Marco Pantaleoni

Vielleicht das älterer Dok könnte etwas leichter sein. Und das gibt es auch noch Lernprogramm oder diese andere. Das letzte ist vielleicht das einfachste.

Hoffe, nicht noch mehr Schmerz hinzugefügt zu haben 🙂

Wenn Sie den Dokumenten folgen, sollte ungefähr Folgendes angezeigt werden (vorausgesetzt, Ihre Bibliothek ist mylib):

MyLib/MyLibConfig.cmake.in

# - Config file for the MyLib package
# It defines the following variables
#  MYLIB_INCLUDE_DIRS - include directories for MyLib
#  MYLIB_LIBRARIES    - libraries to link against
#  MYLIB_EXECUTABLE   - the bar executable

# Compute paths
get_filename_component(MYLIB_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(MYLIB_INCLUDE_DIRS "@[email protected]")

# Our library dependencies (contains definitions for IMPORTED targets)
if(NOT TARGET mylib AND NOT MyLib_BINARY_DIR)
  include("${MYLIB_CMAKE_DIR}/MyLibTargets.cmake")
endif()

# These are IMPORTED targets created by MyLibTargets.cmake
set(MYLIB_LIBRARIES mylib)

MyLib/MyLibConfigVersion.cmake.in

set(PACKAGE_VERSION "@[email protected]")

# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
  set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
  set(PACKAGE_VERSION_COMPATIBLE TRUE)
  if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
    set(PACKAGE_VERSION_EXACT TRUE)
  endif()
endif()

Haupt-MyLib/CMakeLists.txt

...

set(MYLIB_MAJOR_VERSION 0)
set(MYLIB_MINOR_VERSION 1)
set(MYLIB_PATCH_VERSION 0)
set(MYLIB_VERSION
  ${MYLIB_MAJOR_VERSION}.${MYLIB_MINOR_VERSION}.${MYLIB_PATCH_VERSION})

...

add_library(mylib SHARED mylib.c ...)

...

install(TARGETS mylib
  # IMPORTANT: Add the mylib library to the "export-set"
  EXPORT MyLibTargets
  RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
  LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
  PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}/mylib"
    COMPONENT dev)

...

# The interesting stuff goes here
# ===============================

# Add all targets to the build-tree export set
export(TARGETS mylib
  FILE "${PROJECT_BINARY_DIR}/MyLibTargets.cmake")

# Export the package for use from the build-tree
# (this registers the build-tree with a global CMake-registry)
export(PACKAGE MyLib)

# Create the MyLibConfig.cmake and MyLibConfigVersion files
file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}"
   "${INSTALL_INCLUDE_DIR}")
# ... for the build tree
set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}")
configure_file(MyLibConfig.cmake.in
  "${PROJECT_BINARY_DIR}/MyLibConfig.cmake" @ONLY)
# ... for the install tree
set(CONF_INCLUDE_DIRS "\${MYLIB_CMAKE_DIR}/${REL_INCLUDE_DIR}")
configure_file(MyLibConfig.cmake.in
  "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/MyLibConfig.cmake" @ONLY)
# ... for both
configure_file(MyLibConfigVersion.cmake.in
  "${PROJECT_BINARY_DIR}/MyLibConfigVersion.cmake" @ONLY)

# Install the MyLibConfig.cmake and MyLibConfigVersion.cmake
install(FILES
  "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/MyLibConfig.cmake"
  "${PROJECT_BINARY_DIR}/MyLibConfigVersion.cmake"
  DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)

# Install the export set for use with the install-tree
install(EXPORT MyLibTargets DESTINATION
  "${INSTALL_CMAKE_DIR}" COMPONENT dev)

1015560cookie-checkcmake einfaches Konfigurationsdateibeispiel

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

Privacy policy