我有一个库,它需要携带一些从非源文件的内容(在本例中为 OpenGL 着色器代码)注入的常量数据。为了实现这一点,我使用add_custom_command()
生成包含文件,然后我可以#include
在我的代码中初始化 const 静态变量。
这与常规库(静态或共享)完美配合,但现在我想让我的库只包含标题。C++ 让静态方法返回静态数据而不冒在每个翻译单元中复制该数据的风险(“神奇静态”)的能力使这成为可能。
然而,问题是 CMake 似乎假设 INTERFACE 库(这是我用来创建仅标头库的 CMake 功能)不需要构建 - 在这种情况下,这是错误的。
(我意识到我的库没有实际义务仅是标头。在这种特殊情况下,我想要这样做的原因是我希望正在执行 OpenGL 的库保持独立于任何特定的绑定库 [例如GLEW
orGLee
或 newcomer 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()