# Makefile for the bootstrap compiler. # # Copyright © 2021-2025 Samuel Lidén Borell # # SPDX-License-Identifier: EUPL-1.2+ OR LGPL-2.1-or-later srcdir = . builddir = . VPATH = $(srcdir) MKDIR = mkdir MKDIR_P = $(MKDIR) -p RM = rm RM_F = $(RM) -f HOST_CC = $(CC) CFLAGS = -g HOST_CFLAGS = $(CFLAGS) HOST_LDFLAGS = $(LDFLAGS) BASE_WARNINGS = -Wall -Wextra -pedantic \ -Walloca \ -Wbad-function-cast \ -Wcast-align \ -Wconversion \ -Wdate-time \ -Wmissing-declarations \ -Wmissing-prototypes \ -Wmissing-noreturn \ -Wnested-externs \ -Wnull-dereference \ -Wold-style-definition \ -Wshadow \ -Wshift-negative-value \ -Wshift-overflow \ -Wstrict-aliasing \ -Wstrict-overflow=5 \ -Wstrict-prototypes \ -Wswitch-enum \ -Wundef \ -Wunused \ -Wvla \ -Wwrite-strings BASELINE_CFLAGS = -std=c89 $(WARNINGS) $(BASE_WARNINGS) CLANG_ANALYZE_OPTS = --analyzer-output text OBJECTS = \ $(builddir)/ast.o \ $(builddir)/builtins.o \ $(builddir)/funccall.o \ $(builddir)/intrange.o \ $(builddir)/main.o \ $(builddir)/parsedecl.o \ $(builddir)/parseexpr.o \ $(builddir)/parsestmt.o \ $(builddir)/out.o \ $(builddir)/outcommon.o \ $(builddir)/outdecl.o \ $(builddir)/outexpr.o \ $(builddir)/outstmt.o \ $(builddir)/tree.o \ $(builddir)/token.o \ $(builddir)/typechk.o \ $(builddir)/typecompat.o \ $(builddir)/util.o C_SOURCES = \ $(srcdir)/ast.c \ $(srcdir)/builtins.c \ $(srcdir)/funccall.c \ $(srcdir)/intrange.c \ $(srcdir)/main.c \ $(srcdir)/parsedecl.c \ $(srcdir)/parseexpr.c \ $(srcdir)/parsestmt.c \ $(srcdir)/out.c \ $(srcdir)/outcommon.c \ $(srcdir)/outdecl.c \ $(srcdir)/outexpr.c \ $(srcdir)/outstmt.c \ $(srcdir)/tree.c \ $(srcdir)/token.c \ $(srcdir)/typechk.c \ $(srcdir)/typecompat.c \ $(srcdir)/util.c C_HEADERS = \ $(srcdir)/out.h \ $(srcdir)/compiler.h \ $(srcdir)/token.h # TODO should use separate compilation for these too # (but should it use HOST_CC or not? should it be possible to override?) STAGE2_C_SOURCES = \ $(srcdir)/rtl/fail.c \ $(builddir)/stage2_gen.c STAGE2_INCLUDE = \ -I$(srcdir)/rtlincl # perhaps it could pass multiple paths here, to include the backend library # (or, in the future, whatever vendored libraries that the compiler needs) STAGE1_ARGS = $(builddir)/stage2_gen.c $(srcdir)/../compiler COMPILER_SOURCES = \ $(srcdir)/../compiler/misc.slul \ $(srcdir)/../compiler/SomeClass.slul \ $(srcdir)/../compiler/TheCommand.slul all: $(builddir)/stage2 $(OBJECTS): $(srcdir)/compiler.h out.o outcommon.o outdecl.o outexpr.o outstmt.o: $(srcdir)/out.h ast.o funccall.o out.o parsedecl.o parseexpr.o parsestmt.o \ token.o typechk.o: $(srcdir)/token.h .SUFFIXES: .c .o .c.o: $(HOST_CC) $(HOST_CFLAGS) $(BASELINE_CFLAGS) -c -o $@ $< $(builddir)/stage1: $(OBJECTS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ $(OBJECTS) $(builddir)/stage1-boundschecked: $(C_SOURCES) $(C_HEADERS) tcc -b -bt24 -o $@ $(C_SOURCES) $(builddir)/stage2_gen.c: $(builddir)/stage1 $(COMPILER_SOURCES) $(builddir)/stage1 $(STAGE1_ARGS) $(builddir)/stage2: $(STAGE2_C_SOURCES) $(CC) $(CFLAGS) $(BASELINE_CFLAGS) $(STAGE2_DISABLED_WARNINGS) \ $(STAGE2_CFLAGS) $(LDFLAGS) \ $(STAGE2_INCLUDE) \ -o $@ \ $(STAGE2_C_SOURCES) .PHONY: all check check-all check-boundschecked check-valgrind \ check-pmccabe clang-analyze clean gcc-analyzer gdb-stage1 \ longlines outdirs # TODO add a proper test once the stage2 compiler is done check: $(builddir)/stage2 check-all: check check-valgrind check-boundschecked clang-analyze longlines check-valgrind: $(builddir)/stage1 valgrind --leak-check=yes -q $(builddir)/stage1 $(STAGE1_ARGS) check-boundschecked: $(builddir)/stage1-boundschecked TCC_BOUNDS_WARN_POINTER_ADD=1 $(builddir)/stage1-boundschecked \ $(STAGE1_ARGS) clang-analyze: clang --analyze $(CLANG_ANALYZE_OPTS) $(C_SOURCES) longlines: if grep -nE '^.{80,}' $(C_SOURCES) $(C_HEADERS); then \ echo "error: Too long lines detected. Maximum is 80 characters" ;\ false ;\ else \ true ;\ fi # Gives a lot of warnings (possibly false positives) and output gets mixed # up (unless a single file is processed). So not included in check-all. gcc-analyzer: gcc -fanalyzer $(C_SOURCES) check-pmccabe: pmccabe -c $(C_SOURCES) | sort -nr | head -n 20 gdb-stage1: $(builddir)/stage1 gdb -q --args $(builddir)/stage1 $(STAGE1_ARGS) clean: -$(RM_F) \ $(builddir)/stage1 \ $(builddir)/stage1-boundschecked \ $(builddir)/stage2_gen.c \ $(builddir)/stage2 \ $(OBJECTS) outdirs: $(MKDIR_P) $(builddir)