Skip to content

Instantly share code, notes, and snippets.

@OrangeTide
Last active November 10, 2023 16:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OrangeTide/8e2adb72ea5d28b9e8ae5046fcc520a3 to your computer and use it in GitHub Desktop.
Save OrangeTide/8e2adb72ea5d28b9e8ae5046fcc520a3 to your computer and use it in GitHub Desktop.
small and low-configuration project Makefile (GNU make required)
# small and low-configuration project Makefile (GNU make required)
# Nov 10 2023 - Jon
# usage:
# 1. place this in the directory of a small C/C++ project.
# 2. modify type= configuration option to select executable or library modes.
# 3. all c/c++ and assembler sources will be linked into a single
# executable or library.
# 4. adjust configuration options for desired compiler and linker flags.
# examples of typical usage:
# make clean
# make
# make RELEASE=1 all
# example of cross-compiling:
# make CC=x86_64-w64-mingw32-cc CXX=x86_64-w64-mingw32-c++ OS=Windows_NT clean-all all
#
# available at: https://gist.github.com/OrangeTide/8e2adb72ea5d28b9e8ae5046fcc520a3
.SUFFIXES:
.PHONY:all clean clean-all
E:=.c .cpp .S .asm
OS:=$(if $(OS),$(OS),$(shell uname -o))
ARCH:=$(if $(ARCH),$(ARCH),$(shell uname -a))
##detection##
B:=$(notdir $(realpath $(dir $(lastword $(MAKEFILE_LIST)))))
S:=$(wildcard $(addprefix *,$E))
O:=$(filter %.o,$(foreach e,$E,$(S:%$e=%.o)))
D:=$(patsubst %.o,%.d,$O)
ifeq ($(OS),Windows_NT)
X:=.exe
L:=.dll
A:=.lib
else
X:=
L:=.so
A:=.a
endif
.SUFFIXES:.o $E $X $L $A
##functions##
.o.c=$(CC) -c -o $@ -MMD $(CPPFLAGS) $(CFLAGS) $(CFLAGS.$(OS)) $<
.o.cpp=$(CXX) -c -o $@ -MMD $(CPPFLAGS) $(CFLAGS) $(CFLAGS.$(OS)) $(CXXFLAGS) $(CXXFLAGS.$(OS)) $<
.o.S=$(CC) -c -o $@ $(CPPFLAGS) $(ASFLAGS) $(ASFLAGS.$(OS)) $<
.o.asm=$(NASM) $(NASMFLAGS) $(NASMFLAGS.$(OS)) -o $@ -MD $*.d $<
link$X=$(cc) -o $@ $(LDFLAGS) $^ $(LDLIBS)
trash-%$X:;
link.so=$(cc) -o $@ -shared -Wl,-soname=$@.$V $(LDFLAGS) $^ $(LDLIBS)
trash-%.so:;
link.dll=$(eval trash+=lib$*.dll.a)$(cc) -o $@ -shared $(LDFLAGS) \
-Wl,--out-implib=lib$*.dll.a \
-Wl,--export-all-symbols \
-Wl,--enable-auto-import \
-Wl,--whole-archive $^ \
-Wl,--no-whole-archive \
$(LDLIBS)
trash-%.dll:;$(eval trash+=lib$*.dll.a)
link$A=$(if $^,$(AR) $(ARFLAGS) $@ $^,$(error No files for archive))
trash-%$A:;
$(foreach y,$E,$(eval $y.o:;$$(.o$y)))
##toolchain configuration##
NASM=nasm
ifneq (${RELEASE},)
# Deterministic mode is preferred for release builds
ARFLAGS=rvD
else
CFLAGS=-g
# Non-deterministic mode is preferred for make dependency checking
ARFLAGS=rvU
endif
##target configuration##
#windows
CFLAGS.Windows_NT=
LDFLAGS.Windows_NT=-mconsole
NASMFLAGS.Windows_NT=-fwin64
#linux
CFLAGS.Linux=-ffunction-sections -fdata-sections
LDFLAGS.Linux=-Wl,-gc-sections -Wl,--strip-all
NASMFLAGS.Linux=-felf64
##project configuration##
#$X=executable $L=shared-library $A=static-library
type=$X
f=$B$(type)
all::$f
#$f:ASFLAGS=
#$f:NASMFLAGS=
#$f:CXXFLAGS=
#$f:CPPFLAGS=
$f:CFLAGS+=-W -Wall -O3
$f:LDFLAGS+=
$f:LDLIBS+=-lm
$f:V=0.1.0
##base definition##
$f:T:=$(type)
$f:S:=$S
$f:O:=$O
$f:cc:=$(if $(filter %.cpp,$S),$(CXX),$(CC))
$f:$O;$(link$T)
$(eval clean::;$$(RM) $f $O)
$(eval clean-all::clean trash-$f;$$(RM) $D $$(trash))
-include $D
$(foreach v,F S O D type,$(eval undefine $v))
#$(info F=$F S=$S O=$O D=$D type=$(type))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment