Issue
From the following example:
CMakeList.txt file:
include_directories(inc)
# Grab all the cpp and h files to be compile.
file(GLOB SOURCES
inc/*.h
inc/*.hpp
src/*.cpp
)
add_library(MyStaticLib STATIC ${SOURCES} )
target_link_libraries(MyStaticLib PUBLIC "${OPENCV_LIBS}/opencv_world410.lib" )
target_link_libraries(MyStaticLib PUBLIC "${OPENCV_LIBS}/opencv_world410d.lib" )
Does this create a single static library? I thought you could not link a static library to a static library in c++? Why does this work? Also, what would be the best way to do this? For example, if I create an API that is a static Lib i.e., MyStaticLib and it’s dependent on opencv’s Static lib, what would be the best way to set this up in CMake?
Solution
In short
When target_link_libraries
is applied to the static library, it won't affect on the resulted library file. But it affects on the target in the similar way, as it would affect on the target of the shared library.
So, you can use target_link_libraries
both for static and shared libraries in the same manner.
In details
When applied to the static library, target_link_libraries
doesn't have immediate effect on the creation of this library. That is, when static library will be created (as file), it won't store that linkage:
add_library(MyStaticLib STATIC ${SOURCES} )
target_link_libraries(MyStaticLib PUBLIC "${OPENCV_LIBS}/opencv_world410.lib")
# When file 'MyStaticLib.lib' will be created,
# it will NOT be linked with 'opencv_world410.lib'.
(As you probably know, a static library doesn't store any information about the linkage, a static library is just a collection of object files.)
But while the file with the static library doesn't store linkage information, the CMake target, which represents that static library, will be "aware of linkage". This can be useful in many cases:
If in the same project you create an executable or a shared library, and link it with the static library (using
target_link_libraries
), that executable will actually linked with the dependent library:add_executable(myExe ...) target_link_libraries(myExe PRIVATE MyStaticLib) # When file 'myExe.exe' will be created, it WILL be linked with 'opencv_world410.lib'
If in the same project you create another static library, and link it with the static one, the another static library will be "aware of linkage" both with the initial static library and its dependency.
add_library(MyStaticLibAnother STATIC ..) target_link_libraries(MyStaticLibAnother PUBLIC MyStaticLib) # "As if" following line is executed # target_link_libraries(MyStaticLibAnother PUBLIC "${OPENCV_LIBS}/opencv_world410.lib")
If you install your library target and export it using command
install(TARGETS ... EXPORT ...)
, then the library can be found withfind_package
. And thatfind_package
will create a static library target, which will be aware of linkage with all its dependencies:# [In main project] install(TARGETS MyStaticLib EXPORT MyProject) install(EXPORT MyProject NAMESPACE MyProject::)
# [In another project] find_package(MyProject REQUIRED) # It creates the target MyProject::MyStaticLib which is # "aware of linkage" with 'opencv_world410.lib'.
Additionally, if you link a static library with a target (not with a plain file), and that target contains compile definitions or other information, applicable to the compile stage, the static library will be compiled using that compile information.
Answered By - Tsyvarev Answer Checked By - Candace Johnson (WPSolving Volunteer)