CMake:如何在不同子目录指定FLEX和BISON目标并解决依赖问题
解决CMake跨子目录识别Flex/Bison目标的问题
这个错误的核心原因是CMake的作用域隔离:你在flex子目录定义的lex目标,默认只在flex子目录和根目录(父作用域)可见,但bison子目录是独立的子作用域,无法直接访问其他子目录的目标,所以add_flex_bison_dependency(lex syntax)会找不到lex目标。
下面给你两种可行的解决方案,按推荐程度排序:
方案1:将Flex/Bison目标定义移到根目录(最简洁)
把flex和bison的规则统一放到根目录的CMakeLists.txt里,这样两个目标都处于同一个作用域,add_flex_bison_dependency可以直接识别它们。
修改根目录的CMakeLists.txt:
# 先定义Flex目标,指定源文件路径和生成文件的输出位置 flex_target( lex ${CMAKE_SOURCE_DIR}/flex/xxx.l ${CMAKE_BINARY_DIR}/flex/lex.yy.c ) # 再定义Bison目标 bison_target( syntax ${CMAKE_SOURCE_DIR}/bison/xxx.y ${CMAKE_BINARY_DIR}/bison/syntax.tab.c ) # 添加Flex和Bison的依赖关系,此时两个目标都在根作用域,不会报错 add_flex_bison_dependency(lex syntax) # 最后把生成的词法/语法分析源文件添加到你的项目目标中 add_executable(your_project_name # 其他源文件... ${FLEX_lex_OUTPUTS} ${BISON_syntax_OUTPUTS} )
然后你可以删除flex和bison子目录里的CMakeLists.txt(如果不需要其他子目录逻辑的话),或者保留但移除里面的flex_target/bison_target相关代码。
方案2:跨子目录传递目标信息(保留子目录结构)
如果你坚持要在各自子目录里定义Flex/Bison规则,需要手动把Flex目标的信息传递到Bison子目录,替代add_flex_bison_dependency的自动依赖处理:
- 修改
flex/CMakeLists.txt,将Flex生成的文件路径暴露给父作用域:
flex_target(lex xxx.l ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c) # 把Flex生成的源文件路径传递到根目录 set(FLEX_LEX_OUTPUT_FILE ${FLEX_lex_OUTPUTS} PARENT_SCOPE)
- 修改根目录的
CMakeLists.txt,确保变量能传递到Bison子目录:
add_subdirectory(flex) # 将Flex的输出文件变量传递给Bison子目录 set(FLEX_LEX_OUTPUT_FILE ${FLEX_LEX_OUTPUT_FILE}) add_subdirectory(bison)
- 修改
bison/CMakeLists.txt,手动添加Bison对Flex文件的依赖:
bison_target(syntax xxx.y ${CMAKE_CURRENT_BINARY_DIR}/syntax.tab.c) # 让Bison生成的文件依赖于Flex生成的文件,替代add_flex_bison_dependency的作用 set_source_files_properties(${BISON_syntax_OUTPUTS} PROPERTIES OBJECT_DEPENDS ${FLEX_LEX_OUTPUT_FILE} )
这种方法通过手动传递变量和设置依赖,绕开了CMake的作用域限制,但比方案1繁琐一些,适合子目录有其他复杂逻辑的场景。
内容的提问来源于stack exchange,提问作者Daniel Shao
相关产品推荐
相关产品推荐

