I'm trying to build a header-only library using CMake (Microsoft/GSL), in such a way that I can use variables like GSL_INCLUDE_DIRS
and GSL_LIBRARIES
to link to the target and propagate the appropriate dependencies.
The project I'm working on has a TON of sub-directories, and all the external projects are built in their own sub-directories, hence why the variables are important.
I'm using CMake 3.2.3
Typically (for a library with an actual .lib or .a) I'd do something like:
SET(TARGET_NAME gsl)
include(ExternalProject)
ExternalProject_Add(
${TARGET_NAME}-ext
URL "http://target/url"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
) # download/unzip the header-only project
# Specify include dir
SET(${TARGET_NAME}_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/include CACHE STRING "${TARGET_NAME} include directory")
# Library
add_library(${TARGET_NAME} SHARED IMPORTED GLOBAL)
SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
IMPORTED_LOCATION "some/path/to/some/lib"
)
add_dependencies(${TARGET_NAME} ${TARGET_NAME}-ext)
SET(${TARGET_NAME}_LIBRARIES ${TARGET_NAME} CACHE STRING "${TARGET_NAME} library location")
MARK_AS_ADVANCED(${TARGET_NAME_UPPER}_DIR ${TARGET_NAME_UPPER}_INCLUDE_DIRS ${TARGET_NAME_UPPER}_LIBRARIES)
The problem here is that the header-only library has no lib to set the imported path for, so I can't use an IMPORTED
library. If I don't use a library at all, then I can't set the dependencies in other modules on GSL without building (i.e. downloading/unzipping) every single time, which I don't want to do. a custom_target
would have the same problem, so that's a no-go.
I think what I want is an interface library, something like
add_library(${TARGET_NAME} INTERFACE)
add_dependencies(${TARGET_NAME} ${TARGET_NAME}-ext)
but then cmake complains that
CMake Error at 3rdParty/gsl/CMakeLists.txt:33 (add_dependencies): add_dependencies Cannot add target-level dependencies to INTERFACE library target "gsl".
Is there someway I can use the interface library (or something) to propagate the dependency on the external project?
Disallowing dependencies on INTERFACE
libraries was an oversight that was corrected in CMake version 3.3. After upgrading to the latest-stable release, I was able to use the methodology described in the question, and it worked exactly as desired.