Initial commit from sysy-main

This commit is contained in:
Lixuanwang
2025-02-27 23:14:53 +08:00
commit cc523fd30b
1125 changed files with 257793 additions and 0 deletions

View File

@ -0,0 +1,136 @@
# CMake Antlr4 Package Usage
## The `antlr4-generator` Package
To use the Package you must insert a
```cmake
find_package(antlr4-generator REQUIRED)
```
line in your `CMakeList.txt` file.
The package exposes a function `antlr4_generate` that generates the required setup to call ANTLR for a
given input file during build.
The following table lists the parameters that can be used with the function:
Argument# | Required | Default | Use
----------|-----------|---------|---
0 | Yes | n/a | Unique target name. It is used to generate CMake Variables to reference the various outputs of the generation
1 | Yes | n/a | Input file containing the lexer/parser definition
2 | Yes | n/a | Type of Rules contained in the input: LEXER, PARSER or BOTH
4 | No | FALSE | Boolean to indicate if a listener interface should be generated
5 | No | FALSE | Boolean to indicate if a visitor interface should be generated
6 | No | none | C++ namespace in which the generated classes should be placed
7 | No | none | Additional files on which the input depends
8 | No | none | Library path to use during generation
The `ANTLR4_JAR_LOCATION` CMake variable must be set to the location where the `antlr-4*-complete.jar` generator is located. You can download the file from [here](http://www.antlr.org/download.html).
Additional options to the ANTLR4 generator can be passed in the `ANTLR4_GENERATED_OPTIONS` variable. Add the installation prefix of `antlr4-runtime` to `CMAKE_PREFIX_PATH` or set
`antlr4-runtime_DIR` to a directory containing the files.
The following CMake variables are available following a call to `antlr4_generate`
Output variable | Meaning
---|---
`ANTLR4_INCLUDE_DIR_<Target name>` | Directory containing the generated header files
`ANTLR4_SRC_FILES_<Target name>` | List of generated source files
`ANTLR4_TOKEN_FILES_<Target name>` | List of generated token files
`ANTLR4_TOKEN_DIRECTORY_<Target name>` | Directory containing the generated token files
#### Sample:
```cmake
# generate parser with visitor classes.
# put the classes in C++ namespace 'antlrcpptest::'
antlr4_generate(
antlrcpptest_parser
${CMAKE_CURRENT_SOURCE_DIR}/TLexer.g4
LEXER
FALSE
TRUE
"antlrcpptest"
)
```
**Remember that the ANTLR generator requires a working Java installation on your machine!**
## The `antlr4-runtime` Package
To use the Package you must insert a
```cmake
find_package(antlr4-runtime REQUIRED)
```
line in your `CMakeList.txt` file.
The package exposes two different targets:
Target|Use
--|--
antlr4_shared|Shared library version of the runtime
antlr4_static|Static library version of the runtime
Both set the following CMake variables:
Output variable | Meaning
---|---
`ANTLR4_INCLUDE_DIR` | Include directory containing the runtime header files
`ANTLR4_LIB_DIR` | Library directory containing the runtime library files
#### Sample:
```cmake
# add runtime include directories on this project.
include_directories( ${ANTLR4_INCLUDE_DIR} )
# add runtime to project dependencies
add_dependencies( Parsertest antlr4_shared )
# add runtime to project link libraries
target_link_libraries( Parsertest PRIVATE
antlr4_shared)
```
### Full Example:
```cmake
# Bring in the required packages
find_package(antlr4-runtime REQUIRED)
find_package(antlr4-generator REQUIRED)
# Set path to generator
set(ANTLR4_JAR_LOCATION ${PROJECT_SOURCE_DIR}/thirdparty/antlr/antlr-4.13.2-complete.jar)
# generate lexer
antlr4_generate(
antlrcpptest_lexer
${CMAKE_CURRENT_SOURCE_DIR}/TLexer.g4
LEXER
FALSE
FALSE
"antlrcpptest"
)
# generate parser
antlr4_generate(
antlrcpptest_parser
${CMAKE_CURRENT_SOURCE_DIR}/TParser.g4
PARSER
FALSE
TRUE
"antlrcpptest"
"${ANTLR4_TOKEN_FILES_antlrcpptest_lexer}"
"${ANTLR4_TOKEN_DIRECTORY_antlrcpptest_lexer}"
)
# add directories for generated include files
include_directories( ${PROJECT_BINARY_DIR} ${ANTLR4_INCLUDE_DIR} ${ANTLR4_INCLUDE_DIR_antlrcpptest_lexer} ${ANTLR4_INCLUDE_DIR_antlrcpptest_parser} )
# add generated source files
add_executable( Parsertest main.cpp ${ANTLR4_SRC_FILES_antlrcpptest_lexer} ${ANTLR4_SRC_FILES_antlrcpptest_parser} )
# add required runtime library
add_dependencies( Parsertest antlr4_shared )
target_link_libraries( Parsertest PRIVATE
antlr4_shared)
```

View File

@ -0,0 +1,177 @@
cmake_minimum_required(VERSION 3.7)
if(POLICY CMP0114)
cmake_policy(SET CMP0114 NEW)
endif()
include(ExternalProject)
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()
# Ensure that the include dir already exists at configure time (to avoid cmake erroring
# on non-existent include dirs)
file(MAKE_DIRECTORY "${ANTLR4_INCLUDE_DIRS}")
if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*")
set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/runtime/$(Configuration))
elseif(${CMAKE_GENERATOR} MATCHES "Xcode.*")
set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/runtime/$(CONFIGURATION))
else()
set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/runtime)
endif()
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.13.2.dll)
elseif(APPLE)
set(ANTLR4_RUNTIME_LIBRARIES
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dylib)
else()
set(ANTLR4_RUNTIME_LIBRARIES
${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.so)
endif()
endif()
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()
if(NOT DEFINED ANTLR4_WITH_STATIC_CRT)
set(ANTLR4_WITH_STATIC_CRT ON)
endif()
if(ANTLR4_ZIP_REPOSITORY)
ExternalProject_Add(
antlr4_runtime
PREFIX antlr4_runtime
URL ${ANTLR4_ZIP_REPOSITORY}
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}
-DDISABLE_WARNINGS:BOOL=ON
# -DCMAKE_CXX_STANDARD:STRING=17 # if desired, compile the runtime with a different C++ standard
# -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} # alternatively, compile the runtime with the same C++ standard as the outer project
INSTALL_COMMAND ""
EXCLUDE_FROM_ALL 1)
else()
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}
-DDISABLE_WARNINGS:BOOL=ON
# -DCMAKE_CXX_STANDARD:STRING=17 # if desired, compile the runtime with a different C++ standard
# -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} # alternatively, compile the runtime with the same C++ standard as the outer project
INSTALL_COMMAND ""
EXCLUDE_FROM_ALL 1)
endif()
# Separate build step as rarely people want both
set(ANTLR4_BUILD_DIR ${ANTLR4_ROOT})
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14.0")
# CMake 3.14 builds in above's SOURCE_SUBDIR when BUILD_IN_SOURCE is true
set(ANTLR4_BUILD_DIR ${ANTLR4_ROOT}/runtime/Cpp)
endif()
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_BUILD_DIR})
ExternalProject_Add_StepTargets(antlr4_runtime build_static)
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})
target_include_directories(antlr4_static
INTERFACE
${ANTLR4_INCLUDE_DIRS}
)
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_BUILD_DIR})
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})
target_include_directories(antlr4_shared
INTERFACE
${ANTLR4_INCLUDE_DIRS}
)
if(ANTLR4_SHARED_LIBRARIES)
set_target_properties(antlr4_shared PROPERTIES
IMPORTED_IMPLIB ${ANTLR4_SHARED_LIBRARIES})
endif()

