Запрещение сгенерированного CMake make-файла для библиотеки с дополнительным заголовком при компиляции исходных файлов в режиме только заголовка

У меня есть библиотека, которую можно использовать как библиотеку только для заголовков и как традиционную библиотеку. Чтобы включить эту необязательную функцию только для заголовка, библиотека включает .cpp исходные файлы, если они скомпилированы в режиме только заголовка. Пример:

// 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

Когда пользователь включает Vector.hpp в одном из его / ее проектов, если LIBRARY_HEADERONLY определяется, исходные файлы реализации будут включены сразу после заголовочных файлов. Осторожное использование inline Ключевое слово применяется, чтобы избежать нескольких определений.

Если LIBRARY_HEADERONLY не определено, .cpp файлы будут скомпилированы и библиотека должна быть связана.


Моя система сборки выбора CMake.

Используя флаг CMake, пользователь может определить или отменить определение LIBRARY_HEADERONLY,

CMakeLists.txt Файл похож на это:

# (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 .)

К сожалению, созданный CMake make-файл всегда компилирует .cpp файлы, даже если включен режим только заголовка и цель HEADER_ONLY_TARGET,

Как я могу помешать сгенерированному CMake make-файлу компилировать исходные файлы в режиме только заголовка?

Обратите внимание, что Среды IDE, зависящие от сгенерированного CMake вывода, такого как Qt Creator, должны отображать как заголовочные, так и исходные файлы как часть проекта.

Если я не потерю какой-либо исходный файл, а только .hpp Заголовочные файлы, CMake будет жаловаться на то, что исходные файлы не были выбраны для цели библиотеки, а в средах разработки, использующих файлы CMake, не будет отображаться никакой элемент.

2

Решение

Попробуйте установить исходные файлы HEADER_FILE_ONLY свойство препятствовать их строительству, например:

if (LIBRARY_HEADERONLY)
set_source_files_properties(${SRC_LIST} PROPERTIES HEADER_FILE_ONLY 1)
...
endif()

Также см. документация.

4

Другие решения

if (Create_Header_Only)
add_library(TargetName INTERFACE)
# Clients will build with -DLIBRARY_HEADERONLY
target_compile_definitions(TargetName INTERFACE LIBRARY_HEADERONLY)
else()
add_library(TargetName STATIC thesource.cpp)
endif()

# Clients will build with -Iinclude
target_include_directories(TargetName INTERFACE include)

Код клиента просто делает:

add_executable(mine main.cpp)
target_link_libraries(mine TargetName)

Смотрите также Требования к транзитивному использованию и все остальные руководства CMake по созданию пакетов и т. д.

Подход к определению всех типов библиотек и предоставлению возможности выбора между ними представлен в:

Отключить только заголовочные библиотеки с CMake

Что-то вроде:

add_library(lib_shared SHARED ...)
add_library(lib_shared STATIC ...)
add_library(lib_iface INTERFACE)

Так что потребитель делает выбор, на который ссылаться:

# target_link_libraries(consumer lib_static)
# target_link_libraries(consumer lib_shared)
target_link_libraries(consumer lib_iface)
4

Почему вы не отделяете файлы GLOB для HEADERS и SRC? Вы можете добавить dummy.cpp (пустой файл .cpp) для создания библиотек только для заголовков. Я имею в виду:

# Glob all library header files
file(GLOB_RECURSE HEADER_ONLY_LIST "${INC_DIR}/*.hpp")

# Glob all library src files
file(GLOB_RECURSE SRC_ONLY_LIST "${SRC_DIR}/*.cpp")

# Check if LIBRARY_HEADERONLY is defined, so you can filter the target files
if(LIBRARY_HEADERONLY)
set(SRC_LIST ${HEADER_ONLY_LIST} dummy.cpp) # I don't know if it's needed to add a dummy.cpp file with your set_target_properties(HEADER_ONLY_TARGET ...)
else()
set(SRC_LIST ${HEADER_ONLY_LIST} ${SRC_ONLY_LIST})
endif(LIBRARY_HEADERONLY)

# 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 .)

В любом случае, CMake 3.X.X дает вам возможность создавать Библиотеки INTERFACE (только для заголовков).

0
По вопросам рекламы [email protected]