首页 > 解决方案 > 如何以正确的方式构建 CMakeLists?

问题描述

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

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})

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

target_link_libraries( # Specifies the target library.
        libplayer
        libcodec)

在这个配置之后,我还需要包含loglib 才能使其工作。首先,我需要找到这个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以包含loglib:

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

log如果你要在 中使用这个库,一切都很好libplayer,但是如果你要在libcodecset 中使用它,你会得到这个错误:

对“__android_log_print”的未定义引用

clang++.exe:错误:链接器命令失败,退出代码为 1(使用 -v 查看调用)

这意味着链接器看不到此方法的实现。

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

https://stackoverflow.com/a/47803975/5709159

为了解决这个问题,我在我的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在两个库中提到 lib。

问题是- 为什么链接器看不到loglib in libcodec?为什么我必须添加附加块?

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

使loglib 对链接器可见libcodec

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

如果我错过了问题中的某些内容,请随时提问。

标签: c++cmakeandroid-ndklinker

解决方案


如果您libcodec使用 中定义的实现log-lib,则必须显式链接log-liblibcodec。这个电话:

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

链接libcodeclog-liblibplayer,它链接log-liblibcodec。它暗示了这个依赖图:

        libplayer
        /       \
  libcodec     log-lib

调用的第一个参数target_link_libraries()是“链接到”库,以下所有目标都链接到第一个。因此,您需要链接log-liblibcodec,如下所示:

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

现在,libcodec将了解 中定义的实现log-lib,在这里暗示依赖图:

        libplayer
        /       \
  libcodec     log-lib
     /
log-lib

不过,您可以使这个更清洁。我们可以删除 和 之间的直接链接libplayer,并log-lib允许log-lib实现传播libcodeclibplayer

target_link_libraries(libcodec PUBLIC
        ${log-lib}
        )

target_link_libraries(libplayer PRIVATE
        libcodec
        )

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

        libplayer
        /
  libcodec
     /
log-lib

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


推荐阅读