0

After reading some articles on static and shared libs I think I know the difference but I still cannot figure out a way to fix my use case. I have the following project structure

Project
├── A
│   ├── A.cpp
│   ├── A.h
│   └── CMakeLists.txt
├── B
│   ├── CMakeLists.txt
│   └── B.cpp
├── CMakeLists.txt

in folder A I have:

//content of A.h
#include <opencv2/opencv.hpp>
cv::Mat A_load_image(std::string file_path);

//content of A.cpp
#include "A.h"
cv::Mat A_load_image(std::string file_path) {
    return cv::imread(file_path);
}

// content of CMakelists.txt in A
set(TARGET A)
add_library( ${TARGET} STATIC A.cpp )
target_include_directories(${TARGET} PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}
        /path/to/opencv/include/folder )
link_directories( /path/to/opencv/lib/folder)
target_link_libraries( ${TARGET} PUBLIC libopencv_core.a )

then in my folder B I have:

//content of B.cpp
#include "A.h"

cv::Mat B_load_image() {
    return A_load_image("img.bmp");
}

// content of CMakelists.txt in B
set(TARGET B)

add_library(A STATIC IMPORTED)
set_target_properties(A PROPERTIES IMPORTED_LOCATION /PATH/TO/libA.a)

add_library(${TARGET} SHARED B.cpp)
target_include_directories(${TARGET} PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/../A
        /path/to/opencv/include/folder )
 
target_link_libraries(${TARGET} PUBLIC A libopencv_core.a)

And of course I have the CMakelists.txt file in the project root has:

cmake_minimum_required(VERSION 3.4.1)
add_subdirectory(B)
add_subdirectory(A)

I have questions below regarding this project.

  1. How to tell cmake to compile B first so that when I import B for A, it is already updated if any changes
  2. The above setup does not work as I got error when linking B: "cannot find -lopencv_core", I already used PUBLIC for linking A, I also tried to add link_directories( /path/to/opencv/lib/folder) to the CMakelists.txt for B, but still not working. I believe "cannot find -lopencv_core" failed because it is looking for dynamic lib, e.g., libopencv_core.so rather than the static one. But why is that and how I force to link to the static lib?
shelper
  • 10,053
  • 8
  • 41
  • 67
  • I do not understand you, why are you making it so hard? Are you following any cmake documentation? Like https://docs.opencv.org/2.4/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.html exaplins how to find_package opencv. Target properties are __transitive__ in cmake, you do not need to repeat yourself on each target add the same libraries and directories. – KamilCuk Jul 30 '20 at 15:35
  • @KamilCuk its just an example. B is from someone else that uses opencv, and i am building A based on B. I know how to link to opencv, i just dont know how do i link my shared lib to a static lib that links to opencv – shelper Jul 30 '20 at 15:39
  • @KamilCuk I think i have it and it does not work, that is why i ask it ... – shelper Jul 30 '20 at 15:42
  • So maybe you want this: https://stackoverflow.com/questions/11429055/cmake-how-create-a-single-shared-library-from-all-static-libraries-of-subprojec ? Ie. `A` is a static library and you want to create a shared from it? `How to tell cmake to compile B first so that when I import B for A` `add_dependencies(B A)`. Ooooch I guess I see what you are try do, but what for? Why `add_library(A STATIC IMPORTED)` just link with `A`. – KamilCuk Jul 30 '20 at 15:43

1 Answers1

0

Try an object library:

cmake_minimum_required(VERSION 3.11)
add_subdirectory(A)
add_subdirectory(B)

# A/CMakeLists.txt
find_package(OpenCV REQUIRED)
add_library(A OBJECT A.cpp)
target_include_directories(A PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(A PUBLIC ${OpenCV_LIBS})

# B/CMakeLists.txt
add_library(B SHARED B.cpp)
target_include_directories(B PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(B PUBLIC A)
# also try
target_link_options(B PRIVATE "-Wl,--whole-archive")
# or maybe
target_link_options(B PRIVATE "-Wl,--export-all-symbols")
# or maybe also
target_sources(B $<TARGET_OBJECTS:A>)
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • I tried all 3 options, `target_link_options(B PRIVATE "-Wl,--whole-archive")` gives a lot of multiple definition error, second one says no options --export-all-symbols, and third one just does not work, wrong arguments. Forget my example here, my question can be just: if i have static libs for opencv, how can I create shared libs using opencv's static libs. – shelper Jul 30 '20 at 20:22