Reputation: 3124
I have a code folder structure like this:
project/
CMakeLists.txt
src/
project.cpp
lib/
libA/
CMakeLists.txt
src/
libA.cpp
include/
libA.h
libB/
CMakeLists.txt
src/
libB.cpp
include/
libB.h
Now, libA
is totally standalone, so I have a CMakeLists.txt
similar to this:
cmake_minimum_required(VERSION 2.8)
project ( libA )
set ( LIBA_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE )
include_directories ( include/ )
file (GLOB LIBA_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}
src/libA.cpp
)
add_library ( libA STATIC ${LIBA_SOURCES} )
However, libB
depends on libA
. How can I export the libA.a
output path to be used for linking to libB
, and the corresponding include path?
And furthermore, how do I pass that data to the parent CMakeLists.txt
for the main project?
Upvotes: 3
Views: 1497
Reputation: 42852
Taking @epicbrew and @NicolasHolthaus answers/comments I just wanted to show how the complete example would look in a newer version of CMake and discuss some of the implications:
project/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project( project )
add_subdirectory( lib/libB )
add_subdirectory( lib/libA )
add_executable( project src/project.cpp )
target_link_libraries( project libB )
project/lib/libA/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project( libA )
add_library( libA STATIC src/libA.cpp include/libA.h )
target_include_directories( libA PUBLIC include )
project/lib/libB/CMakeLists.txt
add_library( libB STATIC src/libB.cpp include/libB.h )
target_include_directories( libB PUBLIC include )
target_link_libraries( libB libA )
As you can see
CMakeLists.txt
file that you also need libA
. I was deliberately reversing the add_subdirectory()
calls to show that the order doesn't matter when using target_link_libraries()
(sort of allows target forward declarations). include_directories()
call anymore it's an implicit part of the target_include_directories()
.target_include_directories(... PUBLIC ...)
those include paths are self-propagating.${CMAKE_CURRENT_SOURCE_DIR}
prefixes, those are the defaults.add_executable()
/add_library()
calls for compactness of this example code. Normally I also would place those in local variables.libB
is not standalone, but you could change that e.g. by adding add_subdirectory( ../libA libA )
to its CMakeLists.txt
file. Obviously you then have to remove add_subdirectory( lib/libA )
from the main CMakeLists.txt
.project()
commands. If you still want libA
to be self-sufficient you could add if ( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
/endif()
around the cmake_minimum_required(VERSION 3.0)
/project( libA )
calls.Upvotes: 2
Reputation: 8273
I haven't done this personally, so this answer may only be a starting point, but Qt uses cmake and is able to tie all the include directories and library dependencies into each 'module' (library). If you accomplish that, then you can simply do
add_executable(myExe ...)
target_link_libraries(myExe libB)
to the executable in your main cmake project.
Looking through the Qt scripts, it appears what you need to set (for each library) is:
add_library(libA ...)
set_target_properties(libA PROPERTIES
"INTERFACE_LINK_LIBRARIES" "${LIBRARIES_LIBA_DEPENDS_ON}"
"INTERFACE_INCLUDE_DIRECTORIES" "${LIBA_INCLUDE_DIRECTORIES}"
)
then for libB
add_library(libB ...)
set_target_properties(libB PROPERTIES
"INTERFACE_LINK_LIBRARIES" "libA"
"INTERFACE_INCLUDE_DIRECTORIES" "${LIBB_INCLUDE_DIRECTORIES}"
)
The cool thing about this method is that when done properly, you can chain together as many libraries as you like without having to worry about the combinatorial explosion of dependencies and include dirs.
Upvotes: 2
Reputation: 9352
CMake knows about all of the targets that you've built, so there's no need to export information up to the parent. You simply tell CMake that libB links against libA and CMake takes care of putting the correct path on the linker command line. So just specify libA as a link dependency of libB in your libB/CMakeLists.txt:
target_link_libraries(libB libA)
For the include path you either need to set variables in the parent along the lines of the following in the top level project/CMakeLists.txt:
set(LIBA_INCLUDES libA/include)
set(LIBB_INCLUDES libB/include)
Then reference these in the subprojects CMakeList.txt files.
Or, you could use a relative path in your libB/CMakeLists.txt file:
include_directories(../libA/include)
Upvotes: 1