如何以正确的方式构建 CMakeLists?

How to build CMakeLists the right way?

我有以下问题:我有两组不同的文件(主文件和附加文件),我想将它们分开。所以,我有一组文件(主要),我是这样配置的:

set(libplayersource
        ....
        )

add_library( # Sets the name of the library.
        libplayer

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ${libplayersource})

然后我有第二组文件(附加的),我是这样配置的:

set(codec_source
        ...)

add_library(libcodec SHARED ${codec_source})

最终,我需要link这两组文件:

target_link_libraries( # Specifies the target library.
        libplayer
        libcodec)

并且在此配置之后,我还需要包含 log lib 以使其工作。首先,我需要找到这个 log 库,然后将其包含在我的本机库中。

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

此外,我应该编辑 target_link_libraries 以包含 log lib:

target_link_libraries( # Specifies the target library.
        libplayer
        libcodec
        ${log-lib})

如果你打算在 libplayer 中使用这个 log 库,一切都很好,但如果你打算在 libcodec 集中使用它,你会得到这个错误:

undefined reference to `__android_log_print'

clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

意思是linker没有看到这个方法的实现。

我在 SO 上找到了这个答案:

为了解决这个问题,我在 CMakeLists 文件中添加了这一行:

target_link_libraries( # Specifies the target library.
        libcodec
        android
        ${log-lib}
        )

主要 CMake 文件实现:

...
#Main module
set(libplayersource
        ....
        )

add_library( # Sets the name of the library.
        libplayer

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ${libplayersource})

#Additional module
set(codec_source
        ...)

add_library(libcodec SHARED ${codec_source})

#Log lib
find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

#Linking

target_link_libraries( # Specifies the target library.
        libcodec
        ${log-lib}
        )

target_link_libraries( # Specifies the target library.
        libplayer
        libcodec
        ${log-lib})
...

所以,我需要在两个库中提及 log 库。

问题是 - 为什么linker 看不到libcodec 中的log 库?为什么我必须添加额外的块?

target_link_libraries( # Specifies the target library.
        libcodec
        ${log-lib}
        )

log 库对 libcodec 中的 link 人可见?

P.S 在Visual Studio中,如果你有主项目A和两个库B和C,你在A中包含这些B和C库,就是这样;每个人都知道每个人。我可以从 C 等调用 B 中的方法。为了从 C 调用 B 方法,我不需要将 C 包含在 B 中。将这两个库作为主项目包含在 A 中就足够了...

如果我在问题中遗漏了什么,请随时提问。

如果您的 libcodec 使用 log-lib 中定义的实现,您 必须 link log-liblibcodec 明确地。此调用:

target_link_libraries( # Specifies the target library.
        libplayer
        libcodec
        ${log-lib})

links libcodeclog-liblibplayer,它linklog-liblibcodec。它暗示了这个依赖关系图:

        libplayer
        /       \
  libcodec     log-lib

target_link_libraries() 调用的第一个参数是 "linked-to" 库,以下所有目标都是 linked 到 第一个.因此,你需要 link log-liblibcodec,像这样:

target_link_libraries( # Specifies the target library.
        libcodec
        ${log-lib}
        )

现在,libcodec 将了解 log-lib 中定义的实现,暗示此处的依赖关系图:

        libplayer
        /       \
  libcodec     log-lib
     /
log-lib

可以使它更干净。我们可以删除 libplayerlog-lib 之间的直接 link,并允许 log-lib 实现 propagate 通过 libcodeclibplayer.

target_link_libraries(libcodec PUBLIC
        ${log-lib}
        )

target_link_libraries(libplayer PRIVATE
        libcodec
        )

这会将依赖图简化为以下内容:

        libplayer
        /
  libcodec
     /
log-lib

请参阅 CMake 文档中的 this 部分,了解在 linking 时如何以及何时使用 PUBLICPRIVATE 关键字。