如何以正确的方式构建 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-lib
到 libcodec
明确地。此调用:
target_link_libraries( # Specifies the target library.
libplayer
libcodec
${log-lib})
links libcodec
和log-lib
到libplayer
,它不linklog-lib
到 libcodec
。它暗示了这个依赖关系图:
libplayer
/ \
libcodec log-lib
target_link_libraries()
调用的第一个参数是 "linked-to" 库,以下所有目标都是 linked 到 第一个.因此,你需要 link 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
之间的直接 link,并允许 log-lib
实现 propagate 通过 libcodec
到libplayer
.
target_link_libraries(libcodec PUBLIC
${log-lib}
)
target_link_libraries(libplayer PRIVATE
libcodec
)
这会将依赖图简化为以下内容:
libplayer
/
libcodec
/
log-lib
请参阅 CMake 文档中的 this 部分,了解在 linking 时如何以及何时使用 PUBLIC
和 PRIVATE
关键字。
我有以下问题:我有两组不同的文件(主文件和附加文件),我想将它们分开。所以,我有一组文件(主要),我是这样配置的:
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-lib
到 libcodec
明确地。此调用:
target_link_libraries( # Specifies the target library.
libplayer
libcodec
${log-lib})
links libcodec
和log-lib
到libplayer
,它不linklog-lib
到 libcodec
。它暗示了这个依赖关系图:
libplayer
/ \
libcodec log-lib
target_link_libraries()
调用的第一个参数是 "linked-to" 库,以下所有目标都是 linked 到 第一个.因此,你需要 link 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
之间的直接 link,并允许 log-lib
实现 propagate 通过 libcodec
到libplayer
.
target_link_libraries(libcodec PUBLIC
${log-lib}
)
target_link_libraries(libplayer PRIVATE
libcodec
)
这会将依赖图简化为以下内容:
libplayer
/
libcodec
/
log-lib
请参阅 CMake 文档中的 this 部分,了解在 linking 时如何以及何时使用 PUBLIC
和 PRIVATE
关键字。