forked from rebolsource/r3
-
Notifications
You must be signed in to change notification settings - Fork 27
/
make.r
2125 lines (1871 loc) · 67.6 KB
/
make.r
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
REBOL [
Title: "Top-Level Script for building Rebol"
File: %make.r
Rights: {
Rebol 3 Language Interpreter and Run-time Environment
"Ren-C" branch @ https://github.com/metaeducation/ren-c
Copyright 2012-2019 Ren-C Open Source Contributors
REBOL is a trademark of REBOL Technologies
}
Description: {
See notes on building in README.md
}
Warning: {
This code is not representative of modern practices, because it has
to run in a very old bootstrap executable. It is also very much a
hodgepodge just to keep things running. It's the absolute wrong place
to be looking for exemplary Ren-C code.
}
]
if trap [:import/into] [ ; See %import-shim.r
do load append copy system/script/path %tools/import-shim.r
]
import <tools/bootstrap-shim.r>
import <tools/common.r> ; Note: sets up `repo-dir`
import <tools/platforms.r>
rebmake: import <tools/rebmake.r>
=== "ADJUST TO AN OUT-OF-SOURCE BUILD IF RUN FROM REPOSITORY's DIRECTORY" ===
; NOTE NEW BEHAVIOR IN REN-C, DIFFERENT FROM HISTORICAL REBOL:
;
; When you run a Ren-C script from the command line, the `current-path` is the
; directory where the user was when the script launched.
;
; We default to building in a subdirectory called %build/ if they launch from
; the repository directory itself. Otherwise we build wherever they are.
if repo-dir = what-dir [
launched-from-root: true
output-dir: join repo-dir %build/
make-dir output-dir
] else [
output-dir: what-dir ; out-of-source build
launched-from-root: false
]
tools-dir: join repo-dir %tools/
src-dir: join repo-dir %src/
=== "GLOBALS" ===
; The file list for the core .c files comes from %file-base.r, while the
; file list for extensions comes from that extension's %make-spec.r
;
file-base: make object! load (join repo-dir %tools/file-base.r)
; Start out with a default configuration (may be overridden)
;
user-config: make object! load (join repo-dir %configs/default-config.r)
=== "SPLIT ARGS INTO OPTIONS AND COMMANDS" ===
; Note that we should have launched %make.r with the notion of the current
; directory (WHAT-DIR) being the same as what the user had on the command line.
; So relative paths should be interpreted the same.
; args are:
; [OPTION | COMMAND] ...
; COMMAND = WORD
; OPTION = 'NAME=VALUE' | 'NAME: VALUE'
;
args: parse-args system/script/args ; either from command line or DO/ARGS
; now args are ordered and separated by bar:
; [NAME VALUE ... '| COMMAND ...]
;
if (commands: find args '|) [
options: copy/part args commands
commands: next commands
]
else [
options: args
]
for-each [name value] options [
switch name [
'CONFIG [
; A config file can inherit from other configurations with the
; `Inherits: %some-config.r` header option.
;
config: to-file value
saved-dir: what-dir
; Because the goal is to create an OBJECT! from the top-level
; declarations in the file, this has to build an inheritance stack.
; It must tunnel to the innermost configs and run those first...
; otherwise, the outermost configs wouldn't have the innermost
; config fields visible when the run.
;
config-stack: copy []
while [:config] [
file: split-path/dir config inside [] 'dir
change-dir dir
append config-stack (load read file)
; !!! LOAD has changed between bootstrap versions, for the
; handling of the /HEADER. This just transcodes the file
; again to extract the "Inherits" information.
;
; Note: Inherits may be a good non-config-specific feature.
;
let temp: transcode read file
assert ['REBOL = first temp]
config: select ensure block! second temp 'Inherits
]
while [not empty? config-stack] [
user-config: make user-config take/last config-stack
]
change-dir saved-dir
]
'EXTENSIONS [
; [+|-|*] [NAME {+|-|*|[modules]}]...
use [ext-file user-ext][
user-ext: load value
if not block? user-ext [
fail [
"Selected extensions must be a block, not"
(kind of user-ext)
]
]
all [
not empty? user-ext
find [+ - *] user-ext/1
] then [
value: take user-ext
]
for-each [name value] user-ext [
user-config/extensions/:name: value
]
]
]
] else [
set has user-config (to-word replace/all to text! name #"_" #"-")
attempt [load-value value] else [value]
]
]
=== "CHANGE DIRECTORY" ===
; The baseline directory we are in during the build is where we are writing
; the output products.
;
; But we don't want to actually change to that directory until all the paths
; in the command line were processed, because that was the user's concept of
; where `../` or other relative paths were relative to.
change-dir output-dir
; We relativize `repo-dir` to the output directory, where the build process
; is being run. Using relative paths helps gloss over some Windows and Linux
; differences on file paths. It's also more readable to have short filenames
; like `..\src\foo.c` instead of `C:\Wherever\Deep\Path\src\foo.c` on
; compiliation command lines.
;
repo-dir: relative-to-path repo-dir output-dir
=== "PROCESS COMMANDS" ===
if commands [user-config/target: null] ; was `target: load commands` Why? :-/
=== "MODULES AND EXTENSIONS" ===
platform-config: configure-platform user-config/os-id
rebmake/set-target-platform platform-config/os-base
to-obj-path: func [
return: [file!]
file [any-string?]
][
let ext: find-last file #"."
remove/part ext (length of ext)
return join %objs/ head-of append ext rebmake/target-platform/obj-suffix
]
gen-obj: func [
return: "Rebmake specification object for OBJ"
[object!]
s "file representation, or list if block"
[file! text! word! path! tuple! block!]
/dir "directory" [any-string?]
/D "definitions" [block!]
/I "includes" [block!]
/F "cflags" [block!]
/main "for main object"
][
let prefer-O2: false ; overrides -Os to give -O2, e.g. for %c-eval.c
let standard: user-config/standard ; may have a per-file override
let rigorous: user-config/rigorous ; may have a per-file override
let cplusplus: false ; determined for just this file
let flags: make block! 8
; Microsoft shouldn't bother having the C warning that foo() in standard
; C doesn't mean the same thing as foo(void), when in their own published
; headers (ODBC, Windows.h) they treat them interchangeably. See for
; instance EnableMouseInPointerForThread(). Or ODBCGetTryWaitValue().
;
; Just disable the warning, and hope the Linux build catches most of it.
;
; 'function' : no function prototype given:
; converting '()' to '(void)'
;
append flags <msc:/wd4255>
; Warnings when __declspec(uuid(x)) is used on types, or __declspec is
; used before linkage specifications, etc. etc. These are violated
; e.g. by older versions of %shlobj.h and %ocidl.h. You can get them if
; you use something like a Windows XP-era SDK with a more modern Visual
; Studio compiler (e.g. 2019, which deprecated support for targeting XP).
;
append flags spread [<msc:/wd4917> <msc:/wd4768> <msc:/wd4091>]
; The May 2018 update of Visual Studio 2017 added a warning for when you
; use an #ifdef on something that is #define'd, but 0. Then the internal
; %yvals.h in MSVC tests #ifdef __has_builtin, which has to be defined
; to 0 to work in MSVC. Disable the warning for now.
;
append flags <msc:/wd4574>
; Building as C++ using nmake seems to trigger this warning to say there
; is no exception handling policy in place. We don't use C++ exceptions
; in the C++ build, so we ignore the warning...but if exceptions were used
; there'd have to be an implementation choice made there.
;
append flags <msc:/wd4577>
; There's a warning on reinterpret_cast between related classes, trying to
; suggest you use static_cast instead. This complicates the `cast` macro
; tricks, which just use reinterpret_cast.
;
append flags <msc:/wd4946>
if block? s [
for-each flag next s [
switch flag [
#no-c++ [
;
; !!! The cfg-cplusplus flag is currently set if any files
; are C++. This means that it's a fair indication that
; a previous call to this routine noticed a C++ compiler
; is in effect, e.g. the config maps `gcc` tool to `%g++`.
;
if cfg-cplusplus [
standard: 'c
; Here we inject "compile as c", but to limit the
; impact (e.g. on C compilers that don't know what -x
; is) we only add the flag if it's a C++ build. MSVC
; does not need this because it uses the same
; compiler and only needs switches to turn C++ *on*.
;
append flags <gnu:-x c>
]
]
]
]
]
; Add flags to take into account whether building as C or C++, and which
; version of the standard. Note if the particular file is third party and
; can only be compiled as C, we may have overridden that above.
;
insert flags spread switch standard [
'c [
[] ; empty for spread
]
'gnu89 'c99 'gnu99 'c11 [
reduce [
to tag! unspaced ["gnu:--std=" standard]
;
; Note: MSVC does not have any conformance to C99 or C11 at
; time of writing, and will complain about /std:c99 ... it only
; supports /std:c++11 and /std:c++17 so we basically have to
; just ignore the C versioning in MSVC.
]
]
'c++ [
cfg-cplusplus: cplusplus: true
[
<gnu:-x c++>
<msc:/TP>
]
]
'c++98 'c++0x 'c++11 'c++14 'c++17 'c++20 'c++latest [
cfg-cplusplus: cplusplus: true
compose [
; Compile C files as C++.
;
; !!! Original code appeared to make it so that if a Visual
; Studio project was created, `/TP` option gets removed and it
; was translated into XML under the <CompileAs> option. But
; that meant extensions weren't getting the option, so it has
; been disabled pending review.
;
; !!! For some reason, clang has deprecated`-x c++`, though
; it still works. It is not possible to disable the warning,
; so RIGOROUS can not be used with clang in C++ builds...
; the files would (sadly) need to be renamed to .cpp or .cxx
;
<msc:/TP>
<gnu:-x c++>
; C++ standard, MSVC only supports "c++14/17/latest"
;
(to tag! unspaced ["gnu:--std=" user-config/standard])
(to tag! unspaced [
"msc:/std:" lowercase to text! user-config/standard
])
; There is a shim for `nullptr` used, that's warned about even
; when building as pre-C++11 where it was introduced, unless
; you disable that warning.
;
(if user-config/standard = 'c++98 [<gnu:-Wno-c++0x-compat>])
; Note: The C and C++ user-config/standards do not dictate if
; `char` is signed or unsigned. If you think environments
; all settled on them being signed, they're not... Android NDK
; uses unsigned:
;
; http://stackoverflow.com/questions/7414355/
;
; In order to give the option some exercise, make GCC C++
; builds use unsigned chars.
;
<gnu:-funsigned-char>
; MSVC never bumped the __cplusplus version past 1997, even if
; you compile with C++17. Hence CPLUSPLUS_11 is used by Rebol
; code as the switch for most C++ behaviors, and we have to
; define that explicitly.
;
<msc:/DCPLUSPLUS_11=1>
]
]
fail [
"STANDARD should be one of"
"[c gnu89 gnu99 c99 c11 c++ c++11 c++14 c++17 c++latest]"
"not" (user-config/standard)
]
]
; The `rigorous: yes` setting in the config turns the warnings up to where
; they are considered errors. However, there are a *lot* of warnings
; when you turn things all the way up...and not all of them are relevant.
; Still we'd like to get the best information from any good ones, so
; they're turned off on a case-by-case basis.
;
; NOTE: Microsoft's own header files aren't compliant with the errors in
; their own /Wall. So most people use /W4. It's a matter of philosophy
; whether GCC's definition of /Wall or /W4 is the right one ("all warnings"
; could mean even those which might not be useful, in which case Microsoft
; is more correct).
;
; https://stackoverflow.com/a/4001759
;
; For the moment we still use /Wall and omit any errors triggered in MS's
; own headers
;
append flags spread switch rigorous [
~true~ 'yes 'on 'true [
compose [
<gnu:-Werror> <msc:/WX> ; convert warnings to errors
; If you use pedantic in a C build on an older GNU compiler,
; (that defaults to thinking it's a C89 compiler), it will
; complain about using `//` style comments. There is no
; way to turn this complaint off. So don't use pedantic
; warnings unless you're at c99 or higher, or C++.
;
(if not find [c gnu89] standard [<gnu:--pedantic>])
<gnu:-Wextra>
<gnu:-Wall>
<msc:/Wall> ; see note above why we use instead of /W4
<gnu:-Wchar-subscripts>
<gnu:-Wwrite-strings>
<gnu:-Wundef>
<gnu:-Wformat=2>
<gnu:-Wdisabled-optimization>
<gnu:-Wlogical-op>
<gnu:-Wredundant-decls>
<gnu:-Woverflow>
<gnu:-Wpointer-arith>
<gnu:-Wparentheses>
<gnu:-Wmain>
<gnu:-Wtype-limits>
<gnu:-Wclobbered>
; Neither C++98 nor C89 had "long long" integers, but they
; were fairly pervasive before being present in the standard.
;
<gnu:-Wno-long-long>
; When constness is being deliberately cast away, `m_cast` is
; used (for "m"utability). However, this is just a plain cast
; in C as it has no const_cast. Since the C language has no
; way to say you're doing a mutability cast on purpose, the
; warning can't be used... but assume the C++ build covers it.
;
; !!! This is only checked by default in *release* C++ builds,
; because the performance and debug-stepping impact of the
; template stubs when they aren't inlined is too troublesome.
(
either all [
cplusplus
find app-config/definitions "NDEBUG"
][
<gnu:-Wcast-qual>
][
<gnu:-Wno-cast-qual>
]
)
; 'bytes' bytes padding added after construct 'member_name'
;
; Disable warning C4820; just tells you struct is not an
; exactly round size for the platform.
;
<msc:/wd4820>
; Without disabling this, you likely get:
;
; '_WIN32_WINNT_WIN10_TH2' is not defined as a preprocessor
; macro, replacing with '0' for '#if/#elif'
;
; Seems to be some mistake on Microsoft's part, that some
; report can be remedied by using WIN32_LEAN_AND_MEAN:
;
; https://stackoverflow.com/q/11040133/
;
; But then if you include <winioctl.h> (where the problem is)
; you'd still have it.
;
<msc:/wd4668>
; There are a currently a lot of places where `int` is passed
; to REBLEN, where the signs mismatch. Disable C4365:
;
; 'action' : conversion from 'type_1' to 'type_2',
; signed/unsigned mismatch
;
; and C4245:
;
; 'conversion' : conversion from 'type1' to 'type2',
; signed/unsigned mismatch
;
<msc:/wd4365> <msc:/wd4245>
<gnu:-Wsign-compare>
; The majority of Rebol's C code was written with little
; attention to overflow in arithmetic. In many places a
; bigger type is converted into a smaller type without an
; explicit cast. (REBI64 => SQLUSMALLINT, REBINT => Byte).
; Disable C4242:
;
; 'identifier' : conversion from 'type1' to 'type2',
; possible loss of data
;
; The issue needs systemic review.
;
<msc:/wd4242>
<gnu:-Wno-conversion> <gnu:-Wno-strict-overflow>
;<gnu:-Wstrict-overflow=5>
; Warning about std::is_pod<OptionWrapper<const Value*>>
; having a different answer in different versions, affects the
; UNUSED() variable corrupting in debug build, not a big issue.
;
<msc:/wd4647>
; When an inline function is not referenced, there can be a
; warning about this; but it makes little sense to do so since
; there are a many standard library functions in includes that
; are inline which one does not use (C4514):
;
; 'function' : unreferenced inline function has been removed
;
; Inlining is at the compiler's discretion, it may choose to
; ignore the `inline` keyword. Usually it won't tell you it
; did, but disable the warning that tells you (C4710):
;
; function' : function not inlined
;
; There's also an "informational" warning telling you that a
; function was chosen for inlining when it wasn't requested,
; so disable that also (C4711):
;
; function 'function' selected for inline expansion
;
<msc:/wd4514>
<msc:/wd4710>
<msc:/wd4711>
; It's useful to know when function pointers are assigned to
; an incompatible type of function pointer. But Rebol relies
; on the ability to have a kind of "void*-for-functions", e.g.
; CFunction, which holds arbitrary function pointers. There seems
; to be no way to get function pointer type checking allowing
; downcasts and upcasts from just that pointer type, so it
; has to be completely disabled (or managed with #pragma,
; which we seek to avoid using in the codebase)
;
; 'operator/operation' : unsafe conversion from
; 'type of expression' to 'type required'
;
<msc:/wd4191>
; Though we make sure all enum values are handled with a
; `default:`, this warning doesn't let you use default:` at
; all...forcing every case to be handled explicitly.
;
; enumerator 'identifier' in switch of enum 'enumeration'
; is not explicitly handled by a case label
;
<msc:/wd4061>
; implicit fall-through looking for [[fallthrough]]
;
<msc:/wd5262>
; setjmp() / longjmp() can't be combined with C++ objects due
; to bypassing destructors. Yet Microsoft's compiler seems to
; think even "POD" (plain-old-data) structs qualify as
; "C++ objects", so they run destructors (?)
;
; interaction between 'function' and C++ object destruction
; is non-portable
;
; This is lousy, since it would be a VERY useful warning, if
; not as uninformative as "your C++ program is using setjmp".
;
; https://stackoverflow.com/q/45384718/
;
<msc:/wd4611>
; Assignment within conditional expressions is tolerated in
; core if parentheses are used. `if ((x = 10) != y) {...}`
;
; assignment within conditional expression
;
<msc:/wd4706>
; gethostbyname() is deprecated by Microsoft, but dealing with
; that is not a priority now. It's supposed to be replaced
; with getaddrinfo() or GetAddrInfoW(). This bypasses the
; deprecation warning for now via a #define
;
<msc:/D_WINSOCK_DEPRECATED_NO_WARNINGS>
; This warning happens a lot in a 32-bit builds if you use
; float instead of double in Microsoft Visual C++:
;
; storing 32-bit float result in memory, possible loss
; of performance
;
<msc:/wd4738>
; For some reason, even if you don't actually invoke moves or
; copy constructors, MSVC warns you that you wouldn't be able
; to if you ever did. :-/
;
<msc:/wd5026>
<msc:/wd4626>
<msc:/wd5027>
<msc:/wd4625>
; If a function hasn't been explicitly declared as nothrow,
; passing it to extern "C" routines gets a warning. This is a
; C codebase being built as C++, so there shouldn't be throws.
;
<msc:/wd5039>
; Microsoft's own xlocale/xlocnum/etc. files trigger SEH
; warnings in VC2017 after an update. Apparently they don't
; care--presumably because they're focused on VC2019 now.
;
<msc:/wd4571>
; Same deal with format strings not being string literals.
; Headers in string from MSVC screws this up.
;
<msc:/wd4774>
; There's really no winning with Spectre mitigation warnings.
; Early on it seemed simple changes could make them go away:
;
; https://stackoverflow.com/q/50399940/
;
; But each version of the compiler adds more, thus it looks
; like if you use a comparison operator you will get these.
; It's a losing battle, so just disable the warning.
;
<msc:/wd5045>
; Arithmetic overflow: Using operator '*' on a 4 byte value
; and then casting the result to a 8 byte value. Cast the
; value to the wider type before calling operator '*' to
; avoid overflow
;
; Overflow issues are widespread in Rebol, and this warning
; is not particularly high priority in the scope of what the
; project is exploring. Disable for now.
;
<msc:/wd26451>
; The enum type xxx is unscoped. Prefer 'enum class' over
; 'enum'
; xxx is uninitialized. Always initialize a member...
;
; Ren-C is C, so C++-specific warnings when building as C++
; are not relevant.
;
<msc:/wd26812>
<msc:/wd26495>
; Implicit conversion from `int` to `REBD32`, possible loss.
;
<msc:/wd5219>
; const variable is not used, triggers in MS's type_traits
;
<msc:/wd5264>
]
]
~false~ 'no 'off 'false [
[] ; empty for SPREAD
]
fail ["RIGOROUS [yes no \logic?!\] not" (rigorous)]
]
; Now add the flags for the project overall.
;
append flags maybe spread F
; Now add build flags overridden by the inclusion of the specific file
; (e.g. third party files we don't want to edit to remove warnings from)
;
if block? s [
for-each flag next s [
append flags maybe spread degrade (switch flag [ ; boot ELSE, ()
<no-uninitialized> [
[
<gnu:-Wno-uninitialized>
;-Wno-unknown-warning seems to only modify the
; immediately following option
;
;<gnu:-Wno-unknown-warning>
;<gnu:-Wno-maybe-uninitialized>
<msc:/wd4701> <msc:/wd4703>
]
]
<no-sign-compare> [
[
<gnu:-Wno-sign-compare>
<msc:/wd4388>
<msc:/wd4018> ; a 32-bit variant of the error
]
]
<implicit-fallthru> [
[
<gnu:-Wno-unknown-warning>
<gnu:-Wno-implicit-fallthrough>
]
]
<no-unused-parameter> [
[<gnu:-Wno-unused-parameter>]
]
<no-shift-negative-value> [
[<gnu:-Wno-shift-negative-value>]
]
<no-make-header> [
;for make-header. ignoring
[]
]
<no-unreachable> [
[<msc:/wd4702>]
]
<no-hidden-local> [
[<msc:/wd4456>]
]
<no-constant-conditional> [
[<msc:/wd4127>]
]
#prefer-O2-optimization [
prefer-O2: true
[]
]
#no-c++ [
standard: 'c
[]
]
] else [
reduce [ensure [text! tag!] flag]
])
]
s: s/1
]
; With the flags and settings ready, make a rebmake object and ask it
; to build the requested object file.
;
return make rebmake/object-file-class compose [
assert [any [file? s path? s tuple? s word? s]]
; ^-- e.g. TUPLE! like `foo.o`
; !!! Note: The TEXT! => FILE! conversions of dir and src-dir are
; important, because if source here comes back as a text something
; filters it out. rebmake is a hairball that is destined for complete
; rewrite or the recycle bin...so investigating to find why TEXT! isn't
; an error and just gets dropped on the floor to make a bad makefile
; isn't a priority at the instant I'm writing this comment. Just
; convert the dirs to FILE!.
;
source: case [
dir [
assert [any [file? dir text? dir]]
if text? dir [
dir: to file! dir
]
join dir (to file! s)
]
main [to-file s]
] else [
assert [any [file? src-dir text? src-dir]]
if text? src-dir [
src-dir: to file! src-dir
]
join src-dir (to file! s)
]
output: to-obj-path to text! ;\
either main [
join %main/ to file! (last ensure path! s)
] [s]
cflags: either empty? flags [_] [flags]
definitions: D
includes: I
(if prefer-O2 [[optimization: #prefer-O2-optimization]])
]
]
extension-class: make object! [
class: #extension
name: ~
loadable: yes ;can be loaded at runtime
mode: null ; [<builtin> <dynamic>] or unused
modules: null
source: null ; main script
depends: null ; additional C files compiled in
requires: null ; it might require other extensions
includes: null
definitions: null
cflags: null
searches: null
libraries: null
ldflags: null
hook: null ; FILE! of extension-specific Rebol script to run during rebmake
use-librebol: false ; default right now is use %sys-core.h
; Internal Fields
sequence: null ; the sequence in which the extension should be loaded
visited: false
directory: meth [
return: [text!] ; Should this be [file!]?
][
return lowercase to text! name ; !!! Should remember where it was found
]
]
=== "SCAN TO BUILD LIST OF AVAILABLE EXTENSIONS" ===
extensions: copy []
parse-ext-build-spec: func [
return: [object!]
spec [block!]
][
; !!! Note: This import does not work, e.g. it won't import shimmed COMPOSE
; into a place where the spec would see it. What we are looking to do
; here is an undeveloped feature, of needing a module environment to
; import into but also wanting to use a "base module" of definitions--a
; feature only available in objects. If we could do it, it would probably
; be precarious in bootstrap. Instead, the bootstrap-shim puts its versions
; of COMPOSE and PARSE into the lib context.
;
let ext: make extension-class compose [
comment [import (join (clean-path repo-dir) %tools/bootstrap-shim.r)]
(spread spec)
]
let config
if has ext 'options [
ensure block! ext/options
config: null ; default for locals in modern Ren-C
parse2 ext/options [
opt some [
word! block! opt text! set config group!
]
] else [
fail ["Could not parse extension build spec" mold spec]
]
if config [
do as block! config ; Note: old Ren-Cs disallowed DO of GROUP!
]
]
return ext
]
use [extension-dir entry][
extension-dir: join repo-dir %extensions/
for-each entry read extension-dir [
all [
dir? entry
find read (join extension-dir entry) %make-spec.r
] then [
spec: load join (join extension-dir entry) %make-spec.r
; !!! The specs use `repo-dir` and some other variables.
; Splice those in for starters, but will need deep thought.
;
insert spec spread compose [
repo-dir: (repo-dir)
platform-config: (platform-config)
user-config: (user-config)
]
parsed: parse-ext-build-spec spec
assert [not parsed/mode] ; no build mode assigned at first yet
append extensions parsed
]
]
]
extension-names: map-each x extensions [to-lit-word x/name]
=== "TARGETS" ===
; Collected here so they can be used with `--help targets`
targets: [
'clean [
rebmake/execution/run make rebmake/solution-class [
depends: reduce [
clean
]
]
]
'prep [
rebmake/execution/run make rebmake/solution-class [
depends: flatten reduce [
vars
prep
t-folders
dynamic-libs
]
]
]
'app 'executable 'r3 [
rebmake/execution/run make rebmake/solution-class [
depends: flatten reduce [
vars
t-folders
dynamic-libs
app
]
]
]
'library [
rebmake/execution/run make rebmake/solution-class [
depends: flatten reduce [
vars
t-folders
dynamic-libs
library
]
]
]
'all 'execution [
rebmake/execution/run make rebmake/solution-class [
depends: flatten reduce [
clean
prep
vars
t-folders
dynamic-libs
app
]
]
]
'makefile [
rebmake/makefile/generate %makefile solution
]
'nmake [
rebmake/nmake/generate %makefile solution
]
'vs2019
'visual-studio [
apply :rebmake/visual-studio/generate [
output-dir solution
/x86 (platform-config/os-name = 'Windows-x86)
]
]
'vs2015 [
apply :rebmake/vs2015/generate [
output-dir solution
/x86 (platform-config/os-name = 'Windows-x86)
]
]
'vs2017 [
fail [
"Only minor changes needed to support vs2017, please get in"
"touch if this is an issue and you need it for some reason."
]
]
]
target-names: make block! 16
for-each x targets [
if lit-word? x [
append target-names (noquote x)
append target-names '|
] else [
take/last target-names
append target-names newline
]
]
=== "HELP" ===
indent: func [
text [text!]
/space
][
return apply :replace/all [
text
either space [" "] [newline]
"^/ "
]
]
help-topics: reduce [
; Note: Use only 1 indentation level in help strings
'usage copy {=== USAGE ===^/
> PATH/TO/r3-make PATH/TO/make.r [CONFIG | OPTION | TARGET ...]^/
NOTE 1: current dir is the build dir,
that will contain all generated stuff
(%prep/, %objs/, %makefile, %r3 ...)
You can have multiple build dirs.^/
NOTE 2: but if the current dir is the "root" dir
(where make.r is), then the build dir is %build/^/
NOTE 3: order of configs and options IS relevant^/
MORE HELP:^/
{ -h | -help | --help } { HELP-TOPICS }