summaryrefslogtreecommitdiffstats
path: root/Modules/FindBISON.cmake
blob: 7d81276c8692503b6251c1a4ed31210c087ca138 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#.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(<Name> <YaccInput> <CodeOutput>
#                [COMPILE_FLAGS <flags>]
#                [DEFINES_FILE <file>]
#                [VERBOSE <file>]
#                )
#
# which will create a custom rule to generate a parser.  ``<YaccInput>`` is
# the path to a yacc file.  ``<CodeOutput>`` 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 <flags>``
#   Specify flags to be added to the ``bison`` command line.
#
# ``DEFINES_FILE <file>``
#   Specify a non-default header ``<file>`` to be generated by ``bison``.
#
# ``VERBOSE <file>``
#   Tell ``bison`` to write verbose descriptions of the grammar and
#   parser to the given ``<file>``.
#
# The macro defines the following variables:
#
# ``BISON_<Name>_DEFINED``
#   true is the macro ran successfully
#
# ``BISON_<Name>_INPUT``
#   The input source file, an alias for <YaccInput>
#
# ``BISON_<Name>_OUTPUT_SOURCE``
#   The source file generated by bison
#
# ``BISON_<Name>_OUTPUT_HEADER``
#   The header file generated by bison
#
# ``BISON_<Name>_OUTPUTS``
#   The sources files generated by bison
#
# ``BISON_<Name>_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})

#=============================================================================
# Copyright 2009 Kitware, Inc.
# Copyright 2006 Tristan Carel
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
#  License text for the above reference.)

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
  macro(BISON_TARGET_option_verbose Name BisonOutput filename)
    list(APPEND BISON_TARGET_cmdopt "--verbose")
    get_filename_component(BISON_TARGET_output_path "${BisonOutput}" PATH)
    get_filename_component(BISON_TARGET_output_name "${BisonOutput}" NAME_WE)
    add_custom_command(OUTPUT ${filename}
      COMMAND ${CMAKE_COMMAND}
      ARGS -E copy
      "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output"
      "${filename}"
      DEPENDS
      "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output"
      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
      "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output")
  endmacro()

  # internal macro
  macro(BISON_TARGET_option_extraopts Options)
    set(BISON_TARGET_extraopts "${Options}")
    separate_arguments(BISON_TARGET_extraopts)
    list(APPEND BISON_TARGET_cmdopt ${BISON_TARGET_extraopts})
  endmacro()

  # internal macro
  macro(BISON_TARGET_option_defines Header)
    set(BISON_TARGET_output_header "${Header}")
    list(APPEND BISON_TARGET_cmdopt --defines=${BISON_TARGET_output_header})
  endmacro()

  #============================================================
  # BISON_TARGET (public macro)
  #============================================================
  #
  macro(BISON_TARGET Name BisonInput BisonOutput)
    set(BISON_TARGET_output_header "")
    set(BISON_TARGET_cmdopt "")
    set(BISON_TARGET_outputs "${BisonOutput}")

    # Parsing parameters
    set(BISON_TARGET_PARAM_OPTIONS)
    set(BISON_TARGET_PARAM_ONE_VALUE_KEYWORDS
      VERBOSE
      COMPILE_FLAGS
      DEFINES_FILE
      )
    set(BISON_TARGET_PARAM_MULTI_VALUE_KEYWORDS)
    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")
    else()
      if(NOT "${BISON_TARGET_ARG_VERBOSE}" STREQUAL "")
        BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${BISON_TARGET_ARG_VERBOSE}")
      endif()
      if(NOT "${BISON_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "")
        BISON_TARGET_option_extraopts("${BISON_TARGET_ARG_COMPILE_FLAGS}")
      endif()
      if(NOT "${BISON_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
        BISON_TARGET_option_defines("${BISON_TARGET_ARG_DEFINES_FILE}")
      endif()

      if("${BISON_TARGET_output_header}" STREQUAL "")
        # Header's name generated by bison (see option -d)
        list(APPEND BISON_TARGET_cmdopt "-d")
        string(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\2" _fileext "${BisonOutput}")
        string(REPLACE "c" "h" _fileext ${_fileext})
        string(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\1${_fileext}"
            BISON_TARGET_output_header "${BisonOutput}")
      endif()
      list(APPEND BISON_TARGET_outputs "${BISON_TARGET_output_header}")

      add_custom_command(OUTPUT ${BISON_TARGET_outputs}
        ${BISON_TARGET_extraoutputs}
        COMMAND ${BISON_EXECUTABLE}
        ARGS ${BISON_TARGET_cmdopt} -o ${BisonOutput} ${BisonInput}
        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})
      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