Vittorio Romeo Vittorio Romeo - 3 months ago 15
C++ Question

Preventing CMake-generated makefile for optional-header-only library from compiling source files in header-only mode

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 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 QTCreator, 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.

Answer

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.