# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. #.rst: # FindBISON # --------- # # Find ``bison`` executable and provide a macro to generate custom build rules. # # The module defines the following variables: # # ``BISON_EXECUTABLE`` # path to the ``bison`` program # # ``BISON_VERSION`` # version of ``bison`` # # ``BISON_FOUND`` # true if the program was found # # The minimum required version of ``bison`` can be specified using the # standard CMake syntax, e.g. ``find_package(BISON 2.1.3)``. # # If ``bison`` is found, the module defines the macro:: # # BISON_TARGET( # [COMPILE_FLAGS ] # [DEFINES_FILE ] # [VERBOSE []] # [REPORT_FILE ] # ) # # which will create a custom rule to generate a parser. ```` is # the path to a yacc file. ```` is the name of the source file # generated by bison. A header file is also be generated, and contains # the token list. # # The options are: # # ``COMPILE_FLAGS `` # Specify flags to be added to the ``bison`` command line. # # ``DEFINES_FILE `` # Specify a non-default header ```` to be generated by ``bison``. # # ``VERBOSE []`` # Tell ``bison`` to write a report file of the grammar and parser. # If ```` is given, it specifies path the report file is copied to. # ``[]`` is left for backward compatibility of this module. # Use ``VERBOSE REPORT_FILE ``. # # ``REPORT_FILE `` # Specify a non-default report ````, if generated. # # The macro defines the following variables: # # ``BISON__DEFINED`` # true is the macro ran successfully # # ``BISON__INPUT`` # The input source file, an alias for # # ``BISON__OUTPUT_SOURCE`` # The source file generated by bison # # ``BISON__OUTPUT_HEADER`` # The header file generated by bison # # ``BISON__OUTPUTS`` # All files generated by bison including the source, the header and the report # # ``BISON__COMPILE_FLAGS`` # Options used in the ``bison`` command line # # Example usage: # # .. code-block:: cmake # # find_package(BISON) # BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp # DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/parser.h) # add_executable(Foo main.cpp ${BISON_MyParser_OUTPUTS}) find_program(BISON_EXECUTABLE NAMES bison win_bison DOC "path to the bison executable") mark_as_advanced(BISON_EXECUTABLE) include(CMakeParseArguments) if(BISON_EXECUTABLE) # the bison commands should be executed with the C locale, otherwise # the message (which are parsed) may be translated set(_Bison_SAVED_LC_ALL "$ENV{LC_ALL}") set(ENV{LC_ALL} C) execute_process(COMMAND ${BISON_EXECUTABLE} --version OUTPUT_VARIABLE BISON_version_output ERROR_VARIABLE BISON_version_error RESULT_VARIABLE BISON_version_result OUTPUT_STRIP_TRAILING_WHITESPACE) set(ENV{LC_ALL} ${_Bison_SAVED_LC_ALL}) if(NOT ${BISON_version_result} EQUAL 0) message(SEND_ERROR "Command \"${BISON_EXECUTABLE} --version\" failed with output:\n${BISON_version_error}") else() # Bison++ if("${BISON_version_output}" MATCHES "^bison\\+\\+ Version ([^,]+)") set(BISON_VERSION "${CMAKE_MATCH_1}") # GNU Bison elseif("${BISON_version_output}" MATCHES "^bison \\(GNU Bison\\) ([^\n]+)\n") set(BISON_VERSION "${CMAKE_MATCH_1}") elseif("${BISON_version_output}" MATCHES "^GNU Bison (version )?([^\n]+)") set(BISON_VERSION "${CMAKE_MATCH_2}") endif() endif() # internal macro # sets BISON_TARGET_cmdopt macro(BISON_TARGET_option_extraopts Options) set(BISON_TARGET_cmdopt "") set(BISON_TARGET_extraopts "${Options}") separate_arguments(BISON_TARGET_extraopts) list(APPEND BISON_TARGET_cmdopt ${BISON_TARGET_extraopts}) endmacro() # internal macro # sets BISON_TARGET_output_header and BISON_TARGET_cmdopt macro(BISON_TARGET_option_defines BisonOutput Header) if("${Header}" STREQUAL "") # default header path generated by bison (see option -d) string(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\2" _fileext "${BisonOutput}") string(REPLACE "c" "h" _fileext ${_fileext}) string(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\1${_fileext}" BISON_TARGET_output_header "${BisonOutput}") list(APPEND BISON_TARGET_cmdopt "-d") else() set(BISON_TARGET_output_header "${Header}") list(APPEND BISON_TARGET_cmdopt "--defines=${BISON_TARGET_output_header}") endif() endmacro() # internal macro # sets BISON_TARGET_verbose_file and BISON_TARGET_cmdopt macro(BISON_TARGET_option_report_file BisonOutput ReportFile) if("${ReportFile}" STREQUAL "") get_filename_component(BISON_TARGET_output_path "${BisonOutput}" PATH) get_filename_component(BISON_TARGET_output_name "${BisonOutput}" NAME_WE) set(BISON_TARGET_verbose_file "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output") else() set(BISON_TARGET_verbose_file "${ReportFile}") list(APPEND BISON_TARGET_cmdopt "--report-file=${BISON_TARGET_verbose_file}") endif() endmacro() # internal macro # adds a custom command and sets # BISON_TARGET_cmdopt, BISON_TARGET_verbose_file, BISON_TARGET_extraoutputs macro(BISON_TARGET_option_verbose Name BisonOutput filename) list(APPEND BISON_TARGET_cmdopt "--verbose") list(APPEND BISON_TARGET_extraoutputs "${BISON_TARGET_verbose_file}") if (NOT "${filename}" STREQUAL "") add_custom_command(OUTPUT ${filename} COMMAND ${CMAKE_COMMAND} -E copy "${BISON_TARGET_verbose_file}" "${filename}" VERBATIM DEPENDS "${BISON_TARGET_verbose_file}" COMMENT "[BISON][${Name}] Copying bison verbose table to ${filename}" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) set(BISON_${Name}_VERBOSE_FILE ${filename}) list(APPEND BISON_TARGET_extraoutputs "${filename}") endif() endmacro() #============================================================ # BISON_TARGET (public macro) #============================================================ # macro(BISON_TARGET Name BisonInput BisonOutput) set(BISON_TARGET_outputs "${BisonOutput}") set(BISON_TARGET_extraoutputs "") # Parsing parameters set(BISON_TARGET_PARAM_OPTIONS ) set(BISON_TARGET_PARAM_ONE_VALUE_KEYWORDS COMPILE_FLAGS DEFINES_FILE REPORT_FILE ) set(BISON_TARGET_PARAM_MULTI_VALUE_KEYWORDS VERBOSE ) cmake_parse_arguments( BISON_TARGET_ARG "${BISON_TARGET_PARAM_OPTIONS}" "${BISON_TARGET_PARAM_ONE_VALUE_KEYWORDS}" "${BISON_TARGET_PARAM_MULTI_VALUE_KEYWORDS}" ${ARGN} ) if(NOT "${BISON_TARGET_ARG_UNPARSED_ARGUMENTS}" STREQUAL "") message(SEND_ERROR "Usage") elseif("${BISON_TARGET_ARG_VERBOSE}" MATCHES ";") # [VERBOSE [] hack: is non-multi value by usage message(SEND_ERROR "Usage") else() BISON_TARGET_option_extraopts("${BISON_TARGET_ARG_COMPILE_FLAGS}") BISON_TARGET_option_defines("${BisonOutput}" "${BISON_TARGET_ARG_DEFINES_FILE}") BISON_TARGET_option_report_file("${BisonOutput}" "${BISON_TARGET_ARG_REPORT_FILE}") if(NOT "${BISON_TARGET_ARG_VERBOSE}" STREQUAL "") BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${BISON_TARGET_ARG_VERBOSE}") else() # [VERBOSE []] is used with no argument or is not used set(BISON_TARGET_args "${ARGN}") list(FIND BISON_TARGET_args "VERBOSE" BISON_TARGET_args_indexof_verbose) if(${BISON_TARGET_args_indexof_verbose} GREATER -1) # VERBOSE is used without BISON_TARGET_option_verbose(${Name} ${BisonOutput} "") endif() endif() list(APPEND BISON_TARGET_outputs "${BISON_TARGET_output_header}") add_custom_command(OUTPUT ${BISON_TARGET_outputs} ${BISON_TARGET_extraoutputs} COMMAND ${BISON_EXECUTABLE} ${BISON_TARGET_cmdopt} -o ${BisonOutput} ${BisonInput} VERBATIM DEPENDS ${BisonInput} COMMENT "[BISON][${Name}] Building parser with bison ${BISON_VERSION}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) # define target variables set(BISON_${Name}_DEFINED TRUE) set(BISON_${Name}_INPUT ${BisonInput}) set(BISON_${Name}_OUTPUTS ${BISON_TARGET_outputs} ${BISON_TARGET_extraoutputs}) set(BISON_${Name}_COMPILE_FLAGS ${BISON_TARGET_cmdopt}) set(BISON_${Name}_OUTPUT_SOURCE "${BisonOutput}") set(BISON_${Name}_OUTPUT_HEADER "${BISON_TARGET_output_header}") endif() endmacro() # #============================================================ endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON REQUIRED_VARS BISON_EXECUTABLE VERSION_VAR BISON_VERSION) # FindBISON.cmake ends here