From 10d7878ed1d686cde7dcb3d713b5ee1aa98a4443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Schau?= Date: Mon, 15 Jan 2018 17:31:14 +0100 Subject: [PATCH 1/6] Add code to optionaly generate two cmake package during install when 'ANTLR4_INSTALL' is set: 'antlr4-runtime' which imports the required runtime targets and 'antlr4-generator' which provides a convenient function to use the generator. Only the latter one has a dependency to the Java package. --- runtime/Cpp/CMakeLists.txt | 64 +++++- runtime/Cpp/CMakeSettings.json | 73 +++++++ runtime/Cpp/cmake/antlr4-generator.cmake.in | 225 ++++++++++++++++++++ runtime/Cpp/cmake/antlr4-runtime.cmake.in | 10 + runtime/Cpp/runtime/CMakeLists.txt | 6 +- 5 files changed, 371 insertions(+), 7 deletions(-) create mode 100644 runtime/Cpp/CMakeSettings.json create mode 100644 runtime/Cpp/cmake/antlr4-generator.cmake.in create mode 100644 runtime/Cpp/cmake/antlr4-runtime.cmake.in diff --git a/runtime/Cpp/CMakeLists.txt b/runtime/Cpp/CMakeLists.txt index f4940c0c5..a34889f9d 100644 --- a/runtime/Cpp/CMakeLists.txt +++ b/runtime/Cpp/CMakeLists.txt @@ -126,13 +126,67 @@ if (WITH_DEMO) add_subdirectory(demo) endif(WITH_DEMO) +# Generate CMake Package Files only if install is active +if (ANTLR4_INSTALL) + + include(GNUInstallDirs) + include(CMakePackageConfigHelpers) + + if(NOT ANTLR4_CMAKE_DIR) + set(ANTLR4_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/antlr4 CACHE STRING + "Installation directory for cmake files." FORCE ) + endif(NOT ANTLR4_CMAKE_DIR) + + set(version_config ${PROJECT_BINARY_DIR}/antlr4-config-version.cmake) + set(project_runtime_config ${PROJECT_BINARY_DIR}/antlr4-runtime-config.cmake) + set(project_generator_config ${PROJECT_BINARY_DIR}/antlr4-generator-config.cmake) + set(targets_export_name antlr4-targets) + + set(ANTLR4_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING + "Installation directory for libraries, relative to ${CMAKE_INSTALL_PREFIX}.") + + set(ANTLR4_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/antlr4-runtime CACHE STRING + "Installation directory for include files, relative to ${CMAKE_INSTALL_PREFIX}.") + + configure_package_config_file( + cmake/antlr4-runtime.cmake.in + ${project_runtime_config} + INSTALL_DESTINATION ${ANTLR4_CMAKE_DIR} + PATH_VARS + ANTLR4_INCLUDE_DIR + ANTLR4_LIB_DIR ) + +configure_package_config_file( + cmake/antlr4-generator.cmake.in + ${project_generator_config} + INSTALL_DESTINATION ${ANTLR4_CMAKE_DIR} + PATH_VARS + ANTLR4_INCLUDE_DIR + ANTLR4_LIB_DIR ) + + write_basic_package_version_file( + ${version_config} + VERSION ${ANTLR_VERSION} + COMPATIBILITY SameMajorVersion ) + + install(EXPORT ${targets_export_name} + DESTINATION ${ANTLR4_CMAKE_DIR} ) + + install(FILES ${project_runtime_config} + ${project_generator_config} + ${version_config} + DESTINATION ${ANTLR4_CMAKE_DIR} ) + +endif(ANTLR4_INSTALL) + if( EXISTS LICENSE.txt) -install(FILES LICENSE.txt - DESTINATION "share/doc/libantlr4") -elseif(EXISTS ../../LICENSE.txt) -install(FILES ../../LICENSE.txt - DESTINATION "share/doc/libantlr4") + install(FILES LICENSE.txt + DESTINATION "share/doc/libantlr4") + elseif(EXISTS ../../LICENSE.txt) + install(FILES ../../LICENSE.txt + DESTINATION "share/doc/libantlr4") endif() install(FILES README.md VERSION DESTINATION "share/doc/libantlr4") + diff --git a/runtime/Cpp/CMakeSettings.json b/runtime/Cpp/CMakeSettings.json new file mode 100644 index 000000000..9eec93467 --- /dev/null +++ b/runtime/Cpp/CMakeSettings.json @@ -0,0 +1,73 @@ +{ + // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. + "configurations": [ + { + "name": "x86-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x86" ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "", + "variables": [ + { + "name": "ANTLR4_INSTALL", + "value": "1" + } + ], + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x86-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "inheritEnvironments": [ "msvc_x86" ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "", + "variables": [ + { + "name": "ANTLR4_INSTALL", + "value": "1" + } + ], + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "", + "variables": [ + { + "name": "ANTLR4_INSTALL", + "value": "1" + } + ], + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "", + "variables": [ + { + "name": "ANTLR4_INSTALL", + "value": "1" + } + ], + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + } + ] +} \ No newline at end of file diff --git a/runtime/Cpp/cmake/antlr4-generator.cmake.in b/runtime/Cpp/cmake/antlr4-generator.cmake.in new file mode 100644 index 000000000..6947cd1e8 --- /dev/null +++ b/runtime/Cpp/cmake/antlr4-generator.cmake.in @@ -0,0 +1,225 @@ +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 -> BaseVisitor.h +# -> BaseVisitor.cpp +# -> Visitor.h +# -> Visitor.cpp +# +# Flag -listener active +# Output -> BaseListener.h +# -> BaseListener.cpp +# -> Listener.h +# -> Listener.cpp +# +# The function "antlr4_generate" will generate the required setup to call ANTLR for a given input file +# +# +-----------+-----------+-------------+------------------------------------------------------------------------------+ +# | Argument# | Required | Defaults to | | +# +-----------+-----------+-------------+------------------------------------------------------------------------------+ +# | 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 | No | FALSE | Boolean to indicate if a listener interface should be generated | +# +-----------+-----------+-------------+------------------------------------------------------------------------------+ +# | 3 | No | FALSE | Boolean to indicate if a visitor interface should be generated | +# +-----------+-----------+-------------+------------------------------------------------------------------------------+ +# | 4 | No | none | C++ namespace in which the generated classes should be placed | +# +-----------+-----------+-------------+------------------------------------------------------------------------------+ +# | 5 | No | none | Additional files on which the input depends | +# +-----------+-----------+-------------+------------------------------------------------------------------------------+ +# | 6 | No | none | Library path to use during generation | +# +-----------+-----------+-------------+------------------------------------------------------------------------------+ +# +# The ANTLR4_JAR_LOCATION must be set prior calling the function! +# +# The following CMake variables are available following a call to antlr4_generate +# +# ANTLR4_INCLUDE_DIR_ - Directory containing the generated header files +# ANTLR4_SRC_FILES_ - List of generated source files +# ANTLR4_TOKEN_FILES_ - List of generated token files +# ANTLR4_TOKEN_DIRECTORY_ - Directory containing the generated token files +# +# Sample: +# +# # 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.7.1-complete.jar) +# +# # generate lexer +# antlr4_generate( +# antlrcpptest_lexer +# ${CMAKE_CURRENT_SOURCE_DIR}/TLexer.g4 +# FALSE +# FALSE +# "antlrcpptest" +# ) +# +# # generate parser +# antlr4_generate( +# antlrcpptest_parser +# ${CMAKE_CURRENT_SOURCE_DIR}/TParser.g4 +# 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_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) +# +# +function(antlr4_generate + Antlr4_ProjectTarget + Antlr4_InputFile + ) + + 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" ) + + # Prepare list of generated targets + list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}.h" ) + list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}.cpp" ) + 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" ) + + # process optional arguments ... + + if ( ( ARGC GREATER_EQUAL 3 ) AND ARGV2 ) + 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 4 ) AND ARGV3 ) + 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 5 ) AND (NOT ${ARGV4} STREQUAL "") ) + set(Antlr4_NamespaceOption "-package;${ARGV4}") + + list( APPEND Antlr4_GeneratorStatusMessage " in Namespace ${ARGV4}" ) + else() + set(Antlr4_NamespaceOption "") + endif () + + if ( (ARGC GREATER_EQUAL 6 ) AND (NOT ${ARGV5} STREQUAL "") ) + set(Antlr4_AdditionalDependencies ${ARGV5}) + else() + set(Antlr4_AdditionalDependencies "") + endif () + + if ( (ARGC GREATER_EQUAL 7 ) AND (NOT ${ARGV6} STREQUAL "") ) + set(Antlr4_LibOption "-lib;${ARGV6}") + + list( APPEND Antlr4_GeneratorStatusMessage " using Library ${ARGV6}" ) + 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} -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() diff --git a/runtime/Cpp/cmake/antlr4-runtime.cmake.in b/runtime/Cpp/cmake/antlr4-runtime.cmake.in new file mode 100644 index 000000000..860aeb601 --- /dev/null +++ b/runtime/Cpp/cmake/antlr4-runtime.cmake.in @@ -0,0 +1,10 @@ +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(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake) + +check_required_components(antlr) diff --git a/runtime/Cpp/runtime/CMakeLists.txt b/runtime/Cpp/runtime/CMakeLists.txt index fdb920e99..629b12a1c 100644 --- a/runtime/Cpp/runtime/CMakeLists.txt +++ b/runtime/Cpp/runtime/CMakeLists.txt @@ -97,9 +97,11 @@ set_target_properties(antlr4_static COMPILE_FLAGS "${disabled_compile_warnings} ${extra_static_compile_flags}") install(TARGETS antlr4_shared - DESTINATION lib) + DESTINATION lib + EXPORT antlr4-targets) install(TARGETS antlr4_static - ARCHIVE DESTINATION lib) + DESTINATION lib + EXPORT antlr4-targets) install(DIRECTORY "${PROJECT_SOURCE_DIR}/runtime/src/" DESTINATION "include/antlr4-runtime" From 0218f5454a8eb8e66c71ee860abbc98fc552c3d6 Mon Sep 17 00:00:00 2001 From: Soenke Schau Date: Mon, 15 Jan 2018 18:10:19 +0100 Subject: [PATCH 2/6] Changed the compiler detection code for Clang so that FreeBSD is supported too --- runtime/Cpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/Cpp/CMakeLists.txt b/runtime/Cpp/CMakeLists.txt index a34889f9d..bb5d7fef4 100644 --- a/runtime/Cpp/CMakeLists.txt +++ b/runtime/Cpp/CMakeLists.txt @@ -104,7 +104,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCH endif () elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") -elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND CMAKE_SYSTEM_NAME MATCHES "Linux") +elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND ( CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD") ) execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE CLANG_VERSION) if (NOT (CLANG_VERSION VERSION_GREATER 4.2.1 OR CLANG_VERSION VERSION_EQUAL 4.2.1)) From 8e2126a9e560e5e74bb7b7b33e2986358d12182f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Schau?= Date: Mon, 15 Jan 2018 19:10:27 +0100 Subject: [PATCH 3/6] Change/Add documentation of the CMake package feature --- runtime/Cpp/README.md | 13 ++- runtime/Cpp/cmake/Antlr4Package.md | 139 +++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 runtime/Cpp/cmake/Antlr4Package.md diff --git a/runtime/Cpp/README.md b/runtime/Cpp/README.md index fbcfadd51..f63fa75e4 100644 --- a/runtime/Cpp/README.md +++ b/runtime/Cpp/README.md @@ -41,9 +41,13 @@ Include the antlr4-runtime.h umbrella header in your target application to get e If you are compiling with cmake, the minimum version required is cmake 2.8. -#### Compiling on Windows +#### Compiling on Windows with Visual Studio prior to 2017 Simply open the VS solution (VS 2013+) and build it. +#### Compiling on Windows with Visual Studio VS2017 +Use the "Open Folder" Feature from the File->Open->Folder menu to open the runtime/Cpp directory. +It will automatically use the CMake description to open up a Visual Studio Solution. + #### Compiling on OSX Either open the included XCode project and build that or use the cmake compilation as described for linux. @@ -57,3 +61,10 @@ Either open the included XCode project and build that or use the cmake compilati If you don't want to build the demo then simply run cmake without parameters. There is another cmake script available in the subfolder cmake/ for those who prefer the superbuild cmake pattern. +#### CMake Package support +If the CMake variable 'ANTLR4_INSTALL' is set, CMake Packages will be build and installed during the install step. +They expose two packages: antlr4_runtime and antlr4_generator which can be referenced to ease up the use of the +ANTLR Generator and runtime. +Use and Sample can be found [here](cmake/Antlr4Package.md) + + diff --git a/runtime/Cpp/cmake/Antlr4Package.md b/runtime/Cpp/cmake/Antlr4Package.md new file mode 100644 index 000000000..b1fde5c2b --- /dev/null +++ b/runtime/Cpp/cmake/Antlr4Package.md @@ -0,0 +1,139 @@ +# 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 | | ++-----------+-----------+-------------+------------------------------------------------------------------------------+ +| 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 | No | FALSE | Boolean to indicate if a listener interface should be generated | ++-----------+-----------+-------------+------------------------------------------------------------------------------+ +| 3 | No | FALSE | Boolean to indicate if a visitor interface should be generated | ++-----------+-----------+-------------+------------------------------------------------------------------------------+ +| 4 | No | none | C++ namespace in which the generated classes should be placed | ++-----------+-----------+-------------+------------------------------------------------------------------------------+ +| 5 | No | none | Additional files on which the input depends | ++-----------+-----------+-------------+------------------------------------------------------------------------------+ +| 6 | 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). + +The following CMake variables are available following a call to `antlr4_generate` + +Output variable | Meaning +---|--- +`ANTLR4_INCLUDE_DIR_` | Directory containing the generated header files +`ANTLR4_SRC_FILES_` | List of generated source files +`ANTLR4_TOKEN_FILES_` | List of generated token files +`ANTLR4_TOKEN_DIRECTORY_` | 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 + 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.7.1-complete.jar) + + # generate lexer + antlr4_generate( + antlrcpptest_lexer + ${CMAKE_CURRENT_SOURCE_DIR}/TLexer.g4 + FALSE + FALSE + "antlrcpptest" + ) + + # generate parser + antlr4_generate( + antlrcpptest_parser + ${CMAKE_CURRENT_SOURCE_DIR}/TParser.g4 + 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) + +``` + \ No newline at end of file From 6bd439959b8e0a007f89fcad773371d0ef058a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Schau?= Date: Mon, 15 Jan 2018 19:16:59 +0100 Subject: [PATCH 4/6] Update Antlr4Package.md --- runtime/Cpp/cmake/Antlr4Package.md | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/runtime/Cpp/cmake/Antlr4Package.md b/runtime/Cpp/cmake/Antlr4Package.md index b1fde5c2b..09a3469f4 100644 --- a/runtime/Cpp/cmake/Antlr4Package.md +++ b/runtime/Cpp/cmake/Antlr4Package.md @@ -13,24 +13,15 @@ given input file during build. The following table lists the parameters that can be used with the function: -+-----------+-----------+-------------+------------------------------------------------------------------------------+ -| Argument# | Required | Default | | -+-----------+-----------+-------------+------------------------------------------------------------------------------+ -| 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 | No | FALSE | Boolean to indicate if a listener interface should be generated | -+-----------+-----------+-------------+------------------------------------------------------------------------------+ -| 3 | No | FALSE | Boolean to indicate if a visitor interface should be generated | -+-----------+-----------+-------------+------------------------------------------------------------------------------+ -| 4 | No | none | C++ namespace in which the generated classes should be placed | -+-----------+-----------+-------------+------------------------------------------------------------------------------+ -| 5 | No | none | Additional files on which the input depends | -+-----------+-----------+-------------+------------------------------------------------------------------------------+ -| 6 | No | none | Library path to use during generation | -+-----------+-----------+-------------+------------------------------------------------------------------------------+ +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 | No | FALSE | Boolean to indicate if a listener interface should be generated +3 | No | FALSE | Boolean to indicate if a visitor interface should be generated +4 | No | none | C++ namespace in which the generated classes should be placed +5 | No | none | Additional files on which the input depends +6 | 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). @@ -136,4 +127,4 @@ target_link_libraries( Parsertest PRIVATE antlr4_shared) ``` - \ No newline at end of file + From a39f120a33038abfeb13f4ceac98c50c6efc5fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Schau?= Date: Mon, 15 Jan 2018 19:27:05 +0100 Subject: [PATCH 5/6] Signed the contributers list --- contributors.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/contributors.txt b/contributors.txt index ffd3b9b2e..394adc60d 100644 --- a/contributors.txt +++ b/contributors.txt @@ -179,3 +179,4 @@ YYYY/MM/DD, github id, Full name, email 2017/12/01, SebastianLng, Sebastian Lang, sebastian.lang@outlook.com 2017/12/03, oranoran, Oran Epelbaum, oran / epelbaum me 2017/12/27, jkmar, Jakub Marciniszyn, marciniszyn.jk@gmail.com +2018/01/15, xgcssch, Sönke Schau, xgcssch@users.noreply.github.com From be8b865276618d97f43fc438dd073b5734b6c457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Schau?= Date: Tue, 16 Jan 2018 15:57:26 +0100 Subject: [PATCH 6/6] It turned out that the implemented CMake function generating the runtime files didn't work for combined lexer/parser files. Added a third required parameter which specifies the type of input file. --- runtime/Cpp/cmake/Antlr4Package.md | 16 ++- runtime/Cpp/cmake/antlr4-generator.cmake.in | 124 +++++++------------- 2 files changed, 51 insertions(+), 89 deletions(-) diff --git a/runtime/Cpp/cmake/Antlr4Package.md b/runtime/Cpp/cmake/Antlr4Package.md index 09a3469f4..929840cf7 100644 --- a/runtime/Cpp/cmake/Antlr4Package.md +++ b/runtime/Cpp/cmake/Antlr4Package.md @@ -17,15 +17,18 @@ 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 | No | FALSE | Boolean to indicate if a listener interface should be generated -3 | No | FALSE | Boolean to indicate if a visitor interface should be generated -4 | No | none | C++ namespace in which the generated classes should be placed -5 | No | none | Additional files on which the input depends -6 | No | none | Library path to use during generation +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 option to the ANTLR4 generator can be passed in the `ANTLR4_GENERATED_OPTIONS` variable + The following CMake variables are available following a call to `antlr4_generate` Output variable | Meaning @@ -42,6 +45,7 @@ Output variable | Meaning antlr4_generate( antlrcpptest_parser ${CMAKE_CURRENT_SOURCE_DIR}/TLexer.g4 + LEXER FALSE TRUE "antlrcpptest" @@ -98,6 +102,7 @@ target_link_libraries( Parsertest PRIVATE antlr4_generate( antlrcpptest_lexer ${CMAKE_CURRENT_SOURCE_DIR}/TLexer.g4 + LEXER FALSE FALSE "antlrcpptest" @@ -107,6 +112,7 @@ target_link_libraries( Parsertest PRIVATE antlr4_generate( antlrcpptest_parser ${CMAKE_CURRENT_SOURCE_DIR}/TParser.g4 + PARSER FALSE TRUE "antlrcpptest" diff --git a/runtime/Cpp/cmake/antlr4-generator.cmake.in b/runtime/Cpp/cmake/antlr4-generator.cmake.in index 6947cd1e8..5839cbe28 100644 --- a/runtime/Cpp/cmake/antlr4-generator.cmake.in +++ b/runtime/Cpp/cmake/antlr4-generator.cmake.in @@ -28,81 +28,12 @@ FIND_PACKAGE(Java COMPONENTS Runtime REQUIRED) # -> Listener.h # -> Listener.cpp # -# The function "antlr4_generate" will generate the required setup to call ANTLR for a given input file -# -# +-----------+-----------+-------------+------------------------------------------------------------------------------+ -# | Argument# | Required | Defaults to | | -# +-----------+-----------+-------------+------------------------------------------------------------------------------+ -# | 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 | No | FALSE | Boolean to indicate if a listener interface should be generated | -# +-----------+-----------+-------------+------------------------------------------------------------------------------+ -# | 3 | No | FALSE | Boolean to indicate if a visitor interface should be generated | -# +-----------+-----------+-------------+------------------------------------------------------------------------------+ -# | 4 | No | none | C++ namespace in which the generated classes should be placed | -# +-----------+-----------+-------------+------------------------------------------------------------------------------+ -# | 5 | No | none | Additional files on which the input depends | -# +-----------+-----------+-------------+------------------------------------------------------------------------------+ -# | 6 | No | none | Library path to use during generation | -# +-----------+-----------+-------------+------------------------------------------------------------------------------+ +# See documentation in markup # -# The ANTLR4_JAR_LOCATION must be set prior calling the function! -# -# The following CMake variables are available following a call to antlr4_generate -# -# ANTLR4_INCLUDE_DIR_ - Directory containing the generated header files -# ANTLR4_SRC_FILES_ - List of generated source files -# ANTLR4_TOKEN_FILES_ - List of generated token files -# ANTLR4_TOKEN_DIRECTORY_ - Directory containing the generated token files -# -# Sample: -# -# # 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.7.1-complete.jar) -# -# # generate lexer -# antlr4_generate( -# antlrcpptest_lexer -# ${CMAKE_CURRENT_SOURCE_DIR}/TLexer.g4 -# FALSE -# FALSE -# "antlrcpptest" -# ) -# -# # generate parser -# antlr4_generate( -# antlrcpptest_parser -# ${CMAKE_CURRENT_SOURCE_DIR}/TParser.g4 -# 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_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) -# -# function(antlr4_generate Antlr4_ProjectTarget Antlr4_InputFile + Antlr4_GeneratorType ) set( Antlr4_GeneratedSrcDir ${ANTLR4_GENERATED_SRC_DIR}/${Antlr4_ProjectTarget} ) @@ -111,16 +42,41 @@ function(antlr4_generate 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}.h" ) - list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}.cpp" ) 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 3 ) AND ARGV2 ) + if ( ( ARGC GREATER_EQUAL 4 ) AND ARGV3 ) set(Antlr4_BuildListenerOption "-listener") list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}BaseListener.h" ) @@ -133,7 +89,7 @@ function(antlr4_generate set(Antlr4_BuildListenerOption "-no-listener") endif () - if ( ( ARGC GREATER_EQUAL 4 ) AND ARGV3 ) + if ( ( ARGC GREATER_EQUAL 5 ) AND ARGV4 ) set(Antlr4_BuildVisitorOption "-visitor") list( APPEND Antlr4_GeneratedTargets "${Antlr4_GeneratedSrcDir}/${Antlr4_InputFileBaseName}BaseVisitor.h" ) @@ -146,24 +102,24 @@ function(antlr4_generate set(Antlr4_BuildVisitorOption "-no-visitor") endif () - if ( (ARGC GREATER_EQUAL 5 ) AND (NOT ${ARGV4} STREQUAL "") ) - set(Antlr4_NamespaceOption "-package;${ARGV4}") + if ( (ARGC GREATER_EQUAL 6 ) AND (NOT ${ARGV5} STREQUAL "") ) + set(Antlr4_NamespaceOption "-package;${ARGV5}") - list( APPEND Antlr4_GeneratorStatusMessage " in Namespace ${ARGV4}" ) + list( APPEND Antlr4_GeneratorStatusMessage " in Namespace ${ARGV5}" ) else() set(Antlr4_NamespaceOption "") endif () - if ( (ARGC GREATER_EQUAL 6 ) AND (NOT ${ARGV5} STREQUAL "") ) - set(Antlr4_AdditionalDependencies ${ARGV5}) + if ( (ARGC GREATER_EQUAL 7 ) AND (NOT ${ARGV6} STREQUAL "") ) + set(Antlr4_AdditionalDependencies ${ARGV6}) else() set(Antlr4_AdditionalDependencies "") endif () - if ( (ARGC GREATER_EQUAL 7 ) AND (NOT ${ARGV6} STREQUAL "") ) - set(Antlr4_LibOption "-lib;${ARGV6}") + if ( (ARGC GREATER_EQUAL 8 ) AND (NOT ${ARGV7} STREQUAL "") ) + set(Antlr4_LibOption "-lib;${ARGV7}") - list( APPEND Antlr4_GeneratorStatusMessage " using Library ${ARGV6}" ) + list( APPEND Antlr4_GeneratorStatusMessage " using Library ${ARGV7}" ) else() set(Antlr4_LibOption "") endif () @@ -187,7 +143,7 @@ function(antlr4_generate ${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} -o "${Antlr4_GeneratedSrcDir}" ${Antlr4_NamespaceOption} "${Antlr4_InputFile}" + "${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}