aboutsummaryrefslogtreecommitdiffstats
path: root/build/jam/ArchitectureRules
blob: dc42141e4a3c9fda3ce096e70dae2511af3a07b1 (plain) (blame)
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
rule ArchitectureSetup architecture
{
	# ArchitectureSetup <architecture> ;
	#
	# Initializes all global packaging architecture dependent variables for the
	# given packaging architecture. Also sets HAIKU_ARCH (to the primary
	# architecture), if this is the first invocation of the rule, and adds
	# the architecture to HAIKU_ARCHS, if not yet contained.

	# analyze GCC version
	local gccVersion
		= [ FAnalyzeGCCVersion HAIKU_GCC_RAW_VERSION_$(architecture) ] ;
	HAIKU_GCC_VERSION_$(architecture) = $(gccVersion) ;

	# enable GCC -pipe option, if requested
	local ccBaseFlags ;
	if $(HAIKU_USE_GCC_PIPE) = 1 {
		ccBaseFlags = -pipe ;
	}

	if $(gccVersion[1]) >= 3 {
		# disable strict aliasing on anything newer than gcc 2 as it may lead to
		# unexpected results.
		# TODO: remove the -fno-strict-aliasing option when all code has been
		#		analyzed/fixed with regard to aliasing.
		ccBaseFlags += -fno-strict-aliasing ;

		# Without this flag, GCC deletes many null-pointer checks that are
		# technically undefined behavior (e.g. passing NULL to strdup, among
		# others), which breaks both the kernel and various applications. See:
		#  - https://freelists.org/post/haiku-development/hrev45320-Yet-another-nonobvious-effect-of-ftreevrp-optimization
		#  - https://dev.haiku-os.org/ticket/13285#comment:8 (& subsequent comments)
		#  - https://dev.haiku-os.org/ticket/10803#comment:4 (& subsequent comments)
		# Note that the Linux also does the same:
		#  - https://github.com/torvalds/linux/commit/a3ca86aea507904
		ccBaseFlags += -fno-delete-null-pointer-checks ;

		# disable some builtins that are incompatible with our definitions
		ccBaseFlags += -fno-builtin-fork -fno-builtin-vfork ;
	}

	# default architecture tuning
	local cpu = $(HAIKU_CPU_$(architecture)) ;
	local archFlags ;
	switch $(cpu) {
		case ppc : archFlags += -mcpu=440fp ;
		case arm : archFlags += -march=armv7-a -mfloat-abi=hard ;
		case x86 : archFlags += -march=pentium ;
	}
	if $(HAIKU_CC_IS_CLANG_$(architecture)) = 1 {
		# TODO: These should be included in Clang's compiler specs.
		ccBaseFlags += -fPIC ;
		HAIKU_LINKFLAGS_$(architecture) += -shared ;
	}
	ccBaseFlags += $(archFlags) ;

	# activating graphite optimizations
	if $(HAIKU_USE_GCC_GRAPHITE_$(architecture)) = 1 {
		ccBaseFlags += -floop-interchange -ftree-loop-distribution
			-floop-strip-mine -floop-block ;
	}

	# initial state for flags etc.
	HAIKU_C++_$(architecture) ?= $(HAIKU_CC_$(architecture)) ;
	HAIKU_LINK_$(architecture) ?= $(HAIKU_CC_$(architecture)) ;

	HAIKU_CCFLAGS_$(architecture) += $(ccBaseFlags) -nostdinc ;
	HAIKU_C++FLAGS_$(architecture) += $(ccBaseFlags) -nostdinc ;
	HAIKU_LINKFLAGS_$(architecture) += $(ccBaseFlags) ;
	HAIKU_ASFLAGS_$(architecture) += $(archFlags) -nostdinc ;

	# strip is required
	if ! $(HAIKU_STRIP_$(architecture)) {
		Exit "HAIKU_STRIP_$(architecture) not set. Please re-run configure." ;
	}

	HAIKU_ARCH_$(architecture) = $(cpu) ;
	HAIKU_ARCH ?= $(cpu) ;
		# Set only, if not set yet. This way HAIKU_ARCH is set to the primary
		# architecture.
	if ! $(cpu) in $(HAIKU_ARCHS) {
		HAIKU_ARCHS += $(cpu) ;
	}
	HAIKU_DEFINES_$(architecture) += ARCH_$(cpu) ;

	# directories
	HAIKU_ARCH_OBJECT_DIR_$(architecture)
		= [ FDirName $(HAIKU_OBJECT_BASE_DIR) $(architecture) ] ;
	HAIKU_COMMON_DEBUG_OBJECT_DIR_$(architecture)
		= [ FDirName $(HAIKU_ARCH_OBJECT_DIR_$(architecture)) common ] ;
	HAIKU_DEBUG_0_OBJECT_DIR_$(architecture)
		= [ FDirName $(HAIKU_ARCH_OBJECT_DIR_$(architecture)) release ] ;

	local level ;
	for level in $(HAIKU_DEBUG_LEVELS[2-]) {
		HAIKU_DEBUG_$(level)_OBJECT_DIR_$(architecture)
			= [ FDirName $(HAIKU_ARCH_OBJECT_DIR_$(architecture))
				debug_$(level) ] ;
	}

	# set variables for gcc header options
	SetIncludePropertiesVariables HAIKU : _$(architecture) ;

	# warning flags
	HAIKU_WARNING_CCFLAGS_$(architecture) = -Wall
		-Wno-multichar
		-Wpointer-arith -Wsign-compare
		-Wmissing-prototypes ;
	HAIKU_WARNING_C++FLAGS_$(architecture) = -Wall
		-Wno-multichar
		-Wpointer-arith -Wsign-compare
		-Wno-ctor-dtor-privacy -Woverloaded-virtual ;

	# disable some Clang warnings that are not very useful
	if $(HAIKU_CC_IS_CLANG_$(architecture)) = 1 {
		HAIKU_WARNING_CCFLAGS_$(architecture) += -Wno-address-of-packed-member
			-Wno-unused-private-field -Wno-cast-align -Wno-gnu-designator
			-Wno-builtin-requires-header ;
		HAIKU_WARNING_C++FLAGS_$(architecture) += -Wno-address-of-packed-member
			-Wno-unused-private-field -Wno-cast-align -Wno-gnu-designator
			-Wno-builtin-requires-header ;
	}

	HAIKU_WERROR_FLAGS_$(architecture) = ;

	if $(gccVersion[1]) >= 4 {
		# TODO: Remove all these.
		HAIKU_WERROR_FLAGS_$(architecture) += -Wno-error=unused-but-set-variable
			-Wno-error=deprecated -Wno-error=deprecated-declarations
			-Wno-error=cpp -Wno-error=trigraphs ;
		# But these can stay.
		HAIKU_WERROR_FLAGS_$(architecture) += -Wno-error=cast-align
			-Wno-error=format-truncation ;
	}

	# debug flags
	local debugFlags = -ggdb ;

	# debug 0: suppress asserts
	HAIKU_DEBUG_0_CCFLAGS_$(architecture) = [ FDefines NDEBUG=$(NDEBUG) ] ;
	HAIKU_DEBUG_0_C++FLAGS_$(architecture) = [ FDefines NDEBUG=$(NDEBUG) ] ;

	local level ;
	for level in $(HAIKU_DEBUG_LEVELS[2-]) {
		local flags = $(debugFlags) [ FDefines DEBUG=$(level) ] ;
		HAIKU_DEBUG_$(level)_CCFLAGS_$(architecture) = $(flags) ;
		HAIKU_DEBUG_$(level)_C++FLAGS_$(architecture) = $(flags) ;
	}

	# TODO: Temporary work-around. Should be defined in the compiler specs
	HAIKU_LINKFLAGS_$(architecture) += -Xlinker --no-undefined ;

	if $(gccVersion[1]) < 3 {
		HAIKU_DEFINES_$(architecture) += _BEOS_R5_COMPATIBLE_ ;
	}

	# private shared kernel/libroot headers
	HAIKU_PRIVATE_SYSTEM_HEADERS_$(architecture)
		= [ PrivateHeaders $(DOT) system system/arch/$(cpu) ] ;

	# library and executable glue code
	local commonGlueCode =
		<src!system!glue!$(architecture)>init_term_dyn.o
		<src!system!glue!arch!$(cpu)!$(architecture)>crti.o
		<src!system!glue!arch!$(cpu)!$(architecture)>crtn.o
		;
	HAIKU_LIBRARY_BEGIN_GLUE_CODE_$(architecture) =
		<src!system!glue!arch!$(cpu)!$(architecture)>crti.o
		<$(architecture)>crtbeginS.o
		<src!system!glue!$(architecture)>init_term_dyn.o
		;
	HAIKU_LIBRARY_END_GLUE_CODE_$(architecture) =
		<$(architecture)>crtendS.o
		<src!system!glue!arch!$(cpu)!$(architecture)>crtn.o
		;
	HAIKU_EXECUTABLE_BEGIN_GLUE_CODE_$(architecture) =
		<src!system!glue!arch!$(cpu)!$(architecture)>crti.o
		<$(architecture)>crtbeginS.o
		<src!system!glue!$(architecture)>start_dyn.o
		<src!system!glue!$(architecture)>init_term_dyn.o
		;
	HAIKU_EXECUTABLE_END_GLUE_CODE_$(architecture)
		= $(HAIKU_LIBRARY_END_GLUE_CODE_$(architecture)) ;

	SEARCH on <$(architecture)>crtbeginS.o <$(architecture)>crtendS.o
		= $(HAIKU_GCC_LIB_DIR_$(architecture)) ;

	# init library name map
	local libraryGrist = "" ;
	if $(architecture) != $(HAIKU_PACKAGING_ARCHS[1]) {
		libraryGrist = $(architecture) ;
	}
	local i ;
	for i in be bnetapi debug device game locale mail media midi midi2
			network package root screensaver textencoding tracker
			translation z {
		local library = lib$(i).so ;
		HAIKU_LIBRARY_NAME_MAP_$(architecture)_$(i)
			= $(library:G=$(libraryGrist)) ;
	}
	HAIKU_LIBRARY_NAME_MAP_$(architecture)_localestub
		= <$(architecture)>liblocalestub.a ;
	HAIKU_LIBRARY_NAME_MAP_$(architecture)_shared
		= <$(architecture)>libshared.a ;
	if $(architecture) = $(HAIKU_PACKAGING_ARCHS[1]) {
		HAIKU_LIBRARY_NAME_MAP_$(architecture)_input_server
			= <nogrist>input_server ;
	} else {
		HAIKU_LIBRARY_NAME_MAP_$(architecture)_input_server
			= <$(architecture)>input_server ;
	}
}


