blaise/runtime/Makefile
Graeme Geldenhuys 7dbb981665 build(runtime): enable pipefail so compiler errors fail the build
The Pascal RTL recipes pipe $(BLAISE) --emit-ir through sed to strip
the program section before writing the .ssa file.  Without pipefail,
sed's exit code masks a failing compiler invocation: the recipe
succeeds with an empty .ssa, QBE emits an empty .s, gcc archives an
empty .o, and the first symptom is a downstream link failure with
"no symbols".

Set SHELL=/bin/bash and .SHELLFLAGS=-o pipefail -c at the top of the
Makefile so every recipe inherits pipefail.  Verified by injecting a
parse error into a build driver: make now exits with Error 1 and
prints the compiler's diagnostic, instead of silently producing an
empty archive member.
2026-05-22 15:39:08 +01:00

182 lines
6 KiB
Makefile

#
# Blaise — An Object Pascal Compiler
# Copyright (c) 2026 Graeme Geldenhuys
# SPDX-License-Identifier: Apache-2.0 WITH Swift-exception
# Licensed under the Apache License v2.0 with Runtime Library Exception.
# See LICENSE file in the project root for full license terms.
#
# Use bash with pipefail so that compiler errors in a `... | sed ...`
# pipeline propagate, instead of being masked by sed's exit code.
# Without this, a failing $(BLAISE) invocation produces an empty .ssa
# file and the build silently archives an empty .o (see bugs.txt BUG-004).
SHELL = /bin/bash
.SHELLFLAGS = -o pipefail -c
CC = gcc
CFLAGS = -O2 -Wall -Wextra -std=c11
SRC_DIR = src/main/c
PAS_SRC_DIR = src/main/pascal
ASM_DIR = src/main/asm
OBJ_DIR = target
LIB = $(OBJ_DIR)/blaise_rtl.a
# Where the compiler binary lives — install copies the RTL there so the
# driver finds it automatically next to itself.
COMPILER_BIN = ../compiler/target
BLAISE = $(COMPILER_BIN)/blaise
QBE = ../vendor/qbe/qbe
# Assembly sources — platform-specific, no C compiler needed.
ASM_OBJS = $(OBJ_DIR)/blaise_setjmp_x86_64.o
# Pascal RTL units compiled via the Blaise compiler.
# Each unit is compiled by a thin driver program; the program section is
# stripped from the IR so only the unit's exported functions are archived.
PAS_OBJS = $(OBJ_DIR)/blaise_mem.o \
$(OBJ_DIR)/blaise_str.o \
$(OBJ_DIR)/blaise_arc.o \
$(OBJ_DIR)/blaise_weak.o \
$(OBJ_DIR)/blaise_float.o \
$(OBJ_DIR)/blaise_thread.o \
$(OBJ_DIR)/blaise_exc.o \
$(OBJ_DIR)/rtl_platform_posix.o
OBJS = $(ASM_OBJS) $(PAS_OBJS)
.PHONY: all install clean
all: $(LIB)
$(LIB): $(OBJS)
ar rcs $@ $^
# --- Assembly rules ---
$(OBJ_DIR)/%.o: $(ASM_DIR)/%.s
@mkdir -p $(OBJ_DIR)
$(CC) -c -o $@ $<
# --- Pascal unit rules ---
# Compile via a build driver, strip everything from '# Generated by Blaise'
# onward (the program section), assemble the unit-only IR, then compile to .o.
$(OBJ_DIR)/blaise_mem.ssa: $(PAS_SRC_DIR)/blaise_mem.pas \
$(PAS_SRC_DIR)/blaise_mem_build_driver.pas
@mkdir -p $(OBJ_DIR)
$(BLAISE) --source $(PAS_SRC_DIR)/blaise_mem_build_driver.pas \
--unit-path $(PAS_SRC_DIR) \
--emit-ir \
| sed '/^# Generated by Blaise/,$$d' > $@
$(OBJ_DIR)/blaise_mem.s: $(OBJ_DIR)/blaise_mem.ssa
$(QBE) -o $@ $<
$(OBJ_DIR)/blaise_mem.o: $(OBJ_DIR)/blaise_mem.s
$(CC) -c -o $@ $<
$(OBJ_DIR)/blaise_str.ssa: $(PAS_SRC_DIR)/blaise_str.pas \
$(PAS_SRC_DIR)/blaise_str_build_driver.pas
@mkdir -p $(OBJ_DIR)
$(BLAISE) --source $(PAS_SRC_DIR)/blaise_str_build_driver.pas \
--unit-path $(PAS_SRC_DIR) \
--emit-ir \
| sed '/^# Generated by Blaise/,$$d' > $@
$(OBJ_DIR)/blaise_str.s: $(OBJ_DIR)/blaise_str.ssa
$(QBE) -o $@ $<
$(OBJ_DIR)/blaise_str.o: $(OBJ_DIR)/blaise_str.s
$(CC) -c -o $@ $<
$(OBJ_DIR)/blaise_arc.ssa: $(PAS_SRC_DIR)/blaise_arc.pas \
$(PAS_SRC_DIR)/blaise_arc_build_driver.pas
@mkdir -p $(OBJ_DIR)
$(BLAISE) --source $(PAS_SRC_DIR)/blaise_arc_build_driver.pas \
--unit-path $(PAS_SRC_DIR) \
--emit-ir \
| sed '/^# Generated by Blaise/,$$d' > $@
$(OBJ_DIR)/blaise_arc.s: $(OBJ_DIR)/blaise_arc.ssa
$(QBE) -o $@ $<
$(OBJ_DIR)/blaise_arc.o: $(OBJ_DIR)/blaise_arc.s
$(CC) -c -o $@ $<
$(OBJ_DIR)/rtl_platform_posix.ssa: $(PAS_SRC_DIR)/rtl.platform.pas \
$(PAS_SRC_DIR)/rtl.platform.posix.pas \
$(PAS_SRC_DIR)/rtl.platform.posix_build_driver.pas
@mkdir -p $(OBJ_DIR)
$(BLAISE) --source $(PAS_SRC_DIR)/rtl.platform.posix_build_driver.pas \
--unit-path $(PAS_SRC_DIR) \
--emit-ir \
| sed '/^# Generated by Blaise/d; /^# Source:/d; /^export function w $$main/,/^}$$/d' > $@
$(OBJ_DIR)/rtl_platform_posix.s: $(OBJ_DIR)/rtl_platform_posix.ssa
$(QBE) -o $@ $<
$(OBJ_DIR)/rtl_platform_posix.o: $(OBJ_DIR)/rtl_platform_posix.s
$(CC) -c -o $@ $<
$(OBJ_DIR)/blaise_weak.ssa: $(PAS_SRC_DIR)/blaise_weak.pas \
$(PAS_SRC_DIR)/blaise_weak_build_driver.pas
@mkdir -p $(OBJ_DIR)
$(BLAISE) --source $(PAS_SRC_DIR)/blaise_weak_build_driver.pas \
--unit-path $(PAS_SRC_DIR) \
--emit-ir \
| sed '/^# Generated by Blaise/,$$d' > $@
$(OBJ_DIR)/blaise_weak.s: $(OBJ_DIR)/blaise_weak.ssa
$(QBE) -o $@ $<
$(OBJ_DIR)/blaise_weak.o: $(OBJ_DIR)/blaise_weak.s
$(CC) -c -o $@ $<
$(OBJ_DIR)/blaise_float.ssa: $(PAS_SRC_DIR)/blaise_float.pas \
$(PAS_SRC_DIR)/blaise_float_build_driver.pas
@mkdir -p $(OBJ_DIR)
$(BLAISE) --source $(PAS_SRC_DIR)/blaise_float_build_driver.pas \
--unit-path $(PAS_SRC_DIR) \
--emit-ir \
| sed '/^# Generated by Blaise/,$$d' > $@
$(OBJ_DIR)/blaise_float.s: $(OBJ_DIR)/blaise_float.ssa
$(QBE) -o $@ $<
$(OBJ_DIR)/blaise_float.o: $(OBJ_DIR)/blaise_float.s
$(CC) -c -o $@ $<
$(OBJ_DIR)/blaise_thread.ssa: $(PAS_SRC_DIR)/blaise_thread.pas \
$(PAS_SRC_DIR)/blaise_thread_build_driver.pas
@mkdir -p $(OBJ_DIR)
$(BLAISE) --source $(PAS_SRC_DIR)/blaise_thread_build_driver.pas \
--unit-path $(PAS_SRC_DIR) \
--emit-ir \
| sed '/^# Generated by Blaise/,$$d' > $@
$(OBJ_DIR)/blaise_thread.s: $(OBJ_DIR)/blaise_thread.ssa
$(QBE) -o $@ $<
$(OBJ_DIR)/blaise_thread.o: $(OBJ_DIR)/blaise_thread.s
$(CC) -c -o $@ $<
$(OBJ_DIR)/blaise_exc.ssa: $(PAS_SRC_DIR)/blaise_exc.pas \
$(PAS_SRC_DIR)/blaise_exc_build_driver.pas
@mkdir -p $(OBJ_DIR)
$(BLAISE) --source $(PAS_SRC_DIR)/blaise_exc_build_driver.pas \
--unit-path $(PAS_SRC_DIR) \
--emit-ir \
| sed '/^# Generated by Blaise/,$$d' > $@
$(OBJ_DIR)/blaise_exc.s: $(OBJ_DIR)/blaise_exc.ssa
$(QBE) -o $@ $<
$(OBJ_DIR)/blaise_exc.o: $(OBJ_DIR)/blaise_exc.s
$(CC) -c -o $@ $<
install: $(LIB)
@mkdir -p $(COMPILER_BIN)
cp $(LIB) $(COMPILER_BIN)/blaise_rtl.a
@echo "Installed blaise_rtl.a → $(COMPILER_BIN)/blaise_rtl.a"
clean:
rm -f $(OBJ_DIR)/*.o $(OBJ_DIR)/*.s $(OBJ_DIR)/*.ssa $(LIB)