【问题标题】:Cannot find API header file for shared library with cmake使用 cmake 找不到共享库的 API 头文件
【发布时间】:2020-04-27 17:45:20
【问题描述】:

我正在一个项目中构建一个共享库并在另一个项目中使用它。它们共享一个前缀,但我没有将它们构建在一起(例如,<prefix>/mylib<prefix>/myproject)。 mylibmyproject 都有 srcinclude 目录。

共享库的CMakeList.txt

cmake_minimum_required(VERSION 3.5)
project(mylib)

add_library(mylib SHARED
            src/mylib.c
            )

target_include_directories(mylib PRIVATE include)

set_target_properties(mylib PROPERTIES PUBLIC_HEADER include/mylib.h)

install(TARGETS
  mylib
  LIBRARY DESTINATION lib
  PUBLIC_HEADER DESTINATION include
  RUNTIME DESTINATION bin)

这导致mylib.so 安装在install/mylib/lib/mylib.so 中,mylib.h 安装在install/mylib/include/mylib.h 中,这正是我的意图。

然后我想构建一个使用mylib的项目:

#include "mylib.h"

int main(void)
{
    // use some functions in mylib
}

main.c 的关联 CMakeList.txt 文件:

cmake_minimum_required(VERSION 3.5)
project(myproject)

find_package(mylib REQUIRED)

add_executable(myproject src/main.c)
target_link_libraries(myproject mylib)

install(TARGETS
  myproject
  DESTINATION lib/${PROJECT_NAME})

这会产生:

main.c: fatal error: mylib.h: No such file or directory
#include "mylib.h"
         ^~~~~~~~~

如果我将 CMakeList.txt 更改为包含以下内容:

find_path(MYLIB_INCLUDE_DIR mylib.h)
...
target_include_directories(myproject PUBLIC ${MYLIB_INCLUDE_DIR})

然后它找到标题,但没有找到库。我收到链接器错误:

/usr/bin/ld: cannot find -lmylib

如果我将 CMakeList.txt 更改为包含以下内容:

find_library(MYLIB_LIB mylib)
...
target_link_libraries(myproject ${MYLIB_LIB})

然后构建。

我(想我)理解为什么手动查找库和包含文件是可行的,但这似乎是错误的处理方式......

find_package(mylib) 似乎确实找到了mylib 包(我可以打印cmake 缓存变量和mylib_FOUND=1),但没有找到使用myproject 构建的库和标头。

【问题讨论】:

  • "find_package(mylib) 似乎确实找到了 mylib 包" - 它确实找到了,否则 CMake 会在配置期间发出错误消息。但是不清楚你如何定义这个包。它应该是一个脚本,可以是mylibConfig.cmakeFindmylib.cmake,由find_package(mylib) 调用执行。 CMake 能够为您的mylib 项目生成mylibConfig.cmake。但是您在该项目中的CMakeLists.txtinstall(TARGETS) 调用中不包含EXPORT 关键字,它不包含install(EXPORT) 命令。
  • 你是对的。我需要使用 EXPORT。如果您将其更改为答案,我会接受。也许也可以指向this answer,在你让我朝着正确的方向前进后,我发现它非常有帮助。

标签: c cmake shared-libraries


【解决方案1】:

您需要在库项目的target_include_directories 中为“构建”和“安装”变体指定包含目录:

target_include_directories(mylib PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> # build variant
    $<INSTALL_INTERFACE:include> # install variant
)

顺便说一句,target_include_directories 命令的文档中提供了此类示例。

另外,安装时需要EXPORT库:

install(
  TARGETS mylib
  EXPORT mylib
  LIBRARY DESTINATION lib
  PUBLIC_HEADER DESTINATION include
  RUNTIME DESTINATION bin)

有关使用 cmake 导出库的教程,请参阅 this answer

【讨论】:

  • 我试过这个,但它没有在安装目录中安装我的 API 标头 (mylib.h)。此外,我已经在使用set_target_properties(macaroons PROPERTIES PUBLIC_HEADER include/macaroons.hpp) 。哪个mylib.h 放入&lt;prefix&gt;/install/mylib/include
  • 命令target_include_directories 不处理公共标头安装。它只是定义了包含目录。您仍然需要install(TARGETS ... PUBLIC_HEADER) 命令来安装头文件。
  • 好的。也许我不明白您回答的范围或预期效果。我已经有一个target_include_directories 命令,以及一个set_target_propertiesinstall 命令,如OP 中所示。正如您所建议的那样,更改我的target_include_directories 命令对我的API 标头(mylib.h)的安装位置没有任何影响,也没有在构建myproject 时找到API 标头或库文件的能力。除了您建议对mylib 的文件进行更改之外,我还需要对myprojectCMakeList.txt 文件进行更改吗?
猜你喜欢
  • 2021-04-12
  • 2021-07-17
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
  • 2012-09-30
  • 2015-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多