View File

@ -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.13.2-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})
get_filename_component(ANTLR_INPUT ${InputFile} NAME_WE)
if(ANTLR_TARGET_OUTPUT_DIRECTORY)
set(ANTLR_${Name}_OUTPUT_DIR ${ANTLR_TARGET_OUTPUT_DIRECTORY})
else()
set(ANTLR_${Name}_OUTPUT_DIR
${CMAKE_CURRENT_BINARY_DIR}/antlr4cpp_generated_src/${ANTLR_INPUT})
endif()
unset(ANTLR_${Name}_CXX_OUTPUTS)
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)

View File

@ -0,0 +1,165 @@
## 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 17
set(CMAKE_CXX_STANDARD 17)
# 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)
# Specify the version of the antlr4 library needed for this project.
# By default the latest version of antlr4 will be used. You can specify a
# specific, stable version by setting a repository tag value or a link
# to a zip file containing the libary source.
# set(ANTLR4_TAG 4.13.2)
# set(ANTLR4_ZIP_REPOSITORY https://github.com/antlr/antlr4/archive/refs/tags/4.13.2.zip)
# add external build for antlrcpp
include(ExternalAntlr4Cpp)
# add antlr4cpp 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.13.2-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
COMPILE_FLAGS -lib ${ANTLR_SampleGrammarLexer_OUTPUT_DIR})
# 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 that the input file is a lexer grammar
* `PARSER` - specify that 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)
```
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 the antlr4 library up to date. However, this will require a 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 updating to latest commit.
By defualt the ANTLR C++ runtime source is cloned from GitHub. However, users may specify `ANTLR4_ZIP_REPOSITORY` in order to download source as a zip file from [ANTLR downloads](http://www.antlr.org/download.html) (under *C++ Target*) or other locations. For example, this variable could list a zip file included in your the project directory. This is useful for maintaining a canonical source tree for each new build.
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.
You may need to modify your local copy of ExternalAntlr4Cpp.cpp to modify some build settings. For example, to specify the C++ standard to use when building the runtime, add `-DCMAKE_CXX_STANDARD:STRING=17` to `CMAKE_CACHE_ARGS`.
### 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})
```

