У меня есть библиотека, которая должна содержать некоторые постоянные данные, введенные из содержимого не исходных файлов (в данном случае, код шейдера OpenGL). Чтобы достичь этого, я использую add_custom_command()
для создания включаемых файлов, которые я могу затем #include
добавить в свой код для инициализации константных статических переменных.
Это отлично работает с обычными библиотеками (статическими или общими), но теперь я хотел бы сделать свою библиотеку только заголовком. Способность C++ позволять статическим методам возвращать статические данные без риска дублирования этих данных в каждой единице трансляции («магическая статика») делает это возможным.
Однако проблема заключается в том, что CMake, по-видимому, предполагает, что библиотека INTERFACE (которая является функцией CMake, которую я использую для создания библиотек только для заголовков) не нуждается в сборке, что в данном случае неверно.
(Я понимаю, что моя библиотека не обязана быть только заголовком. В данном конкретном случае причина, по которой я этого хочу, заключается в том, что я хотел бы, чтобы библиотека, выполняющая OpenGL, оставалась независимой от какой-либо конкретной библиотеки привязки [ например, GLEW
или GLee
или новичок glbinding
]. Оставив в моей библиотеке только заголовок, я могу оставить этот выбор пользователю — все, что ему нужно сделать, это #include
заголовок библиотеки привязки перед моим.)
Кто-нибудь видит способ заставить CMake запускать пользовательские команды, генерирующие заголовки, самое позднее, когда создается потребительский проект?
РЕДАКТИРОВАТЬ: я только что понял, что мог бы получить «лучшее из обоих миров», если бы моя библиотека оставалась статической, но при этом сохранялся весь мой код кроме для постоянных данных в файлах заголовков. Таким образом, по-прежнему не будет необходимости выбирать конкретную библиотеку привязки OpenGL. Тем не менее, у библиотеки все еще есть преимущества только для заголовка - простота использования для одного - поэтому я оставляю свой вопрос открытым.
РЕДАКТИРОВАТЬ № 2: Вот соответствующая часть моего файла CMakeLists.txt
(я удалил только зависимости библиотеки - все только заголовки - с конца):
set(SHADER_FILES "src/vertex.glsl" "src/fragment.glsl")
add_library(libGPCGUIGLRenderer INTERFACE)
target_sources(libGPCGUIGLRenderer INTERFACE ${SHADER_FILES})
target_include_directories(libGPCGUIGLRenderer BEFORE
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# Embed shader files
source_group("Shader files" FILES ${SHADER_FILES})
set(GENERATED "${CMAKE_CURRENT_BINARY_DIR}/generated")
target_include_directories(libGPCGUIGLRenderer INTERFACE ${GENERATED})
# Find the GPC Bin2C utility
find_package(GPCBin2C REQUIRED)
# Add a custom target and a dependency for each shader file
foreach(shader ${SHADER_FILES})
get_filename_component(name "${shader}" NAME)
set(shader_header "${GENERATED}/${name}.h")
add_custom_command(
OUTPUT ${shader_header}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${shader}
COMMAND GPCBin2C --input=${CMAKE_CURRENT_SOURCE_DIR}/${shader} --output=${shader_header}
)
target_sources(libGPCGUIGLRenderer INTERFACE ${shader_header})
endforeach()