时间:2011-10-22 20:15:21

标签: cmake antlr

我正在尝试在我的C ++项目中使用ANTLR。我为指定的语法运行了ANTLR生成器,并使主要的prjct依赖它。

ADD_CUSTOM_TARGET(GenerateParser
    COMMAND ${ANTLR_COMMAND} ${PROJECT_SOURCE_DIR}/src/MyGrammar.g 
                             -o ${PROJECT_SOURCE_DIR}/src/MyGrammar
)

ADD_LIBRARY(MainProject ${LIBRARY_TYPE} ${TARGET_SOURCES} ${TARGET_OPTIONS})
ADD_DEPENDENCIES(MainProject GenerateParser)

问题是每次构建项目时都会运行ANTLR生成器并消耗足够的时间。我怎样才能让它只运行我的语法?或者也许可以使ANTLR以某种方式仅为过时语法生成解析器。

4 个答案:

答案 0 :(得分:12)

如果您正确构建对它的调用,

add_custom_command 执行此操作。

这样的事情应该有效:

ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/src/MyGrammar
  COMMAND ${ANTLR_COMMAND} ${PROJECT_SOURCE_DIR}/src/MyGrammar.g
    -o ${PROJECT_SOURCE_DIR}/src/MyGrammar
  DEPENDS ${PROJECT_SOURCE_DIR}/src/MyGrammar.g
)

ADD_CUSTOM_TARGET(GenerateParser ALL
   DEPENDS ${PROJECT_SOURCE_DIR}/src/MyGrammar
)

ADD_LIBRARY(MainProject ${LIBRARY_TYPE} ${TARGET_SOURCES} ${TARGET_OPTIONS})
ADD_DEPENDENCIES(MainProject GenerateParser)

这里,自定义目标每次都会“构建”,但它唯一要做的就是在它依赖的输出上构建自定义命令,但是当且仅当自定义命令的输出过时时才会过时到其DEPENDS文件。

答案 1 :(得分:3)

add_custom_command会不会这样做?在这里,您可以指定DEPENDS [depends ...],这将使命令仅在从属文件更改时执行。

http://www.cmake.org/cmake/help/cmake2.6docs.html#command:add_custom_command

add_custom_command(OUTPUT output1 [output2 ...]
                 COMMAND command1 [ARGS] [args1...]
                 [COMMAND command2 [ARGS] [args2...] ...]
                 [MAIN_DEPENDENCY depend]
                 [DEPENDS [depends...]]
                 [IMPLICIT_DEPENDS <lang1> depend1 ...]
                 [WORKING_DIRECTORY dir]
                 [COMMENT comment] [VERBATIM] [APPEND])

答案 2 :(得分:3)

除了提供自定义目标的解决方案外,如果您的目标依赖于某些生成的源,则常见的工作流程如下:

添加生成源文件的目标。我建议使用完整路径以避免错误。

add_custom_command(OUTPUT ${GENERATED_SOURCE_FILE}
    COMMAND ${GENERATION COMMAND}
    DEPENDS ${DEPENDENCIES}
)

设置生成的源文件的GENERATED属性。所以cmake不会抱怨缺少源文件。

set_source_files_properties(${GENERATED_SOURCE_FILE} PROPERTIES
    GENERATED TRUE
)

照常将生成的源添加到目标。

add_executable(${YOUR_TARGET} SOURCES ${GENERATED_SOURCE_FILE})

因此,在提议的示例中,只有在某些$ {DEPENDENCIES}文件发生更改时才会启动$ {GENERATION COMMAND}。

答案 3 :(得分:0)

我有完全相同的问题。在阅读了如何生成makefile之后(因为cmake文档有很多不足之处),看起来最好的解决方案是使用OUTPUT表单的add_custom_command。这是我的例子

add_custom_command(OUTPUT
                   # In my cmake file I list every file generated
                   ${PROJECT_SOURCE_DIR}/src/MyGrammar/file1
                   ${PROJECT_SOURCE_DIR}/src/MyGrammar/file2
                   COMMAND ${ANTLR_COMMAND} ${PROJECT_SOURCE_DIR}/src/MyGrammar.g
                   -o {PROJECT_SOURCE_DIR}/src/MyGrammar

                   # In my case I used a script checked into source control, 
                   # so I want to know when it changes too
                   DEPENDS ${ANTLR_COMMAND} ${PROJECT_SOURCE_DIR}/src/MyGrammar.g)

# cmake caches are problematic, so list the files in a variable
set(generated_sources src/MyGrammar/file1 src/MyGrammar/file2)
add_library(yourlib ${list_of_source_files} ${generated_sources})

然后在构建cmake时,会在决定重新生成源之前检查命令和语法文件是否有变化。