Issue
I have the following issue: I have two different sets of files (main and an additional one), that I would like to keep separate. So, I have one set of files (main), that I configure this 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})
Then I have second set of files (additional), that I configure this way:
set(codec_source
...)
add_library(libcodec SHARED ${codec_source})
Eventually, I need to link these two sets of files:
target_link_libraries( # Specifies the target library.
libplayer
libcodec)
And after this configuration, I also need to include log lib in order to make it work. Firstly, I need to find this log lib, and then include it in my native 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)
Also, I should to edit target_link_libraries to include log lib:
target_link_libraries( # Specifies the target library.
libplayer
libcodec
${log-lib})
All is fine if you are going to use this log lib in libplayer, but if you are going to use it in libcodec set, you'll get this error:
undefined reference to `__android_log_print'
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)
It is means that the linker doesn't see the implementation of this method.
I found this answer on SO:
https://stackoverflow.com/a/47803975/5709159
and in order to solve the issue, I have added to my CMakeLists file this line:
target_link_libraries( # Specifies the target library.
libcodec
android
${log-lib}
)
Main CMake file implementation:
...
#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})
...
So, I need to mention log lib in both of libraries.
Question is - Why doesn't the linker see log lib in libcodec? Why do I have to add the additional block?
target_link_libraries( # Specifies the target library.
libcodec
${log-lib}
)
to make log lib visible for linker in libcodec?
P.S In Visual Studio, if you have main project A and two libs B and C, you include these B and C libs in A, and that is it; everyone knows about everyone. I can call methods in B from C and so on. In order to call a B method from C, I don't need to include C in B. It is enough that both of these libs are included in A as a main project...
If I missed something in the question, feel free to ask.
Solution
If your libcodec uses the implementations defined in log-lib, you must link log-lib to libcodec explicitly. This call:
target_link_libraries( # Specifies the target library.
libplayer
libcodec
${log-lib})
links libcodec and log-lib to libplayer, it does not link log-lib to libcodec. It implies this dependency graph:
libplayer
/ \
libcodec log-lib
The first argument to the target_link_libraries() call is the "linked-to" library, and all the following targets are linked to the first. Thus, you need to link log-lib to libcodec, like this:
target_link_libraries( # Specifies the target library.
libcodec
${log-lib}
)
Now, libcodec will know about the implementation defined in log-lib, implying the dependency graph here:
libplayer
/ \
libcodec log-lib
/
log-lib
You can make this cleaner though. We can remove the direct link between libplayer and log-lib, and allow the log-lib implementation propagate through libcodec to libplayer.
target_link_libraries(libcodec PUBLIC
${log-lib}
)
target_link_libraries(libplayer PRIVATE
libcodec
)
This will simplify the dependency graph to the following:
libplayer
/
libcodec
/
log-lib
See this section in the CMake documentation for how and when to use the PUBLIC and PRIVATE keywords when linking.
Answered By - Kevin
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.