View File

@ -0,0 +1,181 @@
set(ANTLR_VERSION @ANTLR_VERSION@)
@PACKAGE_INIT@
if (NOT ANTLR4_CPP_GENERATED_SRC_DIR)
set(ANTLR4_GENERATED_SRC_DIR ${CMAKE_BINARY_DIR}/antlr4_generated_src)
endif()
FIND_PACKAGE(Java COMPONENTS Runtime REQUIRED)
#
# The ANTLR generator will output the following files given the input file f.g4
#
# Input -> f.g4
# Output -> f.h
# -> f.cpp
#
# the following files will only be produced if there is a parser contained
# Flag -visitor active
# Output -> <f>BaseVisitor.h
# -> <f>BaseVisitor.cpp
# -> <f>Visitor.h
# -> <f>Visitor.cpp
#
# Flag -listener active
# Output -> <f>BaseListener.h
# -> <f>BaseListener.cpp
# -> <f>Listener.h
# -> <f>Listener.cpp
#
# See documentation in markup
#
function(antlr4_generate
Antlr4_ProjectTarget
Antlr4_InputFile
Antlr4_GeneratorType
)
set( Antlr4_GeneratedSrcDir ${ANTLR4_GENERATED_SRC_DIR}/${Antlr4_ProjectTarget} )
get_filename_component(Antlr4_InputFileBaseName ${Antlr4_InputFile} NAME_WE )
list( APPEND Antlr4_GeneratorStatusMessage "Common Include-, Source- and Tokenfiles" )
if ( ${Antlr4_GeneratorType} STREQUAL "LEXER")
set(Antlr4_LexerBaseName "${Antlr4_InputFileBaseName}")
set(Antlr4_ParserBaseName "")
else()
if ( ${Antlr4_GeneratorType} STREQUAL "PARSER")
set(Antlr4_LexerBaseName "")
set(Antlr4_ParserBaseName "${Antlr4_InputFileBaseName}")
else()
if ( ${Antlr4_GeneratorType} STREQUAL "BOTH")
set(Antlr4_LexerBaseName "${Antlr4_InputFileBaseName}Lexer")
set(Antlr4_ParserBaseName "${Antlr4_InputFileBaseName}Parser")
else()
message(FATAL_ERROR "The third parameter must be LEXER, PARSER or BOTH")
endif ()
endif ()
endif ()
# Prepare list of generated targets
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}.tokens" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}.interp" )
list( APPEND DependentTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}.tokens" )
if ( NOT ${Antlr4_LexerBaseName} STREQUAL "" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_LexerBaseName}.h" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_LexerBaseName}.cpp" )
endif ()
if ( NOT ${Antlr4_ParserBaseName} STREQUAL "" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_ParserBaseName}.h" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_ParserBaseName}.cpp" )
endif ()
# process optional arguments ...
if ( ( ARGC GREATER_EQUAL 4 ) AND ARGV3 )
set(Antlr4_BuildListenerOption "-listener")
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}BaseListener.h" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}BaseListener.cpp" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}Listener.h" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}Listener.cpp" )
list( APPEND Antlr4_GeneratorStatusMessage ", Listener Include- and Sourcefiles" )
else()
set(Antlr4_BuildListenerOption "-no-listener")
endif ()
if ( ( ARGC GREATER_EQUAL 5 ) AND ARGV4 )
set(Antlr4_BuildVisitorOption "-visitor")
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}BaseVisitor.h" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}BaseVisitor.cpp" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}Visitor.h" )
list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}Visitor.cpp" )
list( APPEND Antlr4_GeneratorStatusMessage ", Visitor Include- and Sourcefiles" )
else()
set(Antlr4_BuildVisitorOption "-no-visitor")
endif ()
if ( (ARGC GREATER_EQUAL 6 ) AND (NOT ${ARGV5} STREQUAL "") )
set(Antlr4_NamespaceOption "-package;${ARGV5}")
list( APPEND Antlr4_GeneratorStatusMessage " in Namespace ${ARGV5}" )
else()
set(Antlr4_NamespaceOption "")
endif ()
if ( (ARGC GREATER_EQUAL 7 ) AND (NOT ${ARGV6} STREQUAL "") )
set(Antlr4_AdditionalDependencies ${ARGV6})
else()
set(Antlr4_AdditionalDependencies "")
endif ()
if ( (ARGC GREATER_EQUAL 8 ) AND (NOT ${ARGV7} STREQUAL "") )
set(Antlr4_LibOption "-lib;${ARGV7}")
list( APPEND Antlr4_GeneratorStatusMessage " using Library ${ARGV7}" )
else()
set(Antlr4_LibOption "")
endif ()
if(NOT Java_FOUND)
message(FATAL_ERROR "Java is required to process grammar or lexer files! - Use 'FIND_PACKAGE(Java COMPONENTS Runtime REQUIRED)'")
endif()
if(NOT EXISTS "${ANTLR4_JAR_LOCATION}")
message(FATAL_ERROR "Unable to find antlr tool. ANTLR4_JAR_LOCATION:${ANTLR4_JAR_LOCATION}")
endif()
# The call to generate the files
add_custom_command(
OUTPUT ${Antlr4_GeneratedTargets}
# Remove target directory
COMMAND
${CMAKE_COMMAND} -E remove_directory ${Antlr4_GeneratedSrcDir}
# Create target directory
COMMAND
${CMAKE_COMMAND} -E make_directory ${Antlr4_GeneratedSrcDir}
COMMAND
# Generate files
"${Java_JAVA_EXECUTABLE}" -jar "${ANTLR4_JAR_LOCATION}" -Werror -Dlanguage=Cpp ${Antlr4_BuildListenerOption} ${Antlr4_BuildVisitorOption} ${Antlr4_LibOption} ${ANTLR4_GENERATED_OPTIONS} -o "${Antlr4_GeneratedSrcDir}" ${Antlr4_NamespaceOption} "${Antlr4_InputFile}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
MAIN_DEPENDENCY "${Antlr4_InputFile}"
DEPENDS ${Antlr4_AdditionalDependencies}
)
# set output variables in parent scope
set( ANTLR4_INCLUDE_DIR_${Antlr4_ProjectTarget} ${Antlr4_GeneratedSrcDir} PARENT_SCOPE)
set( ANTLR4_SRC_FILES_${Antlr4_ProjectTarget} ${Antlr4_GeneratedTargets} PARENT_SCOPE)
set( ANTLR4_TOKEN_FILES_${Antlr4_ProjectTarget} ${DependentTargets} PARENT_SCOPE)
set( ANTLR4_TOKEN_DIRECTORY_${Antlr4_ProjectTarget} ${Antlr4_GeneratedSrcDir} PARENT_SCOPE)
# export generated cpp files into list
foreach(generated_file ${Antlr4_GeneratedTargets})
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set_source_files_properties(
${generated_file}
PROPERTIES
COMPILE_FLAGS -Wno-overloaded-virtual
)
endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set_source_files_properties(
${generated_file}
PROPERTIES
COMPILE_FLAGS -wd4251
)
endif ()
endforeach(generated_file)
message(STATUS "Antlr4 ${Antlr4_ProjectTarget} - Building " ${Antlr4_GeneratorStatusMessage} )
endfunction()

View File

@ -0,0 +1,13 @@
set(ANTLR_VERSION @ANTLR_VERSION@)
@PACKAGE_INIT@
set_and_check(ANTLR4_INCLUDE_DIR "@PACKAGE_ANTLR4_INCLUDE_DIR@")
set_and_check(ANTLR4_LIB_DIR "@PACKAGE_ANTLR4_LIB_DIR@")
include(CMakeFindDependencyMacro)
find_dependency(Threads)
include(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake)
check_required_components(antlr)