Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#132 Add a CMake build for C++ port #133

Merged
merged 22 commits into from
Jul 27, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: CMake

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

jobs:
build:
strategy:
matrix:
cmake_build_type: [Asan, Release]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Build Essential
run: sudo apt update && sudo apt install build-essential
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
create-symlink: true
key: ${{ github.job }}-${{ matrix.os }}
- name: Configure
working-directory: ${{github.workspace}}/ports/cpp
run: |
mkdir build
cd build
cmake \
-DANTLR4C3_DEVELOPER=ON \
-DCMAKE_BUILD_TYPE=${{ matrix.cmake_build_type }} \
..
- name: Build
working-directory: ${{github.workspace}}/ports/cpp/build
run: make
- name: Unit Test
working-directory: ${{github.workspace}}/ports/cpp/build/test
run: |
ctest
cat Testing/Temporary/LastTest.log
4 changes: 4 additions & 0 deletions ports/cpp/.clangd
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
InlayHints:
Designators: No
Enabled: No
DeducedTypes: No
6 changes: 6 additions & 0 deletions ports/cpp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# CMake
build/
build-asan/

# Clangd
.cache
14 changes: 14 additions & 0 deletions ports/cpp/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug Test",
"program": "${workspaceFolder}/build/test/${fileDirnameBasename}/antlr4-c3-test",
"args": [],
"cwd": "${workspaceFolder}",
"preLaunchTask": "Build All"
}
]
}
6 changes: 6 additions & 0 deletions ports/cpp/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"clangd.arguments": [
"-compile-commands-dir=./build",
"-header-insertion=never"
]
}
16 changes: 16 additions & 0 deletions ports/cpp/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build All",
"type": "shell",
"command": [
"make",
"all"
],
"options": {
"cwd": "${workspaceFolder}/build"
}
}
]
}
24 changes: 24 additions & 0 deletions ports/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.7)
project(antlr4-c3 VERSION 0.1.0)
Copy link
Contributor Author

@vityaman vityaman Jul 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is an actual version of C++ port? I would like to keep it with zero major version for now because it is still in progress, because of some major CMake structure changes may be required.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very fond of a zero major version for published libraries, but ok, let's start with 0.1.0.


option(ANTLR4C3_DEVELOPER "Enable ${PROJECT_NAME} developer mode" OFF)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

include(cmake/CompileOptions.cmake)
include(cmake/Sanitize.cmake)

set(ANTLR4_TAG 4.13.1)

find_package(Antlr4Cpp REQUIRED)

add_subdirectory(source)

if (ANTLR4C3_DEVELOPER)
include(cmake/Testing.cmake)

find_package(Antlr4Tool REQUIRED)
find_package(GTest REQUIRED)

add_subdirectory(test)
endif()
1 change: 1 addition & 0 deletions ports/cpp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# ANTLRv4 C3 C++ Port
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a bit more information, like required C++ and CMake versions and some instructions to build and run the tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

10 changes: 10 additions & 0 deletions ports/cpp/cmake/CompileOptions.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_compile_options(-Wall -Wextra -Wpedantic)

if(ANTLR4C3_DEVELOPER)
add_compile_options(-Werror)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()
185 changes: 185 additions & 0 deletions ports/cpp/cmake/ExternalAntlr4Cpp.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Source: https://github.com/antlr/antlr4/blob/4.13.1/runtime/Cpp/cmake/ExternalAntlr4Cpp.cmake

cmake_minimum_required(VERSION 3.7)

# Added additionally
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
# Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP
cmake_policy(SET CMP0135 NEW)
endif()

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.1.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()
6 changes: 6 additions & 0 deletions ports/cpp/cmake/FindAntlr4Cpp.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
set(ANTLR4_WITH_STATIC_CRT OFF)
set(ANTLR4_ZIP_REPOSITORY https://github.com/antlr/antlr4/archive/refs/tags/${ANTLR4_TAG}.zip)
add_definitions(-DANTLR4CPP_STATIC)
include(ExternalAntlr4Cpp)

set(ANTLR4C3_ANTLR4_STATIC antlr4_static)
18 changes: 18 additions & 0 deletions ports/cpp/cmake/FindAntlr4Tool.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
file(
DOWNLOAD
https://www.antlr.org/download/antlr-${ANTLR4_TAG}-complete.jar
${CMAKE_BINARY_DIR}/antlr-${ANTLR4_TAG}-complete.jar
)
set(ANTLR_EXECUTABLE ${CMAKE_BINARY_DIR}/antlr-${ANTLR4_TAG}-complete.jar)

function(antlr_generate grammar directory)
message(STATUS "antlr_generate ${grammar} ${directory}")
execute_process(
COMMAND bash -c "java \
-jar ${ANTLR_EXECUTABLE} \
-o ${directory} \
-listener -visitor -Dlanguage=Cpp \
${grammar} \
${grammar}"
)
endfunction()
11 changes: 11 additions & 0 deletions ports/cpp/cmake/FindGTest.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
include(FetchContent)

FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)

# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
include(GoogleTest)
11 changes: 11 additions & 0 deletions ports/cpp/cmake/Sanitize.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set(
CMAKE_CXX_FLAGS_ASAN "-g -fsanitize=address,undefined -fno-sanitize-recover=all"
CACHE STRING "Compiler flags in ASan build"
FORCE
)

set(
CMAKE_CXX_FLAGS_TSAN "-g -fsanitize=thread -fno-sanitize-recover=all"
CACHE STRING "Compiler flags in TSan build"
FORCE
)
29 changes: 29 additions & 0 deletions ports/cpp/cmake/Testing.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
macro(define_grammar_test grammar)
antlr_generate(
${CMAKE_CURRENT_LIST_DIR}/${grammar}
${CMAKE_CURRENT_BINARY_DIR}
)

file(
GLOB_RECURSE SOURCE CONFIGURE_DEPENDS
*.hpp *.cpp
${CMAKE_CURRENT_BINARY_DIR}/*.hpp
${CMAKE_CURRENT_BINARY_DIR}/*.cpp
)

add_executable(${PROJECT_NAME}-test ${SOURCE})

target_include_directories(
${PROJECT_NAME}-test PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)

target_link_libraries(
${PROJECT_NAME}-test PRIVATE
${PROJECT_NAME}
GTest::gtest_main
GTest::gmock
)

gtest_discover_tests(${PROJECT_NAME}-test)
endmacro()
Loading
Loading