cmake 中 link 可以使用哪些库?

Which libraries are available to link in cmake?

我正在为一个项目学习 CMake,在 linking 库时感到困惑。

我发现举个例子更容易提问,因为使用我不熟悉的术语可能会产生误导。

问题是(也在示例代码中注释)

  1. 我怎么知道我可以 link 我的目标的库名称是什么?我可以从构建文件结构中看出这一点吗,或者我需要查看外部库的 CMakeLists.txt。 (例如示例中的 gtest-main 和 libhermes)
  2. 如何使用属于外部库的“孙子”库? (例如示例中的 jsi 库)

例子

假设我正在编写一些依赖于 Hermes Library 的测试。然后我写一个 CMakeList.txt 文件,比如

cmake_minimum_required(VERSION 3.13)
project(mytests_cxx)

set(CMAKE_CXX_STANDARD 14)

include(FetchContent)

FetchContent_Declare(
  hermes
  URL https://github.com/facebook/hermes/archive/d63feeb46d26fe0ca7e789fc793f409e5158b27f.zip
)
FetchContent_MakeAvailable(hermes)

enable_testing()

add_executable(
  hello_test
  ./test.cpp
)

find_library (
  LIB_HERMES
  hermes # <- how can I know what is the name?
)


find_library (
  LIB_JSI
  jsi # <- How could I use a "grandchild" dependency, it is defined here (https://github.com/facebook/hermes/tree/main/API/jsi/jsi)
)

target_link_libraries(
  hello_test
  gtest_main <- Hermes seems to use gtest, how could make sure gtest_main is available?
  LIB_HERMES
  LIB_JSI
)

include(GoogleTest)
gtest_discover_tests(hello_test)

运行 cmake 构建

cmake -S . -B build -DHERMES_BUILD_SHARED_JSI=ON // I see an option defined in heremes'CMakeLists.txt but not sure if I am using it right.

构建中的目录

tree ./build -L 2
./build
├── CMakeCache.txt
├── CMakeFiles
│   ├── 3.23.1
│   ├── CMakeDirectoryInformation.cmake
│   ├── CMakeError.log
│   ├── CMakeOutput.log
│   ├── CMakeRuleHashes.txt
│   ├── CMakeTmp
│   ├── Makefile.cmake
│   ├── Makefile2
│   ├── Progress
│   ├── TargetDirectories.txt
│   ├── cmake.check_cache
│   ├── hello_test.dir
│   └── progress.marks
├── CTestTestfile.cmake
├── ImportHermesc.cmake
├── Makefile
├── _deps
│   ├── hermes-build
│   ├── hermes-src
│   └── hermes-subbuild
├── bin
│   └── hermes-lit
├── cmake_install.cmake
├── compile_commands.json
└── hello_test[1]_include.cmake

然后我 运行 cmake --build build 看到这个错误

/.../test.cpp:8:10: fatal error: 'jsi/jsi.h' file not found
#include <jsi/jsi.h>

你的问题太宽泛了。 要么问一个关于cmake中库列表的问题,要么问一个关于如何用hermes编译和link的问题, 就您的构建中包含第三方的特定问题提出问题。这些应该是本网站上的 3 个独立问题。

how can I know what are the library name I can link to my target?

有两件事您可以 target_link_libraries - 您可以 link 使用系统上可用的库和 link 使用 cmake 中定义的目标。

您可以通过遍历 ld --verbose 输出的所有路径并列出这些目录中的所有 lib*.so 文件来列出系统上可用的库。或 https://unix.stackexchange.com/questions/43187/how-do-i-get-a-list-of-shared-library-filenames-under-linux 或类似的。参见 man ld.so

您可以列出在 cmake 中定义的所有目标。 .

这些列表组合起来包含您可以 link 使用的所有可能的库名称。

Can I tell that from the build file structure

我不明白。号

I need to look into CMakeLists.txt of the external libraries

是的,通常您想要查看任何外部库CMakeLists.txt至少以检查恶意代码。

您通常会查看外部库的文档。而且,因为源代码 项目中的一种文档形式,所以您会查看源代码,是的。

How can I use a "grandchild" library that is part of the external library?

包含外部项目的方法有多种。 中概述了案例。

也就是说,并非所有 CMake 项目都能与 add_subdirectory()(由 FetchContent_MakeAvailable 调用)一起正常工作 - 在许多情况下 third-party 项目 CMakeLists.txt 可能不适用于父项目。在这种情况下,我会编译 并将项目 安装 到子目录 中,例如在 运行 CMake 之前或使用 [=16] =],然后只包含安装目录中hand-crafted find_librarytarget_include_directories的编译结果。

总的来说,包括第三方在内并非总是一件容易的事,它需要您熟悉第三方的具体细节第三方项目及其工作方式和编写方式,并决定您希望如何将其包含在您的项目中。