forked from jasder/antlr
Improved ExternalAntlr4Cpp and added CMake option for static CRT (Fixes #1872)
This commit is contained in:
commit
0a1b3c7df6
|
@ -183,6 +183,7 @@ YYYY/MM/DD, github id, Full name, email
|
|||
2018/01/06, kasbah, Kaspar Emanuel, kaspar@monostable.co.uk
|
||||
2018/02/08, razfriman, Raz Friman, raz@razfriman.com
|
||||
2018/02/11, io7m, Mark Raynsford, code@io7m.com
|
||||
2018/02/25, chaseoxide, Marcus Ong, taccs97[at]gmail[dot]com
|
||||
2018/05/15, johnvanderholt, jan dillingh johnvanderholte@gmail.com
|
||||
2018/06/16, EternalPhane, Zongyuan Zuo, eternalphane@gmail.com
|
||||
2018/05/15, johnvanderholt, jan dillingh johnvanderholte@gmail.com
|
||||
|
@ -192,4 +193,5 @@ YYYY/MM/DD, github id, Full name, email
|
|||
2018/06/16, EternalPhane, Zongyuan Zuo, eternalphane@gmail.com
|
||||
2018/07/03, jgoppert, James Goppert, james.goppert@gmail.com
|
||||
2018/07/27, Maksim Novikov, mnovikov.work@gmail.com
|
||||
2018/08/03, ENDOH takanao, djmchl@gmail.com
|
||||
2018/08/03, ENDOH takanao, djmchl@gmail.com
|
||||
2018/10/29, chrisaycock, Christopher Aycock, chris[at]chrisaycock[dot]com
|
||||
|
|
|
@ -20,6 +20,8 @@ if(NOT WITH_DEMO)
|
|||
endif(NOT WITH_DEMO)
|
||||
|
||||
option(WITH_LIBCXX "Building with clang++ and libc++(in Linux). To enable with: -DWITH_LIBCXX=On" On)
|
||||
option(WITH_STATIC_CRT "(Visual C++) Enable to statically link CRT, which avoids requiring users to install the redistribution package.
|
||||
To disable with: -DWITH_STATIC_CRT=Off" On)
|
||||
|
||||
project(LIBANTLR4)
|
||||
|
||||
|
|
|
@ -1,223 +1,131 @@
|
|||
# -*- mode:cmake -*-
|
||||
#
|
||||
# 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 3.7)
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.2)
|
||||
PROJECT(antlr4cpp_fetcher CXX)
|
||||
INCLUDE(ExternalProject)
|
||||
FIND_PACKAGE(Git REQUIRED)
|
||||
include(ExternalProject)
|
||||
|
||||
# only JRE required
|
||||
FIND_PACKAGE(Java COMPONENTS Runtime REQUIRED)
|
||||
|
||||
############ Download and Generate runtime #################
|
||||
set(ANTLR4CPP_EXTERNAL_ROOT ${CMAKE_BINARY_DIR}/externals/antlr4cpp)
|
||||
|
||||
# external repository
|
||||
# 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}")
|
||||
set(ANTLR4_ROOT ${CMAKE_CURRENT_BINARY_DIR}/antlr4_runtime/src/antlr4_runtime)
|
||||
set(ANTLR4_INCLUDE_DIRS ${ANTLR4_ROOT}/runtime/Cpp/runtime/src)
|
||||
set(ANTLR4_GIT_REPOSITORY https://github.com/antlr/antlr4.git)
|
||||
if(NOT DEFINED ANTLR4_TAG)
|
||||
# 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'
|
||||
set(ANTLR4_TAG master)
|
||||
endif()
|
||||
|
||||
# default path for source files
|
||||
if (NOT ANTLR4CPP_GENERATED_SRC_DIR)
|
||||
set(ANTLR4CPP_GENERATED_SRC_DIR ${CMAKE_BINARY_DIR}/antlr4cpp_generated_src)
|
||||
if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*")
|
||||
set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/dist/$(Configuration))
|
||||
elseif(${CMAKE_GENERATOR} MATCHES "Xcode.*")
|
||||
set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/dist/$(CONFIGURATION))
|
||||
else()
|
||||
set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/dist)
|
||||
endif()
|
||||
|
||||
# !TODO! This should probably check with Cmake Find first?
|
||||
# set(ANTLR4CPP_JAR_LOCATION ${ANTLR4CPP_EXTERNAL_ROOT}/${ANTLR4CPP_JAR_NAME})
|
||||
#
|
||||
# !TODO! Ensure Antlr tool available - copy from internet
|
||||
#
|
||||
# # !TODO! this shold be calculated based on the tags
|
||||
# if (NOT ANTLR4CPP_JAR_NAME)
|
||||
# # default location to find antlr Java binary
|
||||
# set(ANTLR4CPP_JAR_NAME antlr4-4.5.4-SNAPSHOT.jar)
|
||||
# endif()
|
||||
#
|
||||
# if(NOT EXISTS "${ANTLR4CPP_JAR_LOCATION}")
|
||||
# # download Java tool if not installed
|
||||
# ExternalProject_ADD(
|
||||
# #--External-project-name------
|
||||
# antlrtool
|
||||
# #--Core-directories-----------
|
||||
# PREFIX ${ANTLR4CPP_EXTERNAL_ROOT}
|
||||
# #--Download step--------------
|
||||
# DOWNLOAD_DIR ${ANTLR4CPP_EXTERNAL_ROOT}
|
||||
# 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}")
|
||||
if(MSVC)
|
||||
set(ANTLR4_STATIC_LIBRARIES
|
||||
${ANTLR4_OUTPUT_DIR}/antlr4-runtime-static.lib)
|
||||
set(ANTLR4_SHARED_LIBRARIES
|
||||
${ANTLR4_OUTPUT_DIR}/antlr4-runtime.lib)
|
||||
set(ANTLR4_RUNTIME_LIBRARIES
|
||||
${ANTLR4_OUTPUT_DIR}/antlr4-runtime.dll)
|
||||
else()
|
||||
set(ANTLR4_STATIC_LIBRARIES
|
||||
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.a)
|
||||
if(MINGW)
|
||||
set(ANTLR4_SHARED_LIBRARIES
|
||||
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a)
|
||||
set(ANTLR4_RUNTIME_LIBRARIES
|
||||
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll)
|
||||
elseif(CYGWIN)
|
||||
set(ANTLR4_SHARED_LIBRARIES
|
||||
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a)
|
||||
set(ANTLR4_RUNTIME_LIBRARIES
|
||||
${ANTLR4_OUTPUT_DIR}/cygantlr4-runtime-4.7.1.dll)
|
||||
elseif(APPLE)
|
||||
set(ANTLR4_RUNTIME_LIBRARIES
|
||||
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dylib)
|
||||
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()
|
||||
|
||||
add_custom_target("antlr4cpp_generation_${antlr4cpp_project_namespace}"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E make_directory ${ANTLR4CPP_GENERATED_SRC_DIR}
|
||||
COMMAND
|
||||
"${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}"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
DEPENDS "${antlr4cpp_grammar_lexer}" "${antlr4cpp_grammar_parser}"
|
||||
)
|
||||
if(${CMAKE_GENERATOR} MATCHES ".* Makefiles")
|
||||
# This avoids
|
||||
# 'warning: jobserver unavailable: using -j1. Add '+' to parent make rule.'
|
||||
set(ANTLR4_BUILD_COMMAND $(MAKE))
|
||||
elseif(${CMAKE_GENERATOR} MATCHES "Visual Studio.*")
|
||||
set(ANTLR4_BUILD_COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
--build .
|
||||
--config $(Configuration)
|
||||
--target)
|
||||
elseif(${CMAKE_GENERATOR} MATCHES "Xcode.*")
|
||||
set(ANTLR4_BUILD_COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
--build .
|
||||
--config $(CONFIGURATION)
|
||||
--target)
|
||||
else()
|
||||
set(ANTLR4_BUILD_COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
--build .
|
||||
--target)
|
||||
endif()
|
||||
|
||||
# Find all the input files
|
||||
FILE(GLOB generated_files ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}/*.cpp)
|
||||
if(NOT DEFINED ANTLR4_WITH_STATIC_CRT)
|
||||
set(ANTLR4_WITH_STATIC_CRT ON)
|
||||
endif()
|
||||
|
||||
# export generated cpp files into list
|
||||
foreach(generated_file ${generated_files})
|
||||
list(APPEND antlr4cpp_src_files_${antlr4cpp_project_namespace} ${generated_file})
|
||||
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
set_source_files_properties(
|
||||
${generated_file}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS -Wno-overloaded-virtual
|
||||
)
|
||||
endif ()
|
||||
endforeach(generated_file)
|
||||
message(STATUS "Antlr4Cpp ${antlr4cpp_project_namespace} Generated: ${generated_files}")
|
||||
ExternalProject_Add(
|
||||
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}
|
||||
-DWITH_STATIC_CRT:BOOL=${ANTLR4_WITH_STATIC_CRT}
|
||||
INSTALL_COMMAND ""
|
||||
EXCLUDE_FROM_ALL 1)
|
||||
|
||||
# export generated include directory
|
||||
set(antlr4cpp_include_dirs_${antlr4cpp_project_namespace} ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace})
|
||||
message(STATUS "Antlr4Cpp ${antlr4cpp_project_namespace} include: ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}")
|
||||
# Seperate build step as rarely people want both
|
||||
ExternalProject_Add_Step(
|
||||
antlr4_runtime
|
||||
build_static
|
||||
COMMAND ${ANTLR4_BUILD_COMMAND} antlr4_static
|
||||
# Depend on target instead of step (a custom command)
|
||||
# to avoid running dependent steps concurrently
|
||||
DEPENDS antlr4_runtime
|
||||
BYPRODUCTS ${ANTLR4_STATIC_LIBRARIES}
|
||||
EXCLUDE_FROM_MAIN 1
|
||||
WORKING_DIRECTORY ${ANTLR4_ROOT})
|
||||
ExternalProject_Add_StepTargets(antlr4_runtime build_static)
|
||||
|
||||
endmacro()
|
||||
add_library(antlr4_static STATIC IMPORTED)
|
||||
add_dependencies(antlr4_static antlr4_runtime-build_static)
|
||||
set_target_properties(antlr4_static PROPERTIES
|
||||
IMPORTED_LOCATION ${ANTLR4_STATIC_LIBRARIES})
|
||||
|
||||
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,151 @@
|
|||
## 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)
|
||||
|
||||
# using /MD flag for antlr4_runtime (for Visual C++ compilers only)
|
||||
set(ANTLR4_WITH_STATIC_CRT OFF)
|
||||
# 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, DYLIB 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.
|
||||
|
||||
Visual C++ compiler users may want to additionally define `ANTLR4_WITH_STATIC_CRT` before including the file. Set `ANTLR4_WITH_STATIC_CRT` to true if ANTLR4 C++ runtime library should be compiled with `/MT` flag, otherwise will be compiled with `/MD` flag. This variable has a default value of `OFF`. Changing `ANTLR4_WITH_STATIC_CRT` after building the library may require reinitialization of CMake or `clean` for the library to get rebuilt.
|
||||
|
||||
### 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, DYLIB 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})
|
||||
```
|
|
@ -64,8 +64,13 @@ if (WIN32)
|
|||
set(extra_static_compile_flags "-DANTLR4CPP_STATIC")
|
||||
endif(WIN32)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
target_compile_options(antlr4_shared PRIVATE "/MD$<$<CONFIG:Debug>:d>")
|
||||
target_compile_options(antlr4_static PRIVATE "/MT$<$<CONFIG:Debug>:d>")
|
||||
if(WITH_STATIC_CRT)
|
||||
target_compile_options(antlr4_shared PRIVATE "/MT$<$<CONFIG:Debug>:d>")
|
||||
target_compile_options(antlr4_static PRIVATE "/MT$<$<CONFIG:Debug>:d>")
|
||||
else()
|
||||
target_compile_options(antlr4_shared PRIVATE "/MD$<$<CONFIG:Debug>:d>")
|
||||
target_compile_options(antlr4_static PRIVATE "/MD$<$<CONFIG:Debug>:d>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(static_lib_suffix "")
|
||||
|
|
Loading…
Reference in New Issue