Reputation: 3632
I have a project which uses cmake
to build. The project has a number of submodules which build as libraries. The structure looks like this:
src
├── CMakeLists.txt
├── libA
│ ├── CMakeLists.txt
│ ├── include
│ │ └── A
│ │ └── A.h
│ └── src
│ └── A.cpp
│
├── libB
│ ├── CMakeLists.txt
│ ├── include
│ │ └── B
│ │ └── B.h
│ └── src
│ └── B.cpp
│
├── include
│ └── project.h
├── main
│ ├── CMakeLists.txt
│ └── main.cpp
└── other_main
├── CMakeLists.txt
└── main.cpp
Now it turns out that I need to convert module B to be template based rather than a linkable lib; i.e. I want to export just headers from module B.
Currently module B's CMakeLists.txt contains the following:
add_library(B STATIC ${SOURCES})
target_include_directories(B
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
... other include dirs ...
PRIVATE
src)
# B depends on A
target_link_libraries(B A)
export(
TARGETS B
FILE BLibraryConfig.cmake)
What are the minimum changes I need to make to my CMakeLists files (at either module or project scope) to be able to support B as a template library given that B still depends on A and both my main projects make use of A and B?
Upvotes: 1
Views: 4121
Reputation: 6250
As another answer says, you could declare B
as an interface library. This approach has some limitations, though. For instance, you cannot set custom properties on interface libraries. Also B
's headers might not be properly displayed by an IDE, e.g. QtCreator 4.6.1 does not show them in the project tree.
If this is critical for you, there is an alternative. You could have a static library which contains only headers, but you need to manually specify it's linker language.
add_library(B STATIC ${SOURCES})
target_include_directories(B
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
... other include dirs ...
)
# As B does not have any source files, you have to explicitly
# specify the linker language
set_target_properties(B PROPERTIES LINKER_LANGUAGE CXX)
# B depends on A
target_link_libraries(B A)
export(
TARGETS B
FILE BLibraryConfig.cmake)
Upvotes: 3
Reputation: 1457
You can declare B
as an interface library to define it as header-only. It will just require slight modifications of target_include_directories
and target_link_libraries
(define INTERFACE
properties instead of public/private)
add_library(B INTERFACE) # no sources
target_include_directories(B INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
# other include dirs ...
)
# B depends on A
target_link_libraries(B INTERFACE A)
export(
TARGETS B
FILE BLibraryConfig.cmake
)
Upvotes: 2