imsd/Makefile
Jorijn van der Graaf 10379586b5 Add a make build path for distro packaging
Mirror the crafter-build pipeline in a plain GNU Makefile — precompile
the libc++ std module and the Imsd partitions in dependency order,
archive imsd-core, link the three executables with the same clang/
libc++ flags — so distributions can build from source without
packaging crafter-build first. make check runs the same 7 suites;
make install stages the binaries plus the packaging/ files under
DESTDIR/PREFIX.

Rewrite packaging/APKBUILD from a documentation skeleton into a real
source-build APKBUILD on top of it (Alpine's llvm-runtimes ships the
std module sources since 22.x). project.cpp remains the canonical
build description.

Assisted-by: Claude:claude-fable-5
2026-08-07 21:27:29 +02:00

140 lines
5.3 KiB
Makefile

# SPDX-License-Identifier: GPL-3.0-only
# SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
#
# Distro-packaging build path. project.cpp (crafter-build) remains the
# canonical build description; this Makefile mirrors it for environments
# where crafter-build isn't packaged — same clang module pipeline, same
# flags. Keep the two in sync when products, module partitions or link
# flags change.
#
# make -> build/make/{imsd,imsd-media,imsd-dialerd}
# make check -> build + run the 7 unit-test suites
# make install -> DESTDIR/PREFIX staged install (binaries + systemd
# unit, D-Bus policy, dialerd autostart, ims-pdn-up.sh)
#
# Requires clang++ with libc++ and the libc++ std module sources
# (std.cppm — Alpine: llvm-runtimes, Arch: libc++). Override STD_CPPM if
# yours lives elsewhere.
# make's builtin default is CXX=g++, and distro build environments (abuild)
# export CXX=c++ — both gcc, which has no --precompile. This build requires
# clang: the file assignment deliberately ignores the environment while still
# yielding to an explicit `make CXX=...`.
CXX = clang++
AR ?= ar
PKG_CONFIG ?= pkg-config
STD_CPPM ?= /usr/share/libc++/v1/std.cppm
O ?= build/make
PCM = $(O)/pcm
OBJ = $(O)/obj
OPT ?= -O3
# One flag set for every TU: BMIs are rejected on compiler-option mismatch,
# so per-target extras are limited to -I/-D (compile) and -l/-L (link).
ALL_CXXFLAGS = -std=c++26 -stdlib=libc++ $(OPT) $(CXXFLAGS)
ALL_LDFLAGS = -fuse-ld=lld $(LDFLAGS)
# pkg-config gio-2.0: only -I/-D pass through — it also emits -pthread,
# which would config-mismatch the shared std BMI (project.cpp filters
# identically). pthread lives in libc on every platform we target.
GIO_CFLAGS := $(filter -I% -D%,$(shell $(PKG_CONFIG) --cflags gio-2.0))
GIO_LIBS := $(filter -l% -L%,$(shell $(PKG_CONFIG) --libs gio-2.0))
ifeq ($(strip $(GIO_LIBS)),)
GIO_LIBS := -lgio-2.0 -lgobject-2.0 -lglib-2.0
endif
# Imsd module partitions, plus the primary interface last. The BMI file
# names must stay <module>-<partition>.pcm — that is how clang resolves
# `import :Part;` under -fprebuilt-module-path.
PARTITIONS = Imsd-Util Imsd-Sip Imsd-Sdp Imsd-Aka Imsd-Ipsec \
Imsd-Messages Imsd-Engine
CORE_MODULES = $(PARTITIONS) Imsd
CORE_OBJS = $(CORE_MODULES:%=$(OBJ)/%.o)
TESTS = Util Aka Ipsec Messages Engine Sip Sdp
all: $(O)/imsd $(O)/imsd-media $(O)/imsd-dialerd
# ---- module BMIs ----------------------------------------------------------
$(PCM)/std.pcm: $(STD_CPPM) | $(PCM)
$(CXX) $(ALL_CXXFLAGS) -Wno-reserved-identifier \
-Wno-reserved-module-identifier --precompile $< -o $@
$(PCM)/%.pcm: interfaces/%.cppm $(PCM)/std.pcm | $(PCM)
$(CXX) $(ALL_CXXFLAGS) -fprebuilt-module-path=$(PCM) --precompile $< -o $@
# partition import graph (see the `import :X;` lines in interfaces/)
$(PCM)/Imsd-Aka.pcm $(PCM)/Imsd-Ipsec.pcm: $(PCM)/Imsd-Util.pcm
$(PCM)/Imsd-Messages.pcm: $(PCM)/Imsd-Util.pcm $(PCM)/Imsd-Aka.pcm \
$(PCM)/Imsd-Sip.pcm
$(PCM)/Imsd-Engine.pcm: $(PCM)/Imsd-Util.pcm $(PCM)/Imsd-Sip.pcm \
$(PCM)/Imsd-Sdp.pcm $(PCM)/Imsd-Messages.pcm
$(PCM)/Imsd.pcm: $(PARTITIONS:%=$(PCM)/%.pcm)
# ---- imsd-core (static lib of the pure-C++ engine modules) ----------------
$(OBJ)/%.o: $(PCM)/%.pcm | $(OBJ)
$(CXX) $(ALL_CXXFLAGS) -fprebuilt-module-path=$(PCM) -c $< -o $@
$(O)/libimsd-core.a: $(CORE_OBJS)
$(AR) rcs $@ $^
# ---- executables -----------------------------------------------------------
$(OBJ)/main.o: implementations/main.cpp $(PCM)/Imsd.pcm | $(OBJ)
$(CXX) $(ALL_CXXFLAGS) $(GIO_CFLAGS) -fprebuilt-module-path=$(PCM) \
-c $< -o $@
$(O)/imsd: $(OBJ)/main.o $(O)/libimsd-core.a
$(CXX) $(ALL_CXXFLAGS) $(ALL_LDFLAGS) $^ $(GIO_LIBS) -lpthread -o $@
$(OBJ)/media.o: implementations/media.cpp $(PCM)/std.pcm | $(OBJ)
$(CXX) $(ALL_CXXFLAGS) -fprebuilt-module-path=$(PCM) -c $< -o $@
$(O)/imsd-media: $(OBJ)/media.o
$(CXX) $(ALL_CXXFLAGS) $(ALL_LDFLAGS) $^ -ldl -lpthread -o $@
$(OBJ)/dialerd.o: implementations/dialerd.cpp $(PCM)/std.pcm | $(OBJ)
$(CXX) $(ALL_CXXFLAGS) $(GIO_CFLAGS) -fprebuilt-module-path=$(PCM) \
-c $< -o $@
$(O)/imsd-dialerd: $(OBJ)/dialerd.o
$(CXX) $(ALL_CXXFLAGS) $(ALL_LDFLAGS) $^ $(GIO_LIBS) -o $@
# ---- tests -----------------------------------------------------------------
$(O)/tests/%: tests/%/main.cpp $(PCM)/Imsd.pcm $(O)/libimsd-core.a | $(O)/tests
$(CXX) $(ALL_CXXFLAGS) $(ALL_LDFLAGS) -fprebuilt-module-path=$(PCM) \
$< $(O)/libimsd-core.a -lpthread -o $@
check: $(TESTS:%=$(O)/tests/%)
@fail=0; for t in $(TESTS); do \
echo "== $$t"; $(O)/tests/$$t || fail=1; \
done; exit $$fail
# ---- install ----------------------------------------------------------------
PREFIX ?= /usr
install: all
install -Dm755 $(O)/imsd $(DESTDIR)$(PREFIX)/bin/imsd
install -Dm755 $(O)/imsd-dialerd $(DESTDIR)$(PREFIX)/bin/imsd-dialerd
install -Dm755 $(O)/imsd-media $(DESTDIR)$(PREFIX)/libexec/imsd-media
install -Dm755 packaging/ims-pdn-up.sh \
$(DESTDIR)$(PREFIX)/libexec/ims-pdn-up.sh
install -Dm644 packaging/imsd.service \
$(DESTDIR)$(PREFIX)/lib/systemd/system/imsd.service
install -Dm644 packaging/imsd-dialerd.desktop \
$(DESTDIR)/etc/xdg/autostart/imsd-dialerd.desktop
install -Dm644 packaging/net.catcrafts.IMS1.conf \
$(DESTDIR)$(PREFIX)/share/dbus-1/system.d/net.catcrafts.IMS1.conf
$(PCM) $(OBJ) $(O)/tests:
mkdir -p $@
clean:
rm -rf $(O)
.PHONY: all check install clean