Skip to content

Commit 22c437d

Browse files
committed
Simplify the Lemon and RE2C modules
Original work adapted from commits: b1844be 92cb70d
1 parent 5ea56aa commit 22c437d

2 files changed

Lines changed: 260 additions & 263 deletions

File tree

cmake/FindLEMON.cmake

Lines changed: 110 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -47,158 +47,126 @@
4747
find_program(LEMON_EXECUTABLE lemon DOC "path to the lemon executable")
4848
mark_as_advanced(LEMON_EXECUTABLE)
4949

50-
if (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
51-
# look for the template in share
52-
if (DATA_DIR AND EXISTS "${DATA_DIR}/lemon/lempar.c")
53-
set (LEMON_TEMPLATE "${DATA_DIR}/lemon/lempar.c")
54-
elseif (EXISTS "share/lemon/lempar.c")
55-
set (LEMON_TEMPLATE "share/lemon/lempar.c")
56-
elseif (EXISTS "/usr/share/lemon/lempar.c")
57-
set (LEMON_TEMPLATE "/usr/share/lemon/lempar.c")
58-
endif (DATA_DIR AND EXISTS "${DATA_DIR}/lemon/lempar.c")
59-
endif (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
60-
61-
if (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
62-
# look for the template in bin dir
63-
get_filename_component(lemon_path ${LEMON_EXECUTABLE} PATH)
64-
if (lemon_path)
65-
if (EXISTS ${lemon_path}/lempar.c)
66-
set (LEMON_TEMPLATE "${lemon_path}/lempar.c")
67-
endif (EXISTS ${lemon_path}/lempar.c)
68-
if (EXISTS /usr/share/lemon/lempar.c)
69-
set (LEMON_TEMPLATE "/usr/share/lemon/lempar.c")
70-
endif (EXISTS /usr/share/lemon/lempar.c)
71-
endif (lemon_path)
72-
endif(LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
73-
74-
if (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
75-
# fallback
76-
set (LEMON_TEMPLATE "lempar.c")
77-
if (NOT EXISTS ${LEMON_TEMPLATE})
78-
message(WARNING "Lemon's lempar.c template file could not be found automatically, set LEMON_TEMPLATE")
79-
endif (NOT EXISTS ${LEMON_TEMPLATE})
80-
endif (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
81-
82-
mark_as_advanced(LEMON_TEMPLATE)
50+
if (LEMON_EXECUTABLE)
51+
if(NOT LEMON_TEMPLATE)
52+
# look for the template, if we've not already been told where it is
53+
if (DATA_DIR AND EXISTS "${DATA_DIR}/lemon/lempar.c")
54+
find_file(LEMON_TEMPLATE lempar.c
55+
PATHS "${DATA_DIR}/lemon/lempar.c"
56+
NO_DEFAULT_PATH)
57+
endif ()
58+
59+
# If the above did not succeed, check standard locations
60+
get_filename_component(lemon_dir ${LEMON_EXECUTABLE} DIRECTORY)
61+
find_file(LEMON_TEMPLATE lempar.c
62+
PATHS "${lemon_dir}" "/usr/share/lemon"
63+
NO_DEFAULT_PATH)
64+
mark_as_advanced(LEMON_TEMPLATE)
65+
endif()
66+
67+
# We need a template to be able to use lemon correctly
68+
if(NOT LEMON_TEMPLATE)
69+
message(FATAL_ERROR "Failed to find lemon template file (lempar.c) - need to set LEMON_TEMPLATE")
70+
endif()
71+
72+
# Define the function
73+
# LEMON_TARGET(<Name> <LemonInput> <LemonSource> <LemonHeader>
74+
# [<ArgString>])
75+
# which will create a custom rule to generate a parser. <LemonInput> is
76+
# the path to a lemon file. <LemonSource> is the desired name for the
77+
# generated source file. <LemonHeader> is the desired name for the
78+
# generated header which contains the token list. Anything in the optional
79+
# <ArgString> parameter is appended to the lemon command line.
80+
#
81+
# ====================================================================
82+
# Example:
83+
#
84+
# find_package(LEMON)
85+
# LEMON_TARGET(MyParser parser.y parser.c parser.h)
86+
# add_executable(Foo main.cpp ${LEMON_MyParser_OUTPUTS})
87+
# ====================================================================
88+
89+
include(CMakeParseArguments)
90+
91+
if(NOT COMMAND LEMON_TARGET)
92+
function(LEMON_TARGET Name LemonInput LemonOutput)
93+
set(LT_ARGS DEFINES_FILE COMPILE_FLAGS)
94+
cmake_parse_arguments(LEMON_TARGET_ARG "" "${LT_ARGS}" "" ${ARGN})
95+
96+
if(NOT "${LEMON_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "")
97+
set(LEMON_EXECUTABLE_opts "${LEMON_TARGET_ARG_COMPILE_FLAGS}")
98+
separate_arguments(LEMON_EXECUTABLE_opts)
99+
else()
100+
set(LEMON_EXECUTABLE_opts "")
101+
endif()
102+
103+
# check for LemonOutput
104+
get_filename_component(_basename ${LemonOutput} NAME_WE)
105+
get_filename_component(_out_src_file ${LemonOutput} NAME)
106+
get_filename_component(_out_dir ${LemonOutput} PATH)
107+
if(NOT "${_out_dir}" STREQUAL "")
108+
message(WARNING "Full path specified for LemonOutput - should be filename only")
109+
endif()
110+
111+
# set report file
112+
set(_out_rpt_file "${_basename}.out")
113+
114+
# check for DEFINES_FILE
115+
if ("${LEMON_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
116+
set(_out_hdr_file "${_basename}.h")
117+
else()
118+
get_filename_component(_out_dir ${LEMON_TARGET_ARG_DEFINES_FILE} PATH)
119+
get_filename_component(_out_hdr_file ${LEMON_TARGET_ARG_DEFINES_FILE} NAME)
120+
if(NOT "${_out_dir}" STREQUAL "")
121+
message(WARNING "Full path specified for DEFINES_FILE - should be filename only")
122+
endif()
123+
endif()
124+
125+
# input file
126+
get_filename_component(_in_y_path ${LemonInput} ABSOLUTE)
127+
get_filename_component(_in_y_file ${LemonInput} NAME)
128+
129+
# TODO: is this really necessary?
130+
add_custom_command(
131+
OUTPUT ${_in_y_file}
132+
COMMAND ${CMAKE_COMMAND} -E copy ${_in_y_path} ${CMAKE_CURRENT_BINARY_DIR}
133+
)
83134

84-
include(FindPackageHandleStandardArgs)
85-
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LEMON DEFAULT_MSG LEMON_EXECUTABLE LEMON_TEMPLATE)
86-
87-
# Define the macro
88-
# LEMON_TARGET(<Name> <LemonInput> <LemonSource> <LemonHeader>
89-
# [<ArgString>])
90-
# which will create a custom rule to generate a parser. <LemonInput> is
91-
# the path to a lemon file. <LemonSource> is the desired name for the
92-
# generated source file. <LemonHeader> is the desired name for the
93-
# generated header which contains the token list. Anything in the optional
94-
# <ArgString> parameter is appended to the lemon command line.
95-
#
96-
# ====================================================================
97-
# Example:
98-
#
99-
# find_package(LEMON)
100-
# LEMON_TARGET(MyParser parser.y parser.c parser.h)
101-
# add_executable(Foo main.cpp ${LEMON_MyParser_OUTPUTS})
102-
# ====================================================================
103-
104-
include(CMakeParseArguments)
105-
106-
if(NOT COMMAND LEMON_TARGET)
107-
macro(LEMON_TARGET Name Input)
108-
109-
get_filename_component(IN_FILE_WE ${Input} NAME_WE)
110-
set(LVAR_PREFIX ${Name}_${IN_FILE_WE})
111-
112-
if(${ARGC} GREATER 3)
113-
CMAKE_PARSE_ARGUMENTS(${LVAR_PREFIX} "" "OUT_SRC_FILE;OUT_HDR_FILE;WORKING_DIR;EXTRA_ARGS" "" ${ARGN})
114-
endif(${ARGC} GREATER 3)
115-
116-
# Need a working directory
117-
if("${${LVAR_PREFIX}_WORKING_DIR}" STREQUAL "")
118-
set(${LVAR_PREFIX}_WORKING_DIR "${CMAKE_CURRENT_BINARY_DIR}/${LVAR_PREFIX}")
119-
endif("${${LVAR_PREFIX}_WORKING_DIR}" STREQUAL "")
120-
file(MAKE_DIRECTORY ${${LVAR_PREFIX}_WORKING_DIR})
121-
122-
# Output source file
123-
if ("${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "")
124-
set(${LVAR_PREFIX}_OUT_SRC_FILE ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.c)
125-
else ("${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "")
126-
get_filename_component(specified_out_dir ${${LVAR_PREFIX}_OUT_SRC_FILE} PATH)
127-
if(NOT "${specified_out_dir}" STREQUAL "")
128-
message(FATAL_ERROR "\nFull path specified for OUT_SRC_FILE - should be filename only.\n")
129-
endif(NOT "${specified_out_dir}" STREQUAL "")
130-
set(${LVAR_PREFIX}_OUT_SRC_FILE ${${LVAR_PREFIX}_WORKING_DIR}/${${LVAR_PREFIX}_OUT_SRC_FILE})
131-
endif ("${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "")
132-
133-
# Output header file
134-
if ("${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "")
135-
set(${LVAR_PREFIX}_OUT_HDR_FILE ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.h)
136-
else ("${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "")
137-
get_filename_component(specified_out_dir ${${LVAR_PREFIX}_OUT_HDR_FILE} PATH)
138-
if(NOT "${specified_out_dir}" STREQUAL "")
139-
message(FATAL_ERROR "\nFull path specified for OUT_HDR_FILE - should be filename only.\n")
140-
endif(NOT "${specified_out_dir}" STREQUAL "")
141-
set(${LVAR_PREFIX}_OUT_HDR_FILE ${${LVAR_PREFIX}_WORKING_DIR}/${${LVAR_PREFIX}_OUT_HDR_FILE})
142-
endif ("${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "")
143-
144-
# input file
145-
get_filename_component(in_full ${Input} ABSOLUTE)
146-
if("${in_full}" STREQUAL "${Input}")
147-
set(lemon_in_file ${Input})
148-
else("${in_full}" STREQUAL "${Input}")
149-
set(lemon_in_file "${CMAKE_CURRENT_SOURCE_DIR}/${Input}")
150-
endif("${in_full}" STREQUAL "${Input}")
151-
152-
153-
# names of lemon output files will be based on the name of the input file
154-
set(LEMON_GEN_SOURCE ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.c)
155-
set(LEMON_GEN_HEADER ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.h)
156-
set(LEMON_GEN_OUT ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.out)
157-
158-
# copy input to bin directory and run lemon
159-
get_filename_component(INPUT_NAME ${Input} NAME)
160-
add_custom_command(
161-
OUTPUT ${LEMON_GEN_OUT} ${LEMON_GEN_SOURCE} ${LEMON_GEN_HEADER}
162-
COMMAND ${CMAKE_COMMAND} -E copy ${lemon_in_file} ${${LVAR_PREFIX}_WORKING_DIR}/${INPUT_NAME}
163-
COMMAND ${LEMON_EXECUTABLE} -T${LEMON_TEMPLATE} ${${LVAR_PREFIX}_WORKING_DIR}/${INPUT_NAME} ${${LVAR_PREFIX}__EXTRA_ARGS}
164-
DEPENDS ${Input} ${LEMON_TEMPLATE} ${LEMON_EXECUTABLE_TARGET}
165-
WORKING_DIRECTORY ${${LVAR_PREFIX}_WORKING_DIR}
166-
COMMENT "[LEMON][${Name}] Building parser with ${LEMON_EXECUTABLE}"
167-
)
168-
169-
# rename generated outputs
170-
if(NOT "${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "${LEMON_GEN_SOURCE}")
135+
# execute lemon
171136
add_custom_command(
172-
OUTPUT ${${LVAR_PREFIX}_OUT_SRC_FILE}
173-
COMMAND ${CMAKE_COMMAND} -E copy ${LEMON_GEN_SOURCE} ${${LVAR_PREFIX}_OUT_SRC_FILE}
174-
DEPENDS ${LemonInput} ${LEMON_EXECUTABLE_TARGET} ${LEMON_GEN_SOURCE}
137+
OUTPUT ${_out_src_file}
138+
COMMAND ${LEMON_EXECUTABLE} -T${LEMON_TEMPLATE} ${LEMON_EXECUTABLE_opts} ${_in_y_file}
139+
DEPENDS ${_in_y_file}
140+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
141+
COMMENT "[LEMON][${Name}] Building parser with ${LEMON_EXECUTABLE}"
175142
)
176-
set(LEMON_${Name}_OUTPUTS ${${LVAR_PREFIX}_OUT_SRC_FILE} ${LEMON_${Name}_OUTPUTS})
177-
endif(NOT "${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "${LEMON_GEN_SOURCE}")
178-
if(NOT "${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "${LEMON_GEN_HEADER}")
143+
144+
# rename the header
179145
add_custom_command(
180-
OUTPUT ${${LVAR_PREFIX}_OUT_HDR_FILE}
181-
COMMAND ${CMAKE_COMMAND} -E copy ${LEMON_GEN_HEADER} ${${LVAR_PREFIX}_OUT_HDR_FILE}
182-
DEPENDS ${LemonInput} ${LEMON_EXECUTABLE_TARGET} ${LEMON_GEN_HEADER}
146+
OUTPUT ${_out_hdr_file}
147+
COMMAND ${CMAKE_COMMAND} ARGS -E rename ${_basename}.h ${_out_hdr_file}
148+
DEPENDS ${_out_src_file}
149+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
183150
)
184-
set(LEMON_${Name}_OUTPUTS ${${LVAR_PREFIX}_OUT_HDR_FILE} ${LEMON_${Name}_OUTPUTS})
185-
endif(NOT "${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "${LEMON_GEN_HEADER}")
186151

187-
set(LEMON_${Name}_OUTPUTS ${LEMON_${Name}_OUTPUTS} ${LEMON_GEN_OUT})
152+
# set the return values
153+
# TODO: for generated sources even headers should be target dependencies
154+
set(LEMON_${Name}_DEFINED TRUE PARENT_SCOPE)
155+
set(LEMON_${Name}_OUTPUT_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${_out_hdr_file}" PARENT_SCOPE)
156+
set(LEMON_${Name}_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}" PARENT_SCOPE)
157+
set(LEMON_${Name}_OUTPUTS "${_out_src_file}" PARENT_SCOPE)
188158

189-
# make sure we clean up generated output and copied input
190-
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${LEMON_${Name}_OUTPUTS}")
191-
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${${LVAR_PREFIX}_WORKING_DIR}/${INPUT_NAME}")
159+
# make sure we clean up generated output and copied input
160+
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${LEMON_${Name}_OUTPUTS}")
161+
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/${_in_y_file}")
192162

193-
# macro ran successfully
194-
set(LEMON_${Name}_DEFINED TRUE)
163+
endfunction(LEMON_TARGET)
164+
endif(NOT COMMAND LEMON_TARGET)
195165

196-
set(LEMON_${Name}_SRC ${${LVAR_PREFIX}_OUT_SRC_FILE})
197-
set(LEMON_${Name}_HDR ${${LVAR_PREFIX}_OUT_HDR_FILE})
198-
set(LEMON_${Name}_INCLUDE_DIR ${${LVAR_PREFIX}_WORKING_DIR})
166+
endif(LEMON_EXECUTABLE)
199167

200-
endmacro(LEMON_TARGET)
201-
endif(NOT COMMAND LEMON_TARGET)
168+
include(FindPackageHandleStandardArgs)
169+
find_package_handle_standard_args(LEMON REQUIRED_VARS LEMON_EXECUTABLE LEMON_TEMPLATE)
202170

203171
#============================================================
204172
# FindLEMON.cmake ends here

0 commit comments

Comments
 (0)