Sirop4ik
Sirop4ik

Reputation: 5243

I would like to clarify how to connect shared libs properly

Let's take a real example - I have two native android lib modules (CMake). First module name is - libtetdecoder (further here - A) and another one is - libtetplayer(further here - B). So, lib A use opencv and lib B use lib A. Then, opencv is shared lib and it means that in order to make it work in lib A I need to include headers as well as .so files.

I do it in CMakeList.txt this way

...
include_directories(${pathToOpenCv}/sdk/native/jni/include)
add_library(lib_opencv SHARED IMPORTED)
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION
        ${pathToOpenCv}/sdk/native/libs/${CMAKE_ANDROID_ARCH_ABI}/libopencv_java3.so)
...

As I told above lib B use lib A (but not opencv), so chain looks like this B -> A -> opencv(shared). Question is - if I need in this case include opencv configuration(CMake) in lib B? Because as far as I understood if lib B is going to use lib A, so it means that lib B should implement all the dependencies the same as lib A.

Why I ask, because today I have this implementation in lib A and B, if I try to clean up lib B CMakeList.txt and remove opencv config line it doesn't work.

So, question is - if I really need to include this opencv dependency in all derivative libs?

Upvotes: 0

Views: 94

Answers (1)

Marek Piotrowski
Marek Piotrowski

Reputation: 3076

If you are linking it all via target_link_libraries and link them PUBLICly, dependencies should be transitive, look here.

Directory structure:

- src
-- CMakeLists.txt
-- ecu.cpp
-- engine_ecu.cpp
-- ...
- test
-- CMakeLists.txt
-- integration_test.cpp

src/CMakeLists.txt:

project(EngineController)

add_library(Lib1 SHARED
    ecu.cpp
)

add_library(Lib2 SHARED
    engine_ecu.cpp
    load_detector.cpp
    math_helper.cpp
    temperature_sensor.cpp
)

target_link_libraries(Lib1
    PUBLIC
        EngineControllerApi
)

target_link_libraries(Lib2
    PUBLIC
        EngineControllerApi
        Lib1
)

test/CMakeLists.txt:

project(EngineControllerTest)

add_executable(${PROJECT_NAME}
    integration_test.cpp
)

target_link_libraries(${PROJECT_NAME}
    PUBLIC
        Lib2
)

yields the following:

-- Build files have been written to: /diaggen/example/engine_controller/build
[ 11%] Building CXX object src/CMakeFiles/Lib1.dir/ecu.cpp.o
[ 22%] Linking CXX shared library libLib1.so
[ 22%] Built target Lib1
[ 33%] Building CXX object src/CMakeFiles/Lib2.dir/engine_ecu.cpp.o
[ 44%] Building CXX object src/CMakeFiles/Lib2.dir/load_detector.cpp.o
[ 55%] Building CXX object src/CMakeFiles/Lib2.dir/math_helper.cpp.o
[ 66%] Building CXX object src/CMakeFiles/Lib2.dir/temperature_sensor.cpp.o
[ 77%] Linking CXX shared library libLib2.so
[ 77%] Built target Lib2
[ 88%] Building CXX object test/CMakeFiles/EngineControllerTest.dir/integration_test.cpp.o
[100%] Linking CXX executable EngineControllerTest
[100%] Built target EngineControllerTest

I believe CMake should figure it out. First of all, make sure that you call find_package prior to referencing OpenCV at all. I believe that you could stick to target_link_libraries without having to alter PROPERTIES the way you do. Under the hood, I believe that target_link_libraries also modifies some PROPERTIES, but I believe it's much clearer this way.

Upvotes: 1

Related Questions