forked from ElektraInitiative/libelektra
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
186 lines (169 loc) · 7.29 KB
/
CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# This functions checks if the dependencies for the Yan LR plugin are available.
#
# If they are, the function sets the variable `FOUND_DEPENDENCIES` to `TRUE`. The function then also sets:
#
# - `ANTLR_EXECUTABLE` to the name of the ANTLR executable,
# - `ANTLR4CPP_LIBRARIES` to the paths of the libraries provided by ANTLR’s C++ runtime, and
# - `ANTLR4CPP_INCLUDE_DIRS` to the paths of the included directories of ANTLR’s C++ runtime
#
# . If the function was unsuccessful it sets `FOUND_DEPENDENCIES` to `FALSE` and stores the reason for the failure in the variable
# `FAILURE_MESSAGE`.
function (check_dependencies)
set (FOUND_DEPENDENCIES FALSE PARENT_SCOPE)
unset (ANTLR_EXECUTABLE)
unset (FAILURE_MESSAGE)
execute_process (COMMAND antlr4 RESULT_VARIABLE ANTLR4_NOT_AVAILABLE OUTPUT_VARIABLE ANTLR4_OUTPUT)
execute_process (COMMAND antlr RESULT_VARIABLE ANTLR_NOT_AVAILABLE OUTPUT_VARIABLE ANTLR_OUTPUT)
if (ANTLR4_NOT_AVAILABLE AND ANTLR_NOT_AVAILABLE)
set (FAILURE_MESSAGE "ANTLR 4 executable (antlr4, antlr) not found" PARENT_SCOPE)
return ()
else (ANTLR4_NOT_AVAILABLE AND ANTLR_NOT_AVAILABLE)
if (ANTLR4_NOT_AVAILABLE)
set (ANTLR_EXECUTABLE antlr PARENT_SCOPE)
set (ANTLR_VERSION ${ANTLR_OUTPUT})
else (ANTLR4_NOT_AVAILABLE)
set (ANTLR_EXECUTABLE antlr4 PARENT_SCOPE)
set (ANTLR_VERSION ${ANTLR4_OUTPUT})
endif (ANTLR4_NOT_AVAILABLE)
endif (ANTLR4_NOT_AVAILABLE AND ANTLR_NOT_AVAILABLE)
string (REGEX
REPLACE ".*Version ([0-9]+\\.[0-9]+\\.[0-9]+).*"
"\\1"
ANTLR_VERSION
${ANTLR_VERSION})
if ("${ANTLR_VERSION}" VERSION_LESS 4.6)
set (FAILURE_MESSAGE "ANTLR version 4.6 or later required (found version “${ANTLR_VERSION}”)" PARENT_SCOPE)
return ()
endif ("${ANTLR_VERSION}" VERSION_LESS 4.6)
find_package (ANTLR4CPP QUIET)
if (NOT ANTLR4CPP_FOUND)
set (FAILURE_MESSAGE "ANTLR 4 CPP runtime (antlr4-cpp-runtime) not found" PARENT_SCOPE)
return ()
endif (NOT ANTLR4CPP_FOUND)
set (ANTLR4CPP_LIBRARIES ${ANTLR4CPP_LIBRARIES} PARENT_SCOPE)
set (ANTLR4CPP_INCLUDE_DIRS ${ANTLR4CPP_INCLUDE_DIRS} PARENT_SCOPE)
# AdressSanitizer enabled builds of the plugin report runtime errors about member calls, which do not point to an object of type
# `_Sp_counted_base` inside the system header file `shared_ptr_base.h`. In Clang builds of the plugin we ignore this error in our
# [blacklist](tests/sanitizer.blacklist). Unfortunately GCC does not support a blacklist, so we remove the plugin in this case.
set (DISABLE_PLUGIN_ASAN
${ENABLE_ASAN}
AND
"${CMAKE_CXX_COMPILER_ID}"
MATCHES
"GNU"
AND
${CMAKE_CXX_COMPILER_VERSION}
VERSION_LESS
9)
if (${DISABLE_PLUGIN_ASAN})
set (FAILURE_MESSAGE "ASan enabled GCC builds of the plugin report member calls on addresses, "
"which do not point to an object of type `_Sp_counted_base`" PARENT_SCOPE)
return ()
endif (${DISABLE_PLUGIN_ASAN})
set (FOUND_DEPENDENCIES TRUE PARENT_SCOPE)
endfunction (check_dependencies)
# This functions generates the source files of the YAML parser using the given ANTLR executable (`ANTLR_EXECUTABLE`). The function also
# invokes the script `RenameSymbols.cmake` to replace the symbol names used by ANTLR in error messages by a more human readable form.
#
# The function exports the list
#
# - `GENERATED_SOURCE_FILES`, which contains the list of source files generated by ANTLR and `RenameSymbols.cmake`
#
# .
function (generate_code ANTLR_EXECUTABLE)
set (GRAMMAR_NAME YAML)
set (GRAMMAR_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${GRAMMAR_NAME}.g4)
set (TOKEN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${GRAMMAR_NAME}.tokens)
set (GENERATED_SOURCE_FILES_NAMES BaseListener Listener)
set (PARSER_SOURCE_FILE ${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_NAME}.cpp)
set (PARSER_MODIFIED_SOURCE_FILE ${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_NAME}ImprovedSymbolNames.cpp)
foreach (file ${GENERATED_SOURCE_FILES_NAMES} "")
foreach (extension "cpp" "h")
set (filepath ${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_NAME}${file}.${extension})
set_source_files_properties (${filepath}
PROPERTIES
GENERATED
TRUE)
if (CMAKE_COMPILER_IS_GNUCXX)
set_source_files_properties (${filepath}
PROPERTIES
COMPILE_FLAGS
"-Wno-shadow")
endif (CMAKE_COMPILER_IS_GNUCXX)
if (NOT ${filepath} STREQUAL ${PARSER_SOURCE_FILE})
list (APPEND GENERATED_SOURCE_FILES_EXPORT)
endif (NOT ${filepath} STREQUAL ${PARSER_SOURCE_FILE})
list (APPEND GENERATED_SOURCE_FILES ${filepath})
endforeach (extension "cpp" "h")
endforeach (file ${GENERATED_SOURCE_FILES_NAMES})
add_custom_command (OUTPUT ${GENERATED_SOURCE_FILES}
COMMAND ${ANTLR_EXECUTABLE}
-Werror
-Dlanguage=Cpp
-o
${CMAKE_CURRENT_BINARY_DIR}
-package
yanlr
${GRAMMAR_FILE}
DEPENDS ${GRAMMAR_FILE} ${TOKEN_FILE}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set_source_files_properties (${PARSER_MODIFIED_SOURCE_FILE}
PROPERTIES
GENERATED
TRUE)
if (CMAKE_COMPILER_IS_GNUCXX)
set_source_files_properties (${PARSER_MODIFIED_SOURCE_FILE}
PROPERTIES
COMPILE_FLAGS
"-Wno-shadow")
endif (CMAKE_COMPILER_IS_GNUCXX)
add_custom_command (OUTPUT ${PARSER_MODIFIED_SOURCE_FILE}
COMMAND ${CMAKE_COMMAND}
ARGS
-D
PARSER_SOURCE_FILE=${PARSER_SOURCE_FILE}
-D
PARSER_MODIFIED_SOURCE_FILE=${PARSER_MODIFIED_SOURCE_FILE}
-P
${CMAKE_CURRENT_SOURCE_DIR}/RenameSymbols.cmake
DEPENDS ${PARSER_SOURCE_FILE} RenameSymbols.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set (GENERATED_SOURCE_FILES ${GENERATED_SOURCE_FILES_EXPORT} ${PARSER_MODIFIED_SOURCE_FILE} PARENT_SCOPE)
endfunction (generate_code)
if (DEPENDENCY_PHASE)
check_dependencies ()
if (NOT FOUND_DEPENDENCIES)
remove_plugin (yanlr ${FAILURE_MESSAGE})
else (NOT FOUND_DEPENDENCIES)
generate_code (${ANTLR_EXECUTABLE})
set (SOURCE_FILES
"${GENERATED_SOURCE_FILES}"
listener.hpp
listener.cpp
error_listener.hpp
error_listener.cpp
yaml_lexer.hpp
yaml_lexer.cpp
yanlr.hpp
yanlr.cpp)
endif (NOT FOUND_DEPENDENCIES)
endif (DEPENDENCY_PHASE)
# The generated parser code seems to contain a double free that causes the unit test to crash with a segfault on **some** systems that use
# `glibc`. If AddressSanitizer is enabled everything seems to work fine.
set (TEST_ARGUMENTS ADD_TEST CPP_TEST)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL Linux AND NOT ${ENABLE_ASAN})
# We only disable the test, if we detect a GNU C Library based system.
execute_process (COMMAND ldd --version RESULT_VARIABLE ANTLR4_NOT_AVAILABLE OUTPUT_VARIABLE LDD_OUTPUT)
if ("${LDD_OUTPUT}" MATCHES "GLIBC|GNU libc")
set (TEST_ARGUMENTS "")
endif ("${LDD_OUTPUT}" MATCHES "GLIBC|GNU libc")
endif ("${CMAKE_SYSTEM_NAME}" STREQUAL Linux AND NOT ${ENABLE_ASAN})
add_plugin (yanlr CPP ${TEST_ARGUMENTS}
SOURCES ${SOURCE_FILES}
INCLUDE_SYSTEM_DIRECTORIES ${ANTLR4CPP_INCLUDE_DIRS}
LINK_LIBRARIES ${ANTLR4CPP_LIBRARIES}
LINK_ELEKTRA elektra-ease
INSTALL_TEST_DATA TEST_README
# Unfortunately it looks like ANTLR’s code [causes a container-overflow](https://github.com/antlr/antlr4/issues/2332).
TEST_ENVIRONMENT "ASAN_OPTIONS=detect_container_overflow=0"
TEST_REQUIRED_PLUGINS directoryvalue yamlsmith)