-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathmo2_cpp.cmake
More file actions
348 lines (287 loc) · 10.4 KB
/
mo2_cpp.cmake
File metadata and controls
348 lines (287 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
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
cmake_minimum_required(VERSION 3.21)
include(CMakeParseArguments)
include(${CMAKE_CURRENT_LIST_DIR}/mo2_utils.cmake)
#! mo2_configure_warnings : configuration warning for C++ target
#
# \param:WARNINGS level of warnings, possible values are ON/All, OFF, or 1, 2, 3, 4
# for corresponding /W flags (ON is All) (default ON)
# \param:EXTERNAL enable warnings for external libraries, possible values are
# the same as warnings, but ON is 3 (default 1)
#
function(mo2_configure_warnings TARGET)
cmake_parse_arguments(MO2 "" "WARNINGS;EXTERNAL" "" ${ARGN})
mo2_set_if_not_defined(MO2_WARNINGS ON)
mo2_set_if_not_defined(MO2_EXTERNAL 1)
if (${MO2_WARNINGS} STREQUAL "ON")
set(MO2_WARNINGS "All")
endif()
if (${MO2_EXTERNAL} STREQUAL "ON")
set(MO2_EXTERNAL "3")
endif()
if(NOT (${MO2_WARNINGS} STREQUAL "OFF"))
string(TOLOWER ${MO2_WARNINGS} MO2_WARNINGS)
target_compile_options(${TARGET} PRIVATE "/W${MO2_WARNINGS}" "/wd4464")
# external warnings
if (${MO2_EXTERNAL} STREQUAL "OFF")
target_compile_options(${TARGET}
PRIVATE "/external:anglebrackets" "/external:W0")
else()
string(TOLOWER ${MO2_EXTERNAL} MO2_EXTERNAL)
target_compile_options(${TARGET}
PRIVATE "/external:anglebrackets" "/external:W${MO2_EXTERNAL}")
endif()
endif()
endfunction()
#! mo2_target_sources : add sources to a given target, eventually putting them in
# a folder
#
# \param: FILES list of .ui files to add
# \param: RC_FILES list of .qrc or .rc files to add
#
function(mo2_target_sources TARGET)
cmake_parse_arguments(MO2 "" "FOLDER" "PRIVATE;PUBLIC" ${ARGN})
mo2_set_if_not_defined(MO2_PRIVATE "")
mo2_set_if_not_defined(MO2_PUBLIC "")
set(_sources "")
if (MO2_PRIVATE)
target_sources(${TARGET} PRIVATE ${MO2_PRIVATE})
list(APPEND _sources ${MO2_PRIVATE})
endif()
if (MO2_PUBLIC)
target_sources(${TARGET} PUBLIC ${MO2_PUBLIC})
list(APPEND _sources ${MO2_PUBLIC})
endif()
if ((DEFINED MO2_FOLDER) AND _sources)
source_group(${MO2_FOLDER} FILES ${_sources})
endif()
endfunction()
#! mo2_default_source_group : configure default source groups for MO2
#
# \param:NO_SRC if set, the src source_group will not be created, default if false
#
function(mo2_default_source_group)
cmake_parse_arguments(MO2 "SOURCE_TREE" "" "" ${ARGN})
# remove the CMake Rules autogenerated folder
source_group("CMake Rules" REGULAR_EXPRESSION "^$")
source_group(ui REGULAR_EXPRESSION ".*\\.ui")
source_group(cmake FILES CMakeLists.txt)
source_group(autogen REGULAR_EXPRESSION ".*\\cmake_pch.*|.*\\.rule")
source_group(resources REGULAR_EXPRESSION ".*\\.qrc|.*\\.rc")
if (NOT NO_SRC)
source_group(src REGULAR_EXPRESSION ".*\\.(h|cpp)$")
endif()
endfunction()
#! mo2_configure_sources : configure sources for the given C++ target
#
# \param:SOURCE_TREE if set, a source_group will be created using TREE
#
function(mo2_configure_sources TARGET)
cmake_parse_arguments(MO2 "SOURCE_TREE" "" "" ${ARGN})
# find source files
if(DEFINED AUTOGEN_BUILD_DIR)
set(UI_HEADERS_DIR ${AUTOGEN_BUILD_DIR})
else()
set(UI_HEADERS_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_autogen/include_RelWithDebInfo)
endif()
file(GLOB_RECURSE source_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE header_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
file(GLOB_RECURSE qrc_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.qrc)
file(GLOB_RECURSE rc_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.rc)
file(GLOB_RECURSE ui_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.ui)
file(GLOB_RECURSE ui_header_files CONFIGURE_DEPENDS ${UI_HEADERS_DIR}/*.h)
file(GLOB_RECURSE rule_files CONFIGURE_DEPENDS ${CMAKE_BINARY_DIR}/*.rule)
if (${MO2_SOURCE_TREE})
mo2_default_source_group(NO_SRC)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}
PREFIX src FILES ${source_files} ${header_files})
else()
mo2_default_source_group()
endif()
target_sources(${TARGET}
PRIVATE
${source_files}
${header_files}
${ui_files}
${ui_header_files}
${qrc_files}
${rc_files}
${misc_files}
${qm_files})
endfunction()
#! mo2_configure_msvc : set flags for C++ target with MSVC
#
# \param:PERMISSIVE permissive mode (default OFF)
# \param:BIGOBJ enable bigobj (default OFF)
# \param:CLI enable C++/CLR (default OFF)
#
function(mo2_configure_msvc TARGET)
if (NOT MSVC)
return()
endif()
cmake_parse_arguments(MO2 "" "PERMISSIVE;BIGOBJ;CLI" "" ${ARGN})
set(CXX_STANDARD 23)
if (${MO2_CLI})
set(CXX_STANDARD 17)
endif()
set_target_properties(${TARGET} PROPERTIES
CXX_STANDARD ${CXX_STANDARD} CXX_EXTENSIONS OFF)
if(NOT ${MO2_PERMISSIVE})
target_compile_options(${TARGET} PRIVATE "/permissive-")
endif()
if(${MO2_BIGOBJ})
target_compile_options(${TARGET} PRIVATE "/bigobj")
endif()
# multi-threaded compilation
target_compile_options(${TARGET} PRIVATE "/MP")
# VS emits a warning for LTCG, at least for uibase, so maybe not required?
target_link_options(${TARGET}
PRIVATE
$<$<CONFIG:RelWithDebInfo>:
# enable link-time code generation
/LTCG
# disable incremental linking
/INCREMENTAL:NO
# eliminates functions and data that are never referenced
/OPT:REF
# perform identical COMDAT folding
/OPT:ICF
>)
if(${MO2_CLI})
set_target_properties(${TARGET} PROPERTIES COMMON_LANGUAGE_RUNTIME "")
endif()
get_property(CURRENT_STARTUP_PROJECT
DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT)
if (NOT CURRENT_STARTUP_PROJECT)
message(STATUS "MO2: Setting startup project to " ${TARGET} ".")
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${TARGET})
endif()
endfunction()
#! mo2_configure_target : do basic configuration for a MO2 C++ target
#
# this functions does many things:
# - glob relevant files and add them to the target
# - set many compile flags, definitions, etc.
# - add step to create translations (if not turned OFF)
#
# \param:SOURCE_TREE if set, a source_group will be created using TREE
# \param:NO_SOURCES if set, mo2_configure_sources will not be called
# \param:WARNINGS enable all warnings, possible values are ON/All, OFF, or 1, 2, 3, 4
# for corresponding /W flags (ON is All) (default ON)
# \param:EXTERNAL_WARNINGS enable warnings for external libraries, possible values are
# the same as warnings, but ON is 3 (default 1)
# \param:PERMISSIVE permissive mode (default OFF)
# \param:BIGOBJ enable bigobj (default OFF)
# \param:CLI enable C++/CLR (default OFF)
# \param:TRANSLATIONS generate translations (default ON)
# \param:AUTOMOC automoc (and autouic, autoqrc), (default ON)
# \param:EXTRA_TRANSLATIONS extra translations to include (folder)
#
function(mo2_configure_target TARGET)
cmake_parse_arguments(MO2 "SOURCE_TREE;NO_SOURCES"
"WARNINGS;EXTERNAL_WARNINGS;PERMISSIVE;BIGOBJ;CLI;TRANSLATIONS;AUTOMOC"
"EXTRA_TRANSLATIONS"
${ARGN})
# configure parameters and compiler flags
mo2_set_if_not_defined(MO2_NO_SOURCES OFF)
mo2_set_if_not_defined(MO2_PERMISSIVE OFF)
mo2_set_if_not_defined(MO2_BIGOBJ OFF)
mo2_set_if_not_defined(MO2_CLI OFF)
mo2_set_if_not_defined(MO2_TRANSLATIONS ON)
mo2_set_if_not_defined(MO2_AUTOMOC ON)
mo2_set_if_not_defined(MO2_EXTRA_TRANSLATIONS "")
mo2_configure_warnings(${TARGET} ${ARGN})
mo2_configure_msvc(${TARGET} ${ARGN})
if (NOT MO2_NO_SOURCES)
mo2_configure_sources(${TARGET} ${ARGN})
endif()
if (${MO2_AUTOMOC})
find_package(Qt6 COMPONENTS Widgets REQUIRED)
set_target_properties(${TARGET}
PROPERTIES AUTOMOC ON AUTOUIC ON AUTORCC ON)
endif()
if(${MO2_TRANSLATIONS})
mo2_add_translations(${TARGET}
INSTALL_RELEASE
SOURCES ${CMAKE_CURRENT_SOURCE_DIR} ${MO2_EXTRA_TRANSLATIONS})
endif()
mo2_find_git_hash(GIT_COMMIT_HASH)
target_compile_definitions(
${TARGET} PRIVATE NOMINMAX QT_MESSAGELOGCONTEXT GITID="${GIT_COMMIT_HASH}")
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/pch.h)
target_precompile_headers(${PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/pch.h)
endif()
endfunction()
#! mo2_configure_tests : configure a target as a MO2 C++ tests
#
# this function creates a set of tests available in the ${TARGET}_gtests variable
#
# extra arguments are given to mo2_configure_target, TRANSLATIONS and AUTOMOC are
# OFF by default
#
function(mo2_configure_tests TARGET)
cmake_parse_arguments(MO2 "NO_MOCK;NO_MAIN" "" "" ${ARGN})
mo2_configure_target(${TARGET} TRANSLATIONS OFF AUTOMOC OFF ${MO2_UNPARSED_ARGUMENTS})
find_package(GTest REQUIRED)
target_link_libraries(${TARGET} PRIVATE GTest::gtest)
if (NOT MO2_NO_MOCK)
target_link_libraries(${TARGET} PRIVATE GTest::gmock)
endif()
if (NOT MO2_NO_MAIN)
target_link_libraries(${TARGET} PRIVATE GTest::gtest_main)
endif()
# gtest_discover_tests would be nice but it requires Qt DLL, uibase, etc., in the
# path, etc., and is not working right now
#
# there is an open CMake issue: https://gitlab.kitware.com/cmake/cmake/-/issues/21453
#
# gtest_discover_tests(${TARGET}
# WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin
# PROPERTIES
# VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin
# )
#
gtest_add_tests(
TARGET ${TARGET}
TEST_LIST ${TARGET}_gtests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set(${TARGET}_gtests ${${TARGET}_gtests} PARENT_SCOPE)
mo2_deploy_qt_for_tests(
TARGET ${TARGET}
BINARIES "$<FILTER:$<TARGET_RUNTIME_DLLS:${TARGET}>,EXCLUDE,^.*[/\\]Qt[^/\\]*[.]dll>")
set_tests_properties(${${TARGET}_gtests}
PROPERTIES
ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<JOIN:$<TARGET_RUNTIME_DLL_DIRS:${TARGET}>,\;>"
)
endfunction()
#! mo2_configure_plugin : configure a target as a MO2 C++ plugin
#
# this function automatically set uibase as a dependency
#
# extra arguments are given to mo2_configure_target
#
function(mo2_configure_plugin TARGET)
mo2_configure_target(${TARGET} ${ARGN})
mo2_set_project_to_run_from_install(
${TARGET} EXECUTABLE ${CMAKE_INSTALL_PREFIX}/${MO2_INSTALL_BIN}/ModOrganizer.exe)
endfunction()
#! mo2_install_plugin : install the given MO2 plugin
#
# for this to work properly, the target must have been configured
#
# \param:FOLDER install the plugin as a folder, instead of a single DLL
#
function(mo2_install_plugin TARGET)
cmake_parse_arguments(MO2 "FOLDER" "" "" ${ARGN})
if (${MO2_FOLDER})
install(TARGETS ${TARGET} RUNTIME DESTINATION ${MO2_INSTALL_BIN}/plugins/$<TARGET_FILE_BASE_NAME:${TARGET}>)
else()
install(TARGETS ${TARGET} RUNTIME DESTINATION ${MO2_INSTALL_BIN}/plugins)
endif()
if (NOT MO2_INSTALL_IS_BIN)
install(TARGETS ${TARGET} ARCHIVE DESTINATION lib)
# install PDB if possible
install(FILES $<TARGET_PDB_FILE:${TARGET}> DESTINATION pdb OPTIONAL)
endif()
endfunction()