CMake+GraphViz:如何让被忽略目标完全不显示在所有dot文件中?
解决CMake GraphViz生成文件中彻底移除指定目标的问题
方法1:CMake自定义目标+脚本过滤
CMake自带的GRAPHVIZ_IGNORE_TARGETS仅会跳过生成被忽略目标自身的dot文件,但不会从其他目标的依赖关系中剔除这些节点。你可以在CMake生成原始dot文件后,自动调用脚本批量清理所有dot文件中的指定目标:
- 在CMakeLists.txt中添加自定义过滤逻辑:
# 指定需要忽略的目标 set(IGNORED_TARGETS "special_log_lib") # 启用GraphViz生成 set(GRAPHVIZ_GENERATE_PER_TARGET ON) set(GRAPHVIZ_IGNORE_TARGETS ${IGNORED_TARGETS}) include(GraphViz) # 添加自定义目标,依赖原始GraphViz目标,执行过滤脚本 add_custom_target(filter_graphviz_dots DEPENDS ${GRAPHVIZ_TARGETS} COMMAND ${CMAKE_COMMAND} -DIGNORED_TARGETS="${IGNORED_TARGETS}" -DDOT_DIR="${CMAKE_BINARY_DIR}" -P "${CMAKE_SOURCE_DIR}/filter_dots.cmake" )
- 编写
filter_dots.cmake脚本(放在项目源码目录):
# 拆分忽略目标列表 string(REPLACE " " ";" IGNORED_TARGETS_LIST "${IGNORED_TARGETS}") # 遍历所有生成的dot文件 file(GLOB DOT_FILES "${DOT_DIR}/*.dot") foreach(DOT_FILE ${DOT_FILES}) file(READ "${DOT_FILE}" DOT_CONTENT) # 清理每个忽略目标的节点定义、入边、出边 foreach(TARGET ${IGNORED_TARGETS_LIST}) # 删除节点行(如 "special_log_lib [label=\"special_log_lib\"];") string(REGEX REPLACE "\n[^\n]*${TARGET}[^\n]*;" "" DOT_CONTENT "${DOT_CONTENT}") # 删除指向该目标的依赖边(如 "targetA -> special_log_lib;") string(REGEX REPLACE "\n[^\n]*->[ ]*${TARGET}[^\n]*;" "" DOT_CONTENT "${DOT_CONTENT}") # 删除该目标指向其他的边(如 "special_log_lib -> targetB;") string(REGEX REPLACE "\n[^\n]*${TARGET}[ ]*->[^\n]*;" "" DOT_CONTENT "${DOT_CONTENT}") endforeach() # 写回修改后的文件 file(WRITE "${DOT_FILE}" "${DOT_CONTENT}") endforeach()
执行make filter_graphviz_dots(或对应构建系统的目标)即可得到清理后的dot文件。
方法2:使用GraphViz的gvpr工具批量处理
gvpr是GraphViz自带的脚本化处理工具,可以精准删除指定节点及关联边,比手动正则更可靠:
- 编写gvpr脚本
remove_target.gvpr:
BEGIN { # 定义要移除的目标列表 string targets[] = {"special_log_lib"}; } # 删除指定节点 N { for (int i = 0; i < sizeof(targets); i++) { if (strcmp($.name, targets[i]) == 0) { delete(node, $); } } } # 删除关联该节点的所有边 E { for (int i = 0; i < sizeof(targets); i++) { if (strcmp($.tail.name, targets[i]) == 0 || strcmp($.head.name, targets[i]) == 0) { delete(edge, $); } } }
- 批量处理dot文件的shell脚本(或集成到CMake自定义目标):
for dot_file in *.dot; do gvpr -f remove_target.gvpr "$dot_file" > "filtered_${dot_file}" done
如果要集成到CMake,只需把上述shell命令作为add_custom_target的COMMAND即可。
不推荐的思路
不要尝试在CMake构建阶段修改目标依赖来剥离忽略项——这会影响实际的构建逻辑,容易引发编译错误,仅为生成图形修改依赖得不偿失。
内容的提问来源于stack exchange,提问作者comdoxx
相关产品推荐
相关产品推荐

