I have a library that can both be used as an header-only library and as a traditional library. To enable this optional-header-only functionality, the library includes .cpp
source files if compiled in header-only mode. Example:
// Vector.hpp
// (Module file), intended to be included manually by the user
#ifndef LIBRARY_MODULE_VECTOR
#define LIBRARY_MODULE_VECTOR
#include "Library/Vector/Inc/Vector2.hpp"
#include "Library/Vector/Inc/Vector3.hpp"
#include "Library/Vector/Inc/VectorUtils.hpp"
#if defined(LIBRARY_HEADERONLY)
#include "Library/Vector/Src/Vector2.cpp"
#include "Library/Vector/Src/Vector3.cpp"
#include "Library/Vector/Src/VectorUtils.cpp"
#endif
#endif
When the user includes Vector.hpp
in one of his/her projects, if LIBRARY_HEADERONLY
is defined, the implementation source files will be included right after the header files. Careful usage of the inline
keyword is applied to avoid multiple definitions.
If LIBRARY_HEADERONLY
is undefined, the .cpp
files will be compiled and the library will have to be linked.
My build system of choice is CMake.
Using a CMake flag, the user can define or undefine LIBRARY_HEADERONLY
.
The CMakeLists.txt
file is similar to this:
# (not shown) set flag and cache variables...
# Include library directory
include_directories("./${INCLUDE_DIRECTORY}")
# Glob all library header/source files
file(GLOB_RECURSE SRC_LIST "${INC_DIR}/*" "${SRC_DIR}/*")
# (Not shown) Check if header-only mode is enabled
# (from now on we assume header-only mode is enabled and that
# LIBRARY_HEADERONLY is defined)
# Use all source/header files as a library target
add_library(HEADER_ONLY_TARGET STATIC ${SRC_LIST})
set_target_properties(HEADER_ONLY_TARGET PROPERTIES LINKER_LANGUAGE CXX)
install(DIRECTORY ${INC_DIR} DESTINATION .)
Unfortunately, the CMake-generated makefile always compiles the .cpp
files, even when header-only mode is enabled and the target is HEADER_ONLY_TARGET
.
How can I prevent the CMake-generated makefile from compiling the source files in header-only mode?
Note that IDEs reliant on CMake-generated output, such as Qt Creator, should display both the header and source files as part of the project.
If I don't glob any source file, but only the .hpp
header files, CMake will complain that no source files were selected for a library target, and IDEs that rely on CMake files will not display any item.
Try setting the source files' HEADER_FILE_ONLY
property to prevent them from building, e.g.:
if (LIBRARY_HEADERONLY)
set_source_files_properties(${SRC_LIST} PROPERTIES HEADER_FILE_ONLY 1)
...
endif()
Also see the documentation.