-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
2733 lines (2548 loc) · 124 KB
/
Makefile
File metadata and controls
2733 lines (2548 loc) · 124 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
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
# Lambda Project Makefile
# Utilizes Premake5 build system with standard make targets
# Project configuration
PROJECT_NAME = Lambda
DEFAULT_CONFIG = build_lambda_config.json
# Build configurations
BUILD_DIR = build
BUILD_DEBUG_DIR = build_debug
BUILD_RELEASE_DIR = build_release
BUILD_WINDOWS_DIR = build_windows
BUILD_LINUX_DIR = build_linux
# Output executables
LAMBDA_EXE = lambda.exe
LAMBDA_CLI_EXE = lambda-cli.exe
LAMBDA_JUBE_EXE = lambda-jube.exe
# Unicode support is always enabled (utf8proc-based)
# No longer using conditional compilation flags
# Auto-detect number of jobs for parallel compilation
NPROCS := 1
OS := $(shell uname -s)
ifeq ($(OS),Darwin)
NPROCS := $(shell sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 1)
PREMAKE_FILE := premake5.mac.lua
PREMAKE_CLI_FILE := premake5.cli.mac.lua
PREMAKE_JUBE_FILE := premake5.jube.mac.lua
else ifeq ($(OS),Linux)
NPROCS := $(shell nproc 2>/dev/null || echo 1)
PREMAKE_FILE := premake5.lin.lua
PREMAKE_CLI_FILE := premake5.cli.lin.lua
PREMAKE_JUBE_FILE := premake5.jube.lin.lua
else
# Windows/MSYS2 detection
NPROCS := $(shell nproc 2>/dev/null || echo 4)
PREMAKE_FILE := premake5.win.lua
PREMAKE_CLI_FILE := premake5.cli.win.lua
PREMAKE_JUBE_FILE := premake5.jube.win.lua
endif
NPROCS := $(shell n="$(NPROCS)"; if expr "$$n" : '^[1-9][0-9]*$$' >/dev/null; then echo "$$n"; else echo 1; fi)
# Render visual tests are CPU-heavy but independent; leave one core free for
# the OS and browser/reference helpers.
RADIANT_RENDER_JOBS := $(shell n=$(NPROCS); if [ "$$n" -gt 1 ]; then echo $$((n - 1)); else echo 1; fi)
# Optimize parallel jobs: use all cores for compilation, limit linking to 1
JOBS := $(NPROCS)
LINK_JOBS := 1
# Debug+ASan test builds use ~2-3x more memory per compiler instance; cap parallelism
# to avoid OOM kills on machines with limited RAM.
TEST_JOBS := $(shell echo $$(( ($(NPROCS) + 1) / 2 )) )
# Enable ccache for faster builds if available
ifneq ($(shell which ccache 2>/dev/null),)
CC := ccache $(CC)
CXX := ccache $(CXX)
export CCACHE_DIR := $(shell pwd)/build/.ccache
export CCACHE_MAXSIZE := 500M
export CCACHE_COMPRESS := 1
endif
# Detect Python executable
# On MSYS2/Windows, prefer MINGW64 over CLANG64 for Universal CRT avoidance
# Force explicit paths for MSYS environment compatibility
ifeq ($(shell test -f /mingw64/bin/python3 && echo yes),yes)
PYTHON := /mingw64/bin/python3
else ifeq ($(shell test -f /clang64/bin/python3 && echo yes),yes)
PYTHON := /clang64/bin/python3
else
PYTHON := python3
endif
# Detect Premake5 executable
# On MSYS2/Windows, prefer MINGW64 over CLANG64 for Universal CRT avoidance
PREMAKE5 := $(shell command -v premake5 2>/dev/null || command -v /mingw64/bin/premake5 2>/dev/null || command -v /clang64/bin/premake5 2>/dev/null || echo premake5)
# MSYS2/Windows Environment Detection
MSYSTEM_DETECTED := $(shell echo $$MSYSTEM)
IS_MSYS2 := $(shell [ -n "$(MSYSTEM_DETECTED)" ] && echo "yes" || echo "no")
# Detect C/C++ compilers
# All platforms use Clang by default
# On MSYS2/Windows: CLANG64 Clang (avoids Universal CRT, uses MSVCRT.dll)
# Force explicit paths for MSYS environment compatibility
ifeq ($(shell test -f /clang64/bin/clang && echo yes),yes)
CC := /clang64/bin/clang
CXX := /clang64/bin/clang++
AR := /clang64/bin/ar
RANLIB := /clang64/bin/ranlib
else ifeq ($(OS),Linux)
CC := clang
CXX := clang++
AR := ar
RANLIB := ranlib
else
CC := gcc
CXX := g++
AR := ar
RANLIB := ranlib
endif
# Tree-sitter grammar dependencies
# This system automatically manages the dependency chain:
# grammar.js -> parser.c -> ts-enum.h -> C/C++ source files
# When grammar.js is modified, the parser and enum header are automatically regenerated
GRAMMAR_JS = lambda/tree-sitter-lambda/grammar.js
PARSER_C = lambda/tree-sitter-lambda/src/parser.c
GRAMMAR_JSON = lambda/tree-sitter-lambda/src/grammar.json
NODE_TYPES_JSON = lambda/tree-sitter-lambda/src/node-types.json
TS_ENUM_H = lambda/ts-enum.h
UPDATE_TS_ENUM_SCRIPT = ./utils/update_ts_enum.sh
# Auto-generate parser and ts-enum.h when grammar.js changes
$(TS_ENUM_H): $(GRAMMAR_JS)
@echo "Grammar changed, regenerating parser and ts-enum.h..."
@cd lambda/tree-sitter-lambda && npx tree-sitter-cli@0.24.7 generate
$(UPDATE_TS_ENUM_SCRIPT)
@echo "Updated ts-enum.h from grammar changes"
$(PARSER_C) $(GRAMMAR_JSON) $(NODE_TYPES_JSON): $(GRAMMAR_JS)
@echo "Generating parser from grammar.js..."
@cd lambda/tree-sitter-lambda && npx tree-sitter-cli@0.24.7 generate
# Lambda embedding dependencies
# Auto-generate lambda-embed.h when lambda.h changes
# This embeds the lambda.h header file as a byte array for runtime access
LAMBDA_H_FILE = lambda/lambda.h
LAMBDA_EMBED_H_FILE = lambda/lambda-embed.h
# Auto-generate lambda-embed.h when lambda.h changes or lambda-embed.h doesn't exist
$(LAMBDA_EMBED_H_FILE): $(LAMBDA_H_FILE)
@echo "lambda.h changed or lambda-embed.h missing, regenerating lambda-embed.h..."
@if command -v xxd >/dev/null 2>&1; then \
echo "Regenerating $(LAMBDA_EMBED_H_FILE) from $(LAMBDA_H_FILE)..."; \
xxd -i "$(LAMBDA_H_FILE)" > "$(LAMBDA_EMBED_H_FILE)"; \
echo "Successfully regenerated $(LAMBDA_EMBED_H_FILE)"; \
else \
echo "Error: xxd command not found! Cannot regenerate $(LAMBDA_EMBED_H_FILE)"; \
echo "Install xxd or manually run: xxd -i $(LAMBDA_H_FILE) > $(LAMBDA_EMBED_H_FILE)"; \
exit 1; \
fi
# Tree-sitter library targets
# Build from source on all platforms
TREE_SITTER_LIB = lambda/tree-sitter/libtree-sitter.a
TREE_SITTER_LAMBDA_LIB = lambda/tree-sitter-lambda/libtree-sitter-lambda.a
TREE_SITTER_JAVASCRIPT_LIB = lambda/tree-sitter-javascript/libtree-sitter-javascript.a
TREE_SITTER_BASH_LIB = lambda/tree-sitter-bash/libtree-sitter-bash.a
TREE_SITTER_PYTHON_LIB = lambda/tree-sitter-python/libtree-sitter-python.a
TREE_SITTER_TYPESCRIPT_LIB = lambda/tree-sitter-typescript/libtree-sitter-typescript.a
TREE_SITTER_RUBY_LIB = lambda/tree-sitter-ruby/libtree-sitter-ruby.a
TREE_SITTER_LATEX_LIB = lambda/tree-sitter-latex/libtree-sitter-latex.a
TREE_SITTER_LATEX_MATH_LIB = lambda/tree-sitter-latex-math/libtree-sitter-latex-math.a
RE2_LIB = build_temp/re2-noabsl/cmake_build/libre2.a
# MIR JIT library (platform-specific paths match build_lambda_config.json)
ifeq ($(OS),Darwin)
MIR_LIB = mac-deps/mir/libmir.a
MIR_BUILD_DIR = mac-deps/mir
else ifeq ($(IS_MSYS2),yes)
MIR_LIB = win-native-deps/lib/libmir.a
MIR_BUILD_DIR = build_temp/mir
else
MIR_LIB = /usr/local/lib/libmir.a
MIR_BUILD_DIR = build_temp/mir
endif
MIR_PATCH = patches/mir-alloca-branch-fix.patch
# JavaScript scanner dependencies
JS_SCANNER_C = lambda/tree-sitter-javascript/src/scanner.c
# TypeScript grammar and scanner dependencies
TS_GRAMMAR_JS = lambda/tree-sitter-typescript/grammar.js
TS_PARSER_C = lambda/tree-sitter-typescript/src/parser.c
TS_SCANNER_C = lambda/tree-sitter-typescript/src/scanner.c
TS_SCANNER_H = lambda/tree-sitter-typescript/scanner_v2.h
# LaTeX grammar dependencies
LATEX_GRAMMAR_JS = lambda/tree-sitter-latex/grammar.js
LATEX_PARSER_C = lambda/tree-sitter-latex/src/parser.c
LATEX_GRAMMAR_JSON = lambda/tree-sitter-latex/src/grammar.json
LATEX_NODE_TYPES_JSON = lambda/tree-sitter-latex/src/node-types.json
# LaTeX Math grammar dependencies
LATEX_MATH_GRAMMAR_JS = lambda/tree-sitter-latex-math/grammar.js
LATEX_MATH_PARSER_C = lambda/tree-sitter-latex-math/src/parser.c
# Build tree-sitter library (amalgamated build, no ICU dependency)
# Uses lib.c single-file approach - no external ICU/Unicode library needed
$(TREE_SITTER_LIB):
@echo "Building tree-sitter library (amalgamated, no ICU)..."
@cd lambda/tree-sitter && \
rm -f libtree-sitter.a tree_sitter.o && \
$(CC) -c lib/src/lib.c \
-Ilib/include \
-Ilib/src \
-O3 -Wall -Wextra -std=c11 -fPIC \
-D_POSIX_C_SOURCE=200112L -D_DEFAULT_SOURCE \
-o tree_sitter.o && \
$(AR) rcs libtree-sitter.a tree_sitter.o && \
rm -f tree_sitter.o
@echo "✅ tree-sitter library built: lambda/tree-sitter/libtree-sitter.a"
# Build tree-sitter-lambda library (depends on parser generation)
$(TREE_SITTER_LAMBDA_LIB): $(PARSER_C)
@echo "Building tree-sitter-lambda library..."
@echo "🔧 Compiler: $(CC)"
@echo "🔧 CXX: $(CXX)"
@echo "🔧 Environment: MSYSTEM=$(MSYSTEM)"
@echo "🔧 Working directory: lambda/tree-sitter-lambda"
@echo "🔧 Unsetting OS variable to bypass Windows check..."
@echo "🔧 Adding /mingw64/bin to PATH for DLL dependencies..."
env -u OS PATH="/mingw64/bin:$$PATH" $(MAKE) -C lambda/tree-sitter-lambda libtree-sitter-lambda.a CC="$(CC)" CXX="$(CXX)" V=1 VERBOSE=1
# Build tree-sitter-javascript library (depends on scanner source)
$(TREE_SITTER_JAVASCRIPT_LIB): $(JS_SCANNER_C)
@echo "Building tree-sitter-javascript library..."
@echo "🔧 Compiler: $(CC)"
@echo "🔧 CXX: $(CXX)"
@echo "🔧 Environment: MSYSTEM=$(MSYSTEM)"
@echo "🔧 Working directory: lambda/tree-sitter-javascript"
@echo "🔧 Unsetting OS variable to bypass Windows check..."
@echo "🔧 Adding /mingw64/bin to PATH for DLL dependencies..."
env -u OS PATH="/mingw64/bin:$$PATH" $(MAKE) -C lambda/tree-sitter-javascript libtree-sitter-javascript.a CC="$(CC)" CXX="$(CXX)" TS="$(CURDIR)/node_modules/.bin/tree-sitter" V=1 VERBOSE=1
# Build tree-sitter-bash library
$(TREE_SITTER_BASH_LIB):
@echo "Building tree-sitter-bash library..."
env -u OS PATH="/mingw64/bin:$$PATH" $(MAKE) -C lambda/tree-sitter-bash libtree-sitter-bash.a CC="$(CC)" CXX="$(CXX)" V=1 VERBOSE=1
# Build tree-sitter-python library
$(TREE_SITTER_PYTHON_LIB):
@echo "Building tree-sitter-python library..."
env -u OS PATH="/mingw64/bin:$$PATH" $(MAKE) -C lambda/tree-sitter-python libtree-sitter-python.a CC="$(CC)" CXX="$(CXX)" V=1 VERBOSE=1
# Generate TypeScript parser from grammar.js when it changes
$(TS_PARSER_C): $(TS_GRAMMAR_JS)
@echo "Generating TypeScript parser from grammar.js..."
@echo "🔧 Working directory: lambda/tree-sitter-typescript"
@if [ ! -d lambda/tree-sitter-typescript/node_modules/tree-sitter-javascript ]; then \
echo "Installing tree-sitter-javascript dependency..."; \
cd lambda/tree-sitter-typescript && npm install --save tree-sitter-javascript@file:../tree-sitter-javascript; \
fi
@if command -v tree-sitter >/dev/null 2>&1; then \
echo "Using local tree-sitter CLI"; \
cd lambda/tree-sitter-typescript && tree-sitter generate; \
elif command -v npx >/dev/null 2>&1; then \
echo "Using npx tree-sitter-cli"; \
cd lambda/tree-sitter-typescript && npx tree-sitter-cli@0.24.7 generate; \
else \
echo "❌ Error: tree-sitter CLI not found!"; \
echo "Install with: npm install -g tree-sitter-cli"; \
exit 1; \
fi
@echo "✅ TypeScript parser generated successfully"
# Build tree-sitter-typescript library (depends on parser generation + scanner)
$(TREE_SITTER_TYPESCRIPT_LIB): $(TS_PARSER_C) $(TS_SCANNER_C) $(TS_SCANNER_H)
@echo "Building tree-sitter-typescript library..."
env -u OS PATH="/mingw64/bin:$$PATH" $(MAKE) -C lambda/tree-sitter-typescript libtree-sitter-typescript.a CC="$(CC)" CXX="$(CXX)" V=1 VERBOSE=1
# Build tree-sitter-ruby library
$(TREE_SITTER_RUBY_LIB):
@echo "Building tree-sitter-ruby library..."
env -u OS PATH="/mingw64/bin:$$PATH" $(MAKE) -C lambda/tree-sitter-ruby libtree-sitter-ruby.a CC="$(CC)" CXX="$(CXX)" V=1 VERBOSE=1
# Generate LaTeX parser from grammar.js when it changes
$(LATEX_PARSER_C) $(LATEX_GRAMMAR_JSON) $(LATEX_NODE_TYPES_JSON): $(LATEX_GRAMMAR_JS)
@echo "Generating LaTeX parser from grammar.js..."
@echo "🔧 Working directory: lambda/tree-sitter-latex"
@if command -v tree-sitter >/dev/null 2>&1; then \
echo "Using local tree-sitter CLI"; \
cd lambda/tree-sitter-latex && tree-sitter generate; \
elif command -v npx >/dev/null 2>&1; then \
echo "Using npx tree-sitter-cli"; \
cd lambda/tree-sitter-latex && npx tree-sitter-cli@0.24.7 generate; \
else \
echo "❌ Error: tree-sitter CLI not found!"; \
echo "Install with: npm install -g tree-sitter-cli"; \
exit 1; \
fi
@echo "✅ LaTeX parser generated successfully"
# Build tree-sitter-latex library (depends on parser generation)
$(TREE_SITTER_LATEX_LIB): $(LATEX_PARSER_C)
@echo "Building tree-sitter-latex library..."
@echo "🔧 Compiler: $(CC)"
@echo "🔧 CXX: $(CXX)"
@echo "🔧 Environment: MSYSTEM=$(MSYSTEM)"
@echo "🔧 Working directory: lambda/tree-sitter-latex"
@echo "🔧 Unsetting OS variable to bypass Windows check..."
@echo "🔧 Adding /mingw64/bin to PATH for DLL dependencies..."
env -u OS PATH="/mingw64/bin:$$PATH" $(MAKE) -C lambda/tree-sitter-latex libtree-sitter-latex.a CC="$(CC)" CXX="$(CXX)" V=1 VERBOSE=1
# Generate LaTeX Math parser from grammar.js when it changes
$(LATEX_MATH_PARSER_C): $(LATEX_MATH_GRAMMAR_JS)
@echo "Generating LaTeX Math parser from grammar.js..."
@echo "🔧 Working directory: lambda/tree-sitter-latex-math"
@if command -v tree-sitter >/dev/null 2>&1; then \
echo "Using local tree-sitter CLI"; \
cd lambda/tree-sitter-latex-math && tree-sitter generate; \
elif command -v npx >/dev/null 2>&1; then \
echo "Using npx tree-sitter-cli"; \
cd lambda/tree-sitter-latex-math && npx tree-sitter-cli@0.24.7 generate; \
else \
echo "❌ Error: tree-sitter CLI not found!"; \
echo "Install with: npm install -g tree-sitter-cli"; \
exit 1; \
fi
@echo "✅ LaTeX Math parser generated successfully"
# Build tree-sitter-latex-math library (depends on parser generation)
$(TREE_SITTER_LATEX_MATH_LIB): $(LATEX_MATH_PARSER_C)
@echo "Building tree-sitter-latex-math library..."
@echo "🔧 Working directory: lambda/tree-sitter-latex-math"
env -u OS PATH="/mingw64/bin:$$PATH" $(MAKE) -C lambda/tree-sitter-latex-math libtree-sitter-latex-math.a CC="$(CC)" CXX="$(CXX)" V=1 VERBOSE=1
# Build re2 library (reconfigures cmake if CMakeCache is stale/wrong platform)
# On Windows/CLANG64: must pass explicit compiler flags so cmake uses clang++
# with -stdlib=libc++ (matching the rest of the build) instead of defaulting
# to GCC/libstdc++, which would cause an ABI mismatch at link time.
$(RE2_LIB):
@echo "Building re2 library from source..."
@mkdir -p build_temp/re2-noabsl/cmake_build
@cd build_temp/re2-noabsl/cmake_build && \
cmake .. \
-DCMAKE_C_COMPILER="$(CC)$(if $(filter yes,$(IS_MSYS2)),.exe,)" \
-DCMAKE_CXX_COMPILER="$(CXX)$(if $(filter yes,$(IS_MSYS2)),.exe,)" \
-DCMAKE_CXX_FLAGS="$(if $(filter /clang64/bin/clang++,$(CXX)),-stdlib=libc++,) -O2" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DBUILD_SHARED_LIBS=OFF \
-DRE2_BUILD_TESTING=OFF \
-Wno-dev \
-G Ninja 2>&1 | tail -3 && \
ninja -j$(JOBS)
@echo "re2 library built: $(RE2_LIB)"
# Build MIR JIT library (clone, patch, compile)
$(MIR_LIB):
@echo "Building MIR library..."
@if [ ! -d "$(MIR_BUILD_DIR)" ]; then \
echo "Cloning MIR repository..."; \
mkdir -p $(dir $(MIR_BUILD_DIR)); \
git clone https://github.com/vnmakarov/mir.git $(MIR_BUILD_DIR); \
fi
@if [ -f "$(MIR_PATCH)" ]; then \
echo "Applying MIR patches..."; \
cd $(MIR_BUILD_DIR) && git apply "$(CURDIR)/$(MIR_PATCH)" 2>/dev/null || \
echo " (MIR patch already applied or skipped)"; \
fi
ifeq ($(IS_MSYS2),yes)
@cd $(MIR_BUILD_DIR) && CC=/clang64/bin/clang.exe AR=/clang64/bin/llvm-ar.exe \
CFLAGS="-O2 -DNDEBUG -fPIC" make libmir.a
@mkdir -p win-native-deps/lib && cp $(MIR_BUILD_DIR)/libmir.a win-native-deps/lib/
else
@$(MAKE) -C $(MIR_BUILD_DIR) -j$(JOBS)
endif
ifeq ($(OS),Linux)
@echo "Installing MIR to system location (requires sudo)..."
@sudo mkdir -p /usr/local/lib /usr/local/include
@sudo cp $(MIR_BUILD_DIR)/libmir.a /usr/local/lib/
@sudo cp $(MIR_BUILD_DIR)/mir.h /usr/local/include/ 2>/dev/null || true
endif
@echo "✅ MIR built: $(MIR_LIB)"
build-mir: $(MIR_LIB)
# Toolchain Validation Functions
define toolchain_verify
@echo "🔍 Verifying toolchain..."
@if command -v $(CC) >/dev/null 2>&1; then \
echo "✅ Compiler: $(CC) ($(shell $(CC) --version 2>/dev/null | head -1 || echo 'version unknown'))"; \
else \
echo "❌ Compiler $(CC) not found"; \
fi
@if command -v $(CXX) >/dev/null 2>&1; then \
echo "✅ C++ Compiler: $(CXX) ($(shell $(CXX) --version 2>/dev/null | head -1 || echo 'version unknown'))"; \
else \
echo "❌ C++ Compiler $(CXX) not found"; \
fi
endef
# Checking DLL dependencies on Windows (avoid Universal CRT)
define windows_dll_check
@if [ -f "lambda.exe" ]; then \
ldd lambda.exe 2>/dev/null | grep -E "not found|mingw64|msys64|ucrt|api-ms-win-crt" || echo "✅ No problematic dependencies found"; \
else \
echo "⚠️ lambda.exe not found, skipping DLL check"; \
fi
endef
# Function to run make with error collection and summary
# Usage: $(call run_make_with_error_summary,TARGET)
# TARGET: The make target to build (e.g., lambda, radiant)
define run_make_with_error_summary
@echo "🔨 Starting build process for target: $(1)..."
@BUILD_LOG=$$(mktemp) && \
if $(MAKE) -C build/premake config=debug_native $(1) -j$(JOBS) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" RANLIB="$(RANLIB)" LINK_JOBS="$(LINK_JOBS)" 2>&1 | tee "$$BUILD_LOG"; then \
echo "✅ Build completed successfully for target: $(1)"; \
else \
echo "❌ Build failed for target: $(1)"; \
fi; \
echo ""; \
echo "📋 Build Summary:"; \
echo "================"; \
ERROR_COUNT=`grep -E "(error:|Error:|ERROR:|fatal:|Failed:|failed:)" "$$BUILD_LOG" 2>/dev/null | grep -v -E "warning:|Warning:|WARNING:" | wc -l | tr -d ' '`; \
WARNING_COUNT=`grep -E "(warning:|Warning:|WARNING:)" "$$BUILD_LOG" 2>/dev/null | wc -l | tr -d ' '`; \
echo "Errors: $$ERROR_COUNT"; \
echo "Warnings: $$WARNING_COUNT"; \
echo ""; \
if [ "$$ERROR_COUNT" -gt 0 ] 2>/dev/null; then \
echo "🔴 ERRORS FOUND:"; \
echo "================"; \
grep -n -E "(error:|Error:|ERROR:|fatal:|Failed:|failed:)" "$$BUILD_LOG" | grep -v -E "warning:|Warning:|WARNING:" | while IFS=: read -r line_num content; do \
file_info=$$(echo "$$content" | grep -oE "\.\.\/[^[:space:]]+\.[ch]p*p?:[0-9]+:[0-9]+:" | head -1); \
if [ -z "$$file_info" ]; then \
file_info=$$(echo "$$content" | grep -oE "\.\.\/[^[:space:]]+\.[ch]p*p?:[0-9]+:" | head -1); \
fi; \
if [ -z "$$file_info" ]; then \
file_info=$$(echo "$$content" | grep -oE "[^[:space:]]+\.[ch]p*p?:[0-9]+:[0-9]+:" | head -1); \
fi; \
if [ -z "$$file_info" ]; then \
file_info=$$(echo "$$content" | grep -oE "[^[:space:]]+\.[ch]p*p?:[0-9]+:" | head -1); \
fi; \
if [ -n "$$file_info" ]; then \
rel_path=$$(echo "$$file_info" | cut -d: -f1); \
line_no=$$(echo "$$file_info" | cut -d: -f2); \
col_no=$$(echo "$$file_info" | cut -d: -f3); \
if [[ "$$rel_path" == ../* ]]; then \
abs_path="$$(cd build/premake && realpath "$$rel_path" 2>/dev/null || echo "$$(pwd)/$$rel_path")"; \
else \
abs_path="$$(pwd)/build/premake/$$rel_path"; \
fi; \
if [ -n "$$col_no" ] && [ "$$col_no" != "" ]; then \
location="$$line_no:$$col_no"; \
else \
location="$$line_no"; \
fi; \
clean_content=$$(echo "$$content" | sed "s|[^[:space:]]*\.[ch]p*p*:[0-9]*:[0-9]*:||" | sed "s|[^[:space:]]*\.[ch]p*p*:[0-9]*:||"); \
echo " file://$$abs_path:$$location -$$clean_content"; \
else \
echo " $$content"; \
fi; \
done; \
echo ""; \
echo "💡 Click on the file:// links above to jump to errors in VS Code"; \
fi; \
rm -f "$$BUILD_LOG"
endef
# Combined tree-sitter libraries target
# Core: only parsers needed by lambda.exe (Lambda, JS, TS, LaTeX)
tree-sitter-core-libs: $(TREE_SITTER_LIB) $(TREE_SITTER_LAMBDA_LIB) $(TREE_SITTER_JAVASCRIPT_LIB) $(TREE_SITTER_TYPESCRIPT_LIB) $(TREE_SITTER_LATEX_LIB) $(TREE_SITTER_LATEX_MATH_LIB)
# All: includes jube-only parsers (Python, Bash, Ruby)
tree-sitter-libs: tree-sitter-core-libs $(TREE_SITTER_BASH_LIB) $(TREE_SITTER_PYTHON_LIB) $(TREE_SITTER_RUBY_LIB)
# Default target
.DEFAULT_GOAL := build
# Phony targets (don't correspond to actual files)
.PHONY: all build build-ascii clean clean-grammar generate-grammar debug release rebuild \
test test-all test-all-baseline test-lambda-baseline test-bash-baseline test-input-baseline test-radiant-baseline test-layout-baseline test-page-load test-pdf-render test-extended test-input run help \
lambda lambda-cli build-cli lambda-jube build-jube release-jube format lint check check-tag-or check-raw-alloc check-state-store check-radiant-casts check-radiant-ownership docs intellisense analyze-binary \
build-debug build-release clean-all distclean \
tree-sitter-libs tree-sitter-core-libs \
generate-premake clean-premake build-test build-pdf-render-test build-test-linux build-jube-test test-jube run-radiant-baseline \
capture-layout test-layout layout layout-snapshot layout-snapshot-check layout-snapshot-diff count-loc tidy-printf benchmark bench-compile \
fuzz-lambda fuzz-lambda-extended fuzz-radiant fuzz-radiant-quick test-c2mir type-chart build-mir \
test-ui-automation test-reactive-ui test-redex-baseline \
node-official node-official-update-baseline
# Help target - shows available commands
help:
@echo "$(PROJECT_NAME) - Available Make Targets:"
@echo ""
@echo "Build Targets (Premake-based):"
@echo " build - Build lambda (core) using Premake build system (incremental, default)"
@echo " On Windows/MSYS2: Uses CLANG64 Clang (avoids Universal CRT)"
@echo " All platforms use Clang as the default compiler"
@echo " debug - Build with debug symbols and AddressSanitizer using Premake"
@echo " build-release - Build optimized release version using Premake"
@echo " release - Build release version and prepare release artifacts"
@echo " lambda-cli - Build headless CLI-only version (release, no Radiant/GUI, outputs lambda-cli.exe)"
@echo " build-mir - Build MIR JIT library (clone, patch, compile)"
@echo " build-jube - Build polyglot runtime (Lambda + JS/TS + Python + Bash + Ruby + Radiant)"
@echo " release-jube - Build optimized polyglot release version"
@echo " rebuild - Force complete rebuild using Premake"
@echo " lambda - Build lambda project specifically using Premake"
@echo " all - Build all projects"
@echo ""
@echo "Maintenance:"
@echo " clean - Remove build artifacts"
@echo " clean-test - Remove test output and temporary files"
@echo " clean-grammar - Remove generated grammar and embed files (parser.c, ts-enum.h, lambda-embed.h)"
@echo " clean-all - Remove all build directories and tree-sitter libraries"
@echo " distclean - Complete cleanup (build dirs + executables + tests)"
@echo " intellisense - Update VS Code IntelliSense database (compile_commands.json)"
@echo ""
@echo "Premake Build System:"
@echo " generate-premake - Generate premake5.lua from build_lambda_config.json"
@echo " clean-premake - Clean Premake build artifacts and generated files"
@echo " build-test - Build all test executables using Premake"
@echo " build-pdf-render-test - Build PDF render visual gtest executable using Premake"
@echo " build-jube-test - Build lambda-jube and all test executables"
@echo ""
@echo "Grammar & Parser:"
@echo " generate-grammar - Generate parser and ts-enum.h from grammar.js"
@echo " (automatic when grammar.js changes)"
@echo " tree-sitter-libs - Build all tree-sitter libraries (amalgamated, no ICU)"
@echo " Automatically regenerates LaTeX parser if grammar.js changes"
@echo ""
@echo "Development:"
@echo " test - Run ALL test suites (baseline + extended, alias for test-all)"
@echo " test-all - Run ALL test suites (baseline + extended)"
@echo " test-all-baseline - Run ALL BASELINE test suites (core functionality, must pass 100%)"
@echo " test-lambda-baseline - Run LAMBDA baseline test suite only"
@echo " test-bash-baseline - Run Bash transpiler baseline test suite"
@echo " test-input-baseline - Run HTML5 WPT, CommonMark, YAML, ASCII Math, and LaTeX Math parser tests"
@echo " test-radiant-baseline - Run RADIANT layout baseline (baseline, wpt-css-text, pretext, form, text_flow, wpt-css-multicol, puppertino) + render visual + other checks"
@echo " test-reactive-ui - Run Reactive UI event simulation tests (todo toggle/delete)"
@echo " test-redex-baseline - Run Redex formal semantics baseline verification"
@echo " test-pdf-render - Run PDF render visual gtest suite"
@echo " layout-snapshot - Save page suite snapshot: make layout-snapshot suite=page"
@echo " test-extended - Run EXTENDED test suites only (HTTP/HTTPS, ongoing features)"
@echo " test-library - Run library tests only"
@echo " test-input - Run input processing test suite (MIME detection & math)"
@echo " test-validator- Run validator tests only"
@echo " test-mir - Run MIR JIT tests only"
@echo " test-c2mir - Run Lambda baseline tests with legacy C2MIR JIT path"
@echo " test-lambda - Run lambda runtime tests only"
@echo " test-std - Run Lambda Standard Tests (custom test runner)"
@echo " test-coverage - Run tests with code coverage analysis"
@echo " test-benchmark- Run performance benchmark tests"
@echo " fuzz-lambda - Run fuzzy tests (5 minutes, mutation + random generation)"
@echo " fuzz-lambda-extended - Run extended fuzzy tests (1 hour)"
@echo " test-integration - Run end-to-end integration tests"
@echo " test-all - Run complete test suite (all test types)"
@echo " run - Build and run the default executable"
@echo " analyze - Run static analysis with scan-build (fixed for custom build)"
@echo " analyze-verbose - Run detailed static analysis with extra checkers"
@echo " analyze-single - Run static analysis on individual files"
@echo " analyze-direct - Direct clang static analysis (bypasses build system)"
@echo " analyze-compile-db - Use compile_commands.json for analysis (requires bear)"
@echo " tidy - Run clang-tidy analysis on C++ files"
@echo " tidy-full - Comprehensive clang-tidy with compile database"
@echo " tidy-fix - Run clang-tidy with automatic fixes (interactive)"
@echo " tidy-printf - Convert printf/fprintf(stderr) to log_debug() using Clang AST"
@echo " Usage: make tidy-printf FILE='pattern' [DRY_RUN=1] [BACKUP=1]"
@echo " check - Run basic code checks (TODO/FIXME finder)"
@echo " format - Format source code with clang-format"
@echo " lint - Run linter (cppcheck) on source files"
@echo " count-loc - Count lines of code in the repository"
@echo " cheatsheet - Regenerate Lambda_Cheatsheet.pdf from Markdown (requires pandoc, xelatex)"
@echo " bench-compile - Run C/C++ compilation performance benchmark"
@echo " Tests single-file, template, multi-file, and full Lambda builds"
@echo " test-layout - Run Lambda CSS layout integration tests (all suites)"
@echo " Uses Lambda CSS engine (custom CSS cascade and layout)"
@echo " Usage: make test-layout suite=baseline (run specific suite)"
@echo " Usage: make test-layout test=table_simple (run specific test, .html/.htm optional)"
@echo " Usage: make test-layout pattern=float (run tests matching pattern)"
@echo " Note: Uppercase variants also work (SUITE=, TEST=, PATTERN=)"
@echo " Available suites: auto-detected from test/layout/data/"
@echo " layout - Alias for test-layout"
@echo " Usage: make layout suite=baseline"
@echo " Usage: make layout pattern=float (run tests matching pattern)"
@echo " Note: Uppercase variants also work (SUITE=, TEST=, PATTERN=)"
@echo " Available suites: auto-detected from test/layout/data/"
@echo " capture-layout - Extract browser layout references using Puppeteer"
@echo " REQUIRES: test=<name> OR suite=<name>"
@echo " Usage: make capture-layout test=basic-text-align"
@echo " Usage: make capture-layout suite=baseline"
@echo " Usage: make capture-layout test=table_007 force=1"
@echo " Note: Uppercase variants also work (TEST=, SUITE=, FORCE=)"
@echo ""
@echo "Options:"
@echo " JOBS=N - Set number of parallel compilation jobs (default: $(JOBS))"
@echo " CONFIG=file - Use specific configuration file"
@echo ""
@echo "Examples:"
@echo " make build JOBS=4 # Build with 4 parallel jobs"
@echo " make debug # Debug build with AddressSanitizer"
@echo " make rebuild # Force complete rebuild"
# Environment debugging target
env-debug:
@echo "🔍 Environment Detection Debug:"
@echo "MSYSTEM: '$(MSYSTEM)'"
@echo "MSYSTEM_DETECTED: '$(MSYSTEM_DETECTED)'"
@echo "IS_MSYS2: '$(IS_MSYS2)'"
# Main build target (incremental)
build: $(TS_ENUM_H) $(LAMBDA_EMBED_H_FILE) tree-sitter-core-libs $(RE2_LIB) $(MIR_LIB)
@rm -f .lambda_release_build 2>/dev/null || true
ifeq ($(IS_MSYS2),yes)
@echo "Building $(PROJECT_NAME) using MSYS2 CLANG64 environment..."
PATH="/clang64/bin:$$PATH" $(PYTHON) utils/generate_premake.py --output $(PREMAKE_FILE)
@echo "Generating makefiles..."
PATH="/clang64/bin:$$PATH" $(PREMAKE5) gmake --file=$(PREMAKE_FILE)
@echo "Building lambda executable with $(JOBS) parallel jobs..."
PATH="/clang64/bin:$$PATH" $(MAKE) -C build/premake -j$(JOBS) lambda CC="$(CC)" CXX="$(CXX)" AR="$(AR)" RANLIB="$(RANLIB)" --no-print-directory -s CFLAGS="-w" CXXFLAGS="-w"
$(call windows_dll_check)
@echo "✅ Build completed successfully!"
else
@echo "Building $(PROJECT_NAME) using Premake build system..."
$(call toolchain_verify)
@echo "Generating Premake configuration..."
$(PYTHON) utils/generate_premake.py --output $(PREMAKE_FILE)
@echo "Generating makefiles..."
$(PREMAKE5) gmake --file=$(PREMAKE_FILE)
@echo "Building lambda executable with $(JOBS) parallel jobs..."
# Ensure explicit compiler variables are passed to Premake build
@echo "Using CC=$(CC) CXX=$(CXX)"
$(call run_make_with_error_summary,lambda)
endif
print-vars:
@echo "Unicode support: Always enabled (utf8proc)"
print-jobs:
@echo "CPU cores detected (NPROCS): $(NPROCS)"
@echo "Parallel jobs (JOBS): $(JOBS)"
@echo "Link jobs (LINK_JOBS): $(LINK_JOBS)"
$(LAMBDA_EXE): build
# Debug build
debug: $(TS_ENUM_H) $(LAMBDA_EMBED_H_FILE) tree-sitter-libs $(RE2_LIB)
@rm -f .lambda_release_build 2>/dev/null || true
@echo "Building debug version using Premake build system..."
$(call toolchain_verify)
@echo "Generating Premake configuration..."
$(PYTHON) utils/generate_premake.py --output $(PREMAKE_FILE)
@echo "Generating makefiles..."
$(PREMAKE5) gmake --file=$(PREMAKE_FILE)
@echo "Building lambda executable (debug) with $(JOBS) parallel jobs..."
$(MAKE) -C build/premake config=debug_native lambda -j$(JOBS) CC="$(CC)" CXX="$(CXX)"
@echo "Debug build completed. Executable: lambda.exe"
$(call windows_dll_check)
# Release build (optimized with size reduction)
# Optimizations applied:
# 1. Dead code elimination (-ffunction-sections, -fdata-sections, -Wl,-dead_strip)
# 2. log_debug() and log_info() stripped via NDEBUG macro
# 3. Symbol visibility control (-fvisibility=hidden)
# 4. Debug symbols stripped (-s linker flag + post-build strip)
# 5. LTO enabled (-flto)
release: build-release prepare-release
prepare-release:
@bash utils/prepare_release.sh
build-release:
@$(MAKE) clean-all
@$(MAKE) build-release-compile
build-release-compile: $(TS_ENUM_H) $(LAMBDA_EMBED_H_FILE) tree-sitter-core-libs $(RE2_LIB)
@echo "Building release version using Premake build system..."
@echo "Optimizations: LTO, dead code elimination, symbol visibility, stripped logging"
$(call toolchain_verify)
@echo "Generating Premake configuration..."
$(PYTHON) utils/generate_premake.py --output $(PREMAKE_FILE)
@echo "Generating makefiles..."
$(PREMAKE5) gmake --file=$(PREMAKE_FILE)
@echo "Building lambda executable (release) with $(JOBS) parallel jobs..."
$(MAKE) -C build/premake config=release_native lambda -j$(JOBS) CC="$(CC)" CXX="$(CXX)"
ifeq ($(OS),Darwin)
@echo "Stripping debug symbols (macOS)..."
@strip -x lambda_release.exe 2>/dev/null || strip -x lambda.exe 2>/dev/null || true
else
@echo "Stripping debug symbols..."
@strip lambda_release.exe 2>/dev/null || strip lambda.exe 2>/dev/null || true
endif
@echo "Release build completed."
@ls -lh lambda_release.exe 2>/dev/null || ls -lh lambda.exe 2>/dev/null || true
@touch .lambda_release_build
$(call windows_dll_check)
# Headless CLI build (no Radiant layout engine or GUI support)
# Produces lambda-cli.exe with only Lambda scripting capabilities (release build)
lambda-cli: build-cli
build-cli: $(TS_ENUM_H) $(LAMBDA_EMBED_H_FILE) tree-sitter-libs
@echo "Building Lambda CLI (headless, release) using Premake build system..."
@echo "Excluded: Radiant layout engine, GUI windowing, font rendering, image codecs"
$(PYTHON) utils/generate_premake.py --variant cli --output $(PREMAKE_CLI_FILE)
@echo "Generating makefiles..."
$(PREMAKE5) gmake --file=$(PREMAKE_CLI_FILE)
@echo "Building lambda-cli executable (release) with $(JOBS) parallel jobs..."
$(MAKE) -C build/premake config=release_native lambda-cli -j$(JOBS) CC="$(CC)" CXX="$(CXX)" --no-print-directory -s CFLAGS="-w" CXXFLAGS="-w"
ifeq ($(OS),Darwin)
@strip -x lambda-cli.exe 2>/dev/null || true
else
@strip lambda-cli.exe 2>/dev/null || true
endif
@echo "✅ CLI build completed. Executable: lambda-cli.exe"
@ls -lh lambda-cli.exe 2>/dev/null || true
# Polyglot Jube build (Lambda + JS/TS + Python + Bash + Ruby + Radiant)
# Produces lambda-jube.exe with all language runtimes
lambda-jube: build-jube
build-jube: $(TS_ENUM_H) $(LAMBDA_EMBED_H_FILE) tree-sitter-libs
@echo "Building Lambda Jube (polyglot runtime) using Premake build system..."
@echo "Includes: Lambda, JS, TS, Python, Bash, Ruby + Radiant"
$(PYTHON) utils/generate_premake.py --variant jube --output $(PREMAKE_JUBE_FILE)
@echo "Generating makefiles..."
$(PREMAKE5) gmake --file=$(PREMAKE_JUBE_FILE)
@echo "Building lambda-jube executable with $(JOBS) parallel jobs..."
$(MAKE) -C build/premake config=debug_native lambda-jube -j$(JOBS) CC="$(CC)" CXX="$(CXX)" --no-print-directory -s CFLAGS="-w" CXXFLAGS="-w"
@echo "✅ Jube build completed. Executable: lambda-jube.exe"
@ls -lh lambda-jube.exe 2>/dev/null || true
release-jube: $(TS_ENUM_H) $(LAMBDA_EMBED_H_FILE) tree-sitter-libs
@echo "Building Lambda Jube release (polyglot runtime, optimized)..."
$(PYTHON) utils/generate_premake.py --variant jube --output $(PREMAKE_JUBE_FILE)
$(PREMAKE5) gmake --file=$(PREMAKE_JUBE_FILE)
$(MAKE) -C build/premake config=release_native lambda-jube -j$(JOBS) CC="$(CC)" CXX="$(CXX)" --no-print-directory -s CFLAGS="-w" CXXFLAGS="-w"
ifeq ($(OS),Darwin)
@strip -x lambda-jube.exe 2>/dev/null || true
else
@strip lambda-jube.exe 2>/dev/null || true
endif
@echo "✅ Jube release build completed. Executable: lambda-jube.exe"
@ls -lh lambda-jube.exe 2>/dev/null || true
# Build lambda-jube and all test executables
build-jube-test: build-jube build-test
# Run jube-specific tests only (Python, Bash, Ruby)
test-jube: build-jube-test
@echo "Running jube-specific test suites (Python, Bash, Ruby)..."
@LAMBDA_TEST_HEAVY_LOAD=1 node test/test_run.js --target=jube --parallel
# Force rebuild (clean + build)
rebuild: clean-all
@echo "Force rebuilding $(PROJECT_NAME) using Premake build system..."
@echo "Generating Premake configuration..."
$(PYTHON) utils/generate_premake.py --output $(PREMAKE_FILE)
@echo "Generating makefiles..."
$(PREMAKE5) gmake --file=$(PREMAKE_FILE)
@echo "Building lambda executable with $(JOBS) parallel jobs..."
$(MAKE) -C build/premake config=debug_native lambda -j$(JOBS) CC="$(CC)" CXX="$(CXX)"
@echo "Rebuild completed. Executable: lambda.exe"
# Specific project builds
lambda: build
# Build all projects
all: lambda
@echo "All projects built successfully."
build-wasm:
@echo "Building WebAssembly version..."
./compile-wasm.sh --linking-only
# Clean targets
clean:
@echo "Cleaning build artifacts and executables..."
@echo "Cleaning Premake build artifacts..."
@rm -rf $(BUILD_DIR)/obj 2>/dev/null || true
@rm -rf $(BUILD_DIR)/lib 2>/dev/null || true
@echo "Cleaning legacy build artifacts (if any)..."
@rm -rf $(BUILD_DIR)/*.o 2>/dev/null || true
@rm -rf $(BUILD_DEBUG_DIR)/*.o 2>/dev/null || true
@rm -rf $(BUILD_RELEASE_DIR)/*.o 2>/dev/null || true
@rm -rf $(BUILD_WINDOWS_DIR)/*.o 2>/dev/null || true
@rm -rf $(BUILD_LINUX_DIR)/*.o 2>/dev/null || true
@rm -f $(BUILD_DIR)/*.d 2>/dev/null || true
@rm -f $(BUILD_DEBUG_DIR)/*.d 2>/dev/null || true
@rm -f $(BUILD_RELEASE_DIR)/*.d 2>/dev/null || true
@rm -f $(BUILD_WINDOWS_DIR)/*.d 2>/dev/null || true
@rm -f $(BUILD_LINUX_DIR)/*.d 2>/dev/null || true
@rm -f $(BUILD_DIR)/*.compile_log 2>/dev/null || true
@rm -f $(BUILD_DIR)/*.compile_status 2>/dev/null || true
@rm -f $(BUILD_DEBUG_DIR)/*.compile_log 2>/dev/null || true
@rm -f $(BUILD_DEBUG_DIR)/*.compile_status 2>/dev/null || true
@rm -f $(BUILD_RELEASE_DIR)/*.compile_log 2>/dev/null || true
@rm -f $(BUILD_RELEASE_DIR)/*.compile_status 2>/dev/null || true
@rm -f $(BUILD_WINDOWS_DIR)/*.compile_log 2>/dev/null || true
@rm -f $(BUILD_WINDOWS_DIR)/*.compile_status 2>/dev/null || true
@rm -f $(BUILD_LINUX_DIR)/*.compile_log 2>/dev/null || true
@rm -f $(BUILD_LINUX_DIR)/*.compile_status 2>/dev/null || true
@echo "Cleaning executables..."
@rm -f $(LAMBDA_EXE)
@rm -f lambda_debug.exe
@rm -f lambda_release.exe
@rm -f lambda-windows.exe
@rm -f lambda-linux.exe
@rm -f .lambda_release_build
@rm -f .lambda_release_backup.exe
@rm -f .lambda_build_backup.exe
@rm -f temp/_transpiled*.c
@echo "Build artifacts and executables cleaned."
clean-test:
@echo "Cleaning test build outputs..."
@rm -rf test_output/ 2>/dev/null || true
@find test/ -name "*.exe" -type f -delete 2>/dev/null || true
@rm -f test_*.exe 2>/dev/null || true
@rm -f *.exe.tmp 2>/dev/null || true
@rm -f build_test_*.json 2>/dev/null || true
@rm -f build_test_*.json.tmp 2>/dev/null || true
@find test/ -name "*.dSYM" -type d -exec rm -rf {} + 2>/dev/null || true
@find test/ -name "*.o" -type f -delete 2>/dev/null || true
@echo "Test build outputs cleaned."
clean-grammar:
@echo "Cleaning generated grammar and embed files..."
@rm -f $(TS_ENUM_H)
@rm -f $(PARSER_C)
@rm -f $(GRAMMAR_JSON)
@rm -f $(NODE_TYPES_JSON)
@rm -f $(LAMBDA_EMBED_H_FILE)
@echo "Generated grammar and embed files cleaned."
# IntelliSense support
intellisense:
@echo "Updating IntelliSense database..."
@./utils/update_intellisense.sh
# Generate type hierarchy chart
type-chart:
dot -Tsvg doc/type_hierarchy.dot -o doc/type_hierarchy.svg
@echo "Type hierarchy chart generated: doc/type_hierarchy.svg"
# Generate grammar explicitly (useful for development)
generate-grammar: $(TS_ENUM_H)
@echo "Grammar generation complete."
# Generate TypeScript grammar explicitly
generate-grammar-typescript: $(TS_PARSER_C)
@echo "TypeScript grammar generation complete."
clean-all: clean-premake clean-test
@echo "Removing all build directories..."
@rm -rf $(BUILD_DIR)
@rm -rf $(BUILD_DEBUG_DIR)
@rm -rf $(BUILD_RELEASE_DIR)
@rm -rf $(BUILD_WINDOWS_DIR)
@rm -rf $(BUILD_LINUX_DIR)
@echo "Cleaning tree-sitter libraries..."
@rm -f lambda/tree-sitter/libtree-sitter.a lambda/tree-sitter/tree_sitter.o
@rm -f lambda/tree-sitter-lambda/libtree-sitter-lambda.a lambda/tree-sitter-lambda/src/*.o
@rm -f lambda/tree-sitter-javascript/libtree-sitter-javascript.a lambda/tree-sitter-javascript/src/*.o
@rm -f lambda/tree-sitter-bash/libtree-sitter-bash.a lambda/tree-sitter-bash/src/*.o
@rm -f lambda/tree-sitter-python/libtree-sitter-python.a lambda/tree-sitter-python/src/*.o
@rm -f lambda/tree-sitter-typescript/libtree-sitter-typescript.a lambda/tree-sitter-typescript/src/*.o
@rm -f lambda/tree-sitter-ruby/libtree-sitter-ruby.a lambda/tree-sitter-ruby/src/*.o
@rm -f lambda/tree-sitter-latex/libtree-sitter-latex.a lambda/tree-sitter-latex/src/*.o
@rm -f lambda/tree-sitter-latex-math/libtree-sitter-latex-math.a lambda/tree-sitter-latex-math/src/*.o
@rm -rf build_temp/re2-noabsl/cmake_build
@echo "All build directories and tree-sitter libraries cleaned."
distclean: clean-all clean-grammar clean-test
@echo "Complete cleanup..."
@rm -f $(LAMBDA_EXE)
@rm -f lambda_debug.exe
@rm -f lambda_release.exe
@rm -f lambda-windows.exe
@rm -f lambda-linux.exe
@rm -f temp/_transpiled*.c
@rm -f *.exe
@echo "Complete cleanup finished."
# Development targets
test: build-test
@echo "Clearing HTTP cache for clean test runs..."
@rm -rf temp/cache
@echo "Running lambda (core) test suites (excluding jube)..."
@LAMBDA_TEST_HEAVY_LOAD=1 node test/test_run.js --exclude-target=jube --parallel
test-all: build-test
@echo "Clearing HTTP cache for clean test runs..."
@rm -rf temp/cache
@echo "Running ALL test suites (baseline + extended)..."
@LAMBDA_TEST_HEAVY_LOAD=1 node test/test_run.js --parallel
test-all-baseline: build-test
@echo "Clearing HTTP cache for clean test runs..."
@rm -rf temp/cache
@echo "Running BASELINE test suites only..."
@LAMBDA_TEST_HEAVY_LOAD=1 node test/test_run.js --category=baseline --parallel
test-lambda-baseline: build-test test-input-baseline
@echo "Clearing HTTP cache for clean test runs..."
@rm -rf temp/cache
@echo "Running LAMBDA baseline test suite..."
@LAMBDA_TEST_HEAVY_LOAD=1 node test/test_run.js --target=lambda --category=baseline --parallel --input-results=test_output/input_baseline_results.json
test-redex-baseline: build
@echo "Running Redex formal semantics baseline verification..."
@cd lambda/semantics && racket baseline-verify.rkt
test-bash-baseline: build-jube-test
@echo "Running Bash transpiler baseline tests (requires lambda-jube)..."
@./test/test_bash_run_gtest.exe
test-c2mir: build-test
@echo "Clearing HTTP cache for clean test runs..."
@rm -rf temp/cache
@echo "Running LAMBDA baseline tests with C2MIR (legacy JIT path)..."
@LAMBDA_USE_C2MIR=1 LAMBDA_TEST_HEAVY_LOAD=1 node test/test_run.js --target=lambda --category=baseline --parallel
# test262 baseline: run only tests in baseline, must pass 100%
test262-baseline:
@echo "Running test262 baseline ($(shell wc -l < test/js262/test262_baseline.txt | tr -d ' ') entries)..."
@echo "Ensuring release lambda.exe for js262 runtime performance..."
@$(MAKE) build-release-compile
@./test/test_js_test262_gtest.exe --baseline-only --batch-only
# test262 full: run all discovered test262 tests (slow, ~5min)
test262-full: build-test
@echo "Running full test262 suite..."
@echo "Ensuring release lambda.exe for js262 runtime performance..."
@$(MAKE) build-release-compile
@./test/test_js_test262_gtest.exe --batch-only
# test262 update baseline: run all tests and update baseline with current passing set
test262-update-baseline: build-test
@echo "Running full test262 suite and updating baseline..."
@echo "Ensuring release lambda.exe for js262 runtime performance..."
@$(MAKE) build-release-compile
@./test/test_js_test262_gtest.exe --batch-only --update-baseline
# test262 strip comments: create comment-stripped test files for faster I/O
test262-strip:
@echo "Stripping comments from test262 files..."
@python3 utils/strip_test262_comments.py
# Node.js official: install Lambda-compatible shims for test harness
node-shim:
@echo "Installing Lambda test shims into ref/node/test/common/..."
@if [ -d ref/node/test/common ]; then \
if [ ! -f ref/node/test/common/index.js.orig ]; then \
cp ref/node/test/common/index.js ref/node/test/common/index.js.orig; \
fi; \
if [ ! -f ref/node/test/common/tmpdir.js.orig ]; then \
cp ref/node/test/common/tmpdir.js ref/node/test/common/tmpdir.js.orig; \
fi; \
if [ ! -f ref/node/test/common/fixtures.js.orig ]; then \
cp ref/node/test/common/fixtures.js ref/node/test/common/fixtures.js.orig; \
fi; \
cp lambda/js/test_shim/common_index.js ref/node/test/common/index.js; \
cp lambda/js/test_shim/tmpdir.js ref/node/test/common/tmpdir.js; \
cp lambda/js/test_shim/fixtures.js ref/node/test/common/fixtures.js; \
cp lambda/js/test_shim/package.json ref/node/test/common/package.json; \
echo "Shims installed."; \
else \
echo "ERROR: ref/node/test/common/ not found. Clone Node.js repo first."; \
exit 1; \
fi
# Node.js official: restore original common module
node-shim-restore:
@echo "Restoring original ref/node/test/common/..."
@if [ -f ref/node/test/common/index.js.orig ]; then \
mv ref/node/test/common/index.js.orig ref/node/test/common/index.js; \
mv ref/node/test/common/tmpdir.js.orig ref/node/test/common/tmpdir.js; \
mv ref/node/test/common/fixtures.js.orig ref/node/test/common/fixtures.js; \
echo "Originals restored."; \
else \
echo "No backup found — nothing to restore."; \
fi
# Node.js official test suite: run official Node.js tests from ref/node/test/parallel/
node-official: build-test node-shim
@echo "Running Node.js official test suite..."
@./test/test_node_official_gtest.exe
# Node.js official: update baseline with current passing set
node-official-update-baseline: build-test node-shim
@echo "Running Node.js official test suite and updating baseline..."
@./test/test_node_official_gtest.exe --update-baseline
ensure-yaml-submodule:
@if [ ! -f test/yaml/README.md ]; then \
echo "Initializing test/yaml submodule..."; \
git submodule update --init test/yaml; \
fi
test-input-baseline: build-test ensure-yaml-submodule
@echo "Clearing HTTP cache for clean test runs..."
@rm -rf temp/cache
@mkdir -p test_output
@echo "=============================================================="
@echo "🧪 Running INPUT baseline tests"
@echo "=============================================================="
@total_passed=0; \
total_failed=0; \
total_skipped=0; \