311 lines
13 KiB
Makefile
311 lines
13 KiB
Makefile
# The MIT License (MIT)
|
|
#
|
|
# Copyright (C) 2026 Scott Duensing
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to
|
|
# deal in the Software without restriction, including without limitation the
|
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
# sell copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
# IN THE SOFTWARE.
|
|
|
|
# DVX BASIC Makefile
|
|
#
|
|
# Builds:
|
|
# basrt.lib -- BASIC runtime library (VM + values + form
|
|
# runtime + dlregsym init)
|
|
# dvxbasic.app -- BASIC IDE (compiler + UI, links against
|
|
# basrt.lib, standalone stub embedded)
|
|
# basstub.app -- standalone app stub (obj/dvxbasic, embedded
|
|
# into the IDE and bascomp)
|
|
# bin/system/BASCOMP.EXE-- DOS command-line compiler
|
|
# bin/host/bascomp -- host command-line compiler
|
|
# bin/host/basrun -- host headless runner
|
|
# test_compiler, test_compact, test_suite -- host test harnesses
|
|
# ("make tests" builds and runs them)
|
|
# obj/host/basrt.a -- host compiler + runtime + form runtime for the
|
|
# src/test/formrt suite ("make host-basrt")
|
|
#
|
|
# The runtime is a separate library so compiled BASIC apps can use
|
|
# it without including the compiler. The library's constructor calls
|
|
# dlregsym() to register its exports, making them available to DXEs
|
|
# loaded later (apps, widgets, etc.).
|
|
|
|
include ../../../common.mk
|
|
|
|
LIBDVX = ../../../libs/kpunch/libdvx
|
|
TOOLSDIR = ../../../tools
|
|
DVX_INCLUDES = -I$(LIBDVX) -I$(LIBDVX)/platform -I$(LIBDVX)/thirdparty -I.
|
|
CFLAGS = $(DOS_CFLAGS) $(DVX_INCLUDES) -I../../../widgets/kpunch -I../../../libs/kpunch/dvxshell -I../../../libs/kpunch/libtasks
|
|
|
|
OBJDIR = ../../../../obj/dvxbasic
|
|
LIBSDIR = ../../../../bin/libs
|
|
APPDIR = ../../../../bin/apps/kpunch/dvxbasic
|
|
HOSTDIR = ../../../../bin/host
|
|
DVXRES = $(HOSTDIR)/dvxres
|
|
SYSTEMDIR = ../../../../bin/system
|
|
|
|
# Sources every command-line build (bascomp, basrun, test_suite) links:
|
|
# the build pipeline, the full compiler and the runtime without forms.
|
|
COMP_SRCS = compiler/lexer.c compiler/parser.c compiler/codegen.c compiler/symtab.c compiler/strip.c compiler/obfuscate.c compiler/compact.c
|
|
VM_SRCS = runtime/vm.c runtime/values.c runtime/serialize.c
|
|
# Standalone programs that link the VM also need what libdvx provides it
|
|
# at run time on the target (INI access through dvxPrefs).
|
|
VM_LINK_SRCS = $(VM_SRCS) $(LIBDVX)/dvxPrefs.c
|
|
SUPPORT_SRCS = $(LIBDVX)/platform/dvxPlatformUtil.c $(LIBDVX)/thirdparty/stb_ds_impl.c
|
|
RES_SRCS = $(LIBDVX)/dvxResource.c $(TOOLSDIR)/dvxResWrite.c
|
|
CLI_SRCS = basBuild.c $(COMP_SRCS) $(VM_LINK_SRCS) $(RES_SRCS) $(SUPPORT_SRCS)
|
|
|
|
# Runtime library objects (VM + values + form runtime + serialization)
|
|
RT_OBJS = $(OBJDIR)/vm.o $(OBJDIR)/values.o $(OBJDIR)/formrt.o $(OBJDIR)/frmParser.o $(OBJDIR)/basNativeDos.o $(OBJDIR)/serialize.o
|
|
RT_TARGETDIR = $(LIBSDIR)/kpunch/basrt
|
|
RT_TARGET = $(RT_TARGETDIR)/basrt.lib
|
|
|
|
# Compiler objects (only needed by the IDE)
|
|
COMP_OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(COMP_SRCS))) $(OBJDIR)/basBuild.o
|
|
|
|
# IDE app objects
|
|
IDE_OBJS = $(OBJDIR)/ideMain.o $(OBJDIR)/ideDesigner.o $(OBJDIR)/ideMenuEditor.o $(OBJDIR)/ideProject.o $(OBJDIR)/ideToolbox.o $(OBJDIR)/ideProperties.o
|
|
APP_TARGET = $(APPDIR)/dvxbasic.app
|
|
|
|
# Standalone stub (embedded as IDE resource)
|
|
STUB_OBJS = $(OBJDIR)/basstub.o $(OBJDIR)/basModuleRes.o
|
|
STUB_TARGET = $(OBJDIR)/basstub.app
|
|
|
|
# DOS command-line compiler: the same DOS objects the IDE uses plus the
|
|
# resource and support code the loader normally provides.
|
|
DOS_BASCOMP_OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir stub/bascomp.c $(CLI_SRCS)))
|
|
|
|
# ---- Native host tools and harnesses (host gcc, not cross-compiled) ----
|
|
#
|
|
# TESTSAN=1 rebuilds the harnesses, bascomp and basrun under ASan/UBSan
|
|
# (make tests TESTSAN=1). Objects live in one directory per mode; the
|
|
# binaries share bin/host and depend on a mode stamp so switching TESTSAN
|
|
# relinks them instead of running a stale binary.
|
|
HOSTCFLAGS = $(HOST_TOOL_CFLAGS) -Wno-stringop-truncation -D_GNU_SOURCE $(DVX_INCLUDES)
|
|
HOSTLDFLAGS =
|
|
HOSTTOOL_OBJDIR = $(OBJDIR)/host-$(if $(filter 1,$(TESTSAN)),san,plain)
|
|
ifeq ($(TESTSAN),1)
|
|
HOSTCFLAGS += -g $(SAN_FLAGS)
|
|
HOSTLDFLAGS += $(SAN_FLAGS)
|
|
endif
|
|
# COV=1 (make coverage): every host build (harnesses, bascomp, basrun,
|
|
# basrt.a) gets gcov instrumentation and lands under obj/hostcov so it
|
|
# never mixes with the sanitized or release host binaries. dvxres is
|
|
# still the release tool from bin/host. Must precede the rules below
|
|
# because target names expand when they are read.
|
|
ifeq ($(COV),1)
|
|
HOSTDIR = ../../../../obj/hostcov/basic
|
|
DVXRES = ../../../../bin/host/dvxres
|
|
HOSTTOOL_OBJDIR = $(HOSTDIR)/obj
|
|
HOSTCFLAGS += -g --coverage
|
|
HOSTLDFLAGS += --coverage
|
|
endif
|
|
|
|
TESTSAN_STAMP = $(HOSTDIR)/.testsan-$(if $(filter 1,$(TESTSAN)),on,off)
|
|
|
|
# hostObjs SRCS -> the host tool objects for SRCS
|
|
hostObjs = $(patsubst %.c,$(HOSTTOOL_OBJDIR)/%.o,$(notdir $1))
|
|
|
|
TEST_COMPILER = $(HOSTDIR)/test_compiler
|
|
TEST_COMPACT = $(HOSTDIR)/test_compact
|
|
TEST_SUITE = $(HOSTDIR)/test_suite
|
|
BASCOMP_TARGET = $(HOSTDIR)/bascomp
|
|
BASRUN_TARGET = $(HOSTDIR)/basrun
|
|
|
|
TEST_COMPILER_OBJS = $(call hostObjs,test_compiler.c $(COMP_SRCS) $(VM_LINK_SRCS) $(SUPPORT_SRCS))
|
|
TEST_COMPACT_OBJS = $(call hostObjs,test_compact.c $(COMP_SRCS) $(VM_LINK_SRCS) $(SUPPORT_SRCS))
|
|
TEST_SUITE_OBJS = $(call hostObjs,test_suite.c $(CLI_SRCS))
|
|
BASCOMP_OBJS = $(call hostObjs,stub/bascomp.c $(CLI_SRCS))
|
|
BASRUN_OBJS = $(call hostObjs,stub/basrun.c stub/basModuleRes.c $(CLI_SRCS))
|
|
HOSTTOOL_OBJS = $(sort $(TEST_COMPILER_OBJS) $(TEST_COMPACT_OBJS) $(TEST_SUITE_OBJS) $(BASCOMP_OBJS) $(BASRUN_OBJS))
|
|
|
|
# Extra per-object host flags
|
|
HOSTFLAGS_test_suite = -DBAS_TEST_SRC_DIR='"$(abspath .)"'
|
|
|
|
# Host-side BASIC test directory (basrun fixtures, fuzzers, compaction
|
|
# diff) and the scratch directory the harnesses run in (they write files
|
|
# into the working directory).
|
|
BASIC_TESTDIR = ../../../test/basic
|
|
HARNESS_WORK = ../../../../obj/test/harness
|
|
|
|
.PHONY: all clean tests
|
|
|
|
all: $(RT_TARGET) $(RT_TARGETDIR)/basrt.dep $(STUB_TARGET) $(APP_TARGET) $(BASCOMP_TARGET) $(BASRUN_TARGET) $(SYSTEMDIR)/BASCOMP.EXE
|
|
|
|
# Run every built harness and fail the build if any returns non-zero.
|
|
# test_compiler, test_compact and test_suite each report a failure count
|
|
# and return non-zero on failure. make stops at the first one that fails.
|
|
# The src/test/basic suite (sample runs, fixtures, fuzzers, compaction
|
|
# differential) needs bascomp and basrun; it inherits TESTSAN.
|
|
tests: $(TEST_COMPILER) $(TEST_COMPACT) $(TEST_SUITE) $(BASCOMP_TARGET) $(BASRUN_TARGET)
|
|
mkdir -p $(HARNESS_WORK)
|
|
cd $(HARNESS_WORK) && $(abspath $(TEST_COMPILER))
|
|
cd $(HARNESS_WORK) && $(abspath $(TEST_COMPACT))
|
|
cd $(HARNESS_WORK) && $(abspath $(TEST_SUITE))
|
|
$(MAKE) -C $(BASIC_TESTDIR) test TESTSAN=$(TESTSAN)
|
|
|
|
$(TEST_COMPILER): $(TEST_COMPILER_OBJS) $(TESTSAN_STAMP) | $(HOSTDIR)
|
|
$(HOSTCC) $(HOSTLDFLAGS) -o $@ $(TEST_COMPILER_OBJS) -lm
|
|
|
|
$(TEST_COMPACT): $(TEST_COMPACT_OBJS) $(TESTSAN_STAMP) | $(HOSTDIR)
|
|
$(HOSTCC) $(HOSTLDFLAGS) -o $@ $(TEST_COMPACT_OBJS) -lm
|
|
|
|
$(TEST_SUITE): $(TEST_SUITE_OBJS) $(TESTSAN_STAMP) | $(HOSTDIR)
|
|
$(HOSTCC) $(HOSTLDFLAGS) -o $@ $(TEST_SUITE_OBJS) -lm
|
|
|
|
$(BASRUN_TARGET): $(BASRUN_OBJS) $(TESTSAN_STAMP) | $(HOSTDIR)
|
|
$(HOSTCC) $(HOSTLDFLAGS) -o $@ $(BASRUN_OBJS) -lm
|
|
|
|
# Host command-line compiler -- basstub.app is appended as a STUB
|
|
# resource so bascomp is self-contained (no BASSTUB.APP companion file),
|
|
# and noicon.bmp as the ICON32 fallback for projects without an icon.
|
|
$(BASCOMP_TARGET): $(BASCOMP_OBJS) $(TESTSAN_STAMP) $(STUB_TARGET) noicon.bmp $(DVXRES) | $(HOSTDIR)
|
|
$(HOSTCC) $(HOSTLDFLAGS) -o $@ $(BASCOMP_OBJS) -lm
|
|
$(DVXRES) add $@ STUB binary @$(STUB_TARGET)
|
|
$(DVXRES) add $@ noicon icon @noicon.bmp
|
|
|
|
$(TESTSAN_STAMP): | $(HOSTDIR)
|
|
rm -f $(HOSTDIR)/.testsan-on $(HOSTDIR)/.testsan-off
|
|
touch $@
|
|
|
|
# One host object rule per source (the sources live in several dirs).
|
|
define HOST_OBJ_RULE
|
|
$(call hostObjs,$1): $1 $$(DVX_MAKEFILES) | $$(HOSTTOOL_OBJDIR)
|
|
$$(HOSTCC) $$(HOSTCFLAGS) $$(HOSTFLAGS_$(basename $(notdir $1))) -c -o $$@ $$<
|
|
endef
|
|
|
|
$(foreach src,$(sort test_compiler.c test_compact.c test_suite.c stub/bascomp.c stub/basrun.c stub/basModuleRes.c $(CLI_SRCS)),$(eval $(call HOST_OBJ_RULE,$(src))))
|
|
|
|
# DOS command-line compiler (same STUB / noicon embed as the host build)
|
|
$(SYSTEMDIR)/BASCOMP.EXE: $(DOS_BASCOMP_OBJS) $(STUB_TARGET) noicon.bmp $(DVXRES) | $(SYSTEMDIR)
|
|
$(CC) -o $(SYSTEMDIR)/bascomp.exe $(DOS_BASCOMP_OBJS) -lm
|
|
$(EXE2COFF) $(SYSTEMDIR)/bascomp.exe
|
|
cat $(CWSDSTUB) $(SYSTEMDIR)/bascomp > $@
|
|
rm -f $(SYSTEMDIR)/bascomp $(SYSTEMDIR)/bascomp.exe
|
|
$(DVXRES) add $@ STUB binary @$(STUB_TARGET)
|
|
$(DVXRES) add $@ noicon icon @noicon.bmp
|
|
|
|
$(HOSTDIR) $(HOSTTOOL_OBJDIR) $(SYSTEMDIR):
|
|
mkdir -p $@
|
|
|
|
# Runtime library DXE (exports symbols via dlregsym constructor)
|
|
$(RT_TARGET): $(RT_OBJS) | $(RT_TARGETDIR)
|
|
$(DXE3GEN) -o $(RT_TARGETDIR)/basrt.dxe -U $(RT_OBJS)
|
|
mv $(RT_TARGETDIR)/basrt.dxe $@
|
|
|
|
$(RT_TARGETDIR)/basrt.dep: basrt.dep | $(RT_TARGETDIR)
|
|
sed 's/$$/\r/' $< > $@
|
|
|
|
# Standalone stub DXE (embedded as resource in IDE app)
|
|
$(STUB_TARGET): $(STUB_OBJS) | $(OBJDIR)
|
|
$(DXE3GEN) -o $@ -U $(STUB_OBJS)
|
|
|
|
# IDE app DXE (compiler linked in, runtime from basrt.lib, stub embedded)
|
|
$(APP_TARGET): $(COMP_OBJS) $(IDE_OBJS) $(STUB_TARGET) dvxbasic.res | $(APPDIR)
|
|
$(DXE3GEN) -o $@ -U $(COMP_OBJS) $(IDE_OBJS)
|
|
$(DVXRES) build $@ dvxbasic.res
|
|
$(DVXRES) add $@ STUB binary @$(STUB_TARGET)
|
|
|
|
|
|
# DOS object files. One pattern rule per source directory; header
|
|
# dependencies come from the compiler (DEPFLAGS writes a .d next to each
|
|
# object) so no hand-written list can drift out of date.
|
|
$(OBJDIR)/%.o: compiler/%.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(OBJDIR)/%.o: runtime/%.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(OBJDIR)/%.o: formrt/%.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(OBJDIR)/%.o: ide/%.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(OBJDIR)/%.o: stub/%.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(OBJDIR)/%.o: $(LIBDVX)/%.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(OBJDIR)/%.o: $(LIBDVX)/platform/%.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(OBJDIR)/%.o: $(LIBDVX)/thirdparty/%.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(OBJDIR)/%.o: $(TOOLSDIR)/%.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
$(OBJDIR)/%.o: %.c $(DVX_MAKEFILES) | $(OBJDIR)
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
# Directories
|
|
$(OBJDIR):
|
|
mkdir -p $(OBJDIR)
|
|
|
|
$(RT_TARGETDIR):
|
|
mkdir -p $(RT_TARGETDIR)
|
|
|
|
$(APPDIR):
|
|
mkdir -p $(APPDIR)
|
|
|
|
clean: host-basrt-clean
|
|
rm -rf $(RT_OBJS) $(COMP_OBJS) $(IDE_OBJS) $(STUB_OBJS) $(DOS_BASCOMP_OBJS) $(OBJDIR)/*.d $(RT_TARGET) $(APP_TARGET) $(STUB_TARGET) $(BASCOMP_TARGET) $(SYSTEMDIR)/BASCOMP.EXE $(RT_TARGETDIR)/basrt.dep $(RT_TARGETDIR)
|
|
rm -rf $(OBJDIR)/host-plain $(OBJDIR)/host-san $(HARNESS_WORK)
|
|
rm -f $(TEST_COMPILER) $(TEST_COMPACT) $(TEST_SUITE) $(BASRUN_TARGET) $(HOSTDIR)/.testsan-on $(HOSTDIR)/.testsan-off
|
|
$(MAKE) -C $(BASIC_TESTDIR) clean
|
|
|
|
|
|
# ============================================================
|
|
# Host basrt archive (src/test/formrt suite)
|
|
# ============================================================
|
|
#
|
|
# Compiler + runtime + form runtime built with the native toolchain into
|
|
# obj/host/basrt.a, linked by the form-runtime test suite against the
|
|
# host libdvx.a and the widget .so files. basNativeHost.c stands in for
|
|
# the i386 basNativeDos.c trampoline (Makefile object-list selection, no
|
|
# preprocessor conditionals). SAN/COV per common.mk; must match the rest
|
|
# of the host build.
|
|
HOSTRT_DIR = $(HOST_OBJROOT)/basrt
|
|
HOSTRT_TARGET = $(HOST_OBJROOT)/basrt.a
|
|
HOSTRT_SRCS = $(COMP_SRCS) $(VM_SRCS) formrt/formrt.c formrt/frmParser.c formrt/basNativeHost.c
|
|
HOSTRT_OBJS = $(patsubst %.c,$(HOSTRT_DIR)/%.o,$(notdir $(HOSTRT_SRCS)))
|
|
HOSTRT_CFLAGS = $(HOST_CFLAGS) -Wno-stringop-truncation $(DVX_INCLUDES) -I../../../widgets/kpunch -I../../../libs/kpunch/dvxshell -I../../../libs/kpunch/libtasks
|
|
|
|
.PHONY: host-basrt host-basrt-clean
|
|
|
|
host-basrt: $(HOSTRT_TARGET)
|
|
|
|
$(HOSTRT_TARGET): $(HOSTRT_OBJS)
|
|
rm -f $@
|
|
ar rcs $@ $(HOSTRT_OBJS)
|
|
|
|
$(HOSTRT_DIR)/%.o: compiler/%.c $(DVX_MAKEFILES)
|
|
@mkdir -p $(HOSTRT_DIR)
|
|
$(HOSTCC) $(HOSTRT_CFLAGS) -c -o $@ $<
|
|
|
|
$(HOSTRT_DIR)/%.o: runtime/%.c $(DVX_MAKEFILES)
|
|
@mkdir -p $(HOSTRT_DIR)
|
|
$(HOSTCC) $(HOSTRT_CFLAGS) -c -o $@ $<
|
|
|
|
$(HOSTRT_DIR)/%.o: formrt/%.c $(DVX_MAKEFILES)
|
|
@mkdir -p $(HOSTRT_DIR)
|
|
$(HOSTCC) $(HOSTRT_CFLAGS) -c -o $@ $<
|
|
|
|
host-basrt-clean:
|
|
rm -rf $(HOSTRT_DIR) $(HOSTRT_TARGET)
|
|
|
|
-include $(wildcard $(OBJDIR)/*.d) $(HOSTTOOL_OBJS:.o=.d) $(HOSTRT_OBJS:.o=.d)
|