rule KernelArchitectureSetup architecture
{
	# KernelArchitectureSetup <architecture> ;
	#
	# Initializes the global kernel and boot loader related variables. Those
	# don't have a packaging architecture suffix, since they are only set for
	# the primary packaging architecture. <architecture> is the primary
	# packaging architecture (supplied for convenience).

	HAIKU_KERNEL_ARCH = $(HAIKU_ARCH) ;

	local gccVersion = $(HAIKU_GCC_VERSION_$(architecture)) ;
	local cpu = $(HAIKU_CPU_$(architecture)) ;

	switch $(cpu) {
		case ppc :
			HAIKU_KERNEL_PLATFORM ?= openfirmware ;
			HAIKU_BOOT_TARGETS += openfirmware ;

			HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 1440 ; # in kB
			# offset in floppy image (>= sizeof(haiku_loader))
			HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 384 ; # in kB

		case sparc :
			HAIKU_KERNEL_PLATFORM ?= openfirmware ;
			HAIKU_BOOT_TARGETS += openfirmware ;

			HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 1440 ; # in kB
			# offset in floppy image (>= sizeof(haiku_loader))
			HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 384 ; # in kB

		case arm :
			HAIKU_KERNEL_PLATFORM ?= u-boot ;
			HAIKU_BOOT_TARGETS += u-boot ;

			HAIKU_BOOT_SDIMAGE_SIZE ?= 32 ;
			# SOC's like allwinner need an offset to skip the hardcoded initial loader
			HAIKU_BOOT_SDIMAGE_BEGIN = 40950 ; # 512-byte sectors (divisible by 63)

			HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 1440 ;
			# offset in floppy image (>= sizeof(haiku_loader))
			HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 192 ; # in kB - unused yet
			HAIKU_BOOT_LOADER_BASE ?= 0x1000000 ;

			# Modern u-boot fill in sane addresses for us.
			# Leverage the built-in fdt dtb for this board, unless a custom dtb is specified in uEnv.txt
			# We skip uEnv.txt on virtio due to an unknown lockup in qemu around it.
			HAIKU_MMC_UBOOT_SCRIPT = "\
				echo \"Haiku u-boot script entry\" \
				test -e mmc 0 haiku_loader.ub && setenv media mmc \
				test -e virtio 0 haiku_loader.ub && setenv media virtio \
				test -e nvme 0 haiku_loader.ub && setenv media nvme \
				env exists media && echo \"Found Haiku on ${media} 0!\" \
				env exists media || echo \"ERROR: Unable to locate Haiku loader on any media!\" && exit \
				test ${media} != virtio && test -e ${media} 0 uEnv.txt && fatload ${media} 0 ${scriptaddr} uEnv.txt && env import -t ${scriptaddr} ${filesize} \
				echo \"Loading haiku_loader...\" \
				fatload ${media} 0 ${kernel_addr_r} haiku_loader.ub \
				echo \"Loading haiku_floppyboot...\" \
				fatload ${media} 0 ${ramdisk_addr_r} haiku_floppyboot.ub \
				env exists dtb && echo \"Loading DTB...\" && fatload ${media} 0 ${fdt_addr_r} ${dtb} && fdt addr ${fdt_addr_r} && bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} \
				echo \"Booting Haiku!\" \
				fdt addr ${fdtcontroladdr} && bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdtcontroladdr}" ;

		case arm64 :
			HAIKU_KERNEL_PLATFORM ?= efi ;

			HAIKU_BOOT_SDIMAGE_SIZE ?= 32 ;
			# SOC's like allwinner need an offset to skip the hardcoded initial loader
			HAIKU_BOOT_SDIMAGE_BEGIN = 40950 ; # 512-byte sectors (divisible by 63)

			HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 1440 ;
			# offset in floppy image (>= sizeof(haiku_loader))
			HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 192 ; # in kB - unused yet
			HAIKU_BOOT_LOADER_BASE ?= 0x1000000 ;

		case x86 :
			HAIKU_KERNEL_PLATFORM ?= bios_ia32 ;
			HAIKU_BOOT_TARGETS += bios_ia32 pxe_ia32 ;
			HAIKU_ANYBOOT_LEGACY = 1 ;

			HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 2880 ; # in kB
			# offset in floppy image (>= sizeof(haiku_loader))
			HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 320 ; # in kB

			# nasm is required for target arch x86
			if ! $(HAIKU_NASM) {
				Exit "HAIKU_NASM not set. Please re-run configure." ;
			}

		case riscv64 :
			HAIKU_KERNEL_PLATFORM ?= efi ;
			HAIKU_BOOT_TARGETS += efi ;

			HAIKU_BOOT_SDIMAGE_SIZE ?= 128 ;
			# SOC's like allwinner need an offset to skip the hardcoded initial loader
			HAIKU_BOOT_SDIMAGE_BEGIN = 40950 ; # 512-byte sectors (divisible by 63)

			HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 1440 ;
			# offset in floppy image (>= sizeof(haiku_loader))
			HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 192 ; # in kB - unused yet
			HAIKU_BOOT_LOADER_BASE ?= 0x1000000 ;

		case x86_64 :
			# x86_64 completely shares the x86 bootloader for MBR.
			HAIKU_KERNEL_PLATFORM ?= bios_ia32 ;
			HAIKU_BOOT_TARGETS += bios_ia32 efi pxe_ia32 ;

			HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 2880 ; # in kB
			# offset in floppy image (>= sizeof(haiku_loader))
			HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 320 ; # in kB

			# x86_64 kernel source is under arch/x86.
			HAIKU_KERNEL_ARCH = x86 ;

			# nasm is required for target arch x86_64
			if ! $(HAIKU_NASM) {
				Exit "HAIKU_NASM not set. Please re-run configure." ;
			}

		case m68k :
			HAIKU_KERNEL_PLATFORM ?= atari_m68k ;
			HAIKU_BOOT_TARGETS += amiga_m68k atari_m68k ;
			switch $(HAIKU_KERNEL_PLATFORM) {
				case atari_m68k :
				{
					HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 1440 ; # in kB
				}
				case amiga_m68k :
				{
					# for now we have trouble reading from double-sided images
					HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 880 ; # in kB
				}
			}
			# offset in floppy image (>= sizeof(haiku_loader))
			HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 260 ; # in kB
			HAIKU_CONTAINER_STRIP_EXECUTABLES on
				$(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME) = 1 ;

		case * :
			Exit "Currently unsupported target CPU:" $(cpu) ;
	}

	# private kernel headers to be used when compiling kernel code
	HAIKU_PRIVATE_KERNEL_HEADERS =
		[ PrivateHeaders $(DOT) kernel libroot shared
			kernel/boot/platform/$(HAIKU_KERNEL_PLATFORM) ]
		[ ArchHeaders $(HAIKU_KERNEL_ARCH) ]
		[ FDirName $(HAIKU_COMMON_DEBUG_OBJECT_DIR_$(architecture)) system
			kernel ]
		$(HAIKU_PRIVATE_SYSTEM_HEADERS_$(architecture))
		;

	# C/C++ flags
	local ccBaseFlags = -finline -fno-builtin ;

	if $(gccVersion[1]) >= 4 {
		if $(HAIKU_CC_IS_CLANG_$(architecture)) != 1 {
			# Clang does not yet understand this flag.
			ccBaseFlags += -fno-semantic-interposition ;
		}

		ccBaseFlags += -ffreestanding ;
	}

	local c++BaseFlags = $(ccBaseFlags) -fno-exceptions ;

	if $(gccVersion[1]) >= 3 && $(HAIKU_CC_IS_CLANG_$(architecture)) != 1 {
		c++BaseFlags += -fno-use-cxa-atexit ;
	}

	HAIKU_KERNEL_CCFLAGS = $(HAIKU_CCFLAGS_$(architecture)) $(ccBaseFlags) ;
	HAIKU_KERNEL_C++FLAGS = $(HAIKU_C++FLAGS_$(architecture)) $(c++BaseFlags) ;
	HAIKU_KERNEL_PIC_CCFLAGS = ;
	HAIKU_KERNEL_PIC_LINKFLAGS = ;
	HAIKU_KERNEL_ADDON_LINKFLAGS = ;

	# Common boot-related cflags which apply to all loaders
	HAIKU_BOOT_CCFLAGS = $(HAIKU_CCFLAGS_$(architecture)) $(ccBaseFlags) ;
	HAIKU_BOOT_C++FLAGS = $(HAIKU_C++FLAGS_$(architecture)) $(c++BaseFlags) ;
	HAIKU_BOOT_LINKFLAGS = ;
	HAIKU_BOOT_LDFLAGS = -Bstatic ;

	# Remove -fPIC and other unwanted options from the BOOT flags (they are sometimes
	# added to force PIC in general.)
	local fixedBootCCFlags ;
	local fixedBootC++Flags ;
	for flag in $(HAIKU_BOOT_CCFLAGS) {
		if $(flag) = "-fpic" || $(flag) = "-fPIC" {
			continue ;
		}
		fixedBootCCFlags += $(flag) ;
	}
	for flag in $(HAIKU_BOOT_C++FLAGS) {
		if $(flag) = "-fpic" || $(flag) = "-fPIC" {
			continue ;
		}
		fixedBootC++Flags += $(flag) ;
	}
	HAIKU_BOOT_CCFLAGS = $(fixedBootCCFlags) ;
	HAIKU_BOOT_C++FLAGS = $(fixedBootC++Flags) ;

	# Any special kernel base addresses
	if $(HAIKU_BOOT_LOADER_BASE) {
		HAIKU_BOOT_LDFLAGS +=
			--defsym BOOT_LOADER_BASE=$(HAIKU_BOOT_LOADER_BASE) ;
	}

	switch $(cpu) {
		case arm :
			# Workaround for ld using 32k for alignment despite forcing it in the config...
			# should definitely not be needed!
			HAIKU_KERNEL_LINKFLAGS +=
				-Wl,-z -Wl,max-page-size=0x1000
				-Wl,-z -Wl,common-page-size=0x1000 ;

		case arm64 :
			# Workaround for ld using 32k for alignment despite forcing it in the config...
			# should definitely not be needed!
			HAIKU_KERNEL_LINKFLAGS +=
				-Wl,-z -Wl,max-page-size=0x1000
				-Wl,-z -Wl,common-page-size=0x1000 ;

			HAIKU_KERNEL_PIC_CCFLAGS = -fPIC ;
			HAIKU_KERNEL_PIC_LINKFLAGS = -shared -fPIC ;

		case ppc :
			# Build a position independent PPC kernel. We need to be able to
			# relocate the kernel, since the virtual address space layout at
			# boot time is not fixed.
			HAIKU_KERNEL_PIC_CCFLAGS = -fPIE ;
			HAIKU_KERNEL_PIC_LINKFLAGS = -shared -fPIE ;

		case m68k :
			# We don't want to have to handle emulating missing FPU opcodes for
			# 040 and 060 in the kernel.
			HAIKU_KERNEL_CCFLAGS += -mtune=68020-60 ;
			HAIKU_KERNEL_C++FLAGS += -mtune=68020-60 ;

		case riscv64 :
			# Kernel lives within any single 2 GiB address space.
			# Default is medlow (-2GiB / +2GiB)
			HAIKU_KERNEL_CCFLAGS += -mcmodel=medany ;
			HAIKU_KERNEL_C++FLAGS += -mcmodel=medany ;

		case x86 :
			HAIKU_KERNEL_PIC_CCFLAGS = -fno-pic ;
			HAIKU_KERNEL_CCFLAGS += -march=pentium ;
			HAIKU_KERNEL_C++FLAGS += -march=pentium ;

		case x86_64 :
			# Kernel lives in the top 2GB of the address space, use kernel code
			# model.
			HAIKU_KERNEL_PIC_CCFLAGS = -fno-pic -mcmodel=kernel ;

			# Disable the red zone, which cannot be used in kernel code due to
			# interrupts, and always enable the frame pointer so stack traces
			# are correct.
			HAIKU_KERNEL_CCFLAGS += -mno-red-zone -fno-omit-frame-pointer ;
			HAIKU_KERNEL_C++FLAGS += -mno-red-zone -fno-omit-frame-pointer ;
			HAIKU_KERNEL_PIC_LINKFLAGS += -z max-page-size=0x1000 ;
			HAIKU_KERNEL_ADDON_LINKFLAGS += -z max-page-size=0x1000 ;

			if x86 in $(HAIKU_ARCHS[2-]) || x86_gcc2 in $(HAIKU_ARCHS[2-]) {
				Echo "Enable kernel ia32 compatibility" ;
				HAIKU_KERNEL_DEFINES += _COMPAT_MODE ;
				HAIKU_KERNEL_COMPAT_MODE = 1 ;
			}
	}

	# bootloader-centric flags
	local bootTarget ;
	for bootTarget in $(HAIKU_BOOT_TARGETS) {
		switch $(bootTarget) {
			case efi :
				# efi bootloader is PIC
				HAIKU_BOOT_$(bootTarget:U)_CCFLAGS += -fpic -fno-stack-protector
					-fPIC -fshort-wchar -Wno-error=unused-variable -Wno-error=main ;
				HAIKU_BOOT_$(bootTarget:U)_C++FLAGS += -fpic -fno-stack-protector
					-fPIC -fshort-wchar -Wno-error=unused-variable -Wno-error=main ;
				switch $(cpu) {
					case x86 :
						if $(HAIKU_CC_IS_CLANG_$(architecture)) != 1 {
							HAIKU_BOOT_$(bootTarget:U)_CCFLAGS += -maccumulate-outgoing-args ;
							HAIKU_BOOT_$(bootTarget:U)_C++FLAGS += -maccumulate-outgoing-args ;
						}
					case x86_64 :
						HAIKU_BOOT_$(bootTarget:U)_CCFLAGS += -mno-red-zone ;
						HAIKU_BOOT_$(bootTarget:U)_C++FLAGS += -mno-red-zone ;
						if $(HAIKU_CC_IS_CLANG_$(architecture)) != 1 {
							HAIKU_BOOT_$(bootTarget:U)_CCFLAGS += -maccumulate-outgoing-args ;
							HAIKU_BOOT_$(bootTarget:U)_C++FLAGS += -maccumulate-outgoing-args ;
						}
				}
				HAIKU_BOOT_$(bootTarget:U)_LDFLAGS = -Bstatic -Bsymbolic
					-nostdlib -znocombreloc -no-undefined ;
			case bios_ia32 :
				# bios_ia32 is non-PIC
				HAIKU_BOOT_$(bootTarget:U)_CCFLAGS += -fno-pic -march=pentium ;
				HAIKU_BOOT_$(bootTarget:U)_C++FLAGS += -fno-pic -march=pentium ;
				if $(HAIKU_CC_IS_CLANG_$(architecture)) = 1 {
					HAIKU_BOOT_$(bootTarget:U)_LDFLAGS += -m elf_i386 ;
				} else {
					HAIKU_BOOT_$(bootTarget:U)_LDFLAGS += -m elf_i386_haiku ;
				}
				if $(gccVersion[1]) >= 3 {
					HAIKU_BOOT_$(bootTarget:U)_CCFLAGS += -Wno-error=main -m32 ;
					HAIKU_BOOT_$(bootTarget:U)_C++FLAGS += -Wno-error=main -m32 ;
				}
			case pxe_ia32 :
				# pxe_ia32 is non-PIC
				HAIKU_BOOT_$(bootTarget:U)_CCFLAGS += -fno-pic -march=pentium ;
				HAIKU_BOOT_$(bootTarget:U)_C++FLAGS += -fno-pic -march=pentium ;
				if $(HAIKU_CC_IS_CLANG_$(architecture)) = 1 {
					HAIKU_BOOT_$(bootTarget:U)_LDFLAGS += -m elf_i386 ;
				} else {
					HAIKU_BOOT_$(bootTarget:U)_LDFLAGS += -m elf_i386_haiku ;
				}
				if $(gccVersion[1]) >= 3 {
					HAIKU_BOOT_$(bootTarget:U)_CCFLAGS += -Wno-error=main -m32 ;
					HAIKU_BOOT_$(bootTarget:U)_C++FLAGS += -Wno-error=main -m32 ;
				}
			case * :
				# all other bootloaders are non-PIC
				HAIKU_BOOT_$(bootTarget:U)_CCFLAGS += -fno-pic -Wno-error=main ;
				HAIKU_BOOT_$(bootTarget:U)_C++FLAGS += -fno-pic -Wno-error=main ;
		}
	}

	# warning flags
	HAIKU_KERNEL_WARNING_CCFLAGS = $(HAIKU_WARNING_CCFLAGS_$(architecture)) ;
	HAIKU_KERNEL_WARNING_C++FLAGS = $(HAIKU_WARNING_C++FLAGS_$(architecture)) ;

	# debug flags
	local level ;
	for level in $(HAIKU_DEBUG_LEVELS) {
		local flags = $(HAIKU_DEBUG_FLAGS) [ FDefines DEBUG=$(level) ] ;
		HAIKU_KERNEL_DEBUG_$(level)_CCFLAGS
			= $(HAIKU_DEBUG_$(level)_CCFLAGS_$(architecture)) ;
		HAIKU_KERNEL_DEBUG_$(level)_C++FLAGS
			= $(HAIKU_DEBUG_$(level)_C++FLAGS_$(architecture)) ;
	}

	# defines
	HAIKU_KERNEL_DEFINES += _KERNEL_MODE ;

	HAIKU_DEFINES_$(architecture)
		+= BOOT_ARCHIVE_IMAGE_OFFSET=$(HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET) ;
		# TODO: That doesn't need to be a general define. It's just needed for
		# compiling (part of) the boot loader.

	# kernel add-on glue code
	HAIKU_KERNEL_ADDON_BEGIN_GLUE_CODE = <$(architecture)>crtbeginS.o
		<src!system!glue!$(architecture)>haiku_version_glue.o ;
	HAIKU_KERNEL_ADDON_END_GLUE_CODE = <$(architecture)>crtendS.o ;
}


