-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
395 lines (345 loc) · 14.8 KB
/
CMakeLists.txt
File metadata and controls
395 lines (345 loc) · 14.8 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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# Copyright 2025 Advanced Micro Devices, Inc.
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
cmake_minimum_required(VERSION 3.24)
# Avoid in-source builds (prevent build artifacts from cluttering the source directory)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(
FATAL_ERROR
"Do not build in-source. Please remove CMakeCache.txt and the CMakeFiles/ directory. Then build out-of-source."
)
endif()
# Get version number from file
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version.json VERSION_JSON_STRING)
string(JSON PACKAGE_VERSION GET ${VERSION_JSON_STRING} package-version)
string(REGEX MATCH "(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*" BASE_VERSION ${PACKAGE_VERSION})
project(
fusilli
VERSION ${BASE_VERSION}
DESCRIPTION "Fusilli: A C++ Graph API and Frontend backed by IREE code-generated kernels"
LANGUAGES C CXX)
# Set C++ standard
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# https://discourse.cmake.org/t/cmake-3-28-cmake-cxx-compiler-clang-scan-deps-notfound-not-found/9244/3
set(CMAKE_CXX_SCAN_FOR_MODULES OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(MSVC)
add_compile_options(
# Increase max sections in obj files to 2^32 for large translation units
# https://learn.microsoft.com/en-us/cpp/build/reference/bigobj-increase-number-of-sections-in-dot-obj-file
/bigobj
# Exclude rarely-used Windows APIs (crypto, DDE, shell) for faster builds
# https://learn.microsoft.com/en-us/windows/win32/winprog/using-the-windows-headers
/DWIN32_LEAN_AND_MEAN
# Prevent windows.h from defining min/max macros that conflict with STL
# https://stackoverflow.com/a/4914108
/DNOMINMAX
)
endif()
# Includes
include(CTest)
include(FetchContent)
include(CheckCXXCompilerFlag)
# Local Includes
list(APPEND CMAKE_MODULE_PATH
${CMAKE_CURRENT_LIST_DIR}/build_tools/cmake/
)
include(FusilliBuildUtils)
include(FusilliTestUtils)
# Build options
option(FUSILLI_BUILD_TESTS "Builds C++ tests and samples" ON)
option(FUSILLI_BUILD_BENCHMARKS "Builds C++ benchmarks" ON)
option(FUSILLI_CODE_COVERAGE "Enable code coverage for tests" OFF)
option(FUSILLI_ENABLE_LOGGING "Enable logging for tests and samples" OFF)
option(FUSILLI_ENABLE_CLANG_TIDY "Enable clang-tidy" OFF)
option(FUSILLI_SYSTEMS_AMDGPU "Builds for AMD GPU systems" OFF)
option(FUSILLI_ENABLE_ASAN "Enable AddressSanitizer" OFF)
option(FUSILLI_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer" OFF)
message(STATUS "Fusilli supported systems:")
if(FUSILLI_SYSTEMS_AMDGPU)
message(STATUS " - AMD GPU")
endif()
message(STATUS " - Host")
if(FUSILLI_ENABLE_ASAN AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message(FATAL_ERROR "AddressSanitizer requires Clang as the C++ compiler, but '${CMAKE_CXX_COMPILER_ID}' was detected.")
endif()
if(FUSILLI_ENABLE_UBSAN AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message(FATAL_ERROR "UndefinedBehaviorSanitizer requires Clang as the C++ compiler, but '${CMAKE_CXX_COMPILER_ID}' was detected.")
endif()
if(FUSILLI_ENABLE_ASAN AND FUSILLI_CODE_COVERAGE)
message(FATAL_ERROR "FUSILLI_ENABLE_ASAN and FUSILLI_CODE_COVERAGE cannot be enabled simultaneously.")
endif()
if(FUSILLI_ENABLE_UBSAN AND FUSILLI_CODE_COVERAGE)
message(FATAL_ERROR "FUSILLI_ENABLE_UBSAN and FUSILLI_CODE_COVERAGE cannot be enabled simultaneously.")
endif()
################################################################################
# IREE Dependency
#
# Fusilli takes a source dependency on the IREE runtime for interfacing with its
# C-API. The runtime is structured as a modular set of library components designed
# to be (statically) linked into applications directly and compiled with LTO style
# optimizations.
#
# To point to a local IREE source directory, simply specify:
#
# -DIREE_SOURCE_DIR=</path/to/iree/source>
#
# When not specified, Fusilli will FetchContent the IREE sources from GitHub
# at the tag specified by `IREE_GIT_TAG`.
#
# Fusilli shall not take a source dependency on the IREE compiler, which is quite
# heavy and can be slow to build. It is left to the consumer of Fusilli to either
# bring a prebuilt `libIREECompile.so` via `find_package` for C-API interfacing,
# or side-load a python-installed `iree-compile` binary via `find_program` for
# CLI integration.
#
################################################################################
# Version pins for dependencies.
# IREE_GIT_TAG is read from version.json (single source of truth).
# Prefer to keep the IREE_GIT_TAG synced with the python-installed IREE version.
# At a minimum, the compiler from those packages must be compatible with the
# runtime at this source ref.
string(JSON IREE_VERSION GET ${VERSION_JSON_STRING} iree-version)
set(IREE_GIT_TAG "iree-${IREE_VERSION}")
set(IREE_SOURCE_DIR "" CACHE FILEPATH "Path to IREE source")
set(IREE_COMPILER_LIB "" CACHE FILEPATH "Path to libIREECompiler.so")
# Set IREE build flags.
set(IREE_VISIBILITY_HIDDEN OFF)
set(IREE_BUILD_COMPILER OFF)
set(IREE_BUILD_TESTS OFF)
set(IREE_BUILD_SAMPLES OFF)
# Disable missing submodules error because we are only building the runtime.
set(IREE_ERROR_ON_MISSING_SUBMODULES OFF)
# Only enable local_sync/local_task/hip drivers for now.
set(IREE_HAL_DRIVER_DEFAULTS OFF)
set(IREE_HAL_DRIVER_LOCAL_SYNC ON)
set(IREE_HAL_DRIVER_LOCAL_TASK ON)
# Enable HAL HIP driver for AMD GPU systems.
if(FUSILLI_SYSTEMS_AMDGPU)
set(IREE_HAL_DRIVER_HIP ON)
set(IREE_HIP_TEST_TARGET_CHIP "" CACHE STRING "Enable ROCm testing on specific architecture (e.g. gfx942)")
endif()
# Enable ASAN build for IREE if ASAN is used in Fusilli
if(FUSILLI_ENABLE_ASAN)
set(IREE_ENABLE_ASAN ON)
endif()
# Enable UBSAN build for IREE if UBSAN is used in Fusilli
if(FUSILLI_ENABLE_UBSAN)
set(IREE_ENABLE_UBSAN ON)
endif()
if(IREE_SOURCE_DIR)
message(STATUS "Using existing IREE sources: ${IREE_SOURCE_DIR}")
add_subdirectory(${IREE_SOURCE_DIR} fusilli_iree SYSTEM EXCLUDE_FROM_ALL)
else()
message(STATUS "Fetching IREE sources from tag ${IREE_GIT_TAG}")
set(IREE_SUBMODULES "third_party/benchmark third_party/flatcc third_party/hip-build-deps third_party/printf")
FetchContent_Declare(
fusilli_iree
GIT_REPOSITORY https://github.com/iree-org/iree.git
GIT_TAG "${IREE_GIT_TAG}"
GIT_SUBMODULES ${IREE_SUBMODULES}
GIT_SHALLOW TRUE
SYSTEM
EXCLUDE_FROM_ALL
)
FetchContent_GetProperties(fusilli_iree)
if(NOT fusilli_iree_POPULATED)
FetchContent_MakeAvailable(fusilli_iree)
endif()
endif()
# Defines variables CMAKE_INSTALL_<dir> for common install locations.
include(GNUInstallDirs)
# Create header-only library.
add_library(libfusilli INTERFACE)
# Consumers of exported/installed target use fusilli::fusilli.
set_target_properties(libfusilli PROPERTIES EXPORT_NAME fusilli)
# Create alias for consistent naming in consuming projects building locally (via
# FetchContent) and against an installed version (via find_package).
add_library(fusilli::fusilli ALIAS libfusilli)
# Enable clang-tidy.
fusilli_enable_clang_tidy(libfusilli)
# INTERFACE libraries don't install/export header files added via
# `target_include_directories`. Using a file set property ensures headers are
# available in the installed/exported package.
file(GLOB_RECURSE FUSILLI_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/include/*.h
)
target_sources(libfusilli INTERFACE
FILE_SET fusilli_headers TYPE HEADERS # file sets require lowercase name
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
FILES ${FUSILLI_HEADERS}
)
# Statically link IREERuntime
target_link_libraries(libfusilli INTERFACE iree_runtime_unified)
# Build Type - Release/Debug
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "Setting CMAKE_BUILD_TYPE to Release")
set(CMAKE_BUILD_TYPE Release CACHE STRING "Release build" FORCE)
endif()
if(FUSILLI_CODE_COVERAGE)
message(STATUS "Setting CMAKE_BUILD_TYPE to Debug")
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Debug build" FORCE)
endif()
# Configure sanitizer flags
set(FUSILLI_SANITIZER_COMPILE_FLAGS "")
set(FUSILLI_SANITIZER_LINK_FLAGS "")
if(FUSILLI_ENABLE_ASAN)
message(STATUS "AddressSanitizer (ASAN) enabled")
list(APPEND FUSILLI_SANITIZER_COMPILE_FLAGS -fsanitize=address -fno-omit-frame-pointer -g)
list(APPEND FUSILLI_SANITIZER_LINK_FLAGS -fsanitize=address)
# Optionally enable recovery mode so the program can continue past
# ASAN errors, allowing multiple issues to be reported in a single run.
# This is experimental and only supported by some compilers. It takes
# effect when `ASAN_OPTIONS=halt_on_error=0` is set at runtime; the
# default (halt_on_error=1) still aborts on the first error.
check_cxx_compiler_flag("-fsanitize-recover=address" ASAN_RECOVER_SUPPORTED)
if (ASAN_RECOVER_SUPPORTED)
list(APPEND FUSILLI_SANITIZER_COMPILE_FLAGS -fsanitize-recover=address)
endif()
endif()
if(FUSILLI_ENABLE_UBSAN)
message(STATUS "UndefinedBehaviorSanitizer (UBSAN) enabled")
list(APPEND FUSILLI_SANITIZER_COMPILE_FLAGS -fsanitize=undefined -fno-omit-frame-pointer -g)
list(APPEND FUSILLI_SANITIZER_LINK_FLAGS -fsanitize=undefined)
# The vptr check requires all linked code (including third-party libraries
# like Catch2 and libstdc++) to be compiled with UBSAN. Since pre-built
# libraries are not UBSAN-instrumented, the vptr check causes undefined
# symbol errors at link time (__ubsan_vptr_type_cache). Disable it.
list(APPEND FUSILLI_SANITIZER_COMPILE_FLAGS -fno-sanitize=vptr)
# Disable recovery mode and abort on the first UBSAN error, ensuring
# UB issues get flagged as test failures rather than silent warnings;
# the default UBSAN behavior is to continue past the first error.
list(APPEND FUSILLI_SANITIZER_COMPILE_FLAGS -fno-sanitize-recover=undefined)
endif()
# Configure sanitizer environment variables for CTest targets.
# These are appended to test ENVIRONMENT properties so that LSAN/UBSAN
# suppressions and behavior flags are set consistently across all test,
# sample, lit, and benchmark targets.
set(FUSILLI_SANITIZER_TEST_ENV_VARS "")
if(FUSILLI_ENABLE_ASAN)
list(APPEND FUSILLI_SANITIZER_TEST_ENV_VARS
"LSAN_OPTIONS=suppressions=${PROJECT_SOURCE_DIR}/build_tools/sanitizers/lsan_suppressions.txt")
endif()
if(FUSILLI_ENABLE_UBSAN)
list(APPEND FUSILLI_SANITIZER_TEST_ENV_VARS
"UBSAN_OPTIONS=suppressions=${PROJECT_SOURCE_DIR}/build_tools/sanitizers/ubsan_suppressions.txt:halt_on_error=1:print_stacktrace=1")
endif()
# Enable AMD GPU build if requested
if(FUSILLI_SYSTEMS_AMDGPU)
# Check for Linux AMD GPU device node - `/dev/kfd`
if(NOT EXISTS "/dev/kfd")
message(WARNING "No AMD GPU detected (`/dev/kfd` not found) but FUSILLI_SYSTEMS_AMDGPU is set; Only proceed if cross-compiling for AMD GPU systems.")
endif()
target_compile_definitions(libfusilli INTERFACE FUSILLI_ENABLE_AMDGPU)
endif()
# Bake IREE compiler library path into the binary so LD_LIBRARY_PATH is not
# needed at runtime.
if(IREE_COMPILER_LIB)
if(NOT EXISTS "${IREE_COMPILER_LIB}")
message(FATAL_ERROR "IREE_COMPILER_LIB set to '${IREE_COMPILER_LIB}' but the file does not exist.")
endif()
message(STATUS "Using IREE compiler lib: ${IREE_COMPILER_LIB}")
target_compile_definitions(libfusilli INTERFACE
FUSILLI_DEFAULT_IREE_COMPILER_LIB="${IREE_COMPILER_LIB}")
endif()
# Both tests and benchmarks depend on iree-compile, Catch2, and libutils
if(FUSILLI_BUILD_TESTS OR FUSILLI_BUILD_BENCHMARKS)
# Side-load iree-compile program
fusilli_find_program(iree-compile INSTALL_INSTRUCTIONS "Please install iree-compile (e.g., pip install iree-base-compiler).")
# Bake iree-compile path into the binary so it can be found at runtime without
# needing it on PATH or setting FUSILLI_EXTERNAL_IREE_COMPILE env var.
target_compile_definitions(libfusilli INTERFACE
FUSILLI_DEFAULT_IREE_COMPILE="$<TARGET_FILE:iree-compile>")
# Find prebuilt Catch2 library or fetch it if not found
find_package(Catch2 3 QUIET)
if(NOT Catch2_FOUND)
message(STATUS "Catch2 not found on system: Fetching from GitHub")
FetchContent_Declare(
Catch2
QUIET
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.11.0
# SYSTEM marks Catch2 headers as system includes, suppressing compiler
# warnings and clang-tidy diagnostics from third-party code.
SYSTEM
)
FetchContent_MakeAvailable(Catch2)
endif()
# Add library for tests/utils.h
add_library(libutils INTERFACE)
target_include_directories(libutils INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/tests)
target_link_libraries(libutils INTERFACE
libfusilli
Catch2::Catch2WithMain
)
# Enable clang-tidy.
fusilli_enable_clang_tidy(libutils)
endif()
# Build tests and samples
if(FUSILLI_BUILD_TESTS)
message(STATUS "Building Fusilli tests and samples")
# Add tests and samples sub directories
add_subdirectory(tests)
add_subdirectory(samples)
# Activate CTest integration
enable_testing()
endif()
# Build benchmarks
if(FUSILLI_BUILD_BENCHMARKS)
message(STATUS "Building Fusilli benchmarks")
# Get CLI11 (argparse library for C++)
FetchContent_Declare(
cli11_proj
QUIET
GIT_REPOSITORY https://github.com/CLIUtils/CLI11.git
GIT_TAG v2.6.1
)
FetchContent_MakeAvailable(cli11_proj)
# Add benchmarks sub directory
add_subdirectory(benchmarks)
endif()
# Add libfusilli target to export set
install(TARGETS libfusilli
EXPORT FusilliTargets
FILE_SET fusilli_headers
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
# Create FusilliTargets.cmake in the install tree from FusilliTargets export set
install(EXPORT FusilliTargets
FILE FusilliTargets.cmake
NAMESPACE fusilli::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fusilli
)
# Create FusilliTargets.cmake in the build tree from FusilliTargets export set,
# allowing for other projects to find_package directly from the build directory
# without installing.
export(TARGETS libfusilli
FILE ${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/fusilli/FusilliTargets.cmake
NAMESPACE fusilli::
)
# Generate config file in build directory.
#
# configure_package_config_file uses INSTALL_DESTINATION to calculate relative
# paths within the generated config file. But it does NOT actually install the
# file, you must use install(FILES...) for that. INSTALL_DESTINATION must match
# the DESTINATION in the install(FILES...) command below, but CMake doesn't
# verify that for you.
#
# We're generating FusilliConfig.cmake in the build tree, so no extra work is
# needed to make it consumable via find_package directly from the build
# directory, i.e. we don't need an `export(FILE...` call.
include(CMakePackageConfigHelpers)
configure_package_config_file(
${CMAKE_CURRENT_SOURCE_DIR}/build_tools/cmake/templates/FusilliConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/fusilli/FusilliConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fusilli
)
# Write FusilliConfig.cmake file to install tree
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/fusilli/FusilliConfig.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fusilli
)