forked from jorio/CandyCrisis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
280 lines (227 loc) · 10.8 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
if(APPLE OR WIN32)
cmake_minimum_required(VERSION 3.21)
else()
# Oldest supported Ubuntu is 20.04, which ships with cmake 3.16.
# When we can stop supporting Ubuntu 20.04, bump to CMake 3.21.
cmake_minimum_required(VERSION 3.16)
endif()
if(APPLE OR WIN32)
set(GAME_TARGET "CandyCrisis")
else()
set(GAME_TARGET "candycrisis")
endif()
set(GAME_FRIENDLY_NAME "Candy Crisis")
set(GAME_BUNDLE_ID "io.jor.candycrisis")
set(GAME_DATA_DIR "CandyCrisisResources")
set(GAME_MAC_COPYRIGHT "https://github.com/jorio/CandyCrisis")
# Apply macOS deployment target and architectures to all subprojects
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11" CACHE STRING "Minimum macOS deployment version")
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "Target macOS architectures")
if (${CMAKE_VERSION} VERSION_LESS "3.21")
set(CMAKE_C_STANDARD 11)
else()
set(CMAKE_C_STANDARD 17)
endif()
project(${GAME_TARGET} LANGUAGES C
VERSION 3.0.1)
# Create an option to switch between a system sdl library and a vendored sdl library
option(BUILD_SDL_FROM_SOURCE "Build SDL from source" OFF)
option(STATIC_SDL "Static link SDL" OFF)
option(SANITIZE "Build with asan/ubsan" OFF)
set(CODE_SIGN_IDENTITY "" CACHE STRING "macOS code signing identity. If omitted, the app won't be signed.")
if(NOT WIN32 AND NOT APPLE)
if(SANITIZE)
message("Sanitizers enabled")
else()
message("Sanitizers disabled (pass -DSANITIZE=1 to enable)")
endif()
endif()
# Set Visual Studio startup project
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${GAME_TARGET})
set(GAME_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
#------------------------------------------------------------------------------
# FIND SDL
#------------------------------------------------------------------------------
# If SDL2_DIR wasn't specified, discover if the user put some prebuilt SDL2 package in the project's root directory
if(NOT DEFINED SDL2_DIR)
if(APPLE)
set(_sdl2_maybe "${CMAKE_SOURCE_DIR}/SDL2.framework/Resources/CMake")
elseif(WIN32)
set(_sdl2_maybe "${CMAKE_SOURCE_DIR}/SDL2/cmake")
endif()
if(DEFINED _sdl2_maybe AND EXISTS "${_sdl2_maybe}")
set(SDL2_DIR "${_sdl2_maybe}")
else()
message("Couldn't find prebuilt SDL2 package in: ${_sdl2_maybe}")
endif()
unset(_sdl2_maybe)
endif()
if(NOT BUILD_SDL_FROM_SOURCE)
# 1. Look for an SDL2 package, 2. look for the SDL2 component and 3. fail if none can be found
find_package(SDL2 CONFIG REQUIRED COMPONENTS SDL2)
# 1. Look for an SDL2 package, 2. Look for the SDL2maincomponent and 3. DO NOT fail when SDL2main is not available
find_package(SDL2 REQUIRED CONFIG COMPONENTS SDL2main)
message("Found pre-built SDL: " ${SDL2_PREFIX})
else()
if(NOT DEFINED SDL2_DIR)
set(SDL2_DIR "${CMAKE_SOURCE_DIR}/SDL")
endif()
message("Building SDL from source: " ${SDL2_DIR})
add_subdirectory("${SDL2_DIR}" EXCLUDE_FROM_ALL)
endif()
#------------------------------------------------------------------------------
# GENERATED FILES
#------------------------------------------------------------------------------
# Write header file containing version info
configure_file(${GAME_SOURCE_DIR}/version.h.in ${GAME_SOURCE_DIR}/version.h)
# Readme file containing version info
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packaging/ReadMe.txt.in ${CMAKE_CURRENT_BINARY_DIR}/ReadMe.txt)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packaging/version.txt.in ${CMAKE_CURRENT_BINARY_DIR}/version.txt)
#------------------------------------------------------------------------------
# EXECUTABLE TARGET
#------------------------------------------------------------------------------
file(GLOB_RECURSE GAME_SOURCES CONFIGURE_DEPENDS ${GAME_SOURCE_DIR}/*.c ${GAME_SOURCE_DIR}/*.h)
if(WIN32)
list(APPEND GAME_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/app.exe.rc)
elseif(APPLE)
list(APPEND GAME_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/app.icns)
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/packaging/app.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
endif()
# Executable
add_executable(${GAME_TARGET} ${GAME_SOURCES})
target_include_directories(${GAME_TARGET} PRIVATE ${GAME_SOURCE_DIR})
# Create macOS app bundle with friendly name
if(APPLE)
set_target_properties(${GAME_TARGET} PROPERTIES OUTPUT_NAME "${GAME_FRIENDLY_NAME}")
endif()
set_target_properties(${GAME_TARGET} PROPERTIES
#--------------------------------------------------------------------------
# MSVC/WIN32
#--------------------------------------------------------------------------
WIN32_EXECUTABLE TRUE # GUI application instead of console application
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
VS_DPI_AWARE "PerMonitor"
#--------------------------------------------------------------------------
# APPLE
#--------------------------------------------------------------------------
# Build it as an .app bundle
MACOSX_BUNDLE TRUE
# Set up Info.plist values
MACOSX_BUNDLE_ICON_FILE "app.icns" # CFBundleIconFile
MACOSX_BUNDLE_EXECUTABLE_NAME "${GAME_TARGET}" # CFBundleExecutable - executable name inside the bundle
MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}" # CFBundleShortVersionString
MACOSX_BUNDLE_COPYRIGHT "${GAME_MAC_COPYRIGHT}" # NSHumanReadableCopyright (supersedes CFBundleGetInfoString (MACOSX_BUNDLE_INFO_STRING))
MACOSX_BUNDLE_BUNDLE_NAME "${GAME_FRIENDLY_NAME}" # CFBundleName - user-visible short name for the bundle
MACOSX_BUNDLE_GUI_IDENTIFIER "${GAME_BUNDLE_ID}" # CFBundleIdentifier - unique bundle ID in reverse-DNS format
# Set framework search path to (App bundle)/Contents/Frameworks so the game can use its embedded SDL2.framework
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks"
# If CODE_SIGN_IDENTITY is NOT empty: tell Xcode to codesign the app properly
# Otherwise, if it's empty: explicitly turn off code signing, otherwise downloaded app will be quarantined forever
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${CODE_SIGN_IDENTITY}"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "" # don't bother signing debug build
# Bundle ID required for code signing - must match CFBundleIdentifier otherwise xcode will complain
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER ${GAME_BUNDLE_ID}
# Don't bother with universal builds when we're working on the debug version
XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[variant=Debug] "YES"
XCODE_EMBED_FRAMEWORKS "${SDL2_FRAMEWORK_PATH}"
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY "YES" # frameworks must be signed by the same developer as the binary
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY "YES" # not strictly necessary, but that's cleaner
XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Debug] "NO" # avoid "skipping copy phase strip" warning while working on Debug config
# The following is to pass notarization requirements
XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES"
XCODE_ATTRIBUTE_CODE_SIGN_INJECT_BASE_ENTITLEMENTS "NO"
XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--options=runtime --timestamp"
)
#------------------------------------------------------------------------------
# COMPILER/LINKER OPTIONS
#------------------------------------------------------------------------------
add_compile_definitions(
"$<$<CONFIG:DEBUG>:_DEBUG>"
)
if(NOT MSVC)
target_compile_options(${GAME_TARGET} PRIVATE
-Wall
-Wextra
#-Wshadow # Note: Candy Crisis goes crazy with shadowing
-Werror=return-type
-Wstrict-aliasing=2
-Wno-multichar
)
# Sanitizers in debug mode (Linux only)
# When using a debugger, you should export LSAN_OPTIONS=detect_leaks=0
if(SANITIZE)
list(INSERT GAME_LIBRARIES 0 asan ubsan)
target_compile_options(${GAME_TARGET} PRIVATE
-fsanitize=alignment
-fsanitize=address
-fsanitize=leak
-fsanitize=undefined
-fno-omit-frame-pointer
)
endif()
else()
# On Win32, we need NOGDI and NOUSER to be able to define some Mac functions
# whose names are otherwise taken by Windows APIs.
target_compile_definitions(${GAME_TARGET} PRIVATE
WIN32_LEAN_AND_MEAN
_CRT_SECURE_NO_WARNINGS # quit whining about snprintf_s
)
target_compile_options(${GAME_TARGET} PRIVATE
/W4
/wd5105 # see https://developercommunity.visualstudio.com/t/1249671
/we4013 # treat warning as error: undefined function (assuming extern returning int)
/MP # multiprocessor build
/Zi # output info to PDB
)
# Let executable be debugged with PDB, even in Release builds
target_link_options(${GAME_TARGET} PRIVATE /DEBUG)
# Enable console for debug builds
set_target_properties(${GAME_TARGET} PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
set_target_properties(${GAME_TARGET} PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE")
endif()
#------------------------------------------------------------------------------
# LINK LIBRARIES
#------------------------------------------------------------------------------
# Explicitly link math lib on Linux
if(NOT APPLE AND NOT WIN32)
target_link_libraries(${GAME_TARGET} PRIVATE m)
endif()
# SDL2::SDL2main may or may not be available. It is e.g. required by Windows GUI applications
if(TARGET SDL2::SDL2main)
# It has an implicit dependency on SDL2 functions, so it MUST be added before SDL2::SDL2 (or SDL2::SDL2-static)
target_link_libraries(${GAME_TARGET} PRIVATE SDL2::SDL2main)
endif()
if(NOT STATIC_SDL)
target_link_libraries(${GAME_TARGET} PRIVATE SDL2::SDL2)
else()
target_link_libraries(${GAME_TARGET} PRIVATE SDL2::SDL2-static)
endif()
#------------------------------------------------------------------------------
# COPY ASSETS
#------------------------------------------------------------------------------
if(APPLE)
set(GAME_DATA_TARGET_LOCATION "$<TARGET_FILE_DIR:${GAME_TARGET}>/../Resources")
else()
set(GAME_DATA_TARGET_LOCATION "$<TARGET_FILE_DIR:${GAME_TARGET}>/${GAME_DATA_DIR}")
endif()
add_custom_command(TARGET ${GAME_TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/${GAME_DATA_DIR}" "${GAME_DATA_TARGET_LOCATION}")
# Copy SDL2 DLL for convenience (WARNING: TARGET_RUNTIME_DLLS requires CMake 3.21, so this copy command was separated from the command above.)
if(WIN32)
add_custom_command(TARGET ${GAME_TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:${GAME_TARGET}> $<TARGET_FILE_DIR:${GAME_TARGET}>)
endif()
#------------------------------------------------------------------------------
# INSTALL
#------------------------------------------------------------------------------
# Install Windows-specific libraries (cmake --install): copy Visual Studio redistributable DLLs to install location
if(WIN32)
include(InstallRequiredSystemLibraries)
elseif(APPLE)
# no-op
else()
install(TARGETS ${GAME_TARGET} DESTINATION bin)
install(FILES ${CMAKE_SOURCE_DIR}/packaging/${GAME_TARGET}.desktop DESTINATION share/applications/)
install(FILES ${CMAKE_SOURCE_DIR}/packaging/${GAME_TARGET}.png DESTINATION share/icons/hicolor/128x128/apps/)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/${GAME_DATA_DIR}/ DESTINATION share/${GAME_TARGET}/)
endif()