-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerate
executable file
·879 lines (766 loc) · 28.8 KB
/
generate
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
#!/usr/bin/env bash
# file : generate
# license : MIT
# Create the infrastructure required by our Qt packages:
#
# - Create a source layout more suitable to our purposes which is still
# compatible the Qt upstream (the way they include stuff, etc).
#
owd="$(pwd)"
trap "{ cd '$owd'; exit 1; }" ERR
set -o errtrace # Trap in functions and subshells.
set -o pipefail # Fail if any pipeline command fails.
shopt -s lastpipe # Execute last pipeline command in the current shell.
shopt -s nullglob # Expand no-match globs to nothing rather than themselves.
function info () { echo "$*" 1>&2; }
function error () { info "$*"; exit 1; }
# Recursively remove all files in <dir> that are symlinks.
#
function rm_symlinks () # <dir>
{
find "$1" -type l -exec rm {} \;
}
# Recursively remove all empty directories in <dir>.
#
function rm_empty_dirs () # <dir>
{
local d="${1%/}"
local sd # Subdirectory.
for sd in "$d"/*/; do
# Remove subdirectory contents, then remove subdirectory itself if empty.
#
rm_empty_dirs "$sd"
if [[ -z "$(ls -A "$sd")" ]]; then
rmdir "$sd"
fi
done
}
# Remove previously-generated files and directories.
#
rm_symlinks Qt6Moc/moc/
rm_empty_dirs Qt6Moc/moc/
rm -f Qt6Moc/moc/QtCore/Q*
rm_symlinks Qt6Rcc/rcc/
rm_empty_dirs Qt6Rcc/rcc/
rm -f Qt6Rcc/rcc/QtCore/Q*
rm_symlinks Qt6Uic/uic/
rm_empty_dirs Qt6Uic/uic/
rm -f Qt6Uic/uic/QtCore/Q*
rm_symlinks libQt6Core/QtCore/
rm_empty_dirs libQt6Core/QtCore/
rm -f libQt6Core/QtCore/Q*
rm -rf libQt6Core/3rdparty
rm_symlinks libQt6Gui/QtGui/
rm_empty_dirs libQt6Gui/QtGui/
rm -rf libQt6Gui/mkspecs
rm -rf libQt6Gui/3rdparty/
rm -rf libQt6Gui/QtGui/qpa/
rm -rf libQt6Gui/QtGui/private/QtGui/qpa/
rm -rf libQt6Gui/QtGui/rhi/
rm -f libQt6Gui/QtGui/Q*
rm_symlinks libQt6Gui/QtGuiPlugins/
rm_empty_dirs libQt6Gui/QtGuiPlugins/
rm_symlinks libQt6Widgets/QtWidgets/
rm_empty_dirs libQt6Widgets/QtWidgets/
rm -f libQt6Widgets/mkspecs
rm -f libQt6Widgets/QtWidgets/Q*
rm_symlinks libQt6Widgets/QtWidgetsPlugins/
rm_empty_dirs libQt6Widgets/QtWidgetsPlugins/
rm_symlinks libQt6WidgetsTests/widgets-app/
# Create output directories.
#
# 3rdparty/ has to be a sibling to QtCore/ because the QtCore source files use
# include paths such as "../../3rdparty/freebsd/strtoll.c".
#
mkdir -p Qt6Moc/moc/QtCore/private/QtCore/private
mkdir -p Qt6Rcc/rcc/QtCore/private/QtCore/private
mkdir -p Qt6Uic/uic/QtCore/private/QtCore/private
mkdir libQt6Core/3rdparty
mkdir libQt6Gui/3rdparty
mkdir libQt6Gui/QtGui/qpa
mkdir libQt6Gui/QtGui/private/QtGui/qpa
mkdir libQt6Gui/QtGui/rhi
# Create a symlink to one or more upstream directories and set the
# `symlink=dir` attribute on each in the containing directory's
# .gitattributes.
#
# Create symlinks to all <target-dir-path> arguments inside
# <symlink-dir-path>.
#
# Recreates .gitattributes from scratch so invoke this function only once for
# each containing directory.
#
function symlink_dirs ()
# <target-dir-path> [<target-dir-path>..] <symlink-dir-path>
{
local args=("$@")
# Process the symlink path (the last function argument).
#
local si="${#args[@]}"-1 # Symlink path's index in `args()`
local sp="${args[$si]}" # Symlink path.
sp="${sp%/}" # Strip trailing '/'.
unset "args[$si]" # Remove from `args` (leaving only targets).
# Target path prefix consisting of the right number of "../"s to get from
# the symlink directory to the project root (working) directory.
#
local tpfx="$(sed -E 's%[^/]+%..%g' <<<"$sp")"
rm -f "$sp/.gitattributes"
# Apply the prefix to each target and create its entry in .gitattributes.
#
local i # Index into `args` array.
for i in "${!args[@]}"; do
local t="${args[$i]}" # Target path currently being processed.
t="${t%/}" # Strip trailing '/'.
args["$i"]="$tpfx/$t" # Apply prefix to target path.
echo "$(basename "$t") symlink=dir" >> "$sp/.gitattributes"
done
# Create the symlinks.
#
ln -s "${args[@]}" "$sp/"
}
# Symlink upstream directories.
#
symlink_dirs upstream/qtbase/mkspecs \
upstream/qtbase/src/tools/shared \
Qt6Moc/moc/
symlink_dirs upstream/qtbase/src/3rdparty/{rfc6234,sha1} \
Qt6Moc/moc/3rdparty/
symlink_dirs upstream/qtbase/mkspecs \
Qt6Rcc/rcc/
symlink_dirs upstream/qtbase/src/3rdparty/{rfc6234,sha1} \
Qt6Rcc/rcc/3rdparty/
symlink_dirs upstream/qtbase/mkspecs \
Qt6Uic/uic/
symlink_dirs upstream/qtbase/src/3rdparty/{rfc6234,sha1} \
Qt6Uic/uic/3rdparty/
# The testlib/ symlink is made necessary by the inclusion of
# "../testlib/3rdparty/valgrind_p.h" by corelib/tools/qsimd.cpp. (That is,
# QtCore includes a private header from QTestLib, an entirely different
# library...)
#
symlink_dirs upstream/qtbase/mkspecs \
upstream/qtbase/src/testlib \
libQt6Core/QtCore/
symlink_dirs upstream/qtbase/src/3rdparty/{easing,forkfd} \
upstream/qtbase/src/3rdparty/{md4,md5,rfc6234,sha1,sha3} \
libQt6Core/3rdparty/
symlink_dirs upstream/qtbase/mkspecs \
libQt6Gui/
symlink_dirs upstream/qtbase/src/3rdparty/{icc,wintab,D3D12MemoryAllocator} \
libQt6Gui/3rdparty/
symlink_dirs upstream/qtbase/mkspecs libQt6Widgets/
# Symlink an upstream source file into our project directory structure.
#
# If there is a downstream version of the source file (which may have a .in
# extension), its symlink gets the upstream filename while the upstream
# original's symlink gets the upstream filename with a ".orig" extension.
#
# <symlink-target-path>: path to the symlink's upstream target, relative to
# the destination directory (so will contain some
# `../`s).
#
# <destination-dir-path>: path to the directory that will contain the symlink,
# relative to the project root.
#
# For example, assuming downstream/foo/bar/baz.cpp exists:
#
# call: symlink_source_file ../../upstream/foo/bar/baz.cpp foo/bar/
# result: foo/bar/baz.cpp -> downstream/foo/bar/baz.cpp
# foo/bar/baz.cpp.orig -> upstream/foo/bar/baz.cpp
#
function symlink_source_file () # <symlink-target-path> <destination-dir-path>
{
local ut="${1%/}" # Upstream symlink target path.
local d="${2%/}" # Destination directory path.
local fn="$(basename "$ut")" # Upstream target file name.
# Path to the downstream version of the symlink target, relative to the
# destination directory. (Don't use sed because doing so for every file is
# too slow).
#
local dt="${ut/upstream/downstream}" # Downstream symlink target path.
# If a downstream version was not found, try again with a .in extension.
#
if [[ ! -f "$d/$dt" ]]; then
dt="$dt.in"
fi
if [[ -f "$d/$dt" ]]; then
ln -sf "$ut" "$d/$fn.orig"
ln -sf "$dt" "$d/"
else
ln -sf "$ut" "$d/$fn"
fi
}
# Symlink the sources of an upstream non-module.
#
# Non-modules include tools, plugins, and internal modules such as those in
# upstream/qtbase/src/platformsupport/.
#
# Note that we don't rearrange non-modules' sources as we do those of "proper"
# Qt modules such as QtCore and QtGui because it does not seem worth the
# trouble for the following reasons: 1) These subprojects have a different
# layout in that there are source files in the root directory (for example, in
# upstream/qtbase/src/plugins/platforms/xcb/) which is where subdirectory
# headers would be copied to, and 2) in some instances source files are more
# than one directory level down from the root (for example, in
# upstream/qtbase/src/plugins/platforms/xcb/gl_integrations/xcb_egl/). And 3)
# tools are not libraries while the plugin libraries are loaded at runtime by
# one of the "proper" Qt modules (for example, libQt6Gui loads libqxcb) and
# are thus not user-facing to the same degree.
#
function symlink_non_module () # <source-directory> <destination-directory>
{
local s="${1%/}" # Source directory.
local d="${2%/}/$(basename "$s")" # Destination directory.
# Prefix to make target path relative to the destination directory (one
# `../` for each directory component in the destination path).
#
local tp="$(sed -Ee 's%[^/]+%..%g' <<<"$d")" # Target prefix.
local t # Target file.
for t in "$s"/*; do
case "$t" in
*.h|*.cpp|*.c|*.mm|*.json)
symlink_source_file "$tp/$t" "$d"
;;
*)
if [[ -d "$t" ]]; then
local sp="$d/$(basename "$t")" # Directory symlink path.
mkdir -p "$sp"
symlink_non_module "$t" "$d"
# Remove the directory if it's empty (contained no interesting
# files).
#
if [[ -z "$(ls "$sp")" ]]; then
rmdir "$sp"
fi
fi
esac
done
}
# Regexes which identify QPA and RHI headers. Taken from
# upstream/qtbase/src/gui/CMakeLists.txt.
#
qpa_re='(^|/)qplatform.+\.h$|(^|/)qwindowsystem.+\.h$'
rhi_re='(^|/)qrhi\.h$|(^|/)qrhi_platform\.h$|(^|/)qshader\.h$|(^|/)qshaderdescription\.h$'
# Symlink all of the sources and other files of interest in the upstream Qt
# module subdirectory <subdir> into <output-path-prefix>/<module-name>/,
# preserving subdirectories.
#
# <subdir> is a path of the following form:
# upstream/qtbase/src/module/foo[/bar[/baz]].
#
# Note that we have to rearrange the upstream sources because they cannot be
# built the way they're laid out in upstream/qtbase/src/module (the upstream
# build also rearranges them).
#
# From the upstream directory layout (after the repeated application of this
# function to all of a module's subdirectories):
#
# upstream/qtbase/src/module
# ├── foo
# │ ├── foo.cpp
# │ ├── foo.h
# │ ├── foo_p.h
# │ ...
# ├── bar
# │ ├── bar.cpp
# │ ├── bar.h
# │ ├── bar_p.h
# │ ...
# ...
#
# create the following layout:
#
# <output-path-prefix>
# └── QtModuleName
# ├── foo
# │ ├── foo.cpp
# │ ...
# ├── bar
# │ ├── bar.cpp
# │ ...
# ├── private
# │ └── QtModuleName
# │ └── private
# │ ├── foo_p.h
# │ ├── bar_p.h
# │ ...
# ├── foo.h
# ├── bar.h
# ...
#
function symlink_module_subdir () # <output-path-prefix> <module-name> <subdir>
{
local opp="$1" # Output path prefix.
local mod="$2" # Qt module name.
local sd="${3%/}" # Subdir path (with upstream/qtbase/src/module prefix).
# Unprefixed subdir path. For example, a <subdir> argument of
# "upstream/qtbase/src/corelib/kernel" becomes "kernel" and
# "upstream/qtbase/src/gui/platform/unix" becomes "platform/unix".
#
local usd="$(sed -E 's%upstream/qtbase/src/[^/]+/%%' <<<"$sd")"
# Symlink target path prefix base: the relative path to get to the project
# directory from <output-path-prefix>.
#
# For example, "../../" for a <output-path-prefix> of Qt6Moc/moc/:
#
# ln -s ../../upstream/qtbase/src/tools/moc/main.cpp Qt6Moc/moc/
#
local tpp_base="$(sed -E 's%[^/]+%..%g' <<<"$opp")"
# Portion of the symlink target path prefix corresponding to the unprefixed
# subdir path (that is, needs to be appended to `tpp_base`).
#
local tpp_sd="$(sed -E 's%[^/]+%..%g' <<<"$mod/$usd")"
# Create the output directory for non-header files.
#
mkdir -p "$opp/$mod/$usd"
# All of the source files of interest are directly under one of
# src/<module>/'s subdirectories (that is, nested no deeper).
#
local f
for f in "$sd"/*; do
tpp= # Target path prefix.
spp= # Symlink path prefix.
# Skip QPA and RHI headers (they get special treatment later).
#
if [[ "$f" =~ $qpa_re || "$f" =~ $rhi_re ]]; then
continue
fi
case "$f" in
# Private header.
#
*_p.h)
tpp="$tpp_base/../../../.."
spp="$opp/$mod/private/$mod/private"
;;
# Public header.
#
*.h)
tpp="$tpp_base/.."
spp="$opp/$mod"
;;
# Source files and other file types we are interested in.
#
*.cpp | *.mm | *.c | *.xml | *.qsb)
tpp="$tpp_base/$tpp_sd"
spp="$opp/$mod/$usd"
;;
# Not an interesting file type. Recurse into subdirectories and skip
# regular files.
#
*)
if [[ -d "$f" ]]; then
symlink_module_subdir "$opp" "$mod" "$sd/$(basename "$f")"
fi
continue
;;
esac
symlink_source_file "$tpp/$f" "$spp"
done
# Remove the output directory for non-header files if it is empty (which
# would be the case if the upstream directory contained no files of
# interest).
#
if [[ -z "$(ls "$opp/$mod/$usd")" ]]; then
rmdir "$opp/$mod/$usd"
fi
}
# Symlink the moc and rcc applications' headers and source files into
# Qt6Moc/moc/, Qt6Rcc/rcc/, and Qt6Uic/uic/.
#
symlink_non_module upstream/qtbase/src/tools/moc \
Qt6Moc/
symlink_non_module upstream/qtbase/src/tools/rcc \
Qt6Rcc/
symlink_non_module upstream/qtbase/src/tools/uic \
Qt6Uic/
# Symlink the upstream QtCore sources and other files into Qt6Moc/, Qt6Rcc/,
# Qt6Uic/, and libQt6Core/. Although the Qt6{Moc,Rcc,Uic} builds include only
# a subset of the QtCore sources we symlink all of them for the sake of
# simplicity (their buildfiles do not use wildcards).
#
for d in upstream/qtbase/src/corelib/*/; do
if [[ "$(basename "$d")" == doc ]]; then
continue
fi
symlink_module_subdir Qt6Moc/moc QtCore "$d"
symlink_module_subdir Qt6Rcc/rcc QtCore "$d"
symlink_module_subdir Qt6Uic/uic QtCore "$d"
symlink_module_subdir libQt6Core QtCore "$d"
done
# libQt6Core
#
ln -s ../../upstream/qtbase/.cmake.conf \
libQt6Core/QtCore/cmake.conf
ln -s ../../upstream/qtbase/cmake/modulecppexports.h.in \
libQt6Core/QtCore/qtcoreexports.h.in
# Qt6Moc
#
ln -s ../../upstream/qtbase/.cmake.conf \
Qt6Moc/moc/cmake.conf
ln -s ../../../upstream/qtbase/cmake/modulecppexports.h.in \
Qt6Moc/moc/QtCore/qtcoreexports.h.in
ln -s ../../../libQt6Core/QtCore/qconfig.h.in Qt6Moc/moc/QtCore/
# Qt6Rcc
#
ln -s ../../upstream/qtbase/.cmake.conf \
Qt6Rcc/rcc/cmake.conf
ln -s ../../../upstream/qtbase/cmake/modulecppexports.h.in \
Qt6Rcc/rcc/QtCore/qtcoreexports.h.in
ln -s ../../../libQt6Core/QtCore/qconfig.h.in Qt6Rcc/rcc/QtCore/
# Qt6Uic
#
ln -s ../../upstream/qtbase/.cmake.conf \
Qt6Uic/uic/cmake.conf
ln -s ../../../upstream/qtbase/cmake/modulecppexports.h.in \
Qt6Uic/uic/QtCore/qtcoreexports.h.in
ln -s ../../../libQt6Core/QtCore/qconfig.h.in Qt6Uic/uic/QtCore/
# Symlink the upstream QtGui sources into libQt6Gui/.
#
for d in upstream/qtbase/src/gui/*/; do
if [[ "$(basename "$d")" == doc ]]; then
continue
fi
symlink_module_subdir libQt6Gui QtGui "$d"
done
ln -s ../../upstream/qtbase/cmake/modulecppexports.h.in \
libQt6Gui/QtGui/qtguiexports.h.in
symlink_non_module upstream/qtbase/src/plugins/platforms/xcb/ \
libQt6Gui/QtGuiPlugins/platforms/
symlink_non_module upstream/qtbase/src/plugins/platforms/cocoa/ \
libQt6Gui/QtGuiPlugins/platforms/
symlink_non_module upstream/qtbase/src/plugins/platforms/windows/ \
libQt6Gui/QtGuiPlugins/platforms/
# Symlink the Cocoa plugin's resources.
#
symlink_dirs upstream/qtbase/src/plugins/platforms/cocoa/images/ \
libQt6Gui/QtGuiPlugins/platforms/cocoa/
# Symlink the Windows plugin's resources.
#
symlink_dirs upstream/qtbase/src/plugins/platforms/windows/images/ \
libQt6Gui/QtGuiPlugins/platforms/windows/
symlink_non_module \
upstream/qtbase/src/plugins/platforminputcontexts/compose/ \
libQt6Gui/QtGuiPlugins/platforminputcontexts/
# Symlink directly to the imageformats plugins' directories (not their
# contents).
#
symlink_dirs upstream/qtbase/src/plugins/imageformats/{gif,ico,jpeg} \
libQt6Gui/QtGuiPlugins/imageformats/
# qguiapplication-{develop,install}.cpp: see libQt6Gui/QtGui/buildfile for
# details.
#
mv libQt6Gui/QtGui/kernel/qguiapplication.cpp.in \
libQt6Gui/QtGui/kernel/qguiapplication-develop.cpp.in
mv libQt6Gui/QtGui/kernel/qguiapplication.cpp.orig \
libQt6Gui/QtGui/kernel/qguiapplication-develop.cpp.orig
ln -s ../../../upstream/qtbase/src/gui/kernel/qguiapplication.cpp \
libQt6Gui/QtGui/kernel/qguiapplication-install.cpp
# Symlink the upstream QtWidgets sources into libQt6Widgets/.
#
for d in upstream/qtbase/src/widgets/*/; do
if [[ "$(basename "$d")" == doc ]]; then
continue
fi
symlink_module_subdir libQt6Widgets QtWidgets "$d"
done
ln -s ../../upstream/qtbase/cmake/modulecppexports.h.in \
libQt6Widgets/QtWidgets/qtwidgetsexports.h.in
# qapplication-{develop,install}.cpp: see libQt6Widgets/QtWidgets/buildfile
# for details.
#
mv libQt6Widgets/QtWidgets/kernel/qapplication.cpp.in \
libQt6Widgets/QtWidgets/kernel/qapplication-develop.cpp.in
mv libQt6Widgets/QtWidgets/kernel/qapplication.cpp.orig \
libQt6Widgets/QtWidgets/kernel/qapplication-develop.cpp.orig
ln -s ../../../upstream/qtbase/src/widgets/kernel/qapplication.cpp \
libQt6Widgets/QtWidgets/kernel/qapplication-install.cpp
# Symlink upstream Qt resources collection files and their associated
# resources into libQt6Widgets/.
#
symlink_dirs upstream/qtbase/src/widgets/styles/images \
libQt6Widgets/QtWidgets/styles/
ln -s ../../../upstream/qtbase/src/widgets/dialogs/qfiledialog.ui \
libQt6Widgets/QtWidgets/dialogs/
symlink_dirs upstream/qtbase/src/widgets/dialogs/images \
libQt6Widgets/QtWidgets/dialogs/
symlink_non_module upstream/qtbase/src/plugins/styles/mac/ \
libQt6Widgets/QtWidgetsPlugins/styles/
symlink_non_module upstream/qtbase/src/plugins/styles/modernwindows/ \
libQt6Widgets/QtWidgetsPlugins/styles/
ln -s ../../upstream/qtbase/examples/widgets/widgets/spinboxes/window.h \
libQt6WidgetsTests/widgets-app/
ln -s ../../upstream/qtbase/examples/widgets/widgets/spinboxes/window.cpp \
libQt6WidgetsTests/widgets-app/
# Create the few QtCore camelcase headers required by the Qt compilers.
#
echo '#include "qalgorithms.h"' > Qt6Moc/moc/QtCore/QtAlgorithms
echo '#include "qstring.h"' > Qt6Moc/moc/QtCore/QString
echo '#include "qfile.h"' > Qt6Moc/moc/QtCore/QFile
echo '#include "qbytearray.h"' > Qt6Moc/moc/QtCore/QByteArray
echo '#include "qbytearrayview.h"' > Qt6Moc/moc/QtCore/QByteArrayView
echo '#include "qvarlengtharray.h"' > Qt6Moc/moc/QtCore/QVarLengthArray
echo '#include "qalgorithms.h"' > Qt6Rcc/rcc/QtCore/QtAlgorithms
echo '#include "qbytearrayview.h"' > Qt6Rcc/rcc/QtCore/QByteArrayView
echo '#include "qvarlengtharray.h"' > Qt6Rcc/rcc/QtCore/QVarLengthArray
echo '#include "qcoreapplication.h"' > Qt6Rcc/rcc/QtCore/QCoreApplication
echo '#include "qalgorithms.h"' > Qt6Uic/uic/QtCore/QtAlgorithms
echo '#include "qbytearrayview.h"' > Qt6Uic/uic/QtCore/QByteArrayView
echo '#include "qlist.h"' > Qt6Uic/uic/QtCore/QList
echo '#include "qvarlengtharray.h"' > Qt6Uic/uic/QtCore/QVarLengthArray
echo '#include "qcoreapplication.h"' > Qt6Uic/uic/QtCore/QCoreApplication
# This file is generated by upstream/qtbase/cmake/QtTargetHelpers.cmake.
#
echo '#include <private/qtrace_p.h>' > libQt6Core/QtCore/qtcore_tracepoints_p.h
# Extract the Qt version from upstream/qtbase/.cmake.conf and break it down
# into its components.
#
# Format: <major>.<minor>.<patch>
#
# For reference, in our buildfiles we do:
#
# QT_VERSION_STR="$version.major.$version.minor.$version.patch"
# QT_VERSION_MAJOR="$version.major"
# QT_VERSION_MINOR="$version.minor"
# QT_VERSION_PATCH="$version.patch"
#
qt_version_str="$(sed -nE 's%^\s*set\(QT_REPO_MODULE_VERSION "(.+)"\)%\1%p' \
upstream/qtbase/.cmake.conf)"
if [[ -z "$qt_version_str" ]]; then
error "failed to extract Qt version"
fi
if [[ "$qt_version_str" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
qt_version_major="${BASH_REMATCH[1]}"
qt_version_minor="${BASH_REMATCH[2]}"
qt_version_patch="${BASH_REMATCH[3]}"
else
error "failed to parse extracted Qt version"
fi
# Compile the syncqt tool.
#
c++ -DQT_VERSION_MAJOR=$qt_version_major \
-DQT_VERSION_MINOR=$qt_version_minor \
-DQT_VERSION_PATCH=$qt_version_patch \
-DQT_VERSION_STR="\"$qt_version_str\"" \
-o syncqt \
upstream/qtbase/src/tools/syncqt/main.cpp
# Generate headers for a Qt module into a temporary directory and copy them
# into our source tree.
#
# In the upstream build the syncqt tool copies and/or transforms headers from
# the source directory tree into a separate include directory tree. The
# majority of the transformed headers are camelcase versions of the public
# headers (foobar.h -> QFooBar) but in some cases headers from different
# subdirectories are placed in a single directory to allow their inclusion
# using a common path prefix (e.g., QPA/RHI headers). A few headers are also
# generated from other types of inputs.
#
# <module-name>: One of QtCore, QtGui, or QtWidgets.
#
# <upstream-src-dir>: The module's upstream directory under
# upstream/qtbase/src/.
#
# <known-modules>: The names of all of the Qt modules (minus the "Qt" prefix)
# this module may include headers from (including itself).
#
# Run syncqt (compiled from upstream sources above) to produce their include
# tree in a temporary directory and copy only those headers that don't already
# exist in our source tree (in which case they are not generated or moved by
# syncqt and will thus already have been symlinked above). Also move the
# private QPA/RHI headers into the private header directory (upstream mixes
# public and private headers in these subdirectories for some reason).
#
# Note that we completely ignore the regular (non-QPA/RHI) private headers
# output by syncqt because those are just copied (not transformed or moved)
# and we have already symlinked them into place above.
#
function gen_hdrs () # <module-name> <upstream-src-dir> <known-modules>
{
local mod="$1" # Module name (QtCore, QtGui, QtWidgets).
local srcdir="$2" # Upstream source directory.
local known_mods="$3" # Known Qt modules.
# The list of public and private module headers to be passed to syncqt.
#
# Note that we cannot simply omit the headers we've already symlinked above
# (in order to prevent overwrites) because syncqt creates multiple outputs
# from some headers (for example, it copies and produces CamelCase versions
# of public headers).
#
local hdrs=()
# Search for upstream headers, skipping the doc directory.
#
local d # Directory
for d in "$PWD/upstream/qtbase/src/$srcdir/"*/; do
if [[ "$(basename "$d")" == "doc" ]]; then
continue
fi
hdrs+=($(find "$d" -name \*.h))
done
# Temporary output directory into which to generate the headers.
#
local tmpdir
if ! tmpdir="$(mktemp -d)"; then
error "mktemp failed"
fi
# A temporary directory to use for syncqt's `binaryDir` argument (the
# module's build directory).
#
# In addition to configure time, the upstream build also runs syncqt at
# build time if any module headers have changed, in which case it may
# process headers in the module's build directory. syncqt also outputs to
# this directory a header exclusion list used by a separate header-checking
# target (QtHeadersClean.cmake) of the upstream build.
#
# Because none of these cases apply to us it's safe to pass a temporary
# directory instead.
#
local bindir
if ! bindir="$(mktemp -d)"; then
error "mktemp failed"
fi
# Temporary directory used by syncqt.
#
local staging_dir
if ! staging_dir="$(mktemp -d)"; then
error "mktemp failed"
fi
# Run syncqt.
#
# Arrange for the output tree to resemble our source tree as far as possible
# (see symlink_module_subdir() above for reference):
#
# <tmpdir>
# ├─ private
# │ └─ QtModuleName
# │ └─ private
# │ ├─ foo_p.h
# │ ├─ bar_p.h
# │ ...
# ├─ qpa
# │ ├─ foo.h
# │ ├─ foo_p.h
# │ ...
# └─ rhi
# ├─ foo.h
# ├─ foo_p.h
# ...
#
# See upsteam/qtbase/src/tools/syncqt/main.cpp for a description of the
# options.
#
# In the upstream build the arguments for the QtCore module, for example,
# can be found in <upstream-build-dir>/src/corelib/Core_syncqt_args.
#
# -copy: Copy instead of symlink the source headers.
# -sourceDir: Module source directory.
# -binaryDir: Module build directory (see above).
# -includeDir: The public header output directory.
# -*IncludeDir: Output directories for the other kinds of headers.
# -knownModules: Other Qt modules this module might include headers from.
# -stagingDir: Temporary directory used by syncqt (see above).
# -headers: List of headers to process.
#
# Note that SSG headers only exist in the QtQuick3D module so the
# `-ssgIncludeDir` does not matter despite being a required option.
#
if ! ./syncqt \
-module "$mod" \
-copy \
-sourceDir "$PWD/upstream/qtbase/src/$srcdir" \
-binaryDir "$bindir" \
-includeDir "$tmpdir" \
-privateIncludeDir "$tmpdir/private" \
-privateHeadersFilter '.+_p(ch)?\.h' \
-qpaIncludeDir "$tmpdir/qpa" \
-qpaHeadersFilter $qpa_re \
-rhiIncludeDir "$tmpdir/rhi" \
-rhiHeadersFilter $rhi_re \
-ssgIncludeDir "$tmpdir/ssg" \
-knownModules "$known_mods" \
-stagingDir "$staging_dir" \
-headers "${hdrs[@]}" \
> /dev/null; then
rm -r "$staging_dir" "$bindir" "$tmpdir"
error "syncqt failed"
fi
# The module's public header directory in our source tree.
#
# For example: libQt6Core/QtCore
#
local outdir="libQt6${mod#Qt}/$mod"
# Copy headers from the temporary syncqt output directory into `outdir`.
#
# Note that we do not descend into private/ because (non-QPA/RHI) private
# headers have already been handled (see above).
#
# @@ TMP This has been moved into this function because syncqt.cpp requires
# the QPA/RHI directory arguments for all modules so presumably
# e.g. QtWidgets could someday have QPA/RHI headers too. So handle
# all modules the same (just like syncqt now does).
#
local p # Path (file or directory)
for p in "$tmpdir"/*; do
local fn="$(basename "$p")" # Filename
if [[ ("$fn" == *.h && ! -e "$outdir/$fn") || "$fn" == Q* ]]; then
# Non-QPA/RHI public headers (qfoo_bar.h or QFooBar).
#
cp "$p" "$outdir/"
elif [[ "$fn" == "qpa" || "$fn" == "rhi" ]]; then
# Handle QPA/RHI subdirectories.
#
local sd="$fn" # Subdirectory name.
local up # Upstream file path.
for up in "$p"/*; do
local dd # Destination directory path
case "$up" in
*_p.h) dd="$outdir/private/$mod/$sd" ;;
*.h) dd="$outdir/$sd" ;;
*) continue ;; # Skip non-headers.
esac
fn="$(basename "$up")" # Filename
# Downstream file path, if there is a patched version. We have to run
# find because the upstream build copies the QPA/RHI headers from
# various source code subdirectories.
#
local dp="$(find "downstream/qtbase/src/$srcdir/" -name "$fn")"
# If a downstream copy exists, copy it to the destination directory
# along with the original (generated by the upstream build) which gets
# a '.orig' suffix. Otherwise just copy the original (without
# suffix). NOTE: a similar scheme is implemented in
# symlink_source_file() above.
#
if [[ -n "$dp" ]]; then
cp "$dp" "$dd/$fn"
cp "$up" "$dd/$fn.orig"
else
cp "$up" "$dd/$fn"
fi
done
fi
done
rm -r "$staging_dir" "$bindir" "$tmpdir"
}
gen_hdrs QtCore corelib "Core"
gen_hdrs QtGui gui "Core Gui"
gen_hdrs QtWidgets widgets "Core Gui Widgets"
# The Qt*Depends headers are generated by cmake in the upstream build.
#
touch libQt6Core/QtCore/QtCoreDepends # Empty in QtCore's case.
cat > libQt6Gui/QtGui/QtGuiDepends << EOF
/* This file was generated by the generate script in the build2 amalgamation
root. Its contents were generated upstream by cmake with the info from
the Gui target.
*/
#ifdef __cplusplus /* create empty PCH in C mode */
# include <QtCore/QtCore>
#endif
EOF
cat > libQt6Widgets/QtWidgets/QtWidgetsDepends << EOF
/* This file was generated by the generate script in the build2 amalgamation
root. Its contents were generated upstream by cmake with the info from
the Widgets target.
*/
#ifdef __cplusplus /* create empty PCH in C mode */
# include <QtCore/QtCore>
# include <QtGui/QtGui>
#endif
EOF