From 6fbd03f863da6429cc964b5353546958b8f3516e Mon Sep 17 00:00:00 2001 From: anth64 Date: Thu, 12 Mar 2026 22:35:03 +0100 Subject: [PATCH] chore(build): add static library output and privilege-safe install - debug and release targets now produce both shared and static libs - obj dirs split into shared/ and static/ to keep fPIC objects isolated - install no longer depends on release, guards with existence check instead - build.sh handles privilege escalation for install/uninstall via doas or sudo, falling back gracefully if already root - uninstall cleans up static lib alongside shared --- bmake.mk | 47 +++++++++++++++++++++++++-------- build.sh | 30 ++++++++++++++++++++- config.mk | 1 + gmake.mk | 79 ++++++++++++++++++++++++++++++++++++++++--------------- 4 files changed, 124 insertions(+), 33 deletions(-) diff --git a/bmake.mk b/bmake.mk index 5d05b21..b8ade5c 100644 --- a/bmake.mk +++ b/bmake.mk @@ -12,43 +12,65 @@ FULL_LIB = lib${LIB_NAME}.dylib FULL_LIB = lib${LIB_NAME}.so .endif +STATIC_LIB = lib${LIB_NAME}.a + LDFLAGS_PLAT = -ldl CFLAGS_PLAT = -fPIC CFLAGS_BASE = -Wall -Wpedantic -I${.CURDIR}/${INC_DIR} -std=c89 ${CFLAGS_PLAT} +CFLAGS_STATIC = .PHONY: all debug release clean test install uninstall all: debug -OBJS_DEBUG = ${SRCS:S/^src\//obj\/debug\//:S/.c$/.o/} -OBJS_RELEASE = ${SRCS:S/^src\//obj\/release\//:S/.c$/.o/} +OBJS_DEBUG_SHARED = ${SRCS:S/^src\//obj\/debug\/shared\//:S/.c$/.o/} +OBJS_DEBUG_STATIC = ${SRCS:S/^src\//obj\/debug\/static\//:S/.c$/.o/} +OBJS_RELEASE_SHARED = ${SRCS:S/^src\//obj\/release\/shared\//:S/.c$/.o/} +OBJS_RELEASE_STATIC = ${SRCS:S/^src\//obj\/release\/static\//:S/.c$/.o/} -debug: ${BIN_DIR}/debug/${FULL_LIB} -release: ${BIN_DIR}/release/${FULL_LIB} +debug: ${BIN_DIR}/debug/${FULL_LIB} ${BIN_DIR}/debug/${STATIC_LIB} +release: ${BIN_DIR}/release/${FULL_LIB} ${BIN_DIR}/release/${STATIC_LIB} -${BIN_DIR}/debug/${FULL_LIB}: ${OBJS_DEBUG} +${BIN_DIR}/debug/${FULL_LIB}: ${OBJS_DEBUG_SHARED} @mkdir -p ${.TARGET:H} ${CC} -shared -o ${.TARGET} ${.ALLSRC} ${LDFLAGS_PLAT} -${BIN_DIR}/release/${FULL_LIB}: ${OBJS_RELEASE} +${BIN_DIR}/debug/${STATIC_LIB}: ${OBJS_DEBUG_STATIC} + @mkdir -p ${.TARGET:H} + ar rcs ${.TARGET} ${.ALLSRC} + +${BIN_DIR}/release/${FULL_LIB}: ${OBJS_RELEASE_SHARED} @mkdir -p ${.CURDIR}/${BIN_DIR}/release ${CC} -shared -s -o ${.CURDIR}/${BIN_DIR}/release/${FULL_LIB} ${.ALLSRC} ${LDFLAGS_PLAT} +${BIN_DIR}/release/${STATIC_LIB}: ${OBJS_RELEASE_STATIC} + @mkdir -p ${.CURDIR}/${BIN_DIR}/release + ar rcs ${.CURDIR}/${BIN_DIR}/release/${STATIC_LIB} ${.ALLSRC} .for _src in ${SRCS} _obj_base = ${_src:S/^src\///:S/.c$/.o/} -obj/debug/${_obj_base}: ${_src} +obj/debug/shared/${_obj_base}: ${_src} @mkdir -p ${.TARGET:H} ${CC} ${CFLAGS_BASE} -g -O0 -MMD -MP -c ${.ALLSRC} -o ${.TARGET} -obj/release/${_obj_base}: ${_src} +obj/debug/static/${_obj_base}: ${_src} + @mkdir -p ${.TARGET:H} + ${CC} ${CFLAGS_BASE} ${CFLAGS_STATIC} -g -O0 -MMD -MP -c ${.ALLSRC} -o ${.TARGET} + +obj/release/shared/${_obj_base}: ${_src} @mkdir -p ${.TARGET:H} ${CC} ${CFLAGS_BASE} -O2 -MMD -MP -c ${.ALLSRC} -o ${.TARGET} + +obj/release/static/${_obj_base}: ${_src} + @mkdir -p ${.TARGET:H} + ${CC} ${CFLAGS_BASE} ${CFLAGS_STATIC} -O2 -MMD -MP -c ${.ALLSRC} -o ${.TARGET} .endfor -.-include "obj/debug/*.d" -.-include "obj/release/*.d" +.-include "obj/debug/shared/*.d" +.-include "obj/debug/static/*.d" +.-include "obj/release/shared/*.d" +.-include "obj/release/static/*.d" clean: rm -rf ${.CURDIR}/${OBJ_DIR} ${.CURDIR}/${BIN_DIR} @@ -57,13 +79,16 @@ test: debug @echo "=== Building and running stk tests ===" cd ${.CURDIR}/test && ${MAKE} -f bmake.mk -install: release +install: + @test -f ${.CURDIR}/${BIN_DIR}/release/${FULL_LIB} || { echo "Run 'make -f bmake.mk release' before installing."; exit 1; } install -d ${LIBDIR} ${INCDIR}/stk install -m 755 ${.CURDIR}/${BIN_DIR}/release/${FULL_LIB} ${LIBDIR}/ + install -m 644 ${.CURDIR}/${BIN_DIR}/release/${STATIC_LIB} ${LIBDIR}/ install -m 644 ${.CURDIR}/${INC_DIR}/stk.h ${INCDIR}/stk/ install -m 644 ${.CURDIR}/${INC_DIR}/stk_version.h ${INCDIR}/stk/ install -m 644 ${.CURDIR}/${INC_DIR}/stk_log.h ${INCDIR}/stk/ uninstall: rm -f ${LIBDIR}/${FULL_LIB} + rm -f ${LIBDIR}/${STATIC_LIB} rm -rf ${INCDIR}/stk diff --git a/build.sh b/build.sh index 3df3691..f14e46a 100755 --- a/build.sh +++ b/build.sh @@ -8,4 +8,32 @@ else MK_FILE="bmake.mk" fi -make -f "$MK_FILE" "$@" +HAS_INSTALL=0 +HAS_UNINSTALL=0 +for arg in "$@"; do + case "$arg" in + install) HAS_INSTALL=1 ;; + uninstall) HAS_UNINSTALL=1 ;; + esac +done + +if [ "$HAS_INSTALL" = "1" ] || [ "$HAS_UNINSTALL" = "1" ]; then + if [ "$HAS_INSTALL" = "1" ]; then + make -f "$MK_FILE" release + fi + + if [ "$(id -u)" = "0" ]; then + PRIV="" + elif command -v doas > /dev/null 2>&1; then + PRIV="doas" + elif command -v sudo > /dev/null 2>&1; then + PRIV="sudo" + else + echo "error: install requires root. neither doas nor sudo found." >&2 + exit 1 + fi + + $PRIV make -f "$MK_FILE" "$@" +else + make -f "$MK_FILE" "$@" +fi diff --git a/config.mk b/config.mk index 20d3239..8ff1f91 100644 --- a/config.mk +++ b/config.mk @@ -4,6 +4,7 @@ OBJ_DIR = obj BIN_DIR = bin LIB_NAME = stk +STATIC_LIB = lib$(LIB_NAME).a SRCS = src/module.c \ src/platform.c \ diff --git a/gmake.mk b/gmake.mk index 7866a8c..56369e5 100644 --- a/gmake.mk +++ b/gmake.mk @@ -2,17 +2,25 @@ include config.mk ifeq ($(OS),Windows_NT) SHELL := cmd.exe - FULL_LIB := $(LIB_NAME).dll - LDFLAGS_PLAT := - CFLAGS_PLAT := + FULL_LIB := $(LIB_NAME).dll + STATIC_LIB := $(LIB_NAME).lib + LDFLAGS_PLAT := + CFLAGS_PLAT := + CFLAGS_STATIC := MKDIR = if not exist $(subst /,\,$(1)) mkdir $(subst /,\,$(1)) RMDIR = if exist $(subst /,\,$(1)) rd /s /q $(subst /,\,$(1)) + AR := lib + ARFLAGS_STATIC := /OUT: else - FULL_LIB := lib$(LIB_NAME).so - LDFLAGS_PLAT := -ldl - CFLAGS_PLAT := -fPIC + FULL_LIB := lib$(LIB_NAME).so + STATIC_LIB := lib$(LIB_NAME).a + LDFLAGS_PLAT := -ldl + CFLAGS_PLAT := -fPIC + CFLAGS_STATIC := MKDIR = mkdir -p $(1) RMDIR = rm -rf $(1) + AR := ar + ARFLAGS_STATIC := rcs endif RELEASE_LDFLAGS := -s @@ -24,31 +32,57 @@ INCDIR ?= $(PREFIX)/include .PHONY: all debug release clean test install uninstall -all: debug +all: debug -debug: $(BIN_DIR)/debug/$(FULL_LIB) -release: $(BIN_DIR)/release/$(FULL_LIB) +debug: $(BIN_DIR)/debug/$(FULL_LIB) $(BIN_DIR)/debug/$(STATIC_LIB) +release: $(BIN_DIR)/release/$(FULL_LIB) $(BIN_DIR)/release/$(STATIC_LIB) # Debug Rules -$(BIN_DIR)/debug/$(FULL_LIB): $(SRCS:src/%.c=obj/debug/%.o) +$(BIN_DIR)/debug/$(FULL_LIB): $(SRCS:src/%.c=obj/debug/shared/%.o) @$(call MKDIR,$(@D)) - $(CC) -shared -o $@ $^ $(LDFLAGS_PLAT) + $(CC) -shared -o $@ $^ $(LDFLAGS_PLAT) -obj/debug/%.o: src/%.c +$(BIN_DIR)/debug/$(STATIC_LIB): $(SRCS:src/%.c=obj/debug/static/%.o) @$(call MKDIR,$(@D)) - $(CC) $(CFLAGS_BASE) -g -O0 -MMD -MP -c $< -o $@ +ifeq ($(OS),Windows_NT) + $(AR) $(ARFLAGS_STATIC)$@ $^ +else + $(AR) $(ARFLAGS_STATIC) $@ $^ +endif + +obj/debug/shared/%.o: src/%.c + @$(call MKDIR,$(@D)) + $(CC) $(CFLAGS_BASE) -g -O0 -MMD -MP -c $< -o $@ + +obj/debug/static/%.o: src/%.c + @$(call MKDIR,$(@D)) + $(CC) $(CFLAGS_BASE) $(CFLAGS_STATIC) -g -O0 -MMD -MP -c $< -o $@ # Release Rules -$(BIN_DIR)/release/$(FULL_LIB): $(SRCS:src/%.c=obj/release/%.o) +$(BIN_DIR)/release/$(FULL_LIB): $(SRCS:src/%.c=obj/release/shared/%.o) @$(call MKDIR,$(@D)) - $(CC) -shared $(RELEASE_LDFLAGS) -o $@ $^ $(LDFLAGS_PLAT) + $(CC) -shared $(RELEASE_LDFLAGS) -o $@ $^ $(LDFLAGS_PLAT) -obj/release/%.o: src/%.c +$(BIN_DIR)/release/$(STATIC_LIB): $(SRCS:src/%.c=obj/release/static/%.o) @$(call MKDIR,$(@D)) - $(CC) $(CFLAGS_BASE) -O2 -MMD -MP -c $< -o $@ +ifeq ($(OS),Windows_NT) + $(AR) $(ARFLAGS_STATIC)$@ $^ +else + $(AR) $(ARFLAGS_STATIC) $@ $^ +endif --include $(wildcard obj/debug/*.d) --include $(wildcard obj/release/*.d) +obj/release/shared/%.o: src/%.c + @$(call MKDIR,$(@D)) + $(CC) $(CFLAGS_BASE) -O2 -MMD -MP -c $< -o $@ + +obj/release/static/%.o: src/%.c + @$(call MKDIR,$(@D)) + $(CC) $(CFLAGS_BASE) $(CFLAGS_STATIC) -O2 -MMD -MP -c $< -o $@ + +-include $(wildcard obj/debug/shared/*.d) +-include $(wildcard obj/debug/static/*.d) +-include $(wildcard obj/release/shared/*.d) +-include $(wildcard obj/release/static/*.d) clean: @$(call RMDIR,$(OBJ_DIR)) @@ -58,23 +92,26 @@ test: debug @echo "=== Building and running stk tests ===" @$(MAKE) -C test -f gmake.mk -# Installation (Unix only) ifneq ($(OS),Windows_NT) -install: release +install: + @test -f $(BIN_DIR)/release/$(FULL_LIB) || { echo "Run 'make -f gmake.mk release' before installing."; exit 1; } install -d $(LIBDIR) $(INCDIR)/stk install -m 755 $(BIN_DIR)/release/$(FULL_LIB) $(LIBDIR)/ + install -m 644 $(BIN_DIR)/release/$(STATIC_LIB) $(LIBDIR)/ install -m 644 $(INC_DIR)/stk.h $(INCDIR)/stk/ install -m 644 $(INC_DIR)/stk_version.h $(INCDIR)/stk/ install -m 644 $(INC_DIR)/stk_log.h $(INCDIR)/stk/ uninstall: rm -f $(LIBDIR)/$(FULL_LIB) + rm -f $(LIBDIR)/$(STATIC_LIB) rm -rf $(INCDIR)/stk else install: @echo "make install is not supported on Windows." @echo "Copy include/ directory contents to your_project/include/stk/" @echo "Copy bin/release/stk.dll to your project's lib directory." + @echo "Copy bin/release/stk.lib to your project's lib directory." uninstall: @echo "make uninstall is not supported on Windows."