194 lines
8.6 KiB
Makefile
194 lines
8.6 KiB
Makefile
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
# See LICENSE.md for license information.
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# DVX build rules: every example as a DVX program (.app).
|
|
#
|
|
# A JoeyLib program on DVX runs in a window of the DVX desktop, or on the
|
|
# whole screen (src/dvx). The library, libjoey.a, is built here with
|
|
# JoeyLib's own DJGPP (DVX is built with the same gcc 12.2.0) against the SDK
|
|
# the installer unpacked from a DVX tree's dist/sdk.zip into
|
|
# toolchains/opt/dvx/sdk (DVX_SDK); the stage and the graphics are the DOS
|
|
# port's (src/x86, the chunky generics). Each example is then a DVX SDK
|
|
# project in build/dvx/apps/<name>/ -- symlinks to its sources and to the
|
|
# port's entry (src/dvx/dvxApp.c), a generated one-topic help file and
|
|
# resource list -- built and packaged by the SDK's own sdk.mk (KIND = app,
|
|
# LIBS = libjoey.a, DATA = its data files) and copied into build/dvx/bin/
|
|
# laid out as it goes into DVX: apps/joeylib/<name>/<name>.app, <name>.hlp
|
|
# and DATA/. The gates and joey-run copy that tree into a DVX installation.
|
|
#
|
|
# This file holds the library and programRules, the DVX rules for one
|
|
# program, which make/programs.mk instantiates for every program (a project
|
|
# reaches both through make/project.mk). JoeyLib's own examples are at the
|
|
# end.
|
|
|
|
PLATFORM := dvx
|
|
include $(dir $(lastword $(MAKEFILE_LIST)))/common.mk
|
|
|
|
$(call requireTool,$(DOS_CC),toolchain:dos)
|
|
$(call requireTool,$(DVX_SDK)/sdk.mk,toolchain:dvx)
|
|
|
|
APPSDIR := $(PROGRAM_BUILD)/apps
|
|
|
|
PORT_DIR := $(SRC_DIR)/dvx
|
|
|
|
# sdk.mk's code generation, so the library matches the programs it links
|
|
# into; -fomit-frame-pointer as on DOS.
|
|
DVX_ARCH := -march=i486 -mtune=i586 -fomit-frame-pointer
|
|
|
|
# The SDK's header folders (sdk.mk's list: all but the BASIC and socket ones),
|
|
# for the port's own files only -- the core never sees a DVX header.
|
|
DVX_SDK_INCS := $(addprefix -I,$(filter-out %/basic %/net,$(patsubst %/,%,$(wildcard $(DVX_SDK)/include/*/))))
|
|
|
|
# A program's exit() and atexit() are the port's (src/dvx/program.c): the
|
|
# handlers run, and JoeyLib shuts down, when the program ends rather than
|
|
# when DVX does. Applied to the library and the programs, never to the port.
|
|
PROGRAM_RENAMES := -Dexit=dvxPortExit -Datexit=dvxPortAtExit
|
|
|
|
CFLAGS := $(COMMON_CFLAGS) $(DVX_ARCH) -DJOEYLIB_PLATFORM_DVX -I$(SRC_X86) -I$(SRC_CG) -MMD -MP
|
|
LIB_CFLAGS := $(CFLAGS) $(PROGRAM_RENAMES)
|
|
PORT_CFLAGS := $(CFLAGS) -I$(PORT_DIR) $(DVX_SDK_INCS)
|
|
|
|
# The flags every program adds to sdk.mk's (which bring the SDK headers and
|
|
# -Werror), with the include folders every port gives its programs: the
|
|
# program's main becomes jlGameMain, which the port calls.
|
|
APP_CFLAGS := -DJOEYLIB_PLATFORM_DVX -Dmain=jlGameMain $(PROGRAM_RENAMES) -fomit-frame-pointer -I$(INCLUDE_DIR) -I$(SRC_CORE) -I$(PORT_DIR)
|
|
|
|
# dvxApp.c is compiled into each program (it names it), not the library.
|
|
PORT_ENTRY := $(PORT_DIR)/dvxApp.c
|
|
PORT_C_SRCS := $(filter-out $(PORT_ENTRY),$(wildcard $(PORT_DIR)/*.c))
|
|
X86_C_SRCS := $(wildcard $(SRC_X86)/*.c)
|
|
|
|
LIB_OBJS := \
|
|
$(patsubst $(SRC_CORE)/%.c,$(BUILD)/obj/core/%.o,$(CORE_C_SRCS)) \
|
|
$(patsubst $(SRC_DIR)/generic/%.c,$(BUILD)/obj/generic/%.o,$(GENERIC_C_SRCS)) \
|
|
$(patsubst $(PORT_DIR)/%.c,$(BUILD)/obj/port/%.o,$(PORT_C_SRCS)) \
|
|
$(patsubst $(SRC_X86)/%.c,$(BUILD)/obj/x86/%.o,$(X86_C_SRCS)) \
|
|
$(BUILD)/obj/codegen/spriteCompile.o \
|
|
$(BUILD)/obj/codegen/spriteStage.o
|
|
|
|
LIB := $(LIBDIR)/libjoey.a
|
|
|
|
$(BUILD)/obj/core/%.o: $(SRC_CORE)/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(DOS_CC) $(LIB_CFLAGS) -c $< -o $@
|
|
|
|
$(BUILD)/obj/generic/%.o: $(SRC_DIR)/generic/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(DOS_CC) $(LIB_CFLAGS) -c $< -o $@
|
|
|
|
$(BUILD)/obj/x86/%.o: $(SRC_X86)/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(DOS_CC) $(LIB_CFLAGS) -c $< -o $@
|
|
|
|
$(BUILD)/obj/codegen/%.o: $(SRC_CG)/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(DOS_CC) $(LIB_CFLAGS) -c $< -o $@
|
|
|
|
$(BUILD)/obj/port/%.o: $(PORT_DIR)/%.c
|
|
@mkdir -p $(dir $@)
|
|
$(DOS_CC) $(PORT_CFLAGS) -c $< -o $@
|
|
|
|
$(LIB): $(LIB_OBJS)
|
|
@mkdir -p $(dir $@)
|
|
rm -f $@
|
|
$(DOS_AR) rcs $@ $^
|
|
|
|
# Pull in per-object header-dependency files generated by gcc -MMD/-MP.
|
|
-include $(LIB_OBJS:.o=.d)
|
|
|
|
# ---- programs -----------------------------------------------------------------
|
|
# A program is a folder laid out as it installs in DVX, apps/<vendor>/<name>/
|
|
# under bin/: <name>.app, <name>.hlp and its DATA/. The name is the id in lower
|
|
# case (DVX runs on DOS: an 8.3 name). DATA is staged apart, in
|
|
# build/dvx/data/<name>/DATA, for the SDK to package.
|
|
# DVX_VENDOR the vendor folder (default joeylib)
|
|
# DVX_KIND what the help and resource texts call a program: "<title> is a
|
|
# <kind> program" (default JoeyLib)
|
|
# DVX_AUTHOR the resource list's author (default JoeyLib)
|
|
DVX_VENDOR := joeylib
|
|
DVX_KIND := JoeyLib
|
|
DVX_AUTHOR := JoeyLib
|
|
PROGRAM_EXT := .app
|
|
PROGRAM_DATA_APART := yes
|
|
programNameRule = $(call lc,$(1))
|
|
programDir = $(or $(call programVar,$(1),BINDIR),$(BINDIR))/apps/$(DVX_VENDOR)/$(call programName,$(1))
|
|
programTarget = app-$(call programName,$(1))
|
|
programTitle = $(or $(call programVar,$(1),TITLE),$(call capFirst,$(call lc,$(1))))
|
|
|
|
# One program, $(1) its id, as the phony app-<name>: (re)write its SDK project
|
|
# in build/dvx/apps/<name>/ -- the Makefile, symlinks to its sources and the
|
|
# port's entry, the help source and the resource list -- then let sdk.mk build
|
|
# and package it, and copy the package into bin/ (or ID_BINDIR). sdk.mk
|
|
# rebuilds only what changed; the project files are rewritten only when their
|
|
# contents change, so an unchanged program is not relinked. Its CFLAGS are
|
|
# added to the program's flags.
|
|
programRules = $(call programDvxRules,$(1),$(call programName,$(1)))
|
|
|
|
# $(1) the id, $(2) the name. Everything that may hold a comma (the title,
|
|
# the help line) is looked up here rather than passed in.
|
|
define programDvxRules
|
|
.PHONY: app-$(2)
|
|
app-$(2): $(LIB) $(call programVar,$(1),SRCS) $(PORT_ENTRY) $(call programVar,$(1),DATA)
|
|
@mkdir -p $(APPSDIR)/$(2)
|
|
@for src in $(call programVar,$(1),SRCS) $(PORT_ENTRY); do ln -sfn $$$$src $(APPSDIR)/$(2)/$$$$(basename $$$$src); done
|
|
@printf '%s\n' \
|
|
'# Generated by make/dvx.mk: the DVX SDK project of the $(DVX_KIND) $(2).' \
|
|
'SDK_DIR = $(DVX_SDK)' \
|
|
'KIND = app' \
|
|
'NAME = $(2)' \
|
|
'VENDOR = $(DVX_VENDOR)' \
|
|
'LIBS = $(LIB)' \
|
|
'DATA = $(if $(call programVar,$(1),DATA),$(call programDataDir,$(1)))' \
|
|
"CFLAGS = $(APP_CFLAGS) $(call programVar,$(1),CFLAGS) -I$(dir $(firstword $(call programVar,$(1),SRCS))) -DDVX_PORT_APP_NAME='\"$(call programTitle,$(1))\"'" \
|
|
'include $$$$(SDK_DIR)/sdk.mk' | $(REPO_DIR)/make/support/dvx/writeIfChanged.sh $(APPSDIR)/$(2)/Makefile
|
|
@printf '%s\n' \
|
|
'.topic $(2).overview' \
|
|
'.title $(call programTitle,$(1))' \
|
|
'.toc 0 $(call programTitle,$(1))' \
|
|
'.default' \
|
|
'.index $(call programTitle,$(1))' \
|
|
'' \
|
|
'.h1 $(call programTitle,$(1))' \
|
|
'' \
|
|
'$(call programVar,$(1),HELP)' \
|
|
'' \
|
|
'$(call programTitle,$(1)) is a $(DVX_KIND) program. It runs in its own window at a virtual 70 frames a second; while the window is active every key goes to it except Alt+Tab (switch programs), Ctrl+Esc (Task Manager) and Alt+F4 (close it). Game > Exit also closes it.' \
|
|
'' \
|
|
'Game > Full Screen, or Alt+Enter, puts it on the whole screen at 320x200 in 256 colours, and back in its window. It starts the way it was left. Alt+Tab or Ctrl+Esc brings the desktop back while it runs on; coming back to it gives it the whole screen again.' \
|
|
| $(REPO_DIR)/make/support/dvx/writeIfChanged.sh $(APPSDIR)/$(2)/$(2).dhs
|
|
@printf '%s\n' \
|
|
'name text "$(call programTitle,$(1))"' \
|
|
'author text "$(DVX_AUTHOR)"' \
|
|
'description text "$(DVX_KIND): $(call programTitle,$(1))"' \
|
|
| $(REPO_DIR)/make/support/dvx/writeIfChanged.sh $(APPSDIR)/$(2)/$(2).res
|
|
$$(MAKE) -C $(APPSDIR)/$(2) DJGPP_PREFIX=$(DOS_PREFIX) package
|
|
@mkdir -p $(or $(call programVar,$(1),BINDIR),$(BINDIR))
|
|
rm -rf $(call programDir,$(1))
|
|
cp -R $(APPSDIR)/$(2)/pkg/apps $(or $(call programVar,$(1),BINDIR),$(BINDIR))/
|
|
endef
|
|
|
|
# ---- JoeyLib's own build: its examples ------------------------------------------
|
|
ifndef JOEY_PROJECT
|
|
|
|
include $(REPO_DIR)/make/examples.mk
|
|
include $(REPO_DIR)/make/programs.mk
|
|
|
|
# UBER's probe build is part of `all` (scripts/verify-dvx-display.sh).
|
|
.DEFAULT_GOAL := all
|
|
.PHONY: all dvx dvx-lib dvx-probe clean-dvx clean
|
|
all dvx: dvx-lib programs dvx-probe
|
|
|
|
dvx-lib: $(LIB)
|
|
|
|
dvx-probe: $(call programTarget,UBERPROB)
|
|
|
|
clean-dvx:
|
|
rm -rf $(BUILD)
|
|
|
|
# `clean` as an alias for `clean-dvx`. Without it a bare
|
|
# `make -f make/dvx.mk clean` FAILS -- and with stderr discarded that
|
|
# looks like success while leaving stale objects the next build links.
|
|
clean: clean-dvx
|
|
|
|
endif
|