FindBISON.cmake 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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_FOUND``
  9. True if the program was found.
  10. ``BISON_EXECUTABLE``
  11. The path to the ``bison`` program.
  12. ``BISON_VERSION``
  13. The version of ``bison``.
  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. .. command:: bison_target
  18. .. code-block:: cmake
  19. bison_target(<Name> <YaccInput> <CodeOutput>
  20. [OPTIONS <options>...]
  21. [COMPILE_FLAGS <string>]
  22. [DEFINES_FILE <file>]
  23. [VERBOSE [<file>]]
  24. [REPORT_FILE <file>]
  25. )
  26. which will create a custom rule to generate a parser. ``<YaccInput>`` is
  27. the path to a yacc file. ``<CodeOutput>`` is the name of the source file
  28. generated by bison. A header file can also be generated, and contains
  29. the token list.
  30. .. versionchanged:: 3.14
  31. When :policy:`CMP0088` is set to ``NEW``, ``bison`` runs in the
  32. :variable:`CMAKE_CURRENT_BINARY_DIR` directory.
  33. The options are:
  34. ``OPTIONS <options>...``
  35. .. versionadded:: 4.0
  36. A :ref:`semicolon-separated list <CMake Language Lists>` of options added to
  37. the ``bison`` command line.
  38. ``COMPILE_FLAGS <string>``
  39. .. deprecated:: 4.0
  40. Space-separated bison options added to the ``bison`` command line.
  41. A :ref:`;-list <CMake Language Lists>` will not work.
  42. This option is deprecated in favor of ``OPTIONS <options>...``.
  43. ``DEFINES_FILE <file>``
  44. .. versionadded:: 3.4
  45. Specify a non-default header ``<file>`` to be generated by ``bison``.
  46. ``VERBOSE [<file>]``
  47. Tell ``bison`` to write a report file of the grammar and parser.
  48. .. deprecated:: 3.7
  49. If ``<file>`` is given, it specifies path the report file is copied to.
  50. ``[<file>]`` is left for backward compatibility of this module.
  51. Use ``VERBOSE REPORT_FILE <file>``.
  52. ``REPORT_FILE <file>``
  53. .. versionadded:: 3.7
  54. Specify a non-default report ``<file>``, if generated.
  55. The macro defines the following variables:
  56. ``BISON_<Name>_DEFINED``
  57. True if the macro ran successfully.
  58. ``BISON_<Name>_INPUT``
  59. The input source file, an alias for ``<YaccInput>``.
  60. ``BISON_<Name>_OUTPUT_SOURCE``
  61. The source file generated by ``bison``.
  62. ``BISON_<Name>_OUTPUT_HEADER``
  63. The header file generated by ``bison``.
  64. ``BISON_<Name>_OUTPUTS``
  65. All files generated by ``bison`` including the source, the header and the
  66. report.
  67. ``BISON_<Name>_OPTIONS``
  68. .. versionadded:: 4.0
  69. Options used in the ``bison`` command line.
  70. ``BISON_<Name>_COMPILE_FLAGS``
  71. .. deprecated:: 4.0
  72. Options used in the ``bison`` command line. This variable is deprecated in
  73. favor of ``BISON_<Name>_OPTIONS`` variable.
  74. Examples
  75. ^^^^^^^^
  76. .. code-block:: cmake
  77. find_package(BISON)
  78. bison_target(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp
  79. DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/parser.h)
  80. add_executable(Foo main.cpp ${BISON_MyParser_OUTPUTS})
  81. Adding additional command-line options to the ``bison`` executable can be passed
  82. as a list. For example, adding the ``-Wall`` option to report all warnings, and
  83. ``--no-lines`` (``-l``) to not generate ``#line`` directives.
  84. .. code-block:: cmake
  85. find_package(BISON)
  86. if(BISON_FOUND)
  87. bison_target(MyParser parser.y parser.cpp OPTIONS -Wall --no-lines)
  88. endif()
  89. Generator expressions can be used in ``OPTIONS <options...``. For example, to
  90. add the ``--debug`` (``-t``) option only for the ``Debug`` build type:
  91. .. code-block:: cmake
  92. find_package(BISON)
  93. if(BISON_FOUND)
  94. bison_target(MyParser parser.y parser.cpp OPTIONS $<$<CONFIG:Debug>:-t>)
  95. endif()
  96. #]=======================================================================]
  97. find_program(BISON_EXECUTABLE NAMES bison win-bison win_bison DOC "path to the bison executable")
  98. mark_as_advanced(BISON_EXECUTABLE)
  99. if(BISON_EXECUTABLE)
  100. # the bison commands should be executed with the C locale, otherwise
  101. # the message (which are parsed) may be translated
  102. set(_Bison_SAVED_LC_ALL "$ENV{LC_ALL}")
  103. set(ENV{LC_ALL} C)
  104. execute_process(COMMAND ${BISON_EXECUTABLE} --version
  105. OUTPUT_VARIABLE BISON_version_output
  106. ERROR_VARIABLE BISON_version_error
  107. RESULT_VARIABLE BISON_version_result
  108. OUTPUT_STRIP_TRAILING_WHITESPACE)
  109. set(ENV{LC_ALL} ${_Bison_SAVED_LC_ALL})
  110. if(NOT ${BISON_version_result} EQUAL 0)
  111. message(SEND_ERROR "Command \"${BISON_EXECUTABLE} --version\" failed with output:\n${BISON_version_error}")
  112. else()
  113. # Bison++
  114. if("${BISON_version_output}" MATCHES "^bison\\+\\+ Version ([^,]+)")
  115. set(BISON_VERSION "${CMAKE_MATCH_1}")
  116. # GNU Bison
  117. elseif("${BISON_version_output}" MATCHES "^bison \\(GNU Bison\\) ([^\n]+)\n")
  118. set(BISON_VERSION "${CMAKE_MATCH_1}")
  119. elseif("${BISON_version_output}" MATCHES "^GNU Bison (version )?([^\n]+)")
  120. set(BISON_VERSION "${CMAKE_MATCH_2}")
  121. endif()
  122. endif()
  123. # internal macro
  124. # sets BISON_TARGET_cmdopt
  125. macro(BISON_TARGET_option_extraopts Options)
  126. set(BISON_TARGET_cmdopt "")
  127. set(BISON_TARGET_extraopts "${Options}")
  128. separate_arguments(BISON_TARGET_extraopts)
  129. list(APPEND BISON_TARGET_cmdopt ${BISON_TARGET_extraopts})
  130. endmacro()
  131. # internal macro
  132. # sets BISON_TARGET_output_header and BISON_TARGET_cmdopt
  133. macro(BISON_TARGET_option_defines BisonOutput Header)
  134. if("${Header}" STREQUAL "")
  135. # default header path generated by bison (see option -d)
  136. string(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\2" _fileext "${BisonOutput}")
  137. string(REPLACE "c" "h" _fileext ${_fileext})
  138. string(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\1${_fileext}"
  139. BISON_TARGET_output_header "${BisonOutput}")
  140. list(APPEND BISON_TARGET_cmdopt "-d")
  141. else()
  142. set(BISON_TARGET_output_header "${Header}")
  143. list(APPEND BISON_TARGET_cmdopt "--defines=${BISON_TARGET_output_header}")
  144. endif()
  145. endmacro()
  146. # internal macro
  147. # sets BISON_TARGET_verbose_file and BISON_TARGET_cmdopt
  148. macro(BISON_TARGET_option_report_file BisonOutput ReportFile)
  149. if("${ReportFile}" STREQUAL "")
  150. get_filename_component(BISON_TARGET_output_path "${BisonOutput}" PATH)
  151. get_filename_component(BISON_TARGET_output_name "${BisonOutput}" NAME_WE)
  152. set(BISON_TARGET_verbose_file
  153. "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output")
  154. else()
  155. set(BISON_TARGET_verbose_file "${ReportFile}")
  156. list(APPEND BISON_TARGET_cmdopt "--report-file=${BISON_TARGET_verbose_file}")
  157. endif()
  158. if(NOT IS_ABSOLUTE "${BISON_TARGET_verbose_file}")
  159. cmake_policy(GET CMP0088 _BISON_CMP0088
  160. PARENT_SCOPE # undocumented, do not use outside of CMake
  161. )
  162. if("x${_BISON_CMP0088}x" STREQUAL "xNEWx")
  163. set(BISON_TARGET_verbose_file "${CMAKE_CURRENT_BINARY_DIR}/${BISON_TARGET_verbose_file}")
  164. else()
  165. set(BISON_TARGET_verbose_file "${CMAKE_CURRENT_SOURCE_DIR}/${BISON_TARGET_verbose_file}")
  166. endif()
  167. unset(_BISON_CMP0088)
  168. endif()
  169. endmacro()
  170. # internal macro
  171. # adds a custom command and sets
  172. # BISON_TARGET_cmdopt, BISON_TARGET_extraoutputs
  173. macro(BISON_TARGET_option_verbose Name BisonOutput filename)
  174. cmake_policy(GET CMP0088 _BISON_CMP0088
  175. PARENT_SCOPE # undocumented, do not use outside of CMake
  176. )
  177. set(_BISON_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
  178. if("x${_BISON_CMP0088}x" STREQUAL "xNEWx")
  179. set(_BISON_WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
  180. endif()
  181. unset(_BISON_CMP0088)
  182. list(APPEND BISON_TARGET_cmdopt "--verbose")
  183. list(APPEND BISON_TARGET_outputs
  184. "${BISON_TARGET_verbose_file}")
  185. if (NOT "${filename}" STREQUAL "")
  186. if(IS_ABSOLUTE "${filename}")
  187. set(BISON_TARGET_verbose_extra_file "${filename}")
  188. else()
  189. set(BISON_TARGET_verbose_extra_file "${_BISON_WORKING_DIRECTORY}/${filename}")
  190. endif()
  191. add_custom_command(OUTPUT ${BISON_TARGET_verbose_extra_file}
  192. COMMAND ${CMAKE_COMMAND} -E copy
  193. "${BISON_TARGET_verbose_file}"
  194. "${filename}"
  195. VERBATIM
  196. DEPENDS
  197. "${BISON_TARGET_verbose_file}"
  198. COMMENT "[BISON][${Name}] Copying bison verbose table to ${filename}"
  199. WORKING_DIRECTORY ${_BISON_WORKING_DIRECTORY})
  200. list(APPEND BISON_TARGET_extraoutputs
  201. "${BISON_TARGET_verbose_extra_file}")
  202. unset(BISON_TARGET_verbose_extra_file)
  203. unset(_BISON_WORKING_DIRECTORY)
  204. endif()
  205. endmacro()
  206. #============================================================
  207. # BISON_TARGET (public macro)
  208. #============================================================
  209. #
  210. macro(BISON_TARGET Name BisonInput BisonOutput)
  211. set(BISON_TARGET_outputs "${BisonOutput}")
  212. set(BISON_TARGET_extraoutputs "")
  213. # Parsing parameters
  214. set(BISON_TARGET_PARAM_OPTIONS
  215. )
  216. set(BISON_TARGET_PARAM_ONE_VALUE_KEYWORDS
  217. COMPILE_FLAGS
  218. DEFINES_FILE
  219. REPORT_FILE
  220. )
  221. set(BISON_TARGET_PARAM_MULTI_VALUE_KEYWORDS
  222. OPTIONS
  223. VERBOSE
  224. )
  225. cmake_parse_arguments(
  226. BISON_TARGET_ARG
  227. "${BISON_TARGET_PARAM_OPTIONS}"
  228. "${BISON_TARGET_PARAM_ONE_VALUE_KEYWORDS}"
  229. "${BISON_TARGET_PARAM_MULTI_VALUE_KEYWORDS}"
  230. ${ARGN}
  231. )
  232. if(NOT "${BISON_TARGET_ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
  233. message(SEND_ERROR "Usage")
  234. elseif("${BISON_TARGET_ARG_VERBOSE}" MATCHES ";")
  235. # [VERBOSE [<file>] hack: <file> is non-multi value by usage
  236. message(SEND_ERROR "Usage")
  237. else()
  238. BISON_TARGET_option_extraopts("${BISON_TARGET_ARG_COMPILE_FLAGS}")
  239. if(BISON_TARGET_ARG_OPTIONS)
  240. list(APPEND BISON_TARGET_cmdopt ${BISON_TARGET_ARG_OPTIONS})
  241. endif()
  242. BISON_TARGET_option_defines("${BisonOutput}" "${BISON_TARGET_ARG_DEFINES_FILE}")
  243. BISON_TARGET_option_report_file("${BisonOutput}" "${BISON_TARGET_ARG_REPORT_FILE}")
  244. if(NOT "${BISON_TARGET_ARG_VERBOSE}" STREQUAL "")
  245. BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${BISON_TARGET_ARG_VERBOSE}")
  246. else()
  247. # [VERBOSE [<file>]] is used with no argument or is not used
  248. set(BISON_TARGET_args "${ARGN}")
  249. list(FIND BISON_TARGET_args "VERBOSE" BISON_TARGET_args_indexof_verbose)
  250. if(${BISON_TARGET_args_indexof_verbose} GREATER -1)
  251. # VERBOSE is used without <file>
  252. BISON_TARGET_option_verbose(${Name} ${BisonOutput} "")
  253. endif()
  254. endif()
  255. list(APPEND BISON_TARGET_outputs "${BISON_TARGET_output_header}")
  256. cmake_policy(GET CMP0088 _BISON_CMP0088
  257. PARENT_SCOPE # undocumented, do not use outside of CMake
  258. )
  259. set(_BISON_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
  260. set(_BisonInput "${BisonInput}")
  261. if("x${_BISON_CMP0088}x" STREQUAL "xNEWx")
  262. set(_BISON_WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
  263. if(NOT IS_ABSOLUTE "${_BisonInput}")
  264. set(_BisonInput "${CMAKE_CURRENT_SOURCE_DIR}/${_BisonInput}")
  265. endif()
  266. endif()
  267. unset(_BISON_CMP0088)
  268. # Bison cannot create output directories. Create any missing determined
  269. # directories where the files will be generated if they don't exist yet.
  270. set(_BisonMakeDirectoryCommand "")
  271. foreach(output IN LISTS BISON_TARGET_outputs)
  272. cmake_path(GET output PARENT_PATH dir)
  273. if(dir)
  274. list(APPEND _BisonMakeDirectoryCommand ${dir})
  275. endif()
  276. unset(dir)
  277. endforeach()
  278. if(_BisonMakeDirectoryCommand)
  279. list(REMOVE_DUPLICATES _BisonMakeDirectoryCommand)
  280. list(
  281. PREPEND
  282. _BisonMakeDirectoryCommand
  283. COMMAND ${CMAKE_COMMAND} -E make_directory
  284. )
  285. endif()
  286. add_custom_command(OUTPUT ${BISON_TARGET_outputs}
  287. ${_BisonMakeDirectoryCommand}
  288. COMMAND ${BISON_EXECUTABLE} ${BISON_TARGET_cmdopt} -o ${BisonOutput} ${_BisonInput}
  289. VERBATIM
  290. DEPENDS ${_BisonInput}
  291. COMMENT "[BISON][${Name}] Building parser with bison ${BISON_VERSION}"
  292. WORKING_DIRECTORY ${_BISON_WORKING_DIRECTORY}
  293. COMMAND_EXPAND_LISTS)
  294. unset(_BISON_WORKING_DIRECTORY)
  295. # define target variables
  296. set(BISON_${Name}_DEFINED TRUE)
  297. set(BISON_${Name}_INPUT ${_BisonInput})
  298. set(BISON_${Name}_OUTPUTS ${BISON_TARGET_outputs} ${BISON_TARGET_extraoutputs})
  299. set(BISON_${Name}_OPTIONS ${BISON_TARGET_cmdopt})
  300. set(BISON_${Name}_COMPILE_FLAGS ${BISON_TARGET_cmdopt})
  301. set(BISON_${Name}_OUTPUT_SOURCE "${BisonOutput}")
  302. set(BISON_${Name}_OUTPUT_HEADER "${BISON_TARGET_output_header}")
  303. unset(_BisonInput)
  304. unset(_BisonMakeDirectoryCommand)
  305. endif()
  306. endmacro()
  307. #
  308. #============================================================
  309. endif()
  310. include(FindPackageHandleStandardArgs)
  311. find_package_handle_standard_args(BISON REQUIRED_VARS BISON_EXECUTABLE
  312. VERSION_VAR BISON_VERSION)