# # - Find perplex executable and provides macros to generate custom build rules # The module defines the following variables # # PERPLEX_EXECUTABLE - path to the perplex program # PERPLEX_TEMPLATE - location of the perplex template file #============================================================================= # F I N D P E R P L E X . C M A K E # # Originally based off of FindBISON.cmake from Kitware's CMake distribution # # Copyright (c) 2010-2016 United States Government as represented by # the U.S. Army Research Laboratory. # Copyright 2009 Kitware, Inc. # Copyright 2006 Tristan Carel # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * The names of the authors may not be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= find_program(PERPLEX_EXECUTABLE perplex DOC "path to the perplex executable") mark_as_advanced(PERPLEX_EXECUTABLE) if(PERPLEX_EXECUTABLE AND NOT PERPLEX_TEMPLATE) get_filename_component(perplex_path ${PERPLEX_EXECUTABLE} PATH) if(perplex_path) set(PERPLEX_TEMPLATE "") if(EXISTS ${perplex_path}/../share/perplex/perplex_template.c) get_filename_component(perplex_template_path "${perplex_path}/../share/perplex/perplex_template.c" ABSOLUTE) set(PERPLEX_TEMPLATE "${perplex_template_path}") endif(EXISTS ${perplex_path}/../share/perplex/perplex_template.c) if(EXISTS ${perplex_path}/../share/perplex_template.c AND NOT PERPLEX_TEMPLATE) get_filename_component(perplex_template_path "${perplex_path}/../share/perplex_template.c" ABSOLUTE) set(PERPLEX_TEMPLATE "${perplex_template_path}") endif(EXISTS ${perplex_path}/../share/perplex_template.c AND NOT PERPLEX_TEMPLATE) endif(perplex_path) if(EXISTS /usr/share/perplex/perplex_template.c AND NOT PERPLEX_TEMPLATE) set(PERPLEX_TEMPLATE "/usr/share/perplex/perplex_template.c") endif(EXISTS /usr/share/perplex/perplex_template.c AND NOT PERPLEX_TEMPLATE) endif(PERPLEX_EXECUTABLE AND NOT PERPLEX_TEMPLATE) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PERPLEX DEFAULT_MSG PERPLEX_EXECUTABLE PERPLEX_TEMPLATE) mark_as_advanced(PERPLEX_TEMPLATE) # Defines two macros - PERPLEX_TARGET, which takes perplex inputs and # runs both perplex and re2c to generate C source code/headers, and # ADD_PERPLEX_LEMON_DEPENDENCY which is used to set up dependencies between # scanner and parser targets when necessary. # # #==================================================================== # Example: # # find_package(LEMON) # find_package(RE2C) # find_package(PERPLEX) # # LEMON_TARGET(MyParser parser.y "${CMAKE_CURRENT_BINARY_DIR}/parser.cpp") # PERPLEX_TARGET(MyScanner scanner.re "${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp" "${CMAKE_CURRENT_BINARY_DIR}/scanner_header.hpp") # ADD_PERPLEX_LEMON_DEPENDENCY(MyScanner MyParser) # # include_directories("${CMAKE_CURRENT_BINARY_DIR}") # add_executable(Foo # Foo.cc # ${LEMON_MyParser_OUTPUTS} # ${PERPLEX_MyScanner_OUTPUTS} # ) # ==================================================================== # #============================================================================= # # Originally based off of FindBISON.cmake from Kitware's CMake distribution # # Copyright (c) 2010-2016 United States Government as represented by # the U.S. Army Research Laboratory. # Copyright 2009 Kitware, Inc. # Copyright 2006 Tristan Carel # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * The names of the authors may not be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= #============================================================ # PERPLEX_TARGET (public macro) #============================================================ include(CMakeParseArguments) if(NOT COMMAND PERPLEX_TARGET) macro(PERPLEX_TARGET Name Input) get_filename_component(IN_FILE_WE ${Input} NAME_WE) set(PVAR_PREFIX ${Name}_${IN_FILE_WE}) if(${ARGC} GREATER 3) CMAKE_PARSE_ARGUMENTS(${PVAR_PREFIX} "" "TEMPLATE;OUT_SRC_FILE;OUT_HDR_FILE;WORKING_DIR" "" ${ARGN}) endif(${ARGC} GREATER 3) # Need a working directory if("${${PVAR_PREFIX}_WORKING_DIR}" STREQUAL "") set(${PVAR_PREFIX}_WORKING_DIR "${CMAKE_CURRENT_BINARY_DIR}/${PVAR_PREFIX}") endif("${${PVAR_PREFIX}_WORKING_DIR}" STREQUAL "") file(MAKE_DIRECTORY ${${PVAR_PREFIX}_WORKING_DIR}) # Set up intermediate and final output names # Output source file if ("${${PVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "") set(${PVAR_PREFIX}_OUT_SRC_FILE ${${PVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.c) else ("${${PVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "") get_filename_component(specified_out_dir ${${PVAR_PREFIX}_OUT_SRC_FILE} PATH) if(NOT "${specified_out_dir}" STREQUAL "") message(FATAL_ERROR "\nFull path specified for OUT_SRC_FILE - should be filename only.\n") endif(NOT "${specified_out_dir}" STREQUAL "") set(${PVAR_PREFIX}_OUT_SRC_FILE ${${PVAR_PREFIX}_WORKING_DIR}/${${PVAR_PREFIX}_OUT_SRC_FILE}) endif ("${${PVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "") # Output header file if ("${${PVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "") set(${PVAR_PREFIX}_OUT_HDR_FILE ${${PVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.h) else ("${${PVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "") get_filename_component(specified_out_dir ${${PVAR_PREFIX}_OUT_HDR_FILE} PATH) if(NOT "${specified_out_dir}" STREQUAL "") message(FATAL_ERROR "\nFull path specified for OUT_HDR_FILE - should be filename only.\n") endif(NOT "${specified_out_dir}" STREQUAL "") set(${PVAR_PREFIX}_OUT_HDR_FILE ${${PVAR_PREFIX}_WORKING_DIR}/${${PVAR_PREFIX}_OUT_HDR_FILE}) endif ("${${PVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "") # input file get_filename_component(in_full ${Input} ABSOLUTE) if("${in_full}" STREQUAL "${Input}") set(perplex_in_file ${Input}) else("${in_full}" STREQUAL "${Input}") set(perplex_in_file "${CMAKE_CURRENT_SOURCE_DIR}/${Input}") endif("${in_full}" STREQUAL "${Input}") # Intermediate file set(re2c_src "${${PVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.re") # Make sure we have a template if ("${${PVAR_PREFIX}_TEMPLATE}" STREQUAL "") if(PERPLEX_TEMPLATE) set(${PVAR_PREFIX}_TEMPLATE ${PERPLEX_TEMPLATE}) else(PERPLEX_TEMPLATE) message(FATAL_ERROR "\nNo Perplex template file specified - please specify the file using the PERPLEX_TEMPLATE variable:\ncmake .. -DPERPLEX_TEMPLATE=/path/to/template_file.c\n") endif(PERPLEX_TEMPLATE) endif ("${${PVAR_PREFIX}_TEMPLATE}" STREQUAL "") get_filename_component(IN_FILE ${Input} NAME) add_custom_command( OUTPUT ${re2c_src} ${${PVAR_PREFIX}_OUT_HDR_FILE} ${${PVAR_PREFIX}_WORKING_DIR}/${IN_FILE} COMMAND ${CMAKE_COMMAND} -E copy ${perplex_in_file} ${${PVAR_PREFIX}_WORKING_DIR}/${IN_FILE} COMMAND ${PERPLEX_EXECUTABLE} -c -o ${re2c_src} -i ${${PVAR_PREFIX}_OUT_HDR_FILE} -t ${${PVAR_PREFIX}_TEMPLATE} ${${PVAR_PREFIX}_WORKING_DIR}/${IN_FILE} DEPENDS ${Input} ${${PVAR_PREFIX}_TEMPLATE} ${PERPLEX_EXECUTABLE_TARGET} ${RE2C_EXECUTABLE_TARGET} WORKING_DIRECTORY ${${PVAR_PREFIX}_WORKING_DIR} COMMENT "[PERPLEX][${Name}] Generating re2c input with ${PERPLEX_EXECUTABLE}" ) if(NOT DEBUGGING_GENERATED_SOURCES) add_custom_command( OUTPUT ${${PVAR_PREFIX}_OUT_SRC_FILE} COMMAND ${RE2C_EXECUTABLE} --no-debug-info --no-generation-date -c -o ${${PVAR_PREFIX}_OUT_SRC_FILE} ${re2c_src} DEPENDS ${Input} ${re2c_src} ${${PVAR_PREFIX}_OUT_HDR_FILE} ${PERPLEX_EXECUTABLE_TARGET} ${RE2C_EXECUTABLE_TARGET} WORKING_DIRECTORY ${${PVAR_PREFIX}_WORKING_DIR} COMMENT "[RE2C][${Name}] Building scanner with ${RE2C_EXECUTABLE}" ) else(NOT DEBUGGING_GENERATED_SOURCES) add_custom_command( OUTPUT ${${PVAR_PREFIX}_OUT_SRC_FILE} COMMAND ${RE2C_EXECUTABLE} --no-generation-date -c -o ${${PVAR_PREFIX}_OUT_SRC_FILE} ${re2c_src} DEPENDS ${Input} ${re2c_src} ${${PVAR_PREFIX}_OUT_HDR_FILE} ${PERPLEX_EXECUTABLE_TARGET} ${RE2C_EXECUTABLE_TARGET} WORKING_DIRECTORY ${${PVAR_PREFIX}_WORKING_DIR} COMMENT "[RE2C][${Name}] Building scanner with ${RE2C_EXECUTABLE}" ) endif(NOT DEBUGGING_GENERATED_SOURCES) set(PERPLEX_${Name}_DEFINED TRUE) set(PERPLEX_${Name}_SRC ${${PVAR_PREFIX}_OUT_SRC_FILE}) set(PERPLEX_${Name}_HDR ${${PVAR_PREFIX}_OUT_HDR_FILE}) set(PERPLEX_${Name}_INCLUDE_DIR ${${PVAR_PREFIX}_WORKING_DIR}) add_custom_command( OUTPUT ${${PVAR_PREFIX}_WORKING_DIR}/${Name}.sentinel COMMAND ${CMAKE_COMMAND} -E touch ${${PVAR_PREFIX}_WORKING_DIR}/${Name}.sentinel DEPENDS ${${PVAR_PREFIX}_OUT_SRC_FILE} ${${PVAR_PREFIX}_OUT_HDR_FILE} ) add_custom_target(${Name} DEPENDS ${${PVAR_PREFIX}_WORKING_DIR}/${Name}.sentinel) endmacro(PERPLEX_TARGET) endif(NOT COMMAND PERPLEX_TARGET) #============================================================ # ADD_PERPLEX_LEMON_DEPENDENCY (public macro) #============================================================ if(NOT COMMAND ADD_PERPLEX_LEMON_DEPENDENCY) macro(ADD_PERPLEX_LEMON_DEPENDENCY PERPLEXTarget LemonTarget) if(NOT PERPLEX_${PERPLEXTarget}_SRC) message(SEND_ERROR "PERPLEX target `${PERPLEXTarget}' does not exists.") endif() if(NOT TARGET ${LemonTarget}) message(SEND_ERROR "Lemon target `${LemonTarget}' does not exists.") endif() set_source_files_properties(${PERPLEX_${PERPLEXTarget}_SRC} PROPERTIES OBJECT_DEPENDS ${LEMON_${LemonTarget}_OUTPUT_HEADER}) endmacro(ADD_PERPLEX_LEMON_DEPENDENCY) endif(NOT COMMAND ADD_PERPLEX_LEMON_DEPENDENCY) #============================================================ # FindPERPLEX.cmake ends here # Local Variables: # tab-width: 8 # mode: cmake # indent-tabs-mode: t # End: # ex: shiftwidth=2 tabstop=8