FindBISON.cmake 11 KB

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