c++ - 如何以正确的方式构建 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)
在这个配置之后,我还需要包含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
set 中使用它,你会得到这个错误:
对“__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
lib in libcodec
?为什么我必须添加附加块?
target_link_libraries( # Specifies the target library.
libcodec
${log-lib}
)
使log
lib 对链接器可见libcodec
?
PS在 Visual Studio 中,如果你有主项目 A 和两个库 B 和 C,则将这些 B 和 C 库包含在 A 中,就是这样;每个人都知道每个人。我可以从 C 调用 B 中的方法等等。为了从C调用B方法,我不需要在B中包含C。这两个库都包含在A中作为主项目就足够了......
如果我错过了问题中的某些内容,请随时提问。
解决方案
如果您libcodec
使用 中定义的实现log-lib
,则必须显式链接log-lib
到libcodec
。这个电话:
target_link_libraries( # Specifies the target library.
libplayer
libcodec
${log-lib})
链接libcodec
和log-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
不过,您可以使这个更清洁。我们可以删除 和 之间的直接链接libplayer
,并log-lib
允许log-lib
实现传播到libcodec
。libplayer
target_link_libraries(libcodec PUBLIC
${log-lib}
)
target_link_libraries(libplayer PRIVATE
libcodec
)
这会将依赖关系图简化为以下内容:
libplayer
/
libcodec
/
log-lib
请参阅CMake 文档中的此部分,了解如何以及何时在链接时使用PUBLIC
andPRIVATE
关键字。
推荐阅读
- c# - C# 代码中的 .bat 脚本,它一直试图逃避我的原始代码
- python - 如何使用python中的交叉表函数从数据框中绘制饼图
- python - 如何使用 Xarray 处理 OCO-2/Tropomi NETCDF4 文件的时间变量?
- python - sci.py 最小化 - 约束函数参数
- regex - Twitch 剪辑正则表达式
- java - 如果我们在 executorService 中传递线程在 Java 多线程中执行调用会发生什么
- adaptive-cards - 如何通过 Action.Http 获取 TextBlock 文本?
- c# - 如何知道目录是否可写?
- android - 尝试通过 Android 设备通过 BLE + BT 连接到 iOS
- firebird - 无法在执行块中删除先前修改的新表