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