forked from jasder/antlr
Improved ExternalAntlr4Cpp (Fixes #1872)
Removed the old macro antlr4cpp_process_grammar as it has a lot of parameters which may not be what the user needs.
This commit is contained in:
parent
9551d12f7c
commit
f296b75473
|
@ -1,223 +1,115 @@
|
||||||
# -*- mode:cmake -*-
|
cmake_minimum_required(VERSION 3.7)
|
||||||
#
|
|
||||||
# This Cmake file is for those using a superbuild Cmake Pattern, it
|
|
||||||
# will download the tools and build locally
|
|
||||||
#
|
|
||||||
# use 2the antlr4cpp_process_grammar to support multiple grammars in the
|
|
||||||
# same project
|
|
||||||
#
|
|
||||||
# - Getting quicky started with Antlr4cpp
|
|
||||||
#
|
|
||||||
# Here is how you can use this external project to create the antlr4cpp
|
|
||||||
# demo to start your project off.
|
|
||||||
#
|
|
||||||
# create your project source folder somewhere. e.g. ~/srcfolder/
|
|
||||||
# + make a subfolder cmake
|
|
||||||
# + Copy this file to srcfolder/cmake
|
|
||||||
# + cut below and use it to create srcfolder/CMakeLists.txt,
|
|
||||||
# + from https://github.com/DanMcLaughlin/antlr4/tree/master/runtime/Cpp/demo Copy main.cpp, TLexer.g4 and TParser.g4 to ./srcfolder/
|
|
||||||
#
|
|
||||||
# next make a build folder e.g. ~/buildfolder/
|
|
||||||
# from the buildfolder, run cmake ~/srcfolder; make
|
|
||||||
#
|
|
||||||
###############################################################
|
|
||||||
# # minimum required CMAKE version
|
|
||||||
# CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.2 FATAL_ERROR)
|
|
||||||
#
|
|
||||||
# LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake )
|
|
||||||
#
|
|
||||||
# # compiler must be 11 or 14
|
|
||||||
# SET (CMAKE_CXX_STANDARD 11)
|
|
||||||
#
|
|
||||||
# # set variable pointing to the antlr tool that supports C++
|
|
||||||
# set(ANTLR4CPP_JAR_LOCATION /home/user/antlr4-4.5.4-SNAPSHOT.jar)
|
|
||||||
# # add external build for antlrcpp
|
|
||||||
# include( ExternalAntlr4Cpp )
|
|
||||||
# # add antrl4cpp artifacts to project environment
|
|
||||||
# include_directories( ${ANTLR4CPP_INCLUDE_DIRS} )
|
|
||||||
# link_directories( ${ANTLR4CPP_LIBS} )
|
|
||||||
# message(STATUS "Found antlr4cpp libs: ${ANTLR4CPP_LIBS} and includes: ${ANTLR4CPP_INCLUDE_DIRS} ")
|
|
||||||
#
|
|
||||||
# # Call macro to add lexer and grammar to your build dependencies.
|
|
||||||
# antlr4cpp_process_grammar(demo antlrcpptest
|
|
||||||
# ${CMAKE_CURRENT_SOURCE_DIR}/TLexer.g4
|
|
||||||
# ${CMAKE_CURRENT_SOURCE_DIR}/TParser.g4)
|
|
||||||
# # include generated files in project environment
|
|
||||||
# include_directories(${antlr4cpp_include_dirs_antlrcpptest})
|
|
||||||
#
|
|
||||||
# # add generated grammar to demo binary target
|
|
||||||
# add_executable(demo main.cpp ${antlr4cpp_src_files_antlrcpptest})
|
|
||||||
# add_dependencies(demo antlr4cpp antlr4cpp_generation_antlrcpptest)
|
|
||||||
# target_link_libraries(demo antlr4-runtime)
|
|
||||||
#
|
|
||||||
###############################################################
|
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.2)
|
include(ExternalProject)
|
||||||
PROJECT(antlr4cpp_fetcher CXX)
|
|
||||||
INCLUDE(ExternalProject)
|
|
||||||
FIND_PACKAGE(Git REQUIRED)
|
|
||||||
|
|
||||||
# only JRE required
|
set(ANTLR4_ROOT ${CMAKE_CURRENT_BINARY_DIR}/antlr4_runtime/src/antlr4_runtime)
|
||||||
FIND_PACKAGE(Java COMPONENTS Runtime REQUIRED)
|
set(ANTLR4_INCLUDE_DIRS ${ANTLR4_ROOT}/runtime/Cpp/runtime/src)
|
||||||
|
set(ANTLR4_GIT_REPOSITORY https://github.com/antlr/antlr4.git)
|
||||||
############ Download and Generate runtime #################
|
if(NOT DEFINED ANTLR4_TAG)
|
||||||
set(ANTLR4CPP_EXTERNAL_ROOT ${CMAKE_BINARY_DIR}/externals/antlr4cpp)
|
# Set to branch name to keep library updated at the cost of needing to rebuild after 'clean'
|
||||||
|
# Set to commit hash to keep the build stable and does not need to rebuild after 'clean'
|
||||||
# external repository
|
set(ANTLR4_TAG master)
|
||||||
# GIT_REPOSITORY https://github.com/antlr/antlr4.git
|
|
||||||
set(ANTLR4CPP_EXTERNAL_REPO "https://github.com/antlr/antlr4.git")
|
|
||||||
set(ANTLR4CPP_EXTERNAL_TAG "4.7.1")
|
|
||||||
|
|
||||||
if(NOT EXISTS "${ANTLR4CPP_JAR_LOCATION}")
|
|
||||||
message(FATAL_ERROR "Unable to find antlr tool. ANTLR4CPP_JAR_LOCATION:${ANTLR4CPP_JAR_LOCATION}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# default path for source files
|
if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*")
|
||||||
if (NOT ANTLR4CPP_GENERATED_SRC_DIR)
|
set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/dist/$(Configuration))
|
||||||
set(ANTLR4CPP_GENERATED_SRC_DIR ${CMAKE_BINARY_DIR}/antlr4cpp_generated_src)
|
else()
|
||||||
|
set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/dist)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# !TODO! This should probably check with Cmake Find first?
|
if(MSVC)
|
||||||
# set(ANTLR4CPP_JAR_LOCATION ${ANTLR4CPP_EXTERNAL_ROOT}/${ANTLR4CPP_JAR_NAME})
|
set(ANTLR4_STATIC_LIBRARIES
|
||||||
#
|
${ANTLR4_OUTPUT_DIR}/antlr4-runtime-static.lib)
|
||||||
# !TODO! Ensure Antlr tool available - copy from internet
|
set(ANTLR4_SHARED_LIBRARIES
|
||||||
#
|
${ANTLR4_OUTPUT_DIR}/antlr4-runtime.lib)
|
||||||
# # !TODO! this shold be calculated based on the tags
|
set(ANTLR4_RUNTIME_LIBRARIES
|
||||||
# if (NOT ANTLR4CPP_JAR_NAME)
|
${ANTLR4_OUTPUT_DIR}/antlr4-runtime.dll)
|
||||||
# # default location to find antlr Java binary
|
else()
|
||||||
# set(ANTLR4CPP_JAR_NAME antlr4-4.5.4-SNAPSHOT.jar)
|
set(ANTLR4_STATIC_LIBRARIES
|
||||||
# endif()
|
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.a)
|
||||||
#
|
if(MINGW)
|
||||||
# if(NOT EXISTS "${ANTLR4CPP_JAR_LOCATION}")
|
set(ANTLR4_SHARED_LIBRARIES
|
||||||
# # download Java tool if not installed
|
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a)
|
||||||
# ExternalProject_ADD(
|
set(ANTLR4_RUNTIME_LIBRARIES
|
||||||
# #--External-project-name------
|
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll)
|
||||||
# antlrtool
|
elseif(CYGWIN)
|
||||||
# #--Core-directories-----------
|
set(ANTLR4_SHARED_LIBRARIES
|
||||||
# PREFIX ${ANTLR4CPP_EXTERNAL_ROOT}
|
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a)
|
||||||
# #--Download step--------------
|
set(ANTLR4_RUNTIME_LIBRARIES
|
||||||
# DOWNLOAD_DIR ${ANTLR4CPP_EXTERNAL_ROOT}
|
${ANTLR4_OUTPUT_DIR}/cygantlr4-runtime-4.7.1.dll)
|
||||||
# DOWNLOAD_COMMAND ""
|
|
||||||
# # URL http://www.antlr.org/download/${ANTLR4CPP_JAR_NAME}
|
|
||||||
# # antlr4-4.5.4-SNAPSHOT.jar
|
|
||||||
# # GIT_TAG v4.5.4
|
|
||||||
# TIMEOUT 10
|
|
||||||
# LOG_DOWNLOAD ON
|
|
||||||
# #--Update step----------
|
|
||||||
# # UPDATE_COMMAND ${GIT_EXECUTABLE} pull
|
|
||||||
# #--Patch step----------
|
|
||||||
# # PATCH_COMMAND sh -c "cp <SOURCE_DIR>/scripts/CMakeLists.txt <SOURCE_DIR>"
|
|
||||||
# #--Configure step-------------
|
|
||||||
# CMAKE_ARGS ""
|
|
||||||
# CONFIGURE_COMMAND ""
|
|
||||||
# LOG_CONFIGURE ON
|
|
||||||
# #--Build step-----------------
|
|
||||||
# BUILD_COMMAND ""
|
|
||||||
# LOG_BUILD ON
|
|
||||||
# #--Install step---------------
|
|
||||||
# INSTALL_COMMAND ""
|
|
||||||
# )
|
|
||||||
# # Verify Antlr Available
|
|
||||||
# if(NOT EXISTS "${ANTLR4CPP_JAR_LOCATION}")
|
|
||||||
# message(FATAL_ERROR "Unable to find ANTLR4CPP_JAR_LOCATION:${ANTLR4CPP_JAR_LOCATION} -> ${ANTLR4CPP_JAR_NAME} not in ${ANTLR4CPP_DIR} ")
|
|
||||||
# endif()
|
|
||||||
# endif()
|
|
||||||
|
|
||||||
# download runtime environment
|
|
||||||
ExternalProject_ADD(
|
|
||||||
#--External-project-name------
|
|
||||||
antlr4cpp
|
|
||||||
#--Depend-on-antrl-tool-----------
|
|
||||||
# DEPENDS antlrtool
|
|
||||||
#--Core-directories-----------
|
|
||||||
PREFIX ${ANTLR4CPP_EXTERNAL_ROOT}
|
|
||||||
#--Download step--------------
|
|
||||||
GIT_REPOSITORY ${ANTLR4CPP_EXTERNAL_REPO}
|
|
||||||
# GIT_TAG ${ANTLR4CPP_EXTERNAL_TAG}
|
|
||||||
TIMEOUT 10
|
|
||||||
LOG_DOWNLOAD ON
|
|
||||||
#--Update step----------
|
|
||||||
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
|
|
||||||
#--Patch step----------
|
|
||||||
# PATCH_COMMAND sh -c "cp <SOURCE_DIR>/scripts/CMakeLists.txt <SOURCE_DIR>"
|
|
||||||
#--Configure step-------------
|
|
||||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release -DANTLR4CPP_JAR_LOCATION=${ANTLR4CPP_JAR_LOCATION} -DBUILD_SHARED_LIBS=ON -BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_SOURCE_DIR:PATH=<SOURCE_DIR>/runtime/Cpp <SOURCE_DIR>/runtime/Cpp
|
|
||||||
LOG_CONFIGURE ON
|
|
||||||
#--Build step-----------------
|
|
||||||
# BUILD_COMMAND ${CMAKE_MAKE_PROGRAM}
|
|
||||||
LOG_BUILD ON
|
|
||||||
#--Install step---------------
|
|
||||||
# INSTALL_COMMAND ""
|
|
||||||
# INSTALL_DIR ${CMAKE_BINARY_DIR}/
|
|
||||||
#--Install step---------------
|
|
||||||
# INSTALL_COMMAND ""
|
|
||||||
)
|
|
||||||
|
|
||||||
ExternalProject_Get_Property(antlr4cpp INSTALL_DIR)
|
|
||||||
|
|
||||||
list(APPEND ANTLR4CPP_INCLUDE_DIRS ${INSTALL_DIR}/include/antlr4-runtime)
|
|
||||||
foreach(src_path misc atn dfa tree support)
|
|
||||||
list(APPEND ANTLR4CPP_INCLUDE_DIRS ${INSTALL_DIR}/include/antlr4-runtime/${src_path})
|
|
||||||
endforeach(src_path)
|
|
||||||
|
|
||||||
set(ANTLR4CPP_LIBS "${INSTALL_DIR}/lib")
|
|
||||||
|
|
||||||
# antlr4_shared ${INSTALL_DIR}/lib/libantlr4-runtime.so
|
|
||||||
# antlr4_static ${INSTALL_DIR}/lib/libantlr4-runtime.a
|
|
||||||
|
|
||||||
############ Generate runtime #################
|
|
||||||
# macro to add dependencies to target
|
|
||||||
#
|
|
||||||
# Param 1 project name
|
|
||||||
# Param 1 namespace (postfix for dependencies)
|
|
||||||
# Param 2 Lexer file (full path)
|
|
||||||
# Param 3 Parser File (full path)
|
|
||||||
#
|
|
||||||
# output
|
|
||||||
#
|
|
||||||
# antlr4cpp_src_files_{namespace} - src files for add_executable
|
|
||||||
# antlr4cpp_include_dirs_{namespace} - include dir for generated headers
|
|
||||||
# antlr4cpp_generation_{namespace} - for add_dependencies tracking
|
|
||||||
|
|
||||||
macro(antlr4cpp_process_grammar
|
|
||||||
antlr4cpp_project
|
|
||||||
antlr4cpp_project_namespace
|
|
||||||
antlr4cpp_grammar_lexer
|
|
||||||
antlr4cpp_grammar_parser)
|
|
||||||
|
|
||||||
if(EXISTS "${ANTLR4CPP_JAR_LOCATION}")
|
|
||||||
message(STATUS "Found antlr tool: ${ANTLR4CPP_JAR_LOCATION}")
|
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Unable to find antlr tool. ANTLR4CPP_JAR_LOCATION:${ANTLR4CPP_JAR_LOCATION}")
|
set(ANTLR4_RUNTIME_LIBRARIES
|
||||||
|
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.so)
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_target("antlr4cpp_generation_${antlr4cpp_project_namespace}"
|
if(${CMAKE_GENERATOR} MATCHES ".* Makefiles")
|
||||||
COMMAND
|
# This avoids
|
||||||
${CMAKE_COMMAND} -E make_directory ${ANTLR4CPP_GENERATED_SRC_DIR}
|
# 'warning: jobserver unavailable: using -j1. Add '+' to parent make rule.'
|
||||||
COMMAND
|
set(ANTLR4_BUILD_COMMAND $(MAKE))
|
||||||
"${Java_JAVA_EXECUTABLE}" -jar "${ANTLR4CPP_JAR_LOCATION}" -Werror -Dlanguage=Cpp -listener -visitor -o "${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}" -package ${antlr4cpp_project_namespace} "${antlr4cpp_grammar_lexer}" "${antlr4cpp_grammar_parser}"
|
elseif(${CMAKE_GENERATOR} MATCHES "Visual Studio.*")
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
set(ANTLR4_BUILD_COMMAND
|
||||||
DEPENDS "${antlr4cpp_grammar_lexer}" "${antlr4cpp_grammar_parser}"
|
${CMAKE_COMMAND}
|
||||||
)
|
--build .
|
||||||
|
--config $(Configuration)
|
||||||
|
--target)
|
||||||
|
else()
|
||||||
|
set(ANTLR4_BUILD_COMMAND
|
||||||
|
${CMAKE_COMMAND}
|
||||||
|
--build .
|
||||||
|
--target)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Find all the input files
|
ExternalProject_Add(
|
||||||
FILE(GLOB generated_files ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}/*.cpp)
|
antlr4_runtime
|
||||||
|
PREFIX antlr4_runtime
|
||||||
|
GIT_REPOSITORY ${ANTLR4_GIT_REPOSITORY}
|
||||||
|
GIT_TAG ${ANTLR4_TAG}
|
||||||
|
DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
BUILD_IN_SOURCE 1
|
||||||
|
SOURCE_DIR ${ANTLR4_ROOT}
|
||||||
|
SOURCE_SUBDIR runtime/Cpp
|
||||||
|
CMAKE_CACHE_ARGS
|
||||||
|
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
EXCLUDE_FROM_ALL 1)
|
||||||
|
|
||||||
# export generated cpp files into list
|
# Seperate build step as rarely people want both
|
||||||
foreach(generated_file ${generated_files})
|
ExternalProject_Add_Step(
|
||||||
list(APPEND antlr4cpp_src_files_${antlr4cpp_project_namespace} ${generated_file})
|
antlr4_runtime
|
||||||
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
build_static
|
||||||
set_source_files_properties(
|
COMMAND ${ANTLR4_BUILD_COMMAND} antlr4_static
|
||||||
${generated_file}
|
# Depend on target instead of step (a custom command)
|
||||||
PROPERTIES
|
# to avoid running dependent steps concurrently
|
||||||
COMPILE_FLAGS -Wno-overloaded-virtual
|
DEPENDS antlr4_runtime
|
||||||
)
|
BYPRODUCTS ${ANTLR4_STATIC_LIBRARIES}
|
||||||
endif ()
|
EXCLUDE_FROM_MAIN 1
|
||||||
endforeach(generated_file)
|
WORKING_DIRECTORY ${ANTLR4_ROOT})
|
||||||
message(STATUS "Antlr4Cpp ${antlr4cpp_project_namespace} Generated: ${generated_files}")
|
ExternalProject_Add_StepTargets(antlr4_runtime build_static)
|
||||||
|
|
||||||
# export generated include directory
|
add_library(antlr4_static STATIC IMPORTED)
|
||||||
set(antlr4cpp_include_dirs_${antlr4cpp_project_namespace} ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace})
|
add_dependencies(antlr4_static antlr4_runtime-build_static)
|
||||||
message(STATUS "Antlr4Cpp ${antlr4cpp_project_namespace} include: ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}")
|
set_target_properties(antlr4_static PROPERTIES
|
||||||
|
IMPORTED_LOCATION ${ANTLR4_STATIC_LIBRARIES})
|
||||||
|
|
||||||
endmacro()
|
ExternalProject_Add_Step(
|
||||||
|
antlr4_runtime
|
||||||
|
build_shared
|
||||||
|
COMMAND ${ANTLR4_BUILD_COMMAND} antlr4_shared
|
||||||
|
# Depend on target instead of step (a custom command)
|
||||||
|
# to avoid running dependent steps concurrently
|
||||||
|
DEPENDS antlr4_runtime
|
||||||
|
BYPRODUCTS ${ANTLR4_SHARED_LIBRARIES} ${ANTLR4_RUNTIME_LIBRARIES}
|
||||||
|
EXCLUDE_FROM_MAIN 1
|
||||||
|
WORKING_DIRECTORY ${ANTLR4_ROOT})
|
||||||
|
ExternalProject_Add_StepTargets(antlr4_runtime build_shared)
|
||||||
|
|
||||||
|
add_library(antlr4_shared SHARED IMPORTED)
|
||||||
|
add_dependencies(antlr4_shared antlr4_runtime-build_shared)
|
||||||
|
set_target_properties(antlr4_shared PROPERTIES
|
||||||
|
IMPORTED_LOCATION ${ANTLR4_RUNTIME_LIBRARIES})
|
||||||
|
if(ANTLR4_SHARED_LIBRARIES)
|
||||||
|
set_target_properties(antlr4_shared PROPERTIES
|
||||||
|
IMPORTED_IMPLIB ${ANTLR4_SHARED_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
find_package(Java QUIET COMPONENTS Runtime)
|
||||||
|
|
||||||
|
if(NOT ANTLR_EXECUTABLE)
|
||||||
|
find_program(ANTLR_EXECUTABLE
|
||||||
|
NAMES antlr.jar antlr4.jar antlr-4.jar antlr-4.7.1-complete.jar)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ANTLR_EXECUTABLE AND Java_JAVA_EXECUTABLE)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Java_JAVA_EXECUTABLE} -jar ${ANTLR_EXECUTABLE}
|
||||||
|
OUTPUT_VARIABLE ANTLR_COMMAND_OUTPUT
|
||||||
|
ERROR_VARIABLE ANTLR_COMMAND_ERROR
|
||||||
|
RESULT_VARIABLE ANTLR_COMMAND_RESULT
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
|
if(ANTLR_COMMAND_RESULT EQUAL 0)
|
||||||
|
string(REGEX MATCH "Version [0-9]+(\\.[0-9])*" ANTLR_VERSION ${ANTLR_COMMAND_OUTPUT})
|
||||||
|
string(REPLACE "Version " "" ANTLR_VERSION ${ANTLR_VERSION})
|
||||||
|
else()
|
||||||
|
message(
|
||||||
|
SEND_ERROR
|
||||||
|
"Command '${Java_JAVA_EXECUTABLE} -jar ${ANTLR_EXECUTABLE}' "
|
||||||
|
"failed with the output '${ANTLR_COMMAND_ERROR}'")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
macro(ANTLR_TARGET Name InputFile)
|
||||||
|
set(ANTLR_OPTIONS LEXER PARSER LISTENER VISITOR)
|
||||||
|
set(ANTLR_ONE_VALUE_ARGS PACKAGE OUTPUT_DIRECTORY DEPENDS_ANTLR)
|
||||||
|
set(ANTLR_MULTI_VALUE_ARGS COMPILE_FLAGS DEPENDS)
|
||||||
|
cmake_parse_arguments(ANTLR_TARGET
|
||||||
|
"${ANTLR_OPTIONS}"
|
||||||
|
"${ANTLR_ONE_VALUE_ARGS}"
|
||||||
|
"${ANTLR_MULTI_VALUE_ARGS}"
|
||||||
|
${ARGN})
|
||||||
|
|
||||||
|
set(ANTLR_${Name}_INPUT ${InputFile})
|
||||||
|
|
||||||
|
if(ANTLR_TARGET_OUTPUT_DIRECTORY)
|
||||||
|
set(ANTLR_${Name}_OUTPUT_DIR ${ANTLR_TARGET_OUTPUT_DIRECTORY})
|
||||||
|
else()
|
||||||
|
set(ANTLR_${Name}_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(ANTLR_${Name}_CXX_OUTPUTS)
|
||||||
|
|
||||||
|
# Get the shortest extension
|
||||||
|
string(REGEX REPLACE "\\.[^.]*$" "" ANTLR_INPUT ${InputFile})
|
||||||
|
|
||||||
|
if((ANTLR_TARGET_LEXER AND NOT ANTLR_TARGET_PARSER) OR
|
||||||
|
(ANTLR_TARGET_PARSER AND NOT ANTLR_TARGET_LEXER))
|
||||||
|
list(APPEND ANTLR_${Name}_CXX_OUTPUTS
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.h
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.cpp)
|
||||||
|
set(ANTLR_${Name}_OUTPUTS
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.interp
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.tokens)
|
||||||
|
else()
|
||||||
|
list(APPEND ANTLR_${Name}_CXX_OUTPUTS
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.h
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.cpp
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Parser.h
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Parser.cpp)
|
||||||
|
list(APPEND ANTLR_${Name}_OUTPUTS
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.interp
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.tokens)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ANTLR_TARGET_LISTENER)
|
||||||
|
list(APPEND ANTLR_${Name}_CXX_OUTPUTS
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseListener.h
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseListener.cpp
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Listener.h
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Listener.cpp)
|
||||||
|
list(APPEND ANTLR_TARGET_COMPILE_FLAGS -listener)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ANTLR_TARGET_VISITOR)
|
||||||
|
list(APPEND ANTLR_${Name}_CXX_OUTPUTS
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseVisitor.h
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseVisitor.cpp
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Visitor.h
|
||||||
|
${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Visitor.cpp)
|
||||||
|
list(APPEND ANTLR_TARGET_COMPILE_FLAGS -visitor)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ANTLR_TARGET_PACKAGE)
|
||||||
|
list(APPEND ANTLR_TARGET_COMPILE_FLAGS -package ${ANTLR_TARGET_PACKAGE})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND ANTLR_${Name}_OUTPUTS ${ANTLR_${Name}_CXX_OUTPUTS})
|
||||||
|
|
||||||
|
if(ANTLR_TARGET_DEPENDS_ANTLR)
|
||||||
|
if(ANTLR_${ANTLR_TARGET_DEPENDS_ANTLR}_INPUT)
|
||||||
|
list(APPEND ANTLR_TARGET_DEPENDS
|
||||||
|
${ANTLR_${ANTLR_TARGET_DEPENDS_ANTLR}_INPUT})
|
||||||
|
list(APPEND ANTLR_TARGET_DEPENDS
|
||||||
|
${ANTLR_${ANTLR_TARGET_DEPENDS_ANTLR}_OUTPUTS})
|
||||||
|
else()
|
||||||
|
message(SEND_ERROR
|
||||||
|
"ANTLR target '${ANTLR_TARGET_DEPENDS_ANTLR}' not found")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${ANTLR_${Name}_OUTPUTS}
|
||||||
|
COMMAND ${Java_JAVA_EXECUTABLE} -jar ${ANTLR_EXECUTABLE}
|
||||||
|
${InputFile}
|
||||||
|
-o ${ANTLR_${Name}_OUTPUT_DIR}
|
||||||
|
-no-listener
|
||||||
|
-Dlanguage=Cpp
|
||||||
|
${ANTLR_TARGET_COMPILE_FLAGS}
|
||||||
|
DEPENDS ${InputFile}
|
||||||
|
${ANTLR_TARGET_DEPENDS}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMENT "Building ${Name} with ANTLR ${ANTLR_VERSION}")
|
||||||
|
endmacro(ANTLR_TARGET)
|
||||||
|
|
||||||
|
endif(ANTLR_EXECUTABLE AND Java_JAVA_EXECUTABLE)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(
|
||||||
|
ANTLR
|
||||||
|
REQUIRED_VARS ANTLR_EXECUTABLE Java_JAVA_EXECUTABLE
|
||||||
|
VERSION_VAR ANTLR_VERSION)
|
|
@ -0,0 +1,137 @@
|
||||||
|
### Getting started with Antlr4cpp
|
||||||
|
|
||||||
|
Here is how you can use this external project to create the antlr4cpp demo to start your project off.
|
||||||
|
|
||||||
|
1. Create your project source folder somewhere. e.g. ~/srcfolder/
|
||||||
|
1. Make a subfolder cmake
|
||||||
|
2. Copy the files in this folder to srcfolder/cmake
|
||||||
|
3. Cut below and use it to create srcfolder/CMakeLists.txt
|
||||||
|
4. Copy main.cpp, TLexer.g4 and TParser.g4 to ./srcfolder/ from [here](https://github.com/antlr/antlr4/tree/master/runtime/Cpp/demo)
|
||||||
|
2. Make a build folder e.g. ~/buildfolder/
|
||||||
|
3. From the buildfolder, run `cmake ~/srcfolder; make`
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# minimum required CMAKE version
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.7 FATAL_ERROR)
|
||||||
|
|
||||||
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
|
# compiler must be 11 or 14
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
|
# required if linking to static library
|
||||||
|
add_definitions(-DANTLR4CPP_STATIC)
|
||||||
|
|
||||||
|
# add external build for antlrcpp
|
||||||
|
include(ExternalAntlr4Cpp)
|
||||||
|
# add antrl4cpp artifacts to project environment
|
||||||
|
include_directories(${ANTLR4_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# set variable pointing to the antlr tool that supports C++
|
||||||
|
# this is not required if the jar file can be found under PATH environment
|
||||||
|
set(ANTLR_EXECUTABLE /home/user/antlr-4.7.1-complete.jar)
|
||||||
|
# add macros to generate ANTLR Cpp code from grammar
|
||||||
|
find_package(ANTLR REQUIRED)
|
||||||
|
|
||||||
|
# Call macro to add lexer and grammar to your build dependencies.
|
||||||
|
antlr_target(SampleGrammarLexer TLexer.g4 LEXER
|
||||||
|
PACKAGE antlrcpptest)
|
||||||
|
antlr_target(SampleGrammarParser TParser.g4 PARSER
|
||||||
|
PACKAGE antlrcpptest
|
||||||
|
DEPENDS_ANTLR SampleGrammarLexer)
|
||||||
|
|
||||||
|
# include generated files in project environment
|
||||||
|
include_directories(${ANTLR_SampleGrammarLexer_OUTPUT_DIR})
|
||||||
|
include_directories(${ANTLR_SampleGrammarParser_OUTPUT_DIR})
|
||||||
|
|
||||||
|
# add generated grammar to demo binary target
|
||||||
|
add_executable(demo main.cpp
|
||||||
|
${ANTLR_SampleGrammarLexer_CXX_OUTPUTS}
|
||||||
|
${ANTLR_SampleGrammarParser_CXX_OUTPUTS})
|
||||||
|
target_link_libraries(demo antlr4_static)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
### Documentation for FindANTLR
|
||||||
|
|
||||||
|
The module defines the following variables:
|
||||||
|
```
|
||||||
|
ANTLR_FOUND - true is ANTLR jar executable is found
|
||||||
|
ANTLR_EXECUTABLE - the path to the ANTLR jar executable
|
||||||
|
ANTLR_VERSION - the version of ANTLR
|
||||||
|
```
|
||||||
|
|
||||||
|
If ANTLR is found, the module will provide the macros:
|
||||||
|
```
|
||||||
|
ANTLR_TARGET(<name> <input>
|
||||||
|
[PACKAGE namespace]
|
||||||
|
[OUTPUT_DIRECTORY dir]
|
||||||
|
[DEPENDS_ANTLR <target>]
|
||||||
|
[COMPILE_FLAGS [args...]]
|
||||||
|
[DEPENDS [depends...]]
|
||||||
|
[LEXER]
|
||||||
|
[PARSER]
|
||||||
|
[LISTENER]
|
||||||
|
[VISITOR])
|
||||||
|
```
|
||||||
|
which creates a custom command to generate C++ files from `<input>`. Running the macro defines the following variables:
|
||||||
|
```
|
||||||
|
ANTLR_${name}_INPUT - the ANTLR input used for the macro
|
||||||
|
ANTLR_${name}_OUTPUTS - the outputs generated by ANTLR
|
||||||
|
ANTLR_${name}_CXX_OUTPUTS - the C++ outputs generated by ANTLR
|
||||||
|
ANTLR_${name}_OUTPUT_DIR - the output directory for ANTLR
|
||||||
|
```
|
||||||
|
|
||||||
|
The options are:
|
||||||
|
* `PACKAGE` - defines a namespace for the generated C++ files
|
||||||
|
* `OUTPUT_DIRECTORY` - the output directory for the generated files. By default it uses ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
* `DEPENDS_ANTLR` - the dependent target generated from antlr_target for the current call
|
||||||
|
* `COMPILE_FLAGS` - additional compile flags for ANTLR tool
|
||||||
|
* `DEPENDS` - specify the files on which the command depends. It works the same way `DEPENDS` in [add_custom_command()](https://cmake.org/cmake/help/v3.11/command/add_custom_command.html)
|
||||||
|
* `LEXER` - specify the input file is a lexer grammar
|
||||||
|
* `PARSER` - specify the input file is a parser grammar
|
||||||
|
* `LISTENER` - tell ANTLR tool to generate a parse tree listener
|
||||||
|
* `VISITOR` - tell ANTLR tool to generate a parse tree visitor
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
To generate C++ files from an ANTLR input file T.g4, which defines both lexer and parser grammar one may call:
|
||||||
|
```cmake
|
||||||
|
find_package(ANTLR REQUIRED)
|
||||||
|
antlr_target(Sample T.g4)
|
||||||
|
```
|
||||||
|
do note that this command will do nothing unless the outputs of `Sample`, i.e. `ANTLR_Sample_CXX_OUTPUTS` gets used by some target.
|
||||||
|
|
||||||
|
---
|
||||||
|
### Documentation for ExternalAntlr4Cpp
|
||||||
|
|
||||||
|
Including ExternalAntlr4Cpp will add `antlr4_static` and `antlr4_shared` as an optional target. It will also define the following variables:
|
||||||
|
```
|
||||||
|
ANTLR4_INCLUDE_DIRS - the include directory that should be included when compiling C++ source file
|
||||||
|
ANTLR4_STATIC_LIBRARIES - path to antlr4 static library
|
||||||
|
ANTLR4_SHARED_LIBRARIES - path to antlr4 shared library
|
||||||
|
ANTLR4_RUNTIME_LIBRARIES - path to antlr4 shared runtime library (such as DLL and SO file)
|
||||||
|
ANTLR4_TAG - branch/tag used for building antlr4 library
|
||||||
|
```
|
||||||
|
`ANTLR4_TAG` is set to master branch by default to keep antlr4 updated. However, it will be required to rebuild after every `clean` is called. Set `ANTLR4_TAG` to a desired commit hash value to avoid rebuilding after every `clean` and keep the build stable, at the cost of not automatically update to latest commit.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
To build and link ANTLR4 static library to a target one may call:
|
||||||
|
```cmake
|
||||||
|
include(ExternalAntlr4Cpp)
|
||||||
|
include_directories(${ANTLR4_INCLUDE_DIRS})
|
||||||
|
add_executable(output main.cpp)
|
||||||
|
target_link_libraries(output antlr4_static)
|
||||||
|
```
|
||||||
|
|
||||||
|
It may also be a good idea to copy the runtime libraries (DLL or SO file) to the executable for it to run properly after build. i.e. To build and link antlr4 shared library to a target one may call:
|
||||||
|
```cmake
|
||||||
|
include(ExternalAntlr4Cpp)
|
||||||
|
include_directories(${ANTLR4_INCLUDE_DIRS})
|
||||||
|
add_executable(output main.cpp)
|
||||||
|
target_link_libraries(output antlr4_shared)
|
||||||
|
add_custom_command(TARGET output
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-E copy ${ANTLR4_RUNTIME_LIBRARIES} .
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
```
|
Loading…
Reference in New Issue