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

时间:2019-11-19 14:02:41

标签: c++ cmake android-ndk linker

我遇到以下问题:我有两套不同的文件(主文件和另一套文件),我想分开。因此,我有一组文件(主文件),可以通过以下方式配置:

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)

在完成此配置后,我还需要包括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})

如果要在log中使用此libplayer库,一切都很好,但是如果要在libcodec集中使用它,则会出现此错误:< / p>

  

未定义对__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。

问题是-链接器为什么看不到log中的libcodec lib?为什么必须添加额外的块?

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

使log中的链接器可以看到libcodec lib吗?

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

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

1 个答案:

答案 0 :(得分:5)

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

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

libcodeclog-lib链接到libplayer,但log-lib链接到libcodec。它暗示了这个依赖图:

        libplayer
        /       \
  libcodec     log-lib

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

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

现在,libcodec将了解log-lib中定义的实现,这意味着此处的依赖关系图:

        libplayer
        /       \
  libcodec     log-lib
     /
log-lib

可以使它更整洁。我们可以删除libplayerlog-lib之间的直接链接,并允许log-lib实现通过libcodeclibplayer传播。< / p>

target_link_libraries(libcodec PUBLIC
        ${log-lib}
        )

target_link_libraries(libplayer PRIVATE
        libcodec
        )

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

        libplayer
        /
  libcodec
     /
log-lib

有关链接时如何以及何时使用PUBLICPRIVATE关键字的信息,请参阅CMake文档中的this部分。