-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
249 lines (220 loc) · 10.4 KB
/
Copy pathCMakeLists.txt
File metadata and controls
249 lines (220 loc) · 10.4 KB
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
cmake_minimum_required(VERSION 3.10)
project(libperf-cpp VERSION 1.1.0 LANGUAGES CXX)
# perf-cpp requires complete std::from_chars support (GCC 11+, Clang 14+).
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11)
message(FATAL_ERROR "perf-cpp requires GCC 11 or newer (found GCC ${CMAKE_CXX_COMPILER_VERSION}).")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
message(FATAL_ERROR "perf-cpp requires Clang 14 or newer (found Clang ${CMAKE_CXX_COMPILER_VERSION}).")
endif()
## Consuming toolchains (e.g., Conan) may request a newer standard; only default to C++17 when nothing is set.
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
endif()
## Detect if perf-cpp is built standalone or embedded into another project (e.g., via add_subdirectory or FetchContent).
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(PERF_CPP_IS_TOP_LEVEL ON)
else()
set(PERF_CPP_IS_TOP_LEVEL OFF)
endif()
## Warning flags are applied per-target below (instead of via CMAKE_CXX_FLAGS) to keep them out of embedding projects.
set(PERF_CPP_WARNING_FLAGS
-Wall -Wextra -Wpedantic -Wconversion -Wcast-align -Wunused -Wshadow -Wold-style-cast -Wpointer-arith
-Wcast-qual -Wnon-virtual-dtor -Woverloaded-virtual -Wnull-dereference -Wdouble-promotion -Wformat=2
-Wno-missing-braces)
## Only override build-type flags and the default build type when building standalone; embedding projects keep their own.
## Release carries no debug info, which would otherwise dominate the size of a packaged build (~60 MB of DWARF for
## a 2.5 MB library); build RelWithDebInfo to profile perf-cpp itself with full line information.
if(PERF_CPP_IS_TOP_LEVEL)
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG")
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
message("Building Mode = ${CMAKE_BUILD_TYPE}")
endif()
#############################################################
# Options #
#############################################################
option(BUILD_EXAMPLES "Build examples in examples/ directory." OFF)
option(BUILD_LIB_SHARED "Build the library as a shared library (default is static)." OFF)
option(BUILD_TESTS "Build the unit tests." OFF)
option(GEN_PROCESSOR_EVENTS "Generate processor-specific events" OFF)
option(ENABLE_CLANG_TIDY "Run clang-tidy alongside compilation." ${PERF_CPP_IS_TOP_LEVEL})
if(PERF_CPP_IS_TOP_LEVEL)
message("Building as Shared Library = ${BUILD_LIB_SHARED}")
message("Building Examples = ${BUILD_EXAMPLES}")
message("Building Tests = ${BUILD_TESTS}")
message("Generating Processor-specific Events = ${GEN_PROCESSOR_EVENTS}")
message("Running clang-tidy = ${ENABLE_CLANG_TIDY}")
endif()
#############################################################
# perf-cpp source files #
#############################################################
set(PERF_CPP_SRC
src/config.cpp
src/counter_definition.cpp
src/event_counter.cpp
src/event_file_descriptor_parser.cpp
src/exception.cpp
src/hardware_info.cpp
src/sampler.cpp
src/counter/counter.cpp
src/counter/event_provider.cpp
src/counter/group.cpp
src/counter/requested_event.cpp
src/counter/result.cpp
src/sample/decoder.cpp
src/sample/trigger.cpp
src/sample/mmap_buffer.cpp
src/sample/recording_values.cpp
src/sample/record_file_writer.cpp
src/sample/result.cpp
src/metric/expression/token.cpp
src/metric/expression/tokenizer.cpp
src/metric/expression/parser.cpp
src/metric/expression/function.cpp
src/metric/expression/expression.cpp
src/analyzer/memory_access.cpp
src/analyzer/flame_graph_generator.cpp
src/util/callchain_trie.cpp
src/util/symbol_resolver.cpp
src/util/table.cpp
)
#############################################################
# Generated source file with processor-specific #
# events. #
#############################################################
if (GEN_PROCESSOR_EVENTS)
set(PROCESSOR_EVENT_SRC_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/processor_specific_event_provider.cpp")
# Execute the Python script to generate the file
execute_process(
COMMAND python3 "${CMAKE_CURRENT_SOURCE_DIR}/script/generate_processor_event_provider.py"
--output "${PROCESSOR_EVENT_SRC_FILE}" --events "${CMAKE_CURRENT_SOURCE_DIR}/events" --verbose
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE SCRIPT_RESULT
)
# Verify the file was created; if yes, add the file and hint perf-cpp that this event provider
# should be included into the default CounterDefinition.
if(EXISTS "${PROCESSOR_EVENT_SRC_FILE}")
set(PERF_CPP_SRC ${PERF_CPP_SRC} "${PROCESSOR_EVENT_SRC_FILE}")
add_compile_definitions(PERFCPP_HAS_PROCESSOR_SPECIFIC_EVENTS)
endif()
endif()
#############################################################
# perf-cpp library definition #
#############################################################
if (BUILD_LIB_SHARED)
add_library(perf-cpp SHARED ${PERF_CPP_SRC})
else ()
add_library(perf-cpp STATIC ${PERF_CPP_SRC})
endif ()
## Attach usage requirements to the target so they travel with the installed export:
## the include directory (source tree when building, <prefix>/include when installed) and C++17.
include(GNUInstallDirs)
target_include_directories(perf-cpp
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_features(perf-cpp PUBLIC cxx_std_17)
## The sampler's overflow worker runs on a std::thread; PUBLIC so consumers linking the static library get the thread library, too.
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(perf-cpp PUBLIC Threads::Threads)
## Compile the library itself with the strict warning set; PRIVATE keeps the flags out of consuming targets.
target_compile_options(perf-cpp PRIVATE ${PERF_CPP_WARNING_FLAGS})
## Version the library; shared builds get a proper soname (e.g., libperf-cpp.so.1).
set_target_properties(perf-cpp PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
)
#############################################################
# clang-tidy integration #
#############################################################
## Lint alongside compilation; off by default for embedded and packaged builds, which should not pay for (or fail on) linting.
if(ENABLE_CLANG_TIDY)
find_program(CLANG_TIDY NAMES "clang-tidy")
if(CLANG_TIDY)
set(CLANG_TIDY_COMMAND "${CLANG_TIDY}" "--config-file=${CMAKE_CURRENT_SOURCE_DIR}/.clang-tidy")
set_target_properties(perf-cpp PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")
else()
message(WARNING "clang-tidy not found")
endif()
endif()
#############################################################
# Examples definition #
#############################################################
if(BUILD_EXAMPLES)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/examples/bin)
include(examples/CMakeLists.txt)
endif()
#############################################################
# Unit tests definition #
#############################################################
if(BUILD_TESTS)
include(test/CMakeLists.txt)
endif()
#############################################################
# Maintainer-only custom targets (docs, perf-list); #
# not added when perf-cpp is embedded into another #
# project. #
#############################################################
if(PERF_CPP_IS_TOP_LEVEL)
## To preview the documentation locally, run: .venv/bin/mkdocs serve
find_program(MKDOCS_EXECUTABLE mkdocs HINTS ${CMAKE_CURRENT_SOURCE_DIR}/.venv/bin)
if(MKDOCS_EXECUTABLE)
add_custom_target(docs
COMMAND ${MKDOCS_EXECUTABLE} build -f ${CMAKE_CURRENT_SOURCE_DIR}/mkdocs.yml -d ${CMAKE_CURRENT_SOURCE_DIR}/site
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Building documentation website into site/"
)
endif()
## Extract hardware events into a CSV file.
add_custom_target(perf-list python3 ${CMAKE_CURRENT_SOURCE_DIR}/script/create_perf_list.py)
endif()
#############################################################
# Rules for installing the library #
#############################################################
include(CMakePackageConfigHelpers)
## Allow package maintainers to override the location of the CMake package config files.
set(PERF_CPP_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/perf-cpp"
CACHE PATH "CMake package config location relative to the install prefix")
mark_as_advanced(PERF_CPP_INSTALL_CMAKEDIR)
## Install the library itself; the EXPORT clause records it for the package config.
install(
TARGETS perf-cpp
EXPORT perf-cppTargets
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
## Install the public headers.
install(
DIRECTORY include/
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h"
)
## Generate a relocatable package config (no hardcoded install prefix).
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/perf-cppConfig.cmake.in"
"${PROJECT_BINARY_DIR}/perf-cppConfig.cmake"
INSTALL_DESTINATION "${PERF_CPP_INSTALL_CMAKEDIR}"
)
## Generate the version file; consumers' find_package(perf-cpp 1.0) checks against this.
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/perf-cppConfigVersion.cmake"
COMPATIBILITY SameMajorVersion
)
install(
FILES
"${PROJECT_BINARY_DIR}/perf-cppConfig.cmake"
"${PROJECT_BINARY_DIR}/perf-cppConfigVersion.cmake"
DESTINATION "${PERF_CPP_INSTALL_CMAKEDIR}"
)
## Install the targets file that the config includes; defines the perf-cpp::perf-cpp target.
install(
EXPORT perf-cppTargets
NAMESPACE perf-cpp::
DESTINATION "${PERF_CPP_INSTALL_CMAKEDIR}"
)