FindBISON.cmake 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file Copyright.txt or https://cmake.org/licensing for details.
  3. #.rst:
  4. # FindBISON
  5. # ---------
  6. #
  7. # Find ``bison`` executable and provide a macro to generate custom build rules.
  8. #
  9. # The module defines the following variables:
  10. #
  11. # ``BISON_EXECUTABLE``
  12. # path to the ``bison`` program
  13. #
  14. # ``BISON_VERSION``
  15. # version of ``bison``
  16. #
  17. # ``BISON_FOUND``
  18. # true if the program was found
  19. #
  20. # The minimum required version of ``bison`` can be specified using the
  21. # standard CMake syntax, e.g. ``find_package(BISON 2.1.3)``.
  22. #
  23. # If ``bison`` is found, the module defines the macro::
  24. #
  25. # BISON_TARGET(<Name> <YaccInput> <CodeOutput>
  26. # [COMPILE_FLAGS <flags>]
  27. # [DEFINES_FILE <file>]
  28. # [VERBOSE [<file>]]
  29. # [REPORT_FILE <file>]
  30. # )
  31. #
  32. # which will create a custom rule to generate a parser. ``<YaccInput>`` is
  33. # the path to a yacc file. ``<CodeOutput>`` is the name of the source file
  34. # generated by bison. A header file is also be generated, and contains
  35. # the token list.
  36. #
  37. # The options are:
  38. #
  39. # ``COMPILE_FLAGS <flags>``
  40. # Specify flags to be added to the ``bison`` command line.
  41. #
  42. # ``DEFINES_FILE <file>``
  43. # Specify a non-default header ``<file>`` to be generated by ``bison``.
  44. #
  45. # ``VERBOSE [<file>]``
  46. # Tell ``bison`` to write a report file of the grammar and parser.
  47. # If ``<file>`` is given, it specifies path the report file is copied to.
  48. # ``[<file>]`` is left for backward compatibility of this module.
  49. # Use ``VERBOSE REPORT_FILE <file>``.
  50. #
  51. # ``REPORT_FILE <file>``
  52. # Specify a non-default report ``<file>``, if generated.
  53. #
  54. # The macro defines the following variables:
  55. #
  56. # ``BISON_<Name>_DEFINED``
  57. # true is the macro ran successfully
  58. #
  59. # ``BISON_<Name>_INPUT``
  60. # The input source file, an alias for <YaccInput>
  61. #
  62. # ``BISON_<Name>_OUTPUT_SOURCE``
  63. # The source file generated by bison
  64. #
  65. # ``BISON_<Name>_OUTPUT_HEADER``
  66. # The header file generated by bison
  67. #
  68. # ``BISON_<Name>_OUTPUTS``
  69. # All files generated by bison including the source, the header and the report
  70. #
  71. # ``BISON_<Name>_COMPILE_FLAGS``
  72. # Options used in the ``bison`` command line
  73. #
  74. # Example usage:
  75. #
  76. # .. code-block:: cmake
  77. #
  78. # find_package(BISON)
  79. # BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp
  80. # DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/parser.h)
  81. # add_executable(Foo main.cpp ${BISON_MyParser_OUTPUTS})
  82. find_program(BISON_EXECUTABLE NAMES bison win_bison DOC "path to the bison executable")
  83. mark_as_advanced(BISON_EXECUTABLE)
  84. if(BISON_EXECUTABLE)
  85. # the bison commands should be executed with the C locale, otherwise
  86. # the message (which are parsed) may be translated
  87. set(_Bison_SAVED_LC_ALL "$ENV{LC_ALL}")
  88. set(ENV{LC_ALL} C)
  89. execute_process(COMMAND ${BISON_EXECUTABLE} --version
  90. OUTPUT_VARIABLE BISON_version_output
  91. ERROR_VARIABLE BISON_version_error
  92. RESULT_VARIABLE BISON_version_result
  93. OUTPUT_STRIP_TRAILING_WHITESPACE)
  94. set(ENV{LC_ALL} ${_Bison_SAVED_LC_ALL})
  95. if(NOT ${BISON_version_result} EQUAL 0)
  96. message(SEND_ERROR "Command \"${BISON_EXECUTABLE} --version\" failed with output:\n${BISON_version_error}")
  97. else()
  98. # Bison++
  99. if("${BISON_version_output}" MATCHES "^bison\\+\\+ Version ([^,]+)")
  100. set(BISON_VERSION "${CMAKE_MATCH_1}")
  101. # GNU Bison
  102. elseif("${BISON_version_output}" MATCHES "^bison \\(GNU Bison\\) ([^\n]+)\n")
  103. set(BISON_VERSION "${CMAKE_MATCH_1}")
  104. elseif("${BISON_version_output}" MATCHES "^GNU Bison (version )?([^\n]+)")
  105. set(BISON_VERSION "${CMAKE_MATCH_2}")
  106. endif()
  107. endif()
  108. # internal macro
  109. # sets BISON_TARGET_cmdopt
  110. macro(BISON_TARGET_option_extraopts Options)
  111. set(BISON_TARGET_cmdopt "")
  112. set(BISON_TARGET_extraopts "${Options}")
  113. separate_arguments(BISON_TARGET_extraopts)
  114. list(APPEND BISON_TARGET_cmdopt ${BISON_TARGET_extraopts})
  115. endmacro()
  116. # internal macro
  117. # sets BISON_TARGET_output_header and BISON_TARGET_cmdopt
  118. macro(BISON_TARGET_option_defines BisonOutput Header)
  119. if("${Header}" STREQUAL "")
  120. # default header path generated by bison (see option -d)
  121. string(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\2" _fileext "${BisonOutput}")
  122. string(REPLACE "c" "h" _fileext ${_fileext})
  123. string(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\1${_fileext}"
  124. BISON_TARGET_output_header "${BisonOutput}")
  125. list(APPEND BISON_TARGET_cmdopt "-d")
  126. else()
  127. set(BISON_TARGET_output_header "${Header}")
  128. list(APPEND BISON_TARGET_cmdopt "--defines=${BISON_TARGET_output_header}")
  129. endif()
  130. endmacro()
  131. # internal macro
  132. # sets BISON_TARGET_verbose_file and BISON_TARGET_cmdopt
  133. macro(BISON_TARGET_option_report_file BisonOutput ReportFile)
  134. if("${ReportFile}" STREQUAL "")
  135. get_filename_component(BISON_TARGET_output_path "${BisonOutput}" PATH)
  136. get_filename_component(BISON_TARGET_output_name "${BisonOutput}" NAME_WE)
  137. set(BISON_TARGET_verbose_file
  138. "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output")
  139. else()
  140. set(BISON_TARGET_verbose_file "${ReportFile}")
  141. list(APPEND BISON_TARGET_cmdopt "--report-file=${BISON_TARGET_verbose_file}")
  142. endif()
  143. endmacro()
  144. # internal macro
  145. # adds a custom command and sets
  146. # BISON_TARGET_cmdopt, BISON_TARGET_verbose_file, BISON_TARGET_extraoutputs
  147. macro(BISON_TARGET_option_verbose Name BisonOutput filename)
  148. list(APPEND BISON_TARGET_cmdopt "--verbose")
  149. list(APPEND BISON_TARGET_extraoutputs
  150. "${BISON_TARGET_verbose_file}")
  151. if (NOT "${filename}" STREQUAL "")
  152. add_custom_command(OUTPUT ${filename}
  153. COMMAND ${CMAKE_COMMAND} -E copy
  154. "${BISON_TARGET_verbose_file}"
  155. "${filename}"
  156. VERBATIM
  157. DEPENDS
  158. "${BISON_TARGET_verbose_file}"
  159. COMMENT "[BISON][${Name}] Copying bison verbose table to ${filename}"
  160. WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
  161. set(BISON_${Name}_VERBOSE_FILE ${filename})
  162. list(APPEND BISON_TARGET_extraoutputs
  163. "${filename}")
  164. endif()
  165. endmacro()
  166. #============================================================
  167. # BISON_TARGET (public macro)
  168. #============================================================
  169. #
  170. macro(BISON_TARGET Name BisonInput BisonOutput)
  171. set(BISON_TARGET_outputs "${BisonOutput}")
  172. set(BISON_TARGET_extraoutputs "")
  173. # Parsing parameters
  174. set(BISON_TARGET_PARAM_OPTIONS
  175. )
  176. set(BISON_TARGET_PARAM_ONE_VALUE_KEYWORDS
  177. COMPILE_FLAGS
  178. DEFINES_FILE
  179. REPORT_FILE
  180. )
  181. set(BISON_TARGET_PARAM_MULTI_VALUE_KEYWORDS
  182. VERBOSE
  183. )
  184. cmake_parse_arguments(
  185. BISON_TARGET_ARG
  186. "${BISON_TARGET_PARAM_OPTIONS}"
  187. "${BISON_TARGET_PARAM_ONE_VALUE_KEYWORDS}"
  188. "${BISON_TARGET_PARAM_MULTI_VALUE_KEYWORDS}"
  189. ${ARGN}
  190. )
  191. if(NOT "${BISON_TARGET_ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
  192. message(SEND_ERROR "Usage")
  193. elseif("${BISON_TARGET_ARG_VERBOSE}" MATCHES ";")
  194. # [VERBOSE [<file>] hack: <file> is non-multi value by usage
  195. message(SEND_ERROR "Usage")
  196. else()
  197. BISON_TARGET_option_extraopts("${BISON_TARGET_ARG_COMPILE_FLAGS}")
  198. BISON_TARGET_option_defines("${BisonOutput}" "${BISON_TARGET_ARG_DEFINES_FILE}")
  199. BISON_TARGET_option_report_file("${BisonOutput}" "${BISON_TARGET_ARG_REPORT_FILE}")
  200. if(NOT "${BISON_TARGET_ARG_VERBOSE}" STREQUAL "")
  201. BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${BISON_TARGET_ARG_VERBOSE}")
  202. else()
  203. # [VERBOSE [<file>]] is used with no argument or is not used
  204. set(BISON_TARGET_args "${ARGN}")
  205. list(FIND BISON_TARGET_args "VERBOSE" BISON_TARGET_args_indexof_verbose)
  206. if(${BISON_TARGET_args_indexof_verbose} GREATER -1)
  207. # VERBOSE is used without <file>
  208. BISON_TARGET_option_verbose(${Name} ${BisonOutput} "")
  209. endif()
  210. endif()
  211. list(APPEND BISON_TARGET_outputs "${BISON_TARGET_output_header}")
  212. add_custom_command(OUTPUT ${BISON_TARGET_outputs}
  213. ${BISON_TARGET_extraoutputs}
  214. COMMAND ${BISON_EXECUTABLE} ${BISON_TARGET_cmdopt} -o ${BisonOutput} ${BisonInput}
  215. VERBATIM
  216. DEPENDS ${BisonInput}
  217. COMMENT "[BISON][${Name}] Building parser with bison ${BISON_VERSION}"
  218. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
  219. # define target variables
  220. set(BISON_${Name}_DEFINED TRUE)
  221. set(BISON_${Name}_INPUT ${BisonInput})
  222. set(BISON_${Name}_OUTPUTS ${BISON_TARGET_outputs} ${BISON_TARGET_extraoutputs})
  223. set(BISON_${Name}_COMPILE_FLAGS ${BISON_TARGET_cmdopt})
  224. set(BISON_${Name}_OUTPUT_SOURCE "${BisonOutput}")
  225. set(BISON_${Name}_OUTPUT_HEADER "${BISON_TARGET_output_header}")
  226. endif()
  227. endmacro()
  228. #
  229. #============================================================
  230. endif()
  231. include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
  232. FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON REQUIRED_VARS BISON_EXECUTABLE
  233. VERSION_VAR BISON_VERSION)