如何使用CMakeLists.txt创建一个库并将其包含在另一个程序中?

时间:2019-05-15 09:18:38

标签: c cmake shared-libraries static-libraries

我是C / C ++开发的新手,并且正与CLion IDE中的CMakeLists.txt挣扎。

我无法创建可以包含在另一个程序中的库(静态或共享)。

我有这种结构:

src/
 |
 |---> utilities/
 |         |---> CMakeLists.txt
 |         |---> utilties.h
 |         |
 |         |---> file_utilities/
 |         |            |---> file_utilities.h
 |         |            |---> file_utilities.c
 |        ...
 |
 |---> my_app
          |---> CMakeLists.txt
          |---> main.c

我生成了一个libutilities.so和一个libutilities.a。在我的main.c文件中,如果我执行#include "../utilities/utilities.h"#include "../utilities/file_utilities/file_utilities.h",它就可以工作。

更糟糕的是,如果我使用另一个程序创建另一个项目并链接我的libutilities.so,则该链接似乎有效,但仍然不能包含我的标题。

我已经尝试了CMakeLists.txt中的许多配置和许多选项,但是直到现在为止,它从未起作用。

这是我用于库的CMakeLists.txt。我很确定问题出在此文件中。

    cmake_minimum_required(VERSION 3.7)
    project(utilities VERSION 1.0.0)

    set(CMAKE_CXX_STANDARD 11)

    link_libraries(pthread)
    link_libraries(ssl)
    link_libraries(crypto)

    find_package(CURL REQUIRED)
    include_directories(${CURL_INCLUDE_DIRS})

    file(GLOB_RECURSE SOURCES RELATIVES "*.c")
    file(GLOB_RECURSE HEADERS RELATIVES "*.h")

    add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS})

    set_target_properties(${PROJECT_NAME} PROPERTIES
            PUBLIC_HEADER "${HEADERS}"
            ARCHIVE_OUTPUT_DIRECTORY "lib"
            LIBRARY_OUTPUT_DIRECTORY "lib"
            OUTPUT_NAME ${PROJECT_NAME})

    target_include_directories(${PROJECT_NAME} PUBLIC .)

    target_link_libraries(${PROJECT_NAME} ${CURL_LIBRARIES})

    include(GNUInstallDirs)
    install(TARGETS ${PROJECT_NAME}
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
            PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})

我想拥有一个更像#include <utilities/utilties.h>的东西,因为它是一个图书馆。但是我无法使其正常工作。

在我提供的示例中,该库是一个简单的“ utils”库,但是我必须创建更多我必须交付的库,并将其集成到我的库之外的其他程序中。

2 个答案:

答案 0 :(得分:0)

我强烈建议您阅读this article,其中创建了一个虚构的库目标,从项目结构到安装/导出。据我了解,作者的目标与您完全相同。刚开始时,这篇文章为我整理了很多东西。我还推荐其中列出的项目结构。

项目结构:

libjsonutils
├── CMakeLists.txt
├── include
│   └── jsonutils
│       └── json_utils.h
├── src
│   ├── file_utils.h
│   └── json_utils.cpp
└── test
    ├── CMakeLists.txt
    └── src
        └── test_main.cpp

具体来说,您将要看一下Targets and Properties,其中生成器表达式用于区分构建时和安装时的include目录:

target_include_directories(JSONUtils
    PUBLIC 
        $<INSTALL_INTERFACE:include>    
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/src
)

稍后在This is how you do CMake中说明目标的安装过程和导出/导入。作者想要做的就是能够通过执行以下操作在其他cmake项目(例如,名为“ example”的目标)中使用该库:

find_package(JSONUtils 1.0 REQUIRED)
target_link_libraries(example JSONUtils::JSONUtils)

为了使此工作有效,您将需要安装和导出该库。作者鼓励这样做进行安装:

include(GNUInstallDirs)
install(TARGETS JSONUtils
    EXPORT jsonutils-export
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

用于导出的

install(EXPORT jsonutils-targets
  FILE
    JSONUtilsTargets.cmake
  NAMESPACE
    JSONUtils::
  DESTINATION
    ${CMAKE_INSTALL_LIBDIR}/cmake/JSONUtils
)

导出将在给定目标中放置一个名为findJsonUtils.cmake的文件。该文件将是您使用find_package机制在其他项目中导入库所需要的。

本文中的所有代码示例均摘自Pablo Arias的链接文章。

答案 1 :(得分:0)

您的CMakeLists.txt位于内部 utilities中,尝试使用它。

src/utilities/CMakeLists.txt

target_include_directories(${PROJECT_NAME}
  PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
)

对于应用程序,您应该具有以下内容: src/my_app/CMakeLists.txt

target_link_libraries(${PROJECT_NAME} PRIVATE utilities)

,你应该简单 src/CMakeLists.txt

add_subdirectory(utilities)
add_subdirectory(my_app)