rule ArchitectureSetupWarnings architecture
{
	# ArchitectureSetupWarnings <architecture> ;
	#
	# Sets up compiler warnings and error flags for various subdirectories for
	# the given packaging architecture.

	if $(HAIKU_CC_IS_CLANG_$(architecture)) = 1 {
		AppendToConfigVar CCFLAGS :
			HAIKU_TOP src system libroot posix glibc :
			-fgnu89-inline -fheinous-gnu-extensions : global ;
	}

	local cpu = $(HAIKU_CPU_$(architecture)) ;
	switch $(cpu) {
		case arm :
			return ;
				# we use #warning as placeholders for things to write...
		case m68k :
			return ;
				# we use #warning as placeholders for things to write...
		case ppc :
			return ;
				# we use #warning as placeholders for things to write...
	}

	# enable -Werror for certain parts of the source tree
	HAIKU_WERROR_ARCH = $(architecture) ;

	rule EnableWerror dirTokens : scope {
		# Clang gives way more warnings than GCC, so that code won't compile
		# with -Werror when using Clang.
		if $(HAIKU_CC_IS_CLANG_$(architecture)) != 1 {
			SetConfigVar WARNINGS : HAIKU_TOP $(dirTokens) : treatAsErrors
				: $(scope) ;
		}
	}

	# Work-around for GCC 2 problem -- despite -Wno-multichar it reports
	# multichar warnings in headers/private/kernel/debugger_keymaps.h included
	# by src/system/kernel/arch/x86/arch_debug_console.cpp.
	local gccVersion = $(HAIKU_GCC_VERSION_$(architecture)) ;
	if $(gccVersion[1]) = 2 {
		local file = <src!system!kernel!arch!x86>arch_debug_console.o ;
		WARNINGS on $(file) = $(WARNINGS) ;
	}

	EnableWerror src add-ons accelerants ;
	EnableWerror src add-ons bluetooth ;
	EnableWerror src add-ons decorators ;
	EnableWerror src add-ons disk_systems ;
	EnableWerror src add-ons input_server devices ;
	EnableWerror src add-ons input_server filters ;
#	EnableWerror src add-ons input_server methods pen ;
	EnableWerror src add-ons input_server methods t9 ;
	EnableWerror src add-ons kernel bluetooth ;
	EnableWerror src add-ons kernel bus_managers acpi ;
	EnableWerror src add-ons kernel bus_managers agp_gart ;
	EnableWerror src add-ons kernel bus_managers ata ;
	EnableWerror src add-ons kernel bus_managers config_manager ;
#	EnableWerror src add-ons kernel bus_managers firewire ;
	EnableWerror src add-ons kernel bus_managers ide ;
	EnableWerror src add-ons kernel bus_managers isa ;
	EnableWerror src add-ons kernel bus_managers pci ;
	EnableWerror src add-ons kernel bus_managers ps2 ;
	EnableWerror src add-ons kernel bus_managers random ;
	EnableWerror src add-ons kernel bus_managers scsi ;
	EnableWerror src add-ons kernel bus_managers tty ;
	EnableWerror src add-ons kernel bus_managers usb ;
	EnableWerror src add-ons kernel bus_managers virtio ;
	EnableWerror src add-ons kernel busses agp_gart ;
	EnableWerror src add-ons kernel busses ata ;
	EnableWerror src add-ons kernel busses scsi ;
	EnableWerror src add-ons kernel busses usb ;
	EnableWerror src add-ons kernel console ;
	EnableWerror src add-ons kernel cpu ;
#	EnableWerror src add-ons kernel debugger ; # gcc2
#	EnableWerror src add-ons kernel drivers audio ;
	EnableWerror src add-ons kernel drivers bluetooth ;
#	EnableWerror src add-ons kernel drivers bus ;
	EnableWerror src add-ons kernel drivers common ;
#	EnableWerror src add-ons kernel drivers disk ;
	EnableWerror src add-ons kernel drivers dvb ;
#	EnableWerror src add-ons kernel drivers graphics ;
	EnableWerror src add-ons kernel drivers graphics intel_extreme ;
#	EnableWerror src add-ons kernel drivers input ;
	EnableWerror src add-ons kernel drivers joystick ;
	EnableWerror src add-ons kernel drivers midi ;
	EnableWerror src add-ons kernel drivers misc ;
#	EnableWerror src add-ons kernel drivers network ;
	EnableWerror src add-ons kernel drivers ports ;
#	EnableWerror src add-ons kernel drivers power ;
	EnableWerror src add-ons kernel drivers printer ;
	EnableWerror src add-ons kernel drivers random ;
	EnableWerror src add-ons kernel drivers tty ;
	EnableWerror src add-ons kernel drivers video ;
	EnableWerror src add-ons kernel file_systems bfs ;
	EnableWerror src add-ons kernel file_systems cdda ;
#	EnableWerror src add-ons kernel file_systems ext2 ;
#	EnableWerror src add-ons kernel file_systems fat ;
#	EnableWerror src add-ons kernel file_systems googlefs ;
	EnableWerror src add-ons kernel file_systems iso9660 ;
	EnableWerror src add-ons kernel file_systems layers ;
#	EnableWerror src add-ons kernel file_systems netfs ;
#	EnableWerror src add-ons kernel file_systems nfs ;
	EnableWerror src add-ons kernel file_systems nfs4 ;
#	EnableWerror src add-ons kernel file_systems ntfs ;
	EnableWerror src add-ons kernel file_systems packagefs ;
#	EnableWerror src add-ons kernel file_systems ramfs ;
#	EnableWerror src add-ons kernel file_systems reiserfs ;
	EnableWerror src add-ons kernel file_systems udf ;
	EnableWerror src add-ons kernel file_systems userlandfs ;
	EnableWerror src add-ons kernel generic ;
#	EnableWerror src add-ons kernel network datalink_protocols ;
	EnableWerror src add-ons kernel network devices ;
	EnableWerror src add-ons kernel network dns_resolver ;
	EnableWerror src add-ons kernel network notifications ;
	EnableWerror src add-ons kernel network ppp ;
	EnableWerror src add-ons kernel network protocols ;
#	EnableWerror src add-ons kernel network stack ;
	EnableWerror src add-ons kernel partitioning_systems ;
	EnableWerror src add-ons kernel power ;
	EnableWerror src add-ons locale ;
	EnableWerror src add-ons mail_daemon ;
	EnableWerror src add-ons media media-add-ons demultiplexer ;
	EnableWerror src add-ons media media-add-ons dvb ;
	EnableWerror src add-ons media media-add-ons esound_sink ;
	EnableWerror src add-ons media media-add-ons finepix_webcam ;
	EnableWerror src add-ons media media-add-ons firewire_dv ;
	EnableWerror src add-ons media media-add-ons legacy ;
	EnableWerror src add-ons media media-add-ons mixer ;
	EnableWerror src add-ons media media-add-ons multi_audio ;
	EnableWerror src add-ons media media-add-ons opensound ;
	EnableWerror src add-ons media media-add-ons radeon ;
	EnableWerror src add-ons media media-add-ons reader ;
	EnableWerror src add-ons media media-add-ons tone_producer_demo ;
	EnableWerror src add-ons media media-add-ons usb_vision ;
#	EnableWerror src add-ons media media-add-ons usb_webcam ;
	EnableWerror src add-ons media media-add-ons video_mixer ;
#	EnableWerror src add-ons media media-add-ons video_producer_demo ;
	EnableWerror src add-ons media media-add-ons videowindow ;
	EnableWerror src add-ons media media-add-ons writer ;
	EnableWerror src add-ons media plugins ape_reader ;
	EnableWerror src add-ons media plugins au_reader ;
#	EnableWerror src add-ons media plugins ffmpeg ;
#	EnableWerror src add-ons media plugins raw_decoder ;
	EnableWerror src add-ons print ;
	EnableWerror src add-ons screen_savers ;
	EnableWerror src add-ons tracker ;
	EnableWerror src add-ons translators bmp ;
	EnableWerror src add-ons translators exr ;
	EnableWerror src add-ons translators gif ;
	EnableWerror src add-ons translators hvif ;
	EnableWerror src add-ons translators ico ;
	EnableWerror src add-ons translators jpeg ;
#	EnableWerror src add-ons translators jpeg2000 ;
	EnableWerror src add-ons translators pcx ;
	EnableWerror src add-ons translators png ;
	EnableWerror src add-ons translators ppm ;
	EnableWerror src add-ons translators raw ;
	EnableWerror src add-ons translators rtf ;
	EnableWerror src add-ons translators sgi ;
	EnableWerror src add-ons translators shared ;
	EnableWerror src add-ons translators stxt ;
	EnableWerror src add-ons translators tga ;
	EnableWerror src add-ons translators tiff ;
	EnableWerror src add-ons translators wonderbrush ;
	EnableWerror src add-ons print ;
	EnableWerror src bin desklink ;
	EnableWerror src bin multiuser ;
	EnableWerror src bin package ;
	EnableWerror src bin package_repo ;
	EnableWerror src bin pkgman ;
	EnableWerror src libs bsd ;
	EnableWerror src apps ;
	EnableWerror src kits ;
	EnableWerror src preferences ;
	EnableWerror src servers ;
	EnableWerror src system boot ;
	EnableWerror src system kernel ;
	EnableWerror src system libroot add-ons ;
	EnableWerror src system libroot os ;
	EnableWerror src system libroot posix locale ;
	EnableWerror src system libroot posix wchar ;
	EnableWerror src system runtime_loader ;
}


