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 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindFLEX
--------
Find Fast Lexical Analyzer (Flex) executable and provides a macro
to generate custom build rules
The module defines the following variables:
::
FLEX_FOUND - True is flex executable is found
FLEX_EXECUTABLE - the path to the flex executable
FLEX_VERSION - the version of flex
FLEX_LIBRARIES - The flex libraries
FLEX_INCLUDE_DIRS - The path to the flex headers
The minimum required version of flex can be specified using the
standard syntax, e.g. :command:`find_package(FLEX 2.5.13)`
If flex is found on the system, the module provides the macro:
::
FLEX_TARGET(Name FlexInput FlexOutput
[COMPILE_FLAGS <string>]
[DEFINES_FILE <string>]
)
which creates a custom command to generate the ``FlexOutput`` file from
the ``FlexInput`` file. Name is an alias used to get details of this custom
command. If ``COMPILE_FLAGS`` option is specified, the next
parameter is added to the flex command line.
.. versionadded:: 3.5
If flex is configured to
output a header file, the ``DEFINES_FILE`` option may be used to specify its
name.
.. versionchanged:: 3.17
When :policy:`CMP0098` is set to ``NEW``, ``flex`` runs in the
:variable:`CMAKE_CURRENT_BINARY_DIR` directory.
The macro defines the following variables:
::
FLEX_${Name}_DEFINED - true is the macro ran successfully
FLEX_${Name}_OUTPUTS - the source file generated by the custom rule, an
alias for FlexOutput
FLEX_${Name}_INPUT - the flex source file, an alias for ${FlexInput}
FLEX_${Name}_OUTPUT_HEADER - the header flex output, if any.
Flex scanners often use tokens defined by Bison: the code generated
by Flex depends of the header generated by Bison. This module also
defines a macro:
::
ADD_FLEX_BISON_DEPENDENCY(FlexTarget BisonTarget)
which adds the required dependency between a scanner and a parser
where ``FlexTarget`` and ``BisonTarget`` are the first parameters of
respectively ``FLEX_TARGET`` and ``BISON_TARGET`` macros.
::
====================================================================
Example:
::
find_package(BISON)
find_package(FLEX)
::
BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp)
FLEX_TARGET(MyScanner lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp)
ADD_FLEX_BISON_DEPENDENCY(MyScanner MyParser)
::
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(Foo
Foo.cc
${BISON_MyParser_OUTPUTS}
${FLEX_MyScanner_OUTPUTS}
)
target_link_libraries(Foo ${FLEX_LIBRARIES})
====================================================================
#]=======================================================================]
find_program(FLEX_EXECUTABLE NAMES flex win-flex win_flex DOC "path to the flex executable")
mark_as_advanced(FLEX_EXECUTABLE)
find_library(FL_LIBRARY NAMES fl
DOC "Path to the fl library")
find_path(FLEX_INCLUDE_DIR FlexLexer.h
DOC "Path to the flex headers")
mark_as_advanced(FL_LIBRARY FLEX_INCLUDE_DIR)
set(FLEX_INCLUDE_DIRS ${FLEX_INCLUDE_DIR})
set(FLEX_LIBRARIES ${FL_LIBRARY})
if(FLEX_EXECUTABLE)
execute_process(COMMAND ${FLEX_EXECUTABLE} --version
OUTPUT_VARIABLE FLEX_version_output
ERROR_VARIABLE FLEX_version_error
RESULT_VARIABLE FLEX_version_result
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT ${FLEX_version_result} EQUAL 0)
if(FLEX_FIND_REQUIRED)
message(SEND_ERROR "Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}")
else()
message("Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}\nFLEX_VERSION will not be available")
endif()
else()
# older versions of flex printed "/full/path/to/executable version X.Y"
# newer versions use "basename(executable) X.Y"
get_filename_component(FLEX_EXE_NAME_WE "${FLEX_EXECUTABLE}" NAME_WE)
get_filename_component(FLEX_EXE_EXT "${FLEX_EXECUTABLE}" EXT)
string(REGEX REPLACE "^.*${FLEX_EXE_NAME_WE}(${FLEX_EXE_EXT})?\"? (version )?([0-9]+[^ ]*)( .*)?$" "\\3"
FLEX_VERSION "${FLEX_version_output}")
unset(FLEX_EXE_EXT)
unset(FLEX_EXE_NAME_WE)
endif()
#============================================================
# FLEX_TARGET (public macro)
#============================================================
#
macro(FLEX_TARGET Name Input Output)
set(FLEX_TARGET_PARAM_OPTIONS)
set(FLEX_TARGET_PARAM_ONE_VALUE_KEYWORDS
COMPILE_FLAGS
DEFINES_FILE
)
set(FLEX_TARGET_PARAM_MULTI_VALUE_KEYWORDS)
cmake_parse_arguments(
FLEX_TARGET_ARG
"${FLEX_TARGET_PARAM_OPTIONS}"
"${FLEX_TARGET_PARAM_ONE_VALUE_KEYWORDS}"
"${FLEX_TARGET_MULTI_VALUE_KEYWORDS}"
${ARGN}
)
set(FLEX_TARGET_usage "FLEX_TARGET(<Name> <Input> <Output> [COMPILE_FLAGS <string>] [DEFINES_FILE <string>]")
if(NOT "${FLEX_TARGET_ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
message(SEND_ERROR ${FLEX_TARGET_usage})
else()
cmake_policy(GET CMP0098 _flex_CMP0098
PARENT_SCOPE # undocumented, do not use outside of CMake
)
set(_flex_INPUT "${Input}")
if("x${_flex_CMP0098}x" STREQUAL "xNEWx")
set(_flex_WORKING_DIR "${CMAKE_CURRENT_BINARY_DIR}")
if(NOT IS_ABSOLUTE "${_flex_INPUT}")
set(_flex_INPUT "${CMAKE_CURRENT_SOURCE_DIR}/${_flex_INPUT}")
endif()
else()
set(_flex_WORKING_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
unset(_flex_CMP0098)
set(_flex_OUTPUT "${Output}")
if(NOT IS_ABSOLUTE ${_flex_OUTPUT})
set(_flex_OUTPUT "${_flex_WORKING_DIR}/${_flex_OUTPUT}")
endif()
set(_flex_TARGET_OUTPUTS "${_flex_OUTPUT}")
set(_flex_EXE_OPTS "")
if(NOT "${FLEX_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "")
set(_flex_EXE_OPTS "${FLEX_TARGET_ARG_COMPILE_FLAGS}")
separate_arguments(_flex_EXE_OPTS)
endif()
set(_flex_OUTPUT_HEADER "")
if(NOT "${FLEX_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
set(_flex_OUTPUT_HEADER "${FLEX_TARGET_ARG_DEFINES_FILE}")
if(IS_ABSOLUTE "${_flex_OUTPUT_HEADER}")
set(_flex_OUTPUT_HEADER_ABS "${_flex_OUTPUT_HEADER}")
else()
set(_flex_OUTPUT_HEADER_ABS "${_flex_WORKING_DIR}/${_flex_OUTPUT_HEADER}")
endif()
list(APPEND _flex_TARGET_OUTPUTS "${_flex_OUTPUT_HEADER_ABS}")
list(APPEND _flex_EXE_OPTS --header-file=${_flex_OUTPUT_HEADER_ABS})
endif()
get_filename_component(_flex_EXE_NAME_WE "${FLEX_EXECUTABLE}" NAME_WE)
add_custom_command(OUTPUT ${_flex_TARGET_OUTPUTS}
COMMAND ${FLEX_EXECUTABLE} ${_flex_EXE_OPTS} -o${_flex_OUTPUT} ${_flex_INPUT}
VERBATIM
DEPENDS ${_flex_INPUT}
COMMENT "[FLEX][${Name}] Building scanner with ${_flex_EXE_NAME_WE} ${FLEX_VERSION}"
WORKING_DIRECTORY ${_flex_WORKING_DIR})
set(FLEX_${Name}_DEFINED TRUE)
set(FLEX_${Name}_OUTPUTS ${_flex_TARGET_OUTPUTS})
set(FLEX_${Name}_INPUT ${_flex_INPUT})
set(FLEX_${Name}_COMPILE_FLAGS ${_flex_EXE_OPTS})
set(FLEX_${Name}_OUTPUT_HEADER ${_flex_OUTPUT_HEADER})
unset(_flex_EXE_NAME_WE)
unset(_flex_EXE_OPTS)
unset(_flex_INPUT)
unset(_flex_OUTPUT)
unset(_flex_OUTPUT_HEADER)
unset(_flex_OUTPUT_HEADER_ABS)
unset(_flex_TARGET_OUTPUTS)
unset(_flex_WORKING_DIR)
endif()
endmacro()
#============================================================
#============================================================
# ADD_FLEX_BISON_DEPENDENCY (public macro)
#============================================================
#
macro(ADD_FLEX_BISON_DEPENDENCY FlexTarget BisonTarget)
if(NOT FLEX_${FlexTarget}_OUTPUTS)
message(SEND_ERROR "Flex target `${FlexTarget}' does not exist.")
endif()
if(NOT BISON_${BisonTarget}_OUTPUT_HEADER)
message(SEND_ERROR "Bison target `${BisonTarget}' does not exist.")
endif()
set_source_files_properties(${FLEX_${FlexTarget}_OUTPUTS}
PROPERTIES OBJECT_DEPENDS ${BISON_${BisonTarget}_OUTPUT_HEADER})
endmacro()
#============================================================
endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FLEX REQUIRED_VARS FLEX_EXECUTABLE
VERSION_VAR FLEX_VERSION)
|