-
Notifications
You must be signed in to change notification settings - Fork 12
/
CMakeLists.txt
274 lines (224 loc) · 10.4 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
cmake_minimum_required(VERSION 3.10)
cmake_policy(VERSION 3.10)
project(QtMips
LANGUAGES C CXX
VERSION 0.8.1
DESCRIPTION "MIPS CPU simulator for education purposes")
set(KAREL_KOCI "Karel Koci <[email protected]>")
set(PAVEL_PISA "Pavel Pisa <[email protected]>")
set(JAKUB_DUPAK "Jakub Dupak <[email protected]>")
set(PROJECT_HOMEPAGE_URL "https://github.com/cvut/qtmips")
set(GENERIC_NAME "MIPS CPU simulator")
set(LICENCE "GPL-3.0-or-later")
set(LONG_DESCRIPTION
"MIPS CPU simulator for education purposes with pipeline and cache visualization.")
string(TIMESTAMP YEAR "%Y")
include(cmake/CopyrightTools.cmake)
copyright(
"Copyright (c) 2017-2019 ${KAREL_KOCI}"
"Copyright (c) 2019-${YEAR} ${PAVEL_PISA}"
"Copyright (c) 2020-${YEAR} ${JAKUB_DUPAK}")
include(cmake/GPL-3.0-or-later.cmake)
# =============================================================================
# Configurable options
# =============================================================================
set(DEV_MODE false CACHE BOOL "Enable developer options in this CMake, like packaging.\
They should be ignored, when user just wants to build this project.")
set(FORCE_ELFLIB_STATIC false CACHE BOOL
"Use included statically linked libelf even if system one is available.")
set(SANITIZERS "address,undefined" CACHE STRING
"Runtime sanitizers to use in debug builds.
Column separated subset of {address, memory, undefined, thread} or none.
Memory and address cannot be used at the same time.")
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/target"
CACHE STRING "Absolute path to place executables to.")
set(PACKAGE_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}/pkg"
CACHE STRING "Absolute path to place generated package files.")
set(FORCE_COLORED_OUTPUT false CACHE BOOL "Always produce ANSI-colored output (GNU/Clang only).")
# =============================================================================
# Generated variables
# =============================================================================
if(${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
set(WASM true)
else()
set(WASM false)
endif()
set(CXX_TEST_PATH ${EXECUTABLE_OUTPUT_PATH})
set(C_TEST_PATH ${EXECUTABLE_OUTPUT_PATH})
# I don't want to relly on the assumption, that this file is invoked as root
# project. Therefore I propagate the information to all subprojects
# MAIN_PROJECT_*. Lowercase and uppercase are used for executable names and
# C defines, respectively.
set(MAIN_PROJECT_NAME "${PROJECT_NAME}")
set(MAIN_PROJECT_VERSION "${PROJECT_VERSION}")
set(MAIN_PROJECT_ORGANIZATION "FEE CTU")
set(MAIN_PROJECT_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}")
string(TOLOWER "${PROJECT_NAME}" MAIN_PROJECT_NAME_LOWER)
string(TOUPPER "${PROJECT_NAME}" MAIN_PROJECT_NAME_UPPER)
# =============================================================================
# CMake config and tools
# =============================================================================
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
if(CMAKE_VERSION VERSION_LESS "3.7.0")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()
include(cmake/BuildType.cmake)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# =============================================================================
# Build options
# - common to all subdirs
# =============================================================================
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT "${SANITIZERS}" MATCHES "none" AND NOT "${WASM}" AND NOT "${MINGW}")
set(CMAKE_C_FLAGS_DEBUG
"${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=${SANITIZERS} -g -g3 -ggdb")
set(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=${SANITIZERS} -g -g3 -ggdb")
set(CMAKE_LINKER_FLAGS_DEBUG
"${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=${SANITIZERS}")
endif()
if("${BUILD_RELEASE}")
message(STATUS "Debug prints globally suppressed.")
add_definitions(-DQT_NO_DEBUG_OUTPUT=1)
endif()
include_directories("src" "src/machine")
if(${FORCE_COLORED_OUTPUT})
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options(-fdiagnostics-color=always)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options(-fcolor-diagnostics)
endif()
endif()
## ============================================================================
## Warning level
## ============================================================================
if(MSVC)
add_compile_options(/W4 /WX)
else()
add_compile_options(-Wall -Wextra)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# This is currently a wont-fix and it will be OK in cpp20.
add_compile_options(-Wno-c99-designator)
endif()
endif()
# =============================================================================
# Dependencies
# =============================================================================
if("${WASM}")
message(STATUS "WASM build detected")
message(STATUS "Enabled WASM exception handling")
add_compile_options("-fexceptions")
add_link_options("-fexceptions")
add_link_options("SHELL:-s DISABLE_EXCEPTION_CATCHING=0")
# Extra options for WASM linking
add_link_options("SHELL:-s FETCH=1")
add_link_options("SHELL:-s WASM=1")
add_link_options("SHELL:-s FULL_ES2=1")
add_link_options("SHELL:-s FULL_ES3=1")
add_link_options("SHELL:-s USE_WEBGL2=1")
add_link_options("SHELL:-s ALLOW_MEMORY_GROWTH=1")
add_link_options("SHELL:-s EXTRA_EXPORTED_RUNTIME_METHODS=[\"UTF16ToString\",\"stringToUTF16\"]")
add_link_options("--bind")
add_definitions(-DQT_NO_DEBUG_OUTPUT=1)
message(STATUS "Debug output disabled")
else()
# Not available for WASM
enable_testing()
if(NOT "${FORCE_ELFLIB_STATIC}")
find_package(LibElf)
if("${LibElf_FOUND}")
# Turn non-cmake library into a cmake target
add_library(libelf INTERFACE)
target_link_libraries(libelf INTERFACE ${LIBELF_LIBRARY})
target_include_directories(libelf INTERFACE ${LIBELF_INCLUDE})
message(STATUS "Using system libelf")
endif()
endif()
endif()
if("${WASM}" OR "${FORCE_ELFLIB_STATIC}" OR NOT "${LibElf_FOUND}")
message(STATUS "Using local libelf fallback.")
add_subdirectory("external/libelf")
endif()
# Detect Qt used qt version
# Based on article https://www.steinzone.de/wordpress/how-to-support-both-qt5-and-qt6-using-cmake/
# Cannot use version-less approach due to Qt 5.9.5 support constraint.
find_package(OpenGL)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
# Normally, we would use variable Qt5 or Qt6 to reference the Qt library. Here we do that through
# this variable based on detected version major of Qt.
set(QtLib "Qt${QT_VERSION_MAJOR}")
find_package(${QtLib}
REQUIRED COMPONENTS Core Widgets Gui Test
OPTIONAL_COMPONENTS PrintSupport)
message(STATUS "${QtLib} version: ${${QtLib}Core_VERSION}")
message(STATUS "${QtLib} print support: ${${QtLib}PrintSupport_FOUND}")
# Qt 5.9.5 is the oldest supported
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050905)
# =============================================================================
# Sources
# =============================================================================
add_subdirectory("src/common")
add_subdirectory("src/machine")
add_subdirectory("src/assembler")
add_subdirectory("src/os_emulation")
add_subdirectory("src/gui")
if(NOT "${WASM}")
add_subdirectory("src/cli")
add_custom_target(all_unit_tests
DEPENDS common_unit_tests machine_unit_tests)
endif()
# =============================================================================
# Installation
# =============================================================================
# Prior to CMake version 3.13, installation must be performed in the subdirectory,
# there the target was created. Therefore executable installation is to be found
# in corresponding CMakeLists.txt.
configure_file(data/gui.desktop.in
"${EXECUTABLE_OUTPUT_PATH}/${MAIN_PROJECT_NAME_LOWER}.desktop")
install(FILES "data/icons/gui.svg"
DESTINATION "share/icons/hicolor/scalable/apps"
RENAME "${MAIN_PROJECT_NAME_LOWER}_gui.svg")
install(FILES "data/icons/48x48/gui.png"
DESTINATION "share/icons/hicolor/48x48/apps"
RENAME "${MAIN_PROJECT_NAME_LOWER}_gui.png")
install(FILES "${EXECUTABLE_OUTPUT_PATH}/${MAIN_PROJECT_NAME_LOWER}.desktop"
DESTINATION share/applications)
# =============================================================================
# Packages
# =============================================================================
if("${DEV_MODE}")
# The condition prevents execution of this section during regular user installation.
# It created files useless to normal users and requires additional tools (git, xz).
message(STATUS "Packaging tools enabled.")
set(PACKAGE_NAME "${MAIN_PROJECT_NAME_LOWER}")
set(PACKAGE_VERSION "${PROJECT_VERSION}")
set(PACKAGE_RELEASE "1")
set(PACKAGE_SOURCE_ARCHIVE_FILE "${PACKAGE_NAME}_${PACKAGE_VERSION}.orig.tar.xz")
set(PACKAGE_SOURCE_ARCHIVE_PATH "${PACKAGE_OUTPUT_PATH}/${PACKAGE_SOURCE_ARCHIVE_FILE}")
set(PACKAGE_TOPLEVEL_DIR "${PACKAGE_NAME}-${PACKAGE_VERSION}")
set(PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}")
set(PACKAGE_LONG_DESCRIPTION "${LONG_DESCRIPTION}")
set(PACKAGE_MAINTAINER "${JAKUB_DUPAK}")
set(PACKAGE_URL "${PROJECT_HOMEPAGE_URL}")
set(PACKAGE_GIT "github.com:cvut/qtmips.git")
set(PACKAGE_LICENCE "${LICENCE} ")
include(cmake/PackageTools.cmake)
# Inject up-to-date information into package config files.
package_config_file(appimage appimage.yml extras/packaging/appimage/appimage.yml.in)
package_config_file(archlinux PKGBUILD extras/packaging/arch/PKGBUILD.in)
package_config_file(rpm ${PACKAGE_NAME}.spec extras/packaging/rpm/spec.in)
# Debian uses whole directory which has to be saved to archive and shipped.
package_debian_quilt(deb
${PACKAGE_NAME}_${PACKAGE_VERSION}-${PACKAGE_RELEASE}.dsc
extras/packaging/deb/dsc.in
extras/packaging/deb/debian
${PACKAGE_NAME}_${PACKAGE_VERSION}-${PACKAGE_RELEASE}.debian.tar.xz)
# Creates bunch of files in ${CMAKE_BINARY_DIR}/target/pkg that you can just pass to
# Open Build Service and it will build all packaging.
# TODO: Currently changelog is not handled automatically.
add_custom_target(open_build_service_bundle
DEPENDS ${PACKAGE_SOURCE_ARCHIVE_FILE} appimage archlinux deb rpm
WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/pkg)
endif()
configure_file(src/project_info.h.in ${CMAKE_CURRENT_LIST_DIR}/src/project_info.h @ONLY)