rule MultiArchIfPrimary ifValue : elseValue : architecture
{
	# MultiArchIfPrimary <ifValue> : <elseValue>
	#	[ : <architecture> = $(TARGET_PACKAGING_ARCH) ] ;
	#
	# Returns one of the two given values depending on whether
	# <architecture> is the primary packaging architecture.

	architecture ?= $(TARGET_PACKAGING_ARCH) ;

	if $(architecture) = $(TARGET_PACKAGING_ARCHS[1]) {
		return $(ifValue) ;
	}
	return $(elseValue) ;
}


rule MultiArchConditionalGristFiles files : primaryGrist : secondaryGrist
	: architecture
{
	# MultiArchConditionalGristFiles <files> : <primaryGrist>
	#	: <secondaryGrist> [ : <architecture> = $(TARGET_PACKAGING_ARCH) ] ;
	#
	# Returns <files> with their grist set to either <primaryGrist> or
	# <secondaryGrist> depending on whether <architecture> is the primary
	# packaging architecture.

	architecture ?= $(TARGET_PACKAGING_ARCH) ;

	local grist = [ MultiArchIfPrimary $(primaryGrist) : $(secondaryGrist)
		: $(architecture) ] ;
	return $(files:G=$(grist:E=)) ;
}


rule MultiArchDefaultGristFiles files : gristPrefix : architecture
{
	# MultiArchDefaultGristFiles <files> : <gristPrefix>
	#	[ : <architecture> = $(TARGET_PACKAGING_ARCH) ] ;
	#
	# Convenient shorthand for MultiArchConditionalGristFiles for the common
	# case that for a secondary packaging architecture the packaging
	# architecture name shall be appended to the grist while it shall be omitted
	# for the primary packaging architecture. IOW, if architecture is the
	# primary packaging architecture, <files> are returned with their grist set
	# to <gristPrefix>, otherwise <files> are returned with their grist set to
	# <gristPrefix>!<architecture> respectively <architecture> (if <gristPrefix>
	# is empty).

	architecture ?= $(TARGET_PACKAGING_ARCH) ;

	local secondaryGrist = $(gristPrefix)!$(architecture) ;
	secondaryGrist ?= $(architecture) ;

	return [ MultiArchConditionalGristFiles $(files) : $(gristPrefix) :
		$(secondaryGrist) : $(architecture) ] ;
}


