CMake:配置时尚未生成的安装文件

2 投票
1 回答
687 浏览
提问于 2025-04-18 07:40

我有一个项目,里面用到了Protobuf接口,我需要用CMake来编译和安装它,以便在Python中使用。

我的 CMakeLists.txt 文件大致是这样的:

file(GLOB PROTO_INPUT "*.proto")
add_custom_target(BuildPythonInterface ALL
  protoc -I=${CMAKE_CURRENT_SOURCE_DIR} --python_out=${CMAKE_CURRENT_BINARY_DIR} ${PROTO_INPUT}
  DEPENDS ${PROTO_INPUT})
file(GLOB PROTOBUF_INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/*_pb2.py")
LIST(APPEND PROTOBUF_INTERFACE "${INIT_PY}" )
install(FILES ${PROTOBUF_INTERFACE} DESTINATION "lib/python2.7/site-packages/${PROJECT_NAME}/proto/")

这个设置确实很好用,当我运行两次的时候效果很好。但是如果我删除了我的构建目录,然后从头开始配置,CMake就找不到Python的protobuf接口文件了,因为这些文件在第一次运行 make all 命令之前是不存在的,所以 file(GLOB PROTOBUF_INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/*_pb2.py") 这行代码就找不到它们。

有没有办法让CMake在第一次构建完成后再执行上面的代码?或者有没有其他更简单的方法来实现这个?

1 个回答

3

在CMake中,推荐的做法是明确列出输入和输出文件,而不是使用 file(GLOB)。这样做有很多原因,其中一个就是你现在遇到的问题;还有一个原因是,使用 GLOB 时,如果你添加了新文件,CMake不会自动重新运行(所以新文件不会被识别)。

不过,如果在你的特定情况下,使用 GLOB 是最合适的选择(就像你在评论中提到的),你可以通过使用 install(DIRECTORY) 来解决这个问题,而不是直接安装文件。可以这样写:

file(GLOB PROTO_INPUT "*.proto")

add_custom_target(BuildPythonInterface ALL
  protoc -I=${CMAKE_CURRENT_SOURCE_DIR} --python_out=${CMAKE_CURRENT_BINARY_DIR}/ToBeInstalled ${PROTO_INPUT}
  DEPENDS ${PROTO_INPUT})

install(
  DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ToBeInstalled/
  DESTINATION "lib/python2.7/site-packages/${PROJECT_NAME}/proto/"
  FILES_MATCHING PATTERN "*_pb2.py"
)

install(FILES ${INIT_PY} DESTINATION "lib/python2.7/site-packages/${PROJECT_NAME}/proto/")

注意 DIRECTORY 参数后面有一个斜杠。这一点很重要:如果没有这个斜杠,名字 ToBeInstalled 会被直接加到目标目录后面。而有了这个斜杠,就不会出现这种情况。

撰写回答