CMake:包含生成文件的仅标头库

JPN*_*gon 10 cmake header-only

我有一个库需要携带从非源文件的内容(在这种情况下,OpenGL着色器代码)注入的一些常量数据.为了实现这一点,我正在使用add_custom_command()生成包含文件,然后我可以#include在我的代码中初始化const静态变量.

这与常规库(静态或共享)完美配合,但现在我想使我的库只有头.C++让静态方法返回静态数据而不会冒着在每个翻译单元中复制数据的风险("魔法静态")的能力使这成为可能.

然而问题是CMake似乎假设INTERFACE库(我用来创建仅头库的CMake功能)不需要构建 - 在这种情况下,这是错误的.

(我意识到我的库没有实际的义务是仅限标题.在这种特殊情况下,我想要的原因是我希望那个做OpenGL的库保持独立于任何特定的绑定库[比如GLEWGLee或新手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()
Run Code Online (Sandbox Code Playgroud)

Una*_*dra 6

创建一个带有标题的静态库作为对我有用的唯一来源。当然,这只是一种变通方法。

  • 创建一个只有头文件的静态库会导致一个空库。我的说!<arch>是唯一的内容。
  • CMake 将自动在子目录之间获取正确的依赖项。
  • 由于所有源都是标头,因此您需要告诉 CMake 应该使用哪种链接器语言。

代码:

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})
Run Code Online (Sandbox Code Playgroud)

在其他目录中使用,如下所示:

# In any other directory of the same CMake project:
add_executable(main main.cpp)
target_link_libraries(main generated-headers)
Run Code Online (Sandbox Code Playgroud)

在 CMake 3.2、3.8 和 3.9 上测试。使用 Ninja 和 Make 生成器。


ste*_*ire 3

您可以使用 CMake 3.1 中的 target_sources 告诉消费者编译接口文件:

add_library(source_only INTERFACE)
target_sources(source_only INTERFACE foo.cpp) 
Run Code Online (Sandbox Code Playgroud)

http://www.cmake.org/cmake/help/v3.1/command/target_sources.html

  • 我已经使用 `target_sources()` 将生成的头文件添加到我的 INTERFACE 库中。但 CMake 不会生成它们 - 显然依赖项(以及解决它的自定义命令)没有被传递给消费者。 (2认同)