rule MultiArchSubDirSetup architectures
{
	# MultiArchSubDirSetup <architectures> ;
	#
	# For each of the given packaging architectures <architectures> that are
	# in the packaging architectures configured for the build (or all configured
	# packaging architectures, if <architectures> is empty) an object is
	# prepared that can be used for an "on ... { ... }" block to set up subdir
	# variables for the respective packaging architecture. Most notably
	# TARGET_PACKAGING_ARCH, TARGET_ARCH are set to the values for the
	# respective packaging architecture. The per-subdir variables SOURCE_GRIST,
	# LOCATE_TARGET, LOCATE_SOURCE, SEARCH_SOURCE, *_LOCATE_TARGET, are reset.
	# All SUBDIR* and config variables are set to the values they had when this
	# rule was invoked.

	local result ;
	architectures ?= $(TARGET_PACKAGING_ARCHS) ;
	local architecture ;
	for architecture in $(architectures) {
		if ! $(architecture) in $(TARGET_PACKAGING_ARCHS) {
			continue ;
		}

		local architectureObject = $(architecture:G=<arch-object>) ;
		result += $(architectureObject) ;

		# Set the variables that default to the values of the respective
		# variables for the primary architecture.
		TARGET_PACKAGING_ARCH on $(architectureObject) = $(architecture) ;

		local var ;
		for var in TARGET_ARCH {
			$(var) on $(architectureObject) = $($(var)_$(architecture)) ;
		}

		# Clone the current config variable values and the variables SubDir
		# resets.
		for var in $(AUTO_SET_UP_CONFIG_VARIABLES) SUBDIR$(SUBDIRRESET) {
			$(var) on $(architectureObject) = $($(var)) ;
		}

		# adjust SOURCE_GRIST and HDRGRIST
		SOURCE_GRIST on $(architectureObject)
			= $(SOURCE_GRIST:E=)!$(architecture) ;

		HDRGRIST on $(architectureObject)
			= $(HDRGRIST:E=)!$(architecture) ;

		# Adjust the subdir's object dirs that are architecture dependent. To
		# avoid duplicating the code from SetupObjectsDir, we call it. Since it
		# sets global variables, we set these variables on our object, call
		# SetupObjectsDir in an "on" block, and grab the new variable values.
		local hostTarget = HOST TARGET ;
		local objectDirVars =
			COMMON_ARCH COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS)
			;
		objectDirVars =
			COMMON_PLATFORM_LOCATE_TARGET
			$(hostTarget)_$(objectDirVars)_LOCATE_TARGET
			LOCATE_TARGET
			LOCATE_SOURCE
			SEARCH_SOURCE
			;

		for var in $(objectDirVars) {
			$(var) on $(architectureObject) = ;
		}

		on $(architectureObject) {
			SetupObjectsDir ;

			for var in $(objectDirVars) {
				$(var) on $(architectureObject) = $($(var)) ;
			}
		}
	}

	return $(result) ;
}