-
Notifications
You must be signed in to change notification settings - Fork 6
/
CMakeLists.txt
1312 lines (1184 loc) · 72.3 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
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
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#----------------------------------------------------------------------------------------------------------------------
# CMakeLists.txt is part of Brewken, and is copyright the following authors 2009-2024:
# • Chris Pavetto <[email protected]>
# • Dan Cavanagh <[email protected]>
# • Daniel Moreno <[email protected]>
# • Daniel Pettersson <[email protected]>
# • Kregg Kemper <[email protected]>
# • Matt Young <[email protected]>
# • Maxime Lavigne (malavv) <[email protected]>
# • Mik Firestone <[email protected]>
# • Philip Greggory Lee <[email protected]>
# • Robby Workman <[email protected]>
# • Théophane Martin <[email protected]>
#
# Brewken is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# Brewken is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#----------------------------------------------------------------------------------------------------------------------
# ⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
# NB: Meson and the `bt` build tool Python script are now the primary way of building and packaging the software. You
# can also still CMake to compile the product and install it locally, but we no longer support using CMake to do
# packaging. (Over time the intention is to remove packaging-specific code from this script, not least as it does
# not work properly on Mac and Windows.)
# ⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
#
# Creates a Makefile in the build directory, from where you can do builds and installs.
#
# NOTE: cmake . -DCMAKE_INSTALL_PREFIX=/tmp/blah && make DESTDIR=/foo
# will install to /foo/tmp/blah.
#
# See also - src/CMakeLists.txt
#
# Standard make targets:
# * make - Regenerate the makefile if necessary and compile the source code. (On Linux, also
# converts the markdown list of changes (CHANGES.markdown) to Debian package format
# changelog.)
#
# NB: Other make targets will NOT regenerate the makefile from this CMakeLists.txt file.
# That means that, if you make a change that affects "make package" or "make clean" etc,
# you must run "make" before you run "make package" or "make clean" etc, otherwise your
# change will not be picked up. (If necessary, you can interrupt the build that "make"
# kicks off, as, by that point, the makefile will be updated.)
#
# * make clean - Delete compiled objects so next build starts from scratch
# * sudo make install - Install locally
# * make test - Run unit tests via CTest
#
# Custom make targets:
# * make source_doc - Makes Doxygen HTML documentation of the source in doc/html
# * make install-data
# * make install-runtime
#
# CMake options
# * CMAKE_INSTALL_PREFIX - /usr/local by default. Set this to /usr on Debian-based systems like Ubuntu.
# * DO_RELEASE_BUILD - OFF by default. If ON, will do a release build. Otherwise, debug build.
# * NO_MESSING_WITH_FLAGS - OFF by default. ON means do not add any build flags whatsoever. May override other options.
# NOTE: You need to run CMake to change the options (you can't change them just by running make, not even by running
# make clean. Eg, in the build directory, run the following to switch to debug builds:
# cmake -DDO_RELEASE_BUILD=OFF ..
#
# Uncomment the next "set" line for slightly verbose build output
# Alternatively, for very verbose output, invoke make as follows:
#
# make VERBOSE=1
#
# On Windows, you need:
#
# cmake --build . --verbose
#
#set(CMAKE_VERBOSE_MAKEFILE ON)
#=======================================================================================================================
#================================================= CMake Configuration =================================================
#=======================================================================================================================
cmake_minimum_required(VERSION 3.16)
cmake_policy(VERSION 3.16)
# Ensure we are using modern behaviour of the project command (introduced in CMake 3.0) which enables setting version
# numbers via it (rather than manually setting individual major/minor/patch vars).
cmake_policy(SET CMP0048 NEW)
# Compatibility settings used with modern CMAKE (>= 3.29) used to pull BoostConfig.cmake from upstream
# -> FindBoost cmake module was removed in recent versions.
# See https://cmake.org/cmake/help/latest/module/FindBoost.html
if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} VERSION_GREATER_EQUAL 3.29)
cmake_policy(SET CMP0167 NEW)
endif()
#=======================================================================================================================
#================================================ Other preliminaries =================================================
#=======================================================================================================================
# Set the target binary architecture for targets on macOS
if(APPLE AND NOT CMAKE_OSX_ARCHITECTURES)
# Per https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_ARCHITECTURES.html, "the value of this variable should
# be set prior to the first project() or enable_language() command invocation because it may influence configuration
# of the toolchain and flags".
set(CMAKE_OSX_ARCHITECTURES x86_64, arm64) # Build both x86_64 and arm64 for Apple silicon.
#set(CMAKE_OSX_ARCHITECTURES i386 x86_64) # Build intel binary.
#set(CMAKE_OSX_ARCHITECTURES ppc i386 ppc64 x86_64) # Build universal binary.
endif()
#=======================================================================================================================
#============================================== Project name and Version ===============================================
#=======================================================================================================================
# It's simplest to keep the project name all lower-case as it means we can use a lot more of the default settings for
# Linux packaging (where directory names etc are expected to be all lower-case)
project(brewken VERSION 1.0.0 LANGUAGES CXX)
message(STATUS "Building ${PROJECT_NAME} version ${PROJECT_VERSION}")
message(STATUS "PROJECT_SOURCE_DIR is ${PROJECT_SOURCE_DIR}")
# Sometimes we do need the capitalised version of the project name
set(capitalisedProjectName Brewken)
# We use this in the program, to tell users where to get support.
set(CONFIG_GITHUB_URL "https://github.com/${capitalisedProjectName}/${projectName}")
set(CONFIG_WEBSITE_URL "https://www.brewken.com/")
set(CONFIG_ORGANIZATION_DOMAIN "brewken.com")
#=======================================================================================================================
#======================================================= Options =======================================================
#=======================================================================================================================
option(DO_RELEASE_BUILD "If on, will do a release build. Otherwise, debug build." OFF)
option(NO_MESSING_WITH_FLAGS "On means do not add any build flags whatsoever. May override other options." OFF)
#=======================================================================================================================
#===================================================== Directories =====================================================
#=======================================================================================================================
#================================================== Source directories =================================================
#
# ${repoDir} = the directory containing this (CMakeLists.txt) file
# ${repoDir}/src = C++ source code
# ${repoDir}/ui = QML UI layout files
# ${repoDir}/data = Binary files, including sounds and default database
# ${repoDir}/translations = Translated texts
# ${repoDir}/mac = Mac-specific files (desktop icon)
# ${repoDir}/win = Windows-specific files (desktop icon)
# ${repoDir}/packaging = Packaging-related config
#
set(repoDir "${CMAKE_CURRENT_SOURCE_DIR}")
# Location of custom CMake modules. (At the moment, there is only one, which is used for Windows packaging
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules")
#================================================= Install directories =================================================
# Note that WIN32 is true "when the target system is Windows, including Win64" (see
# https://cmake.org/cmake/help/latest/variable/WIN32.html), so this is ALL versions of Windows, not just 32-bit.
# UNIX is true when the "the target system is UNIX or UNIX-like", so it is set when we're building for Mac and for
# Linux. There is a separate flag (APPLE) when we're building for Mac, but, AFAICT, no specific flag for Linux.
#
if(UNIX AND NOT APPLE)
#============================================= Linux Install Directories ============================================
# By default, CMAKE_INSTALL_PREFIX is:
# - /usr/local on Linux (& Mac)
# - c:/Program Files/${PROJECT_NAME} on Windows
#
# On a lot of Linux distros, including Debian and derived systems (such as Ubuntu), it's more normal for pretty much
# all user-installed apps to go in /usr/bin rather than /usr/local/bin, so CMAKE_INSTALL_PREFIX can be overridden on
# the command line via "--prefix usr"
#
# (See http://lists.busybox.net/pipermail/busybox/2010-December/074114.html for a great, albeit slightly depressing,
# explanation of why there are so many places for binaries to live on Unix/Linux systems. FWIW, the current
# "standards" for Linux are at https://refspecs.linuxfoundation.org/fhs.shtml but these are open to interpretation.)
#
# .:TBD: We also allow -DEXEC_PREFIX=/usr (used in .github/workflows/linux-ubuntu.yml) but I'm not sure if this is
# needed or could be replaced by "--prefix usr"
#
# Debian standard directories.
if(NOT EXEC_PREFIX)
set(EXEC_PREFIX ${CMAKE_INSTALL_PREFIX})
endif()
set(installSubDir_data "share/${CMAKE_PROJECT_NAME}")
set(installSubDir_doc "share/doc/${CMAKE_PROJECT_NAME}")
set(installSubDir_bin "bin")
# According to https://specifications.freedesktop.org/menu-spec/menu-spec-1.0.html#paths, .desktop files need to live
# in one of the $XDG_DATA_DIRS/applications/. (Note that $XDG_DATA_DIRS is a colon-separated list of directories, typically
# defaulting to /usr/local/share/:/usr/share/. but on another system it might be
# /usr/share/plasma:/usr/local/share:/usr/share:/var/lib/snapd/desktop:/var/lib/snapd/desktop). When combined with
# CMAKE_INSTALL_PREFIX, "share/applications" should end up being one of these.
set(installSubDir_applications "share/applications")
# It's a similar but slightly more complicated story for where to put icons. (See
# https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#directory_layout for all the
# details.)
set(installSubDir_icons "share/icons")
elseif(WIN32)
#============================================ Windows Install Directories ===========================================
set(installSubDir_data "data")
set(installSubDir_doc "doc")
set(installSubDir_bin "bin")
elseif(APPLE)
#============================================== Mac Install Directories =============================================
set(installSubDir_data "Contents/Resources")
set(installSubDir_doc "Contents/Resources/en.lproj")
set(installSubDir_bin "Contents/MacOS")
endif()
#=======================================================================================================================
#====================================================== File Names =====================================================
#=======================================================================================================================
if(APPLE)
# Use capital letters. Don't question the APPLE.
set(fileName_executable "${capitalisedProjectName}")
else()
set(fileName_executable "${PROJECT_NAME}")
endif()
set(fileName_unitTestRunner "${PROJECT_NAME}_tests")
#=======================================================================================================================
#=================================================== General Settings ==================================================
#=======================================================================================================================
# This is needed to enable the add_test() command
enable_testing()
if (APPLE)
# On Mac we ask CMake to try to find static libraries when available -- because it's so painful shipping dynamic
# libraries in a Bundle.
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
endif()
#=======================================================================================================================
#=============================================== Installation Components ===============================================
#=======================================================================================================================
# For architecture-independent data
set(DATA_INSTALL_COMPONENT "Data")
# For architecture-dependent binaries
set(RUNTIME_INSTALL_COMPONENT "Runtime")
#=======================================================================================================================
#============================================== Compiler settings & flags ==============================================
#=======================================================================================================================
# We use different compilers on different platforms. Where possible, we want to let CMake handle the actual compiler
# settings
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# We need C++20 for std::map::contains() and concepts, C++17 or later for nested namespaces and structured bindings, and
# C++11 or later for lambdas.
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
include_directories(${repoDir}/third-party/valijson/include/)
include_directories(${repoDir}/src)
include_directories("${CMAKE_BINARY_DIR}/src") # In case of out-of-source build.
# GCC-specific flags
if(NOT ${NO_MESSING_WITH_FLAGS})
if(CMAKE_COMPILER_IS_GNUCXX)
#
# We would like to avoid having an executable stack, partly as a good thing in itself, and partly because, by
# default, rpmlint with throw a missing-PT_GNU_STACK-section error if we don't.
#
# In theory, the compiler should work out automatically whether we need an executable stack, decide the answer is
# "No" and pass all the right options to the linker. In practice, it seems this doesn't happen for reasons I
# have, as yet, to discover.
#
# We attempt here to to assert manually that the stack should not be executable. The "-z noexecstack" should
# get passed through by gcc the linker (see https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options) and
# the GNU linker (https://sourceware.org/binutils/docs/ld/Options.html) should recognise "-z noexecstack" as
# "Marks the object as not requiring executable stack".
#
# However, this is not sufficient. So, for the moment, we suppress the rpmlint error (see
# packaging/linux/rpmLintFilters.toml).
#
# Additionally, NOTE that "-z options are just not supported for Windows versions of ld" (as mentioned at
# https://stackoverflow.com/questions/55418931/ld-exe-unrecognized-option-z). So we have to exclude that option
# on Windows.
#
if(NOT WIN32)
set(CMAKE_CXX_FLAGS_RELEASE "-Wall -ansi -pedantic -Wno-long-long -O2 -z noexecstack")
else()
set(CMAKE_CXX_FLAGS_RELEASE "-Wall -ansi -pedantic -Wno-long-long -O2")
endif()
#
# -g3 should give even more debugging information than -g (which is equivalent to -g2)
# -no-pie -fno-pie -rdynamic are needed for Boost stacktrace to work properly - at least according to comments
# at https://stackoverflow.com/questions/52583544/boost-stack-trace-not-showing-function-names-and-line-numbers
#
# But, for some reason, gcc on Windows does not accept -rdynamic
#
if(NOT WIN32)
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g3 -no-pie -fno-pie -rdynamic")
else()
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g3 -no-pie -fno-pie")
endif()
endif()
# Speed up compilation if using gcc.
if(UNIX AND NOT APPLE)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pipe")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pipe")
endif()
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
#
# On older versions of GCC, it is not sufficient to specify C++20 to enable concepts, you also have to set a
# special compiler flag.
#
add_compile_options(-fconcepts)
endif()
#
# On Ubuntu 22.04, the packages for Qt6 differ from those for Qt5 in that they require you to build with the PIC option,
# otherwise we'll get the error: "You must build your code with position independent code if Qt was built with
# -reduce-relocations. " "Compile your code with -fPIC (and not with -fPIE)."
#
# On certain instances of Windows, we'll get "relocation truncated to fit" linker errors if we don't build with position
# independent code (see
# https://stackoverflow.com/questions/10486116/what-does-this-gcc-error-relocation-truncated-to-fit-mean for more
# explanation).
#
if((UNIX AND NOT APPLE) OR WIN32)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
# Windows-specific compilation settings
if(WIN32)
# See https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Link-Options.html#Link-Options for more on GCC linker options
# In theory, we could specify "-static-libgcc -static-libstdc++ -static" to statically link all the GCC and MinGW
# libraries, so we don't have to ship DLLs for them. In practice, this (a) does not prevent us needing a fair few
# other DLLs and (b) per https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Link-Options.html#Link-Options it's advised
# not to because:
# "There are several situations in which an application should use the shared libgcc instead of the static
# version. The most common of these is when the application wishes to throw and catch exceptions across different
# shared libraries. In that case, each of the libraries as well as the application itself should use the shared
# libgcc.
# "Therefore, the G++ driver automatically adds -shared-libgcc whenever you build a shared library or a main
# executable, because C++ programs typically use exceptions, so this is the right thing to do."
#
# set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
endif()
if(APPLE)
# As explained at https://stackoverflow.com/questions/5582211/what-does-define-gnu-source-imply, defining _GNU_SOURCE
# gives access to various non-standard GNU/Linux extension functions and changes the behaviour of some POSIX
# functions.
#
# This is needed for Boost stacktrace on Mac
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GNU_SOURCE")
endif()
#======Speed up compilation by using precompiled headers (PCH) for development======
# (ADD_PCH_RULE _header_filename _src_list)
# Version 7/26/2010
#
# use this macro before "add_executable"
#
# _header_filename
# header to make a .gch
#
# _src_list
# the variable name (do not use ${..}) which contains a
# a list of sources (a.cpp b.cpp c.cpp ...)
# This macro will append a header file to it, then this src_list can be used in
# "add_executable..."
#
#
# Now a .gch file should be generated and gcc should use it.
# (add -Winvalid-pch to the cpp flags to verify)
#
# make clean should delete the pch file
#
# example : ADD_PCH_RULE(headers.h myprog_SRCS)
MACRO (ADD_PCH_RULE _header_filename _src_list)
set(_gch_filename "${CMAKE_CURRENT_BINARY_DIR}/${_header_filename}.gch")
set(_header "${CMAKE_CURRENT_SOURCE_DIR}/${_header_filename}")
LIST(APPEND ${_src_list} ${_gch_filename})
SET (_args ${CMAKE_CXX_FLAGS})
LIST(APPEND _args -c ${_header} -o ${_gch_filename})
GET_DIRECTORY_PROPERTY(DIRINC include_directories)
FOREACH(_inc ${DIRINC})
LIST(APPEND _args "-I" ${_inc})
ENDFOREACH(_inc ${DIRINC})
SEPARATE_ARGUMENTS(_args)
ADD_CUSTOM_COMMAND(OUTPUT ${_gch_filename}
COMMAND rm -f ${_gch_filename}
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args}
DEPENDS ${_header})
ENDMACRO(ADD_PCH_RULE _src_list _header_filename)
#=======================================================================================================================
#=================================================== Set build type ====================================================
#=======================================================================================================================
# We might always to tell the compiler to include debugging information (eg via the -g option on gcc). It makes the
# binaries slightly bigger on Linux, but helps greatly in analysing core dumps etc. (In closed-source projects people
# sometimes turn it off for release builds to make it harder to reverse engineer the software, but obviously that's not
# an issue for us.)
#
# However, setting CMAKE_BUILD_TYPE to "Debug", also changes other things, such as the default location for config
# files, which we don't want on a release build, so we would probably need to set compiler flags directly.
#
# .:TBD:. Investigate whether setting CMAKE_BUILD_TYPE to "RelWithDebInfo" does what we want.
#
if(${DO_RELEASE_BUILD})
set(CMAKE_BUILD_TYPE "Release")
else()
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_ENABLE_EXPORTS true)
endif()
message(STATUS "Doing ${CMAKE_BUILD_TYPE} build (DO_RELEASE_BUILD = ${DO_RELEASE_BUILD})")
#=======================================================================================================================
#========================================= Find various libraries we depend on =========================================
#=======================================================================================================================
#======================================================= Find Qt =======================================================
# We need not just the "core" bit of Qt but various "optional" elements.
#
# We try to keep the minimum Qt version we need as low as we can.
#
# Note that if you change the minimum Qt version, you need to make corresponding changes to the .github/workflows/*.yml
# files so that GitHub uses the appropriate version of Qt for the automated builds.
#
if(UNIX AND NOT APPLE)
execute_process(COMMAND lsb_release -rs OUTPUT_VARIABLE RELEASE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
# As of 2024-09-30:
# - Qt 6.2.4 is the maximum available in Ubuntu 22.04 (Jammy).
# - Qt 6.4.2 is the maximum available in Ubuntu 24.04 (Noble).
set(QT_MIN_VERSION 6.2.4)
else()
# Windows and Mac may have newer versions, but we keep everything the same for now
set(QT_MIN_VERSION 6.2.4)
endif()
if(APPLE)
#
# The Qt6 documentation to using CMake at https://doc.qt.io/qt-5/cmake-get-started.html says we need to set
# CMAKE_PREFIX_PATH environment variable to the Qt 5 installation prefix. In theory, setting the corresponding CMake
# variable should do the same job (per https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html).
#
# It seems this is only needed on MacOS. According to ./third-party/valijson/README.md we are not the only ones to
# experience this!
#
execute_process(COMMAND brew --prefix qt6 OUTPUT_VARIABLE CMAKE_PREFIX_PATH)
message(STATUS "CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
endif()
# Set the AUTOMOC property on all targets. This tells CMake to automatically handle the Qt Meta-Object Compiler (moc)
# preprocessor (ie the thing that handles Qt's C++ extensions), without having to use commands such as QT4_WRAP_CPP(),
# QT5_WRAP_CPP(), etc. In particular, it also means we no longer have to manually identify which headers have Q_OBJECT
# declarations etc.
set(CMAKE_AUTOMOC ON)
# Set the AUTOUIC property on all targets. This tells CMake to automatically handle the Qt uic code generator, without
# having to use commands such as QT4_WRAP_UI(), QT5_WRAP_UI(), etc.
set(CMAKE_AUTOUIC ON)
# This tells CMake where to look for .ui files when AUTOUIC is on
set(CMAKE_AUTOUIC_SEARCH_PATHS ${repoDir}/ui)
# Set the AUTORCC property on all targets. This tells CMake to automatically handle the Qt Resource Compiler (rcc),
# without having to use commands such as QT4_ADD_RESOURCES(), QT5_ADD_RESOURCES(), etc.
# Note that you need to add your .qrc file(s) as sources to the target you are building
set(CMAKE_AUTORCC ON)
# Name of FOLDER for *_autogen targets that are added automatically by CMake for targets for which AUTOMOC is enabled.
# Note that this replaces AUTOMOC_TARGETS_FOLDER.
set_property(GLOBAL PROPERTY AUTOGEN_TARGETS_FOLDER ${CMAKE_CURRENT_BINARY_DIR}/autogen)
# Directory where AUTOMOC, AUTOUIC and AUTORCC generate files for the target.
set_property(GLOBAL PROPERTY AUTOGEN_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/autogen)
# As moc files are generated in the binary dir, tell CMake
# to always look for includes there:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
#
# Although it's possible to do individual find_package commands for each bit of Qt we want to use (Qt6Core, Qt6Widgets,
# Qt6Sql, etc), the newer, and more compact, way of doing things (per
# https://cmake.org/cmake/help/latest/manual/cmake-qt.7.html and https://doc.qt.io/qt-5/cmake-get-started.html) is to do
# one find for Qt as a whole and to list the components that we need. Depending on what versions of CMake and Qt you
# have installed, the way to find out what components exist varies a bit, but there is a relatively recent list at
# https://stackoverflow.com/questions/62676472/how-to-list-all-cmake-components-of-qt5
#
set(qtCommonComponents
Core
Gui
Multimedia
Network
PrintSupport
Sql
Svg # Required to make the deploy scripts pick up the svg plugins
Widgets
Xml # TBD: Not sure we need this any more
)
set(qtTestComponents
Test
)
set(qtToolsComponents
LinguistTools
)
list(APPEND qtAllComponents ${qtCommonComponents} ${qtToolsComponents} ${qtTestComponents})
find_package(Qt6 ${QT_MIN_VERSION} COMPONENTS ${qtAllComponents} REQUIRED)
# Each package has its own include directories that we need to make sure the compiler knows about
foreach(qtComponent IN LISTS qtAllComponents)
# Sometimes it's useful that part of a variable name can be specified by expanding another variable!
include_directories(${Qt6${qtComponent}_INCLUDE_DIRS})
endforeach()
# Qt wants position independent code in certain circumstances - specifically "You must build your code with position
# independent code if Qt was built with -reduce-relocations. Compile your code with -fPIC (and not with -fPIE)."
if(Qt6_POSITION_INDEPENDENT_CODE)
# This will initialize the POSITION_INDEPENDENT_CODE property on all the targets
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
# There's apparently a whole bunch of extra work we need to do to use Qt on Windows and Mac
if(WIN32)
#====================================================================================================================
#================================================= Windows Qt Stuff =================================================
#====================================================================================================================
# .:TBD:. Not sure whether/why we need these additional Qt components on Windows
#find_package(Qt6MultimediaWidgets REQUIRED)
#find_package(Qt6OpenGL REQUIRED)
# get_target_property(QtMultimediaWidgets_location Qt6::MultimediaWidgets LOCATION_${CMAKE_BUILD_TYPE})
# get_target_property(QtOpenGL_location Qt6::OpenGL LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtCore_location Qt6::Core LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtGui_location Qt6::Gui LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtMultimedia_location Qt6::Multimedia LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtNetwork_location Qt6::Network LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtPrintSupport_location Qt6::PrintSupport LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtQgif_location Qt6::QGifPlugin LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtQico_location Qt6::QICOPlugin LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtQjpeg_location Qt6::QJpegPlugin LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtQsvgIcon_location Qt6::QSvgIconPlugin LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtQsvg_location Qt6::QSvgPlugin LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtQtiff_location Qt6::QTiffPlugin LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtQWindows_location Qt6::QWindowsIntegrationPlugin LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtSqliteDriver_location Qt6::QSQLiteDriverPlugin LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtSql_location Qt6::Sql LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtSvg_location Qt6::Svg LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtWidgets_location Qt6::Widgets LOCATION_${CMAKE_BUILD_TYPE})
get_target_property(QtXml_location Qt6::Xml LOCATION_${CMAKE_BUILD_TYPE})
# .:TBD:. Not clear whether/where these xxx_DLLs variables get used
set(Qt_DLLs ${QtCore_location}
${QtGui_location}
${QtMultimedia_location}
# ${QtMultimediaWidgets_location}
${QtNetwork_location}
# ${QtOpenGL_location}
${QtPrintSupport_location}
${QtSql_location}
${QtSvg_location}
${QtWebKit_location}
${QtWebKitWidgets_location}
${QtWidgets_location}
${QtXml_location})
set(SQL_Drivers_DLLs ${QtSqliteDriver_location})
set(Image_Formats_DLLs ${QtQgif_location}
${QtQico_location}
${QtQjpeg_location}
${QtQmng_location}
${QtQsvg_location}
${QtQtiff_location})
set(Icon_Engines_DLLs ${QtQsvgIcon_location})
set(Platform_DLLs ${QtQWindows_location})
get_target_property(_qmake_executable Qt6::qmake IMPORTED_LOCATION)
get_filename_component(QT_BIN_DIR "${_qmake_executable}" DIRECTORY)
message("QT_BIN_DIR = ${QT_BIN_DIR}")
#
# Per https://doc.qt.io/qt-6/windows-deployment.html, the windeployqt executable creates all the necessary folder
# tree "containing the Qt-related dependencies (libraries, QML imports, plugins, and translations) required to run
# the application from that folder".
#
# On some systems at least, looks like Qt6::windeployqt is already available in CMake (when Qt5::windeployqt) was
# not. If it is, then we can't try to set it up again as we'll get an error ("add_executable cannot create imported
# target "Qt6::windeployqt" because another target with the same name already exists").
#
if (NOT TARGET Qt6::windeployqt)
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${QT_BIN_DIR}")
if(EXISTS ${WINDEPLOYQT_EXECUTABLE})
# Per https://cmake.org/cmake/help/latest/command/add_executable.html, "IMPORTED executables are useful for
# convenient reference from commands like add_custom_command()".
add_executable(Qt6::windeployqt IMPORTED)
set_target_properties(Qt6::windeployqt PROPERTIES IMPORTED_LOCATION ${WINDEPLOYQT_EXECUTABLE})
endif()
endif()
# International Components for Unicode
file(GLOB IcuDlls "${QT_BIN_DIR}/libicu*.dll")
elseif(APPLE)
#====================================================================================================================
#=================================================== Mac Qt Stuff ===================================================
#====================================================================================================================
# The macdeployqt executable shipped with Qt does for Mac what windeployqt does for Windows -- see
# https://doc.qt.io/qt-6/macos-deployment.html#the-mac-deployment-tool
#
# At first glance, you might thanks that, with a few name changes, we might share all the CMake code for macdeployqt
# and windeployqt. However, as you will see below, the two programs share _only_ a top-level goal ("automate the
# process of creating a deployable [folder / applicaiton bundle] that contains [the necessary Qt dependencies]" - ie
# so that the end user does not have to install Qt to run our software). They have completely different
# implementations and command line options, so it would be unhelpful to try to treat them identically.
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${QT_BIN_DIR}")
if(EXISTS ${MACDEPLOYQT_EXECUTABLE})
# Per https://cmake.org/cmake/help/latest/command/add_executable.html, "IMPORTED executables are useful for
# convenient reference from commands like add_custom_command()".
add_executable(Qt6::macdeployqt IMPORTED)
set_target_properties(Qt6::macdeployqt PROPERTIES IMPORTED_LOCATION ${MACDEPLOYQT_EXECUTABLE})
endif()
endif()
# Uncomment the following line to show what version of Qt is actually being used
message(STATUS "Using Qt version " ${Qt6Core_VERSION})
#===================================================== Find Boost ======================================================
# Boost is a collection of separate libraries, some, but not all, of which are header-only. We only specify the Boost
# libraries that we actually use.
#
# On Linux, there are cases where we need a more recent version of a Boost library than is readily-available in system-
# supplied packages. I haven't found a slick way to solve this in CMake, though https://github.com/Orphis/boost-cmake
# looks promising. (For header-only Boost libraries, you might think it would be relatively painless to pull them in
# from where they are hosted on GitHub (see https://github.com/boostorg), but this is not the case. AFAICT you can't
# easily pull a specific release, and just pulling master doesn't guarantee that everything compiles.) So, anyway, on
# Debian-based distros of Linux, such as Ubuntu, you need to do the following to install Boost 1.79 in place of whatever
# (if anything) is already installed:
#
# $ sudo apt remove boost-all-dev
# $ cd ~
# $ mkdir boost-tmp
# $ cd boost-tmp
# $ wget https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.tar.bz2
# $ tar --bzip2 -xf boost_1_79_0.tar.bz2
# $ cd boost_1_79_0
# $ ./bootstrap.sh --prefix=/usr
# $ sudo ./b2 install
# $ cd ../..
# $ sudo rm -rf boost-tmp
#
# (Obviously if you want to make the necessary change to install an even more recent version than Boost 1.79 then that
# should be fine.)
#
# We do the same in .github/workflows/linux-ubuntu.yml to make GitHub automated builds work.
#
# Note that this means we want to _statically_ link Boost rather than force end users to have to do all the palava above
#
# ************************
# *** Boost Stacktrace ***
# ************************
#
# We use this for diagnostics. In certain error cases it's very helpful to be able to log the call stack.
#
# On Windows, using MSYS2, the mingw-w64-boost packages do not include libboost_stacktrace_backtrace, but
# https://www.boost.org/doc/libs/1_76_0/doc/html/stacktrace/configuration_and_build.html suggests it is not required
# (because on Windows, if you have libbacktrace installed, you can set BOOST_STACKTRACE_USE_BACKTRACE in header-only
# mode).
#
# .:TODO:. Not sure how to get libboost_stacktrace_backtrace installed on Mac. It doesn't seem to be findable by
# CMake after installing Boost via Homebrew (https://brew.sh/). For the moment, skip trying to use
# libboost_stacktrace_backtrace on Mac
#
# .:TODO:. So far don't have stacktraces working properly on Windows (everything shows as register_frame_ctor), so
# that needs some more investigation. (It could be that it's a bug in Boost, at least according to
# https://stackoverflow.com/questions/54333608/boost-stacktrace-not-demangling-names-when-cross-compiled)
#
# ******************
# *** Boost JSON ***
# ******************
#
# Boost JSON is an (optionally) header-only library that was introduced in Boost 1.75 in December 2020. One of the
# features we use, JSON pointers (the equivalent of XML's XPaths) was only introduced in Boost 1.79. As of March
# 2022, Ubunutu 20.04 LTS only has packages for Boost 1.71 from August 2019, hence the need to manually install a
# newer Boost.
#
# ******************
# *** Boost.Core ***
# ******************
#
# Boost.Core, part of collection of the Boost C++ Libraries, is a collection of core utilities used by other Boost
# libraries. Boost JSON needs a more recent version than 1.71.
#
set(Boost_USE_STATIC_LIBS ON)
if(WIN32)
find_package(Boost 1.79.0 REQUIRED)
elseif(APPLE)
find_package(Boost 1.79.0 REQUIRED)
else()
# Note that header-only libraries don't have a component
find_package(Boost 1.79.0 REQUIRED COMPONENTS stacktrace_backtrace)
endif()
include_directories(${Boost_INCLUDE_DIRS})
# Uncomment the next two lines if you want to find where Boost headers and DLLs are on your system
message("Boost include directories: ${Boost_INCLUDE_DIRS}")
message("Boost libraries: ${Boost_LIBRARIES}")
#
# Extra requirements for Boost Stacktrace
#
# Per https://www.boost.org/doc/libs/1_76_0/doc/html/stacktrace/configuration_and_build.html, by default
# Boost.Stacktrace is a header-only library. However, you get better results by linking (either statically or
# dynamically) with a helper library. Of the various options, it seems like boost_stacktrace_backtrace gives the most
# functionality over the most platforms. This has dependencies on:
# - libdl on POSIX platforms -- but see note below
# - libbacktrace
# The latter is an external library on Windows. On POSIX plaforms it's typically already either installed on the system
# (eg see https://man7.org/linux/man-pages/man3/backtrace.3.html) or built in to the compiler. Fortunately, CMake knows
# how to do the right thing in either case, thanks to https://cmake.org/cmake/help/latest/module/FindBacktrace.html.
#
# Just to make things extra fun, in 2021, the GNU compilers did away with libdl and incorporated its functionality into
# libc, per the announcement of GNU C Library v2.3.4 at
# https://sourceware.org/pipermail/libc-alpha/2021-August/129718.html. This means, if we're using the GNU tool chain
# and libc is v2.3.4 or newer, then we should NOT look for libdl, as we won't find it!
#
# Fortunately, CMake has a special variable, CMAKE_DL_LIBS, that is, essentially "whatever library you need to link to
# for dlopen and dlclose", so we don't need to worry about libc versions.
#
if(NOT WIN32)
set(DL_LIBRARY ${CMAKE_DL_LIBS})
endif()
find_package(Backtrace REQUIRED)
# For the moment, leave default settings for Mac as can't work out how to get the backtrace version of stacktrace
# working. (Should still get stack traces on Mac, but might not get as much info in them as we'd like.)
if(NOT APPLE)
if(NOT WIN32)
# TBD Some users report problems getting CMake to find libboost_stacktrace_backtrace on Ubuntu and Gentoo, so disable it
# for now and fallback to the header-only version
# add_compile_definitions(BOOST_STACKTRACE_DYN_LINK)
endif()
# add_compile_definitions(BOOST_STACKTRACE_USE_BACKTRACE)
endif()
message("Backtrace libs ${DL_LIBRARY} | ${Backtrace_LIBRARIES} | ${Boost_LIBRARIES}")
# Defining BOOST_JSON_STANDALONE tells Boost.JSON to use std::string_view (requires C++17) rather than
# boost::string_view (part of Boost.Utility). However, as of recent versions of Boost.JSON, this is "deprecated and
# will be removed in a future release of Boost.JSON".
#ADD_COMPILE_DEFINITIONS(BOOST_JSON_STANDALONE)
#=================================================== Find Xerces-C++ ===================================================
# CMake already knows how to find and configure Xerces-C++, see
# https://cmake.org/cmake/help/latest/module/FindXercesC.html
find_package(XercesC REQUIRED)
include_directories(${XercesC_INCLUDE_DIRS})
# Uncomment the next two lines if you want to find where Xerces headers and DLLs are on your system
message("Xerces-C++ include directories: ${XercesC_INCLUDE_DIRS}")
message("Xerces-C++ libraries: ${XercesC_LIBRARIES}")
#==================================================== Find Xalan-C++ ===================================================
# Same comments apply here as for Xerces above
find_package(XalanC REQUIRED)
include_directories(${XalanC_INCLUDE_DIRS})
# Uncomment the next two lines if you want to find where Xalan headers and DLLs are on your system
message("Xalan-C++ include directories: ${XalanC_INCLUDE_DIRS}")
message("Xalan-C++ libraries: ${XalanC_LIBRARIES}")
if(APPLE)
# TBD: Is this also needed when static linking Xerces on MacOS?
find_package(CURL REQUIRED)
endif()
#=======================================================Valijson========================================================
# Since Valijson is also hosted at github (https://github.com/tristanpenman/valijson) we just add it as a submodule
# (via git clone https://github.com/tristanpenman/valijson third-party/valijson). Then the following also come from
# https://github.com/tristanpenman/valijson#readme
#
# Valijson is a header-only library, so we don't need to build or link to any libraries etc (unless you want to build
# its test suite - in which case, uncomment the add_subdirectory line and add ValiJSON::valijson to both lists of
# target_link_libraries in src/CMakeLists.txt).
#
# Previously we were using CMake ExternalProject_Add to pull Valijson in, but this is unnecessary (because we don't need
# to build Valijson) and somewhat harder to debug when it goes wrong. So, instead, per the readme at
# https://github.com/tristanpenman/valijson, we just added ValiJSON as a git submodule from the command line.
#
message(STATUS "Valijson source at ${CMAKE_CURRENT_SOURCE_DIR}/third-party/valijson")
# Per comment above, leave the next line commented out unless you want to build the ValiJSON test suite
#add_subdirectory(third-party/valijson)
add_compile_definitions(VALIJSON_USE_EXCEPTIONS)
include_directories(${ROOTDIR}/third-party/valijson/include)
execute_process(COMMAND git config --global --add safe.directory third-party/valijson
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
execute_process(COMMAND git submodule update --init --recursive
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
#========================================= Find MinGW (only needed on Windows) =========================================
if(WIN32)
# This is to detect whether we're using MSYS2 and/or MinGW
if(WIN32)
execute_process(COMMAND uname OUTPUT_VARIABLE uname)
message(STATUS "Uname is " ${uname})
if(uname MATCHES "^MSYS" OR uname MATCHES "^MINGW")
message(STATUS "Running on MSYS/MinGW")
set(MINGW true)
endif()
endif()
# Find extra MinGW-specific dlls.
if(MINGW)
if(NOT MINGW_BIN_DIR)
# Yes, it's mingw32-make.exe even on 64-bit systems
FIND_PATH(MINGW_BIN_DIR "mingw32-make.exe")
endif()
if(NOT EXISTS ${MINGW_BIN_DIR})
message(FATAL_ERROR "MinGW bin dir not found. Run cmake again with the option -DMINGW_BIN_DIR=c:/path/to/mingw/bin")
else()
get_filename_component(Mingw_Path ${CMAKE_CXX_COMPILER} PATH)
endif()
message(STATUS "MINGW_BIN_DIR " ${MINGW_BIN_DIR})
endif()
endif()
# Shows all the places we are looking for headers
message(STATUS "CMAKE_SYSTEM_INCLUDE_PATH: ${CMAKE_SYSTEM_INCLUDE_PATH}")
message(STATUS "CMAKE_INCLUDE_PATH: ${CMAKE_INCLUDE_PATH}")
include(InstallRequiredSystemLibraries)
#=======================================================================================================================
#=========================================== Generate config.h from config.in ==========================================
#=======================================================================================================================
# Taking src/config.in as input, we generate (in the build subdirectory only) config.h. This is a way to inject CMake
# variables into the code.
#
# All variables written as "${VAR}" in config.in will be replaced by the value of VAR in config.h.
# Eg "#define CONFIG_DATA_DIR ${CONFIG_DATA_DIR}" in config.in will be replaced by the below corresponding value in
# ${CONFIG_DATA_DIR} below when configure_file() is called.
#
set(CONFIG_DATA_DIR "${CMAKE_INSTALL_PREFIX}/${installSubDir_data}/")
string(TIMESTAMP BUILD_TIMESTAMP "%Y-%m-%d %H:%M:%S (UTC)" UTC)
configure_file(src/config.in src/config.h)
#=======================================================================================================================
#=============================================== Embedded Resource Files ===============================================
#=======================================================================================================================
# We don't need to list the embedded resource files themselves here, just the "Resource Collection File" that lists what
# they are.
set(filesToCompile_qrc "${CMAKE_CURRENT_SOURCE_DIR}/resources.qrc")
#=======================================================================================================================
#=========================================== Files included with the program ===========================================
#=======================================================================================================================
# These are files that actually ship/install as real files, rather than Qt resources
#
# List of documentation files to be installed. Note that ${repoDir}/COPYRIGHT is NOT included here as it needs special
# case handling below.
set(filesToInstall_docs ${repoDir}/README.md)
# List of data files to be installed.
set(filesToInstall_data ${repoDir}/data/default_db.sqlite
${repoDir}/data/DefaultContent001-OriginalDefaultData.xml
${repoDir}/data/DefaultContent002-BJCP_2021_Styles.json
${repoDir}/data/DefaultContent003-Ingredients-Hops-Yeasts.json
${repoDir}/data/DefaultContent004-MoreYeasts.json)
# Desktop files to install.
set(filesToInstall_desktop ${repoDir}/linux/${PROJECT_NAME}.desktop)
# Icon files to install.
set(filesToInstall_icons ${repoDir}/images/${PROJECT_NAME}.svg)
# This is the list of translation files to update (from translatable strings in the source code) and from which the
# binary .qm files will be generated and shipped. Note that src/OptionDialog.cpp controls which languages are shown to
# the user as options for the UI
set(translationSourceFiles ${repoDir}/translations/bt_ca.ts # Catalan
${repoDir}/translations/bt_cs.ts # Czech
${repoDir}/translations/bt_de.ts # German
${repoDir}/translations/bt_en.ts # English
${repoDir}/translations/bt_el.ts # Greek
${repoDir}/translations/bt_es.ts # Spanish
${repoDir}/translations/bt_et.ts # Estonian
${repoDir}/translations/bt_eu.ts # Basque
${repoDir}/translations/bt_fr.ts # French
${repoDir}/translations/bt_gl.ts # Galician
${repoDir}/translations/bt_nb.ts # Norwegian Bokmal
${repoDir}/translations/bt_it.ts # Italian
${repoDir}/translations/bt_lv.ts # Latvian
${repoDir}/translations/bt_nl.ts # Dutch
${repoDir}/translations/bt_pl.ts # Polish
${repoDir}/translations/bt_pt.ts # Portuguese
${repoDir}/translations/bt_hu.ts # Hungarian
${repoDir}/translations/bt_ru.ts # Russian
${repoDir}/translations/bt_sr.ts # Serbian
${repoDir}/translations/bt_sv.ts # Swedish
${repoDir}/translations/bt_tr.ts # Turkish
${repoDir}/translations/bt_zh.ts) # Chinese
set(filesToInstall_windowsIcon ${repoDir}/win/icon.rc)
set(filesToInstall_sounds ${repoDir}/data/sounds/45minLeft.wav
${repoDir}/data/sounds/addFuckinHops.wav
${repoDir}/data/sounds/aromaHops.wav
${repoDir}/data/sounds/beep.wav
${repoDir}/data/sounds/bitteringHops.wav
${repoDir}/data/sounds/checkBoil.wav
${repoDir}/data/sounds/checkFirstRunnings.wav
${repoDir}/data/sounds/checkGravity.wav
${repoDir}/data/sounds/checkHydrometer.wav
${repoDir}/data/sounds/checkMashTemps.wav
${repoDir}/data/sounds/checkTemp.wav
${repoDir}/data/sounds/clarifyingAgent.wav
${repoDir}/data/sounds/cleanup.wav
${repoDir}/data/sounds/closeFuckinValves.wav
${repoDir}/data/sounds/closeValves.wav
${repoDir}/data/sounds/doughIn.wav
${repoDir}/data/sounds/drinkAnotherHomebrew.wav
${repoDir}/data/sounds/drinkHomebrew.wav
${repoDir}/data/sounds/emptyMashTun.wav
${repoDir}/data/sounds/extraPropane.wav
${repoDir}/data/sounds/flameout.wav
${repoDir}/data/sounds/flavorHops.wav
${repoDir}/data/sounds/heatWater.wav
${repoDir}/data/sounds/mashHops.wav
${repoDir}/data/sounds/pitchYeast.wav
${repoDir}/data/sounds/sanitize.wav
${repoDir}/data/sounds/sparge.wav
${repoDir}/data/sounds/startBurner.wav
${repoDir}/data/sounds/startChill.wav
${repoDir}/data/sounds/stirMash.wav)
# We mostly don't need to explicitly specify the .ui files because AUTOUIC will find them all for us. However, I
# haven't found a way to connect AUTOUIC with the translation stuff below, so grab a list of all the .ui files here for
# that.
file(GLOB_RECURSE filesToCompile_ui "${repoDir}/ui/*.ui")
set(filesToInstall_macPropertyList "${repoDir}/mac/Info.plist")
set(filesToInstall_macIcons "${repoDir}/mac/BrewkenIcon.icns")
set(filesToInstall_changeLogUncompressed "${repoDir}/CHANGES.markdown")
# See below for how this one gets created from filesToInstall_changeLogUncompressed
set(filesToInstall_changeLogCompressed "${CMAKE_CURRENT_BINARY_DIR}/changelog.gz")
#=======================================================================================================================
#=========================================== Process other CMakeList.txt files =========================================
#=======================================================================================================================
# We try to restrict src/CMakeLists.txt to just holding lists of source files,
# otherwise the dependencies and interactions between those files and this one get a bit hard to follow.
include(src/CMakeLists.txt)
#=======================================================================================================================
#==================================================== Translations =====================================================
#=======================================================================================================================
#
# We need to do two processes with Translation Source (.ts) XML files:
# - Update them from the source code, ie to ensure they have all the tr(), QObject::tr() etc calls from the .cpp files
# and all the translatable strings from the .ui files -- which can be done manually from the command line with
# lupdate
# - Generate the binary .qm files that ship with the application and are used at run time -- which can be done
# manually from the command line with lrelease
#
# Getting both these things done in Qt5 was a bit complicated as qt_add_translation() _only_ does the latter. But,
# with Qt6, we now have qt_add_lupdate that does the former. NOTE that we will want to tweak the syntax of
# qt_add_lupdate once we are on Qt 6.7 -- per https://doc.qt.io/qt-6/qtlinguist-cmake-qt-add-lupdate.html -- because a
# change is introduced with that release and the syntax used here then becomes deprecated.
#
qt_add_translation(QM_FILES ${translationSourceFiles})
# Add a target for the QM_FILES so that we can add the translations as a dependency for the executable later.
add_custom_target(translationsTarget DEPENDS ${QM_FILES})
qt_add_lupdate(translationsTarget TS_FILES ${repoDir}/src -ts ${translationSourceFiles} SOURCES ${filesToCompile_cpp} ${filesToCompile_ui})
#============================Icon for Windows==================================
set(desktopIcon "")
if(WIN32 AND MINGW)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/src/icon.o
COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR}
-i${filesToInstall_windowsIcon}
-o${CMAKE_BINARY_DIR}/src/icon.o
DEPENDS ${filesToInstall_windowsIcon}
)
set(desktopIcon ${CMAKE_BINARY_DIR}/src/icon.o)
elseif(WIN32)
set(desktopIcon ${filesToInstall_windowsIcon})
endif()
#===========================File ownership==================================
#
# When you do "make install", the last thing CMake does is generate a file called install_manifest.txt in the build
# output directory containing a list of all the files that were installed. On Linux, since we need to run make install
# as root (eg via "sudo make install"), this file would get created with root:root ownership. That's a problem because
# you then when you run "make package" as a non-root user, you get an error "file failed to open for writing (Permission
# denied)". The workaround is to create the install_manifest.txt file as a normal user when "make" is run, so that
# "sudo make install" is just updating an existing file rather than creating it from scratch.
#
file(TOUCH ${CMAKE_BINARY_DIR}/install_manifest.txt)
#===========================Create the binary==================================