-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCMakeLists.txt
353 lines (290 loc) · 10.5 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
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
# Config inspired by https://github.com/krux02/minimal_cmake_example
cmake_minimum_required(VERSION 3.16)
project(vr_engine)
##################################################################
### SETTINGS ###
##################################################################
# Add settings flags here
set(settings
# Window framework: one of {WINDOW_SDL2}
WINDOW_SDL2
# Rendering framework: one of {RENDERER_VULKAN}
RENDERER_VULKAN
)
# Enable/disable sanitizers
set(enable_asan 0)
set(enable_ubsan 0)
# Enable/disable interactivity
# Setting this to 0 will add timers to ensure that no test is blocked in a loop, waiting for user input.
# Useful for CI, where the value is always overridden to 0 automatically.
set(interactive 1)
# Define C and C++ versions
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 20)
# Shaders location
set(shaders_directory "${PROJECT_SOURCE_DIR}/tests/resources/shaders")
set(spirv_directory "${CMAKE_BINARY_DIR}/tests/resources/shaders")
# Enable tests
enable_testing()
# Set unused parameters as warnings instead of errors
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wno-error=unused-parameter)
endif ()
##################################################################
### SOURCES ###
##################################################################
# Add source files for main lib
set(vr_engine_lib_sources
src/core/engine.cpp
src/core/vr/vr_system.cpp
src/core/global.cpp
src/core/renderer/vr_renderer_vulkan.cpp
src/core/window/window_sdl2.cpp
src/utils/global_utils.cpp
src/utils/openxr_utils.cpp
src/core/renderer/scene_vulkan.cpp
src/utils/shared_pointer.cpp
src/utils/data/hash_map.cpp
src/utils/io.cpp
src/utils/vulkan_utils.cpp
)
# Add header directories for main lib
set(vr_engine_lib_header_dir
include
)
# Test resources
set(test_resources
)
##################################################################
### APPLY SETTINGS ###
##################################################################
# Don't change this directly
# Debug vs Release
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_definitions(
DEBUG
USE_OPENXR_VALIDATION_LAYERS
)
elseif (CMAKE_BUILD_TYPE STREQUAL "Release")
add_compile_definitions(
NDEBUG
)
endif ()
# Add dependencies flags
foreach (flag ${settings})
add_compile_definitions(${flag})
set(${flag} "true")
endforeach ()
# Vulkan specific
if (DEFINED RENDERER_VULKAN)
add_compile_definitions(
VK_NO_PROTOTYPES
XR_USE_GRAPHICS_API_VULKAN
)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_definitions(
USE_VK_VALIDATION_LAYERS
)
endif ()
endif ()
# SDL2 specific
if (DEFINED WINDOW_SDL2)
add_compile_definitions(
SDL_MAIN_HANDLED
)
endif ()
# On a CI, override the value of interactive with 0
# We know that we are on a CI if the CI environment variable is set
if (DEFINED ENV{CI})
message(STATUS "Continuous integration detected, disabling interactive mode")
set(interactive 0)
# Also disable sanitizers
set(enable_asan 0)
set(enable_ubsan 0)
endif ()
if (${CMAKE_C_COMPILER_ID} STREQUAL "MSVC")
set(is_msvc 1)
else ()
set(is_msvc 0)
endif ()
if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU" AND WIN32)
set(is_mingw 1)
else ()
set(is_mingw 0)
endif ()
# Enable sanitizers if variable is 1
if (${enable_asan} STREQUAL "1" AND NOT ${is_mingw})
message(STATUS "Enabling address sanitizer")
# MSVC syntax is a bit different
if (${is_msvc})
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")
else ()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
endif ()
endif ()
if (${enable_ubsan} STREQUAL "1" AND NOT ${is_msvc} AND NOT ${is_mingw})
message(STATUS "Enabling undefined behavior sanitizer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
endif ()
# Enable or not interactivity
if (${interactive} STREQUAL "1")
add_compile_definitions(
INTERACTIVE
)
else ()
add_compile_definitions(
NO_INTERACTIVE
)
endif ()
# Get all files in include so that they appear in IDEs
file(GLOB_RECURSE vr_engine_lib_headers
"include/*.h"
"include/*.hpp"
)
##################################################################
### CREATE LIB ###
##################################################################
# Create main lib
add_library(vr_engine_lib STATIC ${vr_engine_lib_sources} ${vr_engine_lib_headers})
target_sources(vr_engine_lib PRIVATE ${vr_engine_lib_sources})
target_include_directories(vr_engine_lib PUBLIC ${vr_engine_lib_header_dir})
##################################################################
### DEPENDENCIES ###
##################################################################
# Find Vulkan if needed
if (DEFINED RENDERER_VULKAN)
find_package(Vulkan REQUIRED)
endif ()
# Load external script
add_subdirectory(external)
# Link dependencies
if (${interactive} STREQUAL "0")
# Link pthread on linux
if (UNIX)
target_link_libraries(vr_engine_lib PUBLIC pthread)
endif ()
endif ()
if (DEFINED RENDERER_VULKAN)
target_link_libraries(vr_engine_lib PUBLIC
Vulkan::Vulkan
volk
vma
)
endif ()
if (DEFINED WINDOW_SDL2)
target_link_libraries(vr_engine_lib PUBLIC
sdl2
)
endif ()
target_link_libraries(vr_engine_lib PUBLIC
openxr
)
##################################################################
### TESTING ###
##################################################################
# Macro inspired by https://bertvandenbroucke.netlify.app/2019/12/12/unit-testing-with-ctest/
# Add a new unit test
# A new target with the test sources is constructed, and a CTest test with the
# same name is created. The new test is also added to the global list of test
# contained in the check target
macro(add_unit_test)
# Define macro arguments
set(options PARALLEL)
set(oneValueArgs FILE)
cmake_parse_arguments(TEST "${options}" "${oneValueArgs}" "" ${ARGN})
# Remove extension of TEST_FILE.
set(TEST_NAME ${TEST_FILE})
string(REGEX REPLACE ".cpp$" "" TEST_NAME ${TEST_NAME})
# Also replace \ by /
string(REGEX REPLACE "/" "-" TEST_NAME ${TEST_NAME})
# Compile test
message(STATUS "Generating test \"${TEST_NAME}\"")
add_executable(${TEST_NAME} EXCLUDE_FROM_ALL tests/${TEST_FILE})
target_sources(${TEST_NAME} PRIVATE tests/${TEST_FILE})
# Set directory for executable
set_target_properties(${TEST_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests"
COMPILE_DEFINITIONS UNIT_TESTS
)
# Link project lib and testing framework
target_link_libraries(${TEST_NAME} vr_engine_lib testing_framework)
# Register test
add_test(NAME ${TEST_NAME}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/tests
COMMAND ${TEST_NAME})
# Add test to list
set(TEST_NAMES ${TEST_NAMES} ${TEST_NAME})
set_tests_properties(${TEST_NAME} PROPERTIES
ENVIRONMENT "TEST_FILE=tests/${TEST_FILE};TEST_LINE=0"
)
endmacro(add_unit_test)
# Get all c++ files in the tests directory, recursively
file(GLOB_RECURSE test_files
"tests/*.cpp"
)
# For each one, add it
foreach (test_file ${test_files})
# Get local path (remove prefix project source)
string(REGEX REPLACE "^${PROJECT_SOURCE_DIR}/tests/" "" test_file ${test_file})
add_unit_test(FILE ${test_file})
endforeach (test_file)
# Save target
add_custom_target(
tests
DEPENDS ${TEST_NAMES}
)
# Copy test resources
foreach (test_resource ${test_resources})
# Get local path (remove prefix project source)
get_filename_component(file_path ${test_resource} PATH)
file(COPY ${test_resource} DESTINATION ${PROJECT_BINARY_DIR}/${file_path})
endforeach ()
##################################################################
### SHADER COMPILATION ###
##################################################################
# Shaders need to be compiled if the rendering engine is Vulkan
if (DEFINED RENDERER_VULKAN)
# Get compiler
find_program(glsl_validator glslangValidator HINTS
/usr/bin
/usr/local/bin
$ENV{VULKAN_SDK}/Bin/
$ENV{VULKAN_SDK}/Bin32/
${PROJECT_SOURCE_DIR}/glslangValidator/bin/ # For GitHub Actions
)
# Error if not found
if (glsl_validator STREQUAL "")
message(FATAL_ERROR "Could not find glslangValidator")
else ()
message(STATUS "Using glslangValidator: ${glsl_validator}")
endif ()
# Find shader files
file(GLOB_RECURSE glsl_source_files
"${shaders_directory}/*.frag"
"${shaders_directory}/*.vert"
"${shaders_directory}/*.comp"
)
# Iterate each shader
foreach (glsl ${glsl_source_files})
get_filename_component(file_name ${glsl} NAME)
# Get relative path of shader in shaders directory
# Then place the spv file at the same location relatively
get_filename_component(file_path ${glsl} PATH)
string(REGEX REPLACE "^${shaders_directory}/" "" file_path ${file_path})
message(STATUS "Registering shader \"${file_path}/${file_name}\"")
set(spirv "${spirv_directory}/${file_path}/${file_name}.spv")
# Execute glslang command to compile that specific shader
add_custom_command(
OUTPUT ${spirv}
COMMAND ${CMAKE_COMMAND} -E make_directory "${spirv_directory}/${file_path}"
COMMAND ${glsl_validator} -V ${glsl} -o ${spirv}
DEPENDS ${glsl})
list(APPEND spirv_binary_files ${spirv})
endforeach (glsl)
# Link it to the main lib
add_custom_target(shaders DEPENDS ${spirv_binary_files})
add_dependencies(vr_engine_lib shaders)
endif ()