我有一个库,需要携带一些从非源文件内容注入的常量数据(在本例中为 OpenGL 着色器代码)。为了实现这一目标,我使用
add_custom_command()
生成包含文件,然后可以将其 #include
放入我的代码中以初始化 const 静态变量。
这与常规库(静态或共享)完美配合,但现在我想让我的库仅包含头文件。 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()
创建一个以标头作为唯一来源的静态库对我有用。当然,这只是一种解决方法。
!<arch>
内容。代码:
set(OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/generated_include")
add_custom_command(
OUTPUT "${OUTDIR}/outfile.h"
# Replace the next two lines with a proper generating script.
COMMAND mkdir -p ${OUTDIR}
COMMAND touch ${OUTDIR}/outfile.h
)
# Note, I am only adding header files to the library.
add_library(generated-headers STATIC
"${OUTDIR}/outfile.h"
)
set_target_properties(generated-headers
PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(generated-headers PUBLIC ${OUTDIR})
在其他目录中使用,如下所示:
# In any other directory of the same CMake project:
add_executable(main main.cpp)
target_link_libraries(main generated-headers)
在 CMake 3.2、3.8 和 3.9 上测试。使用 Ninja 和 Make 生成器。
可以使用CMake 3.1中的target_sources来告诉消费者编译接口文件:
add_library(source_only INTERFACE)
target_sources(source_only INTERFACE foo.cpp)
http://www.cmake.org/cmake/help/v3.1/command/target_sources.html
我在尝试使用glad时遇到了类似的问题:https://github.com/Dav1dde/glad
它使用自定义 CMake 命令来构建绑定,这意味着您需要包含在使用glad的项目中的文件不存在,因此CMake不会构建glad(这将创建这些文件)...
我还没有尝试过,但以下链接的示例 3 似乎是一个很好的解决方案,我相信它可能适合您的情况: https://samthursfield.wordpress.com/2015/11/21/cmake-dependency- Between-targets-and-files-and-custom-commands/
你应该使用这个:
set_source_files_properties(your_generated.h PROPERTIES LANGUAGE CXX)
但请注意,这可能在不同的生成器上仍然会失败 - Xcode 不喜欢这样。但我尝试过的所有其他发电机都工作正常。