【问题标题】:How to write a working cmake file for flex & bison?如何为 flex & bison 编写一个有效的 cmake 文件?
【发布时间】:2018-11-22 11:41:16
【问题描述】:

我正在编写一个小型解析器,但使用 cmake 时遇到问题。

我的目的是:flex F.l => F.cc,bison B.y => B.cc, my_program.cc + F.cc + B.cc => 库

我的第一次尝试:

FIND_PACKAGE(FLEX REQUIRED)
if (FLEX_FOUND)
    ADD_CUSTOM_TARGET(
        flex_target
        COMMAND ${FLEX_EXECUTABLE} 
            --header-file=${CMAKE_CURRENT_SOURCE_DIR}/F.h
            --outfile=${CMAKE_CURRENT_SOURCE_DIR}/F.cc
            ${CMAKE_CURRENT_SOURCE_DIR}/F.l
        COMMENT "Generating F.cc"
    )
endif(FLEX_FOUND)
FIND_PACKAGE(BISON REQUIRED)
if (BISON_FOUND)
    ADD_CUSTOM_TARGET(
        bison_target
        COMMAND ${BISON_EXECUTABLE} 
            --defines=${CMAKE_CURRENT_SOURCE_DIR}/B.h
            --output=${CMAKE_CURRENT_SOURCE_DIR}/B.cc
            ${CMAKE_CURRENT_SOURCE_DIR}/B.y
        COMMENT "Generating B.cc"
    )
endif(BISON_FOUND)

add_library(my_library my_program.cc F.cc B.cc)
add_dependencies(my_library bison_target)
add_dependencies(my_library flex_target)

除了每次运行 make 时都会调用 flex 和 bison 命令之外,一切都很好,甚至 F.l 和 B.y 文件都没有改变。

然后我尝试切换到使用 ADD_CUSTOM_COMMAND 而不是 ADD_CUSTOM_TARGET。

FIND_PACKAGE(FLEX REQUIRED)
if (FLEX_FOUND)
    ADD_CUSTOM_COMMAND(
        OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/F.cc
        SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/F.l
        COMMAND ${FLEX_EXECUTABLE} 
            --header-file=${CMAKE_CURRENT_SOURCE_DIR}/F.h
            --outfile=${CMAKE_CURRENT_SOURCE_DIR}/F.cc
            ${CMAKE_CURRENT_SOURCE_DIR}/F.l
        COMMENT "Generating F.cc"
    )
endif(FLEX_FOUND)
FIND_PACKAGE(BISON REQUIRED)
if (BISON_FOUND)
    ADD_CUSTOM_COMMAND(
        OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/B.cc
        SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/B.y
        COMMAND ${BISON_EXECUTABLE} 
            --defines=${CMAKE_CURRENT_SOURCE_DIR}/B.h
            --output=${CMAKE_CURRENT_SOURCE_DIR}/B.cc
            ${CMAKE_CURRENT_SOURCE_DIR}/B.y
        COMMENT "Generating B.cc"
    )
endif(BISON_FOUND)

add_library(my_library my_program.cc F.cc B.cc)

请注意,我似乎无法为 ADD_CUSTOM_COMMAND 添加依赖项。

然后,当我运行 make 时,似乎 flex & bison 只会运行一次。即使 .l 和 .y 文件被更改,它也不会第二次运行。

有没有办法实现我的目标?

谢谢。

【问题讨论】:

  • 这是一个附带问题,但你真的不应该使用-y bison 选项,如果你指定--defines-d 是多余的。
  • @rici 谢谢,它已在问题中删除。

标签: cmake bison flex-lexer


【解决方案1】:
  1. 是的,您需要使用add_custom_command
  2. 不要输出到源目录,为此使用 inary 目录。
  3. DEPENDS 部分列出输入文件,以使 CMake 跟踪更改并在更改时重新运行命令。

请参阅add_custom_command documentation 了解更多信息。

【讨论】:

    【解决方案2】:

    CMake 具有适用于 FlexBison 的模块,因此您可以这样做:

    find_package(FLEX REQUIRED)
    find_package(BISON REQUIRED)
    
    flex_target(lexer F.l "${CMAKE_CURRENT_BINARY_DIR}/F.cc")
    
    bison_target(parser B.y "${CMAKE_CURRENT_BINARY_DIR}/B.cc")
    
    add_library(my_library STATIC
        ${sources}
        "${CMAKE_CURRENT_BINARY_DIR}/F.cc"
        "${CMAKE_CURRENT_BINARY_DIR}/B.cc"
    )
    

    请注意,flex_targetbison_target 在内部都使用 add_custom_command

    编辑:为了完整起见,正如@vre 在 cmets 中指出的那样,FindFLEX 提供了add_flex_bison_dependency 命令:

    add_flex_bison_dependency(lexer parser)
    

    这使得lexer 依赖于parser,以便允许以后使用以前的令牌。

    【讨论】:

    • +1,但我宁愿使用 FindFLEX.cmake 示例 ${BISON_parser_OUTPUTS} ${FLEX_lexer_OUTPUTS} 中的建议名称,也不愿重复输出名称并提到在某些情况下添加 add_flex_bison_dependency(parser lexer) 的必要性。
    • 谢谢,更新了我的答案(查看文档,正确的顺序是lexer,然后是parser)。
    • 啊,对不起,我弄混了。
    猜你喜欢
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-15
    • 2017-02-10
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多