# SPDX-License-Identifier: MIT
CXX ?= c++
CC ?= cc
CPP ?= cpp
MANDOC ?= mandoc
AWK ?= awk
CARGO ?= cargo
LTO ?= y
FEBUG_VERSION ?= "$(patsubst v%,%,$(shell git describe))"
FEBUG_DATE ?= $(shell date $(shell date --version > /dev/null 2>&1 && echo "--date @" || echo "-r ")$(shell git log -1 --no-show-signature --format=%at) +"%B %e, %Y")
EXTRACCAR ?=
EXTRALDAR ?=
AS_NEEDED := -Wl,--as-needed
SONAME := -soname
SYSTEM := $(shell uname -s)
ifeq "$(SYSTEM)" "NetBSD"
FUSE_ARGS ?= -lrefuse
else ifeq "$(SYSTEM)" "OpenBSD"
FUSE_ARGS ?= -lfuse
else ifeq "$(SYSTEM)" "Darwin"
FUSE_ARGS ?= -lfuse
AS_NEEDED :=
SONAME := -install_name
else
FUSE_ARGS ?= $(shell pkg-config --libs --cflags fuse3)
endif
CXXVER := $(shell $(CXX) --version | head -1)
ifneq "$(findstring clang,$(CXXVER))" ""
# GCC doesn't have this granularity
CXXSPECIFICCC := -Wpedantic -Wno-c++20-designator -Wno-c99-extensions -Wno-unknown-warning-option
ifneq "$(findstring Apple,$(CXXVER))" ""
# CMSG_SPACE() is a macro, and it's decidedly constexpr. i don't care if appleclang can't figure that out
CXXSPECIFICCC += -Wno-vla-extension
endif
ifeq "$(LTO)" "y"
CXXSPECIFICLD := -flto=full # Clang produces .o files with LLVM bitcode, which cannot be linked to if put in .as
else
CXXSPECIFICLD :=
endif
else
CXXSPECIFICCC := -Wno-missing-field-initializers -fno-common
ifeq "$(LTO)" "y"
CXXSPECIFICCC += -flto
endif
CXXSPECIFICLD :=
endif
OUTDIR ?= out/
OBJDIR ?= $(OUTDIR)obj/
CCAR := -g -O3 -pipe -Wall -Wextra -isysteminclude/ $(CXXSPECIFICCC) $(EXTRACCAR)
LDAR := $(AS_NEEDED) -L$(OUTDIR) $(CXXSPECIFICLD) $(EXTRALDAR)
HEADERS := $(wildcard include/*.h include/*.hpp)
EXAMPLES := $(wildcard examples/*.c examples/*.cpp)
EXAMPLES_RS := $(wildcard examples/*.rs)
MANPAGES := $(wildcard man/*.[0123456789])
FEBUG_VERSION := $(FEBUG_VERSION)
FEBUG_DATE := $(FEBUG_DATE)
FUSE_ARGS := $(FUSE_ARGS)
.PHONY : main libfebug++ libfebug examples manpages htmlpages rust-build rust-doc
all : main libfebug++ libfebug examples manpages htmlpages how.png
clean:
rm -rf $(OUTDIR) $(OBJDIR) how.png
main : $(OUTDIR)febug
libfebug++ : $(OUTDIR)libfebug++.a
libfebug : $(OUTDIR)libfebug.a $(OUTDIR)libfebug.so
examples : $(foreach l,$(patsubst %.c,$(OUTDIR)%,$(patsubst %pp,%,$(EXAMPLES))),$(l) $(l)-dont)
manpages : $(patsubst %,$(OUTDIR)%,$(MANPAGES)) $(OBJDIR)man/aliases
htmlpages : $(patsubst %,$(OUTDIR)%.html,$(MANPAGES)) $(OUTDIR)man/style.css
rust-build : $(OUTDIR)febug.rs/target/libfebug.rlib
rust-doc : $(OUTDIR)febug.rs/doc/febug/index.html
$(OUTDIR)febug : main.cpp $(HEADERS)
@mkdir -p $(dir $@)
$(CXX) $< -o$@ -DFEBUG_VERSION='$(FEBUG_VERSION)' -std=c++17 -fno-exceptions -fPIE $(CCAR) $(LDAR) $(FUSE_ARGS)
$(OBJDIR)febug++.o : febug.cpp $(HEADERS)
@mkdir -p $(dir $@)
$(CXX) -c $< -o$@ -std=c++17 -fPIC $(CCAR)
$(OUTDIR)libfebug++.a : $(OBJDIR)febug++.o
@mkdir -p $(dir $@)
ar crs $@ $^
$(OBJDIR)febug.o : febug.c $(HEADERS)
@mkdir -p $(dir $@)
$(CC) -c $< -o$@ -std=c11 -fPIC $(CCAR)
$(OUTDIR)libfebug.a : $(OBJDIR)febug.o
@mkdir -p $(dir $@)
ar crs $@ $^
$(OUTDIR)libfebug.so : $(OBJDIR)febug.o
@mkdir -p $(dir $@)
$(CC) -shared $< -o$(OUTDIR)libfebug.so.0 -std=c11 -fPIC $(CCAR) $(LDAR) -Wl,$(SONAME),libfebug.so.0
ln -fs libfebug.so.0 $@
$(OUTDIR)examples/% : examples/%.cpp $(OUTDIR)libfebug++.a $(HEADERS)
@mkdir -p $(dir $@)
$(CXX) $< -o$@ -std=c++17 -fPIE $(CCAR) $(LDAR) -lfebug++
$(OUTDIR)examples/%-dont : examples/%.cpp $(OUTDIR)libfebug++.a $(HEADERS)
@mkdir -p $(dir $@)
$(CXX) $< -o$@ -DFEBUG_DONT -std=c++17 -fPIE $(CCAR) $(LDAR) -lfebug++
$(OUTDIR)examples/% : examples/%.c $(OUTDIR)libfebug.a $(HEADERS)
@mkdir -p $(dir $@)
$(CC) $< -o$@ -std=c11 -fPIE $(CCAR) $(LDAR) -lfebug
$(OUTDIR)examples/%-dont : examples/%.c $(OUTDIR)libfebug.a $(HEADERS)
@mkdir -p $(dir $@)
$(CC) $< -o$@ -DFEBUG_DONT -std=c11 -fPIE $(CCAR) $(LDAR) -lfebug
$(OBJDIR)man/aliases : man/aliases
@mkdir -p $(dir $@)
@touch $@
$(AWK) '!/^$$/ {print "ln -fs " $$1 " $(OUTDIR)man/" $$2}' man/aliases | sh -x
$(OUTDIR)man/% : man/% $(wildcard man/*.h)
@mkdir -p $(dir $@)
(cd $(dir $<); $(CPP) -nostdinc -Wno-trigraphs -Wno-invalid-pp-token -CC -P -DFEBUG_DATE="$(FEBUG_DATE)" -DFEBUG_VERSION='$(FEBUG_VERSION)' - < $(notdir $<) | \
$(AWK) '/^$$/ {next} $$1 == ".Dt" { print ".ds doc-volume-operating-system" } \
$$1 == "$$include" {gsub(/"/, "", $$2); while((getline line < $$2) > 0) {gsub(/\\/, "\\e", line); print line}; next} \
{print}') > $@
! $(MANDOC) -Tlint $@ 2>&1 | grep -vE -e 'mandoc: outdated mandoc.db' -e 'STYLE: referenced manual not found' -e 'WARNING: unknown manual section: Dt .* 0$$' -e 'STYLE: operating system explicitly specified: Os febug' -e 'STYLE: input text line longer than 80 bytes' -e 'STYLE: .*OpenBSD' -e 'STYLE: RCS id missing'
$(OUTDIR)man/%.html : $(OUTDIR)man/%
(cd man/; $(MANDOC) -Thtml -Oincludes="https://git.sr.ht/~nabijaczleweli/febug/tree/trunk/item/include/%I",man="%N.%S.html;https://manpages.debian.org/bullseye/%N.%S",style="style.css" ../$^ | \
sed -Ee 's/ title=".."//g') > $@
$(OUTDIR)man/style.css : man/style.css
@mkdir -p $(dir $@)
ln -f $^ $@ 2>/dev/null || cp $^ $@
$(OUTDIR)febug.rs/README.md : README.md
@mkdir -p $(dir $@)
ln -f $^ $@ 2>/dev/null || cp $^ $@
$(OUTDIR)febug.rs/%.rs : febug.rs/%.rs
@mkdir -p $(dir $@)
ln -f $^ $@ 2>/dev/null || cp $^ $@
$(OUTDIR)febug.rs/examples/%.rs : examples/%.rs
@mkdir -p $(dir $@)
ln -f $^ $@ 2>/dev/null || cp $^ $@
$(OUTDIR)febug.rs/target/libfebug.rlib : $(OUTDIR)febug.rs/Cargo.toml $(OUTDIR)febug.rs/lib.rs $(OUTDIR)febug.rs/build.rs $(OUTDIR)febug.rs/README.md $(patsubst %,$(OUTDIR)febug.rs/%,$(EXAMPLES_RS))
@mkdir -p $(OUTDIR)examples/
cd $(dir $<); FEBUG_DONT=1 $(CARGO) build --release --examples
$(foreach l,$(patsubst %.rs,%,$(EXAMPLES_RS)),mv $(OUTDIR)febug.rs/target/release/$(l) $(OUTDIR)$(l)-dont; )
cd $(dir $<); $(CARGO) build --release --examples
$(foreach l,$(patsubst %.rs,%,$(EXAMPLES_RS)),mv $(OUTDIR)febug.rs/target/release/$(l) $(OUTDIR)$(l); )
$(OUTDIR)febug.rs/doc/febug/index.html : $(OUTDIR)febug.rs/target/libfebug.rlib
cd $(dir $<); $(CARGO) doc --release
$(OUTDIR)febug.rs/Cargo.toml : febug.rs/Cargo.toml
@mkdir -p $(dir $@)
sed 's;FEBUG_VERSION;$(FEBUG_VERSION);' $< > $@
how.png : how.dot
dot -Tpng $^ -o $@