15a20da1aa
Added ability to log the battery level continuously. Added compile-time option #define USE_LIBNOTIFY to post a low-battery warning with libnotify.
132 lines
4.7 KiB
Makefile
132 lines
4.7 KiB
Makefile
#NEWPROJECT requires refactor.sh main.c
|
|
# Taken from https://stackoverflow.com/questions/30573481/how-to-write-a-makefile-with-separate-source-and-header-directories
|
|
|
|
# Always build targets and unit tests together. This avoids the scenario wherein the targets are built, then the source files are edited, then the unit tests are built and, accidentally, outdated targets are packaged and shipped. I say this knowing full well that I never ship my targets to anyone ever.
|
|
|
|
MAKEFILE_VERSION := Makefile from battery log v1.0
|
|
|
|
PREFIX :=
|
|
SUFFIX :=
|
|
|
|
|
|
SRCDIR := sources
|
|
MAINDIR := $(SRCDIR)/main
|
|
INCDIR := $(abspath $(SRCDIR)/include)
|
|
OBJDIR := objects
|
|
MAINOD := $(OBJDIR)/main
|
|
BINDIR := build
|
|
|
|
INSTDIR := /usr/local/bin
|
|
|
|
REFACTOR := refactor.h
|
|
|
|
TESTCFLAGS:= $(shell pkg-config --cflags criterion)
|
|
TESTLIBS := $(shell pkg-config --libs criterion)
|
|
TESTDIR := $(SRCDIR)/test
|
|
TESTOD := $(OBJDIR)/test
|
|
|
|
HEADERS := $(wildcard $(INCDIR)/*.h)
|
|
|
|
MAINS := $(wildcard $(MAINDIR)/*.c)
|
|
MAINOBJS := $(patsubst $(MAINDIR)/%.c, $(MAINOD)/%.o, $(MAINS))
|
|
|
|
TESTS := $(wildcard $(TESTDIR)/*.c)
|
|
TESTOBJS := $(patsubst $(TESTDIR)/%.c, $(TESTOD)/%.o, $(TESTS))
|
|
|
|
UNITTESTS := $(patsubst $(TESTDIR)/%.c, $(BINDIR)/%, $(TESTS))
|
|
|
|
TARGETS := $(patsubst $(MAINDIR)/%.c, $(BINDIR)/%, $(MAINS))
|
|
|
|
SOURCES := $(wildcard $(SRCDIR)/*.c)
|
|
|
|
OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SOURCES))
|
|
|
|
CPPFLAGS := -I$(INCDIR) -MMD -MP -DUSE_LIBNOTIFY
|
|
CFLAGS := -Wall -Werror -Wpedantic $(shell pkg-config --cflags libnotify)
|
|
LDFLAGS := #-Lmath or whatever
|
|
LDLIBS := $(shell pkg-config --libs libnotify) #-lm or whatever
|
|
|
|
define MANGLE =
|
|
$(dir $(1))$(PREFIX)$(notdir $(1))$(SUFFIX)
|
|
endef
|
|
|
|
.PHONY: all clean version
|
|
|
|
all: | $(TARGETS) $(UNITTESTS)
|
|
|
|
version:
|
|
@echo $(MAKEFILE_VERSION)
|
|
|
|
refactor:
|
|
./refactor.sh
|
|
|
|
$(UNITTESTS): $(OBJECTS) $(TESTOBJS) | $(BINDIR) $(OBJDIR) $(TESTOD)
|
|
@echo "Linking unit tests..."
|
|
$(CC) $(LDFLAGS) $(OBJECTS) $(patsubst $(BINDIR)/%, $(TESTOD)/%.o, $@) $(LDLIBS) $(TESTLIBS) -o $(dir $@)$(PREFIX)$(notdir $@)$(SUFFIX)
|
|
@echo "...Done linking unit tests"
|
|
|
|
$(TARGETS): $(OBJECTS) $(MAINOBJS) | $(BINDIR) $(OBJDIR) $(MAINOD)
|
|
@echo "Linking targets..."
|
|
$(CC) $(LDFLAGS) $(OBJECTS) $(patsubst $(BINDIR)/%, $(MAINOD)/%.o, $@) $(LDLIBS) -o $(dir $@)$(PREFIX)$(notdir $@)$(SUFFIX)
|
|
@echo "...Done linking targets"
|
|
|
|
$(BINDIR) $(OBJDIR) $(MAINOD) $(TESTOD):
|
|
mkdir --parents $@
|
|
|
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(HEADERS) | $(OBJDIR)
|
|
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
|
|
|
|
$(MAINOD)/%.o: $(MAINDIR)/%.c $(HEADERS) | $(MAINOD)
|
|
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
|
|
|
|
$(TESTOD)/%.o: $(TESTDIR)/%.c $(HEADERS) | $(TESTOD)
|
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(TESTCFLAGS) $(TESTLIBS) -c $< -o $@
|
|
|
|
# $| evaluates to the order-only prerequisites, in this case: $(TARGETS)
|
|
# The $(foreach ...) function will evaluate to a semicolon-separated list of 'cp <target> $instdir'
|
|
# Putting this $(foreach ...) into the recipe means that its result
|
|
# cp a /usr/local/bin; cp b /usr/local/bin;
|
|
# will be run as a shell command.
|
|
#
|
|
# Shamelessly derived from:
|
|
# https://stackoverflow.com/questions/7918511/make-execute-an-action-for-each-prerequisite
|
|
|
|
install: | $(TARGETS)
|
|
@echo "Installing executables to $(INSTDIR)"
|
|
@$(foreach target, $|, cp -v $(call MANGLE, $(target)) $(INSTDIR);)
|
|
|
|
uninstall: | $(TARGETS)
|
|
@echo "Removing executables from $(INSTDIR)"
|
|
$(foreach target, $(notdir $(call MANGLE, $|)), rm -v $(INSTDIR)/$(target);)
|
|
|
|
clean:
|
|
$(RM) -rv $(BINDIR) $(OBJDIR)
|
|
|
|
# Lazy kludge to run the first executable specified in $(TARGETS)
|
|
# Could also be accomplished by running $< but this is easier to read
|
|
run: all
|
|
$(eval MANGLEDNAME=$(call MANGLE, $(word 1,$(TARGETS))))
|
|
@echo "Running " $(MANGLEDNAME)
|
|
@$(MANGLEDNAME)
|
|
# @$(dir $(word 1,$(TARGETS)))$(PREFIX)$(notdir $(word 1,$(TARGETS)))$(SUFFIX)
|
|
|
|
# unit testing!
|
|
test: $(TARGETS) $(UNITTESTS)
|
|
@echo "Testing " $(word 1,$(UNITTESTS))
|
|
@$(dir $(word 1,$(UNITTESTS)))$(PREFIX)$(notdir $(word 1,$(UNITTESTS)))$(SUFFIX)
|
|
|
|
.PHONY: variable
|
|
variable: all
|
|
$(eval mangle2=$(dir $(word 1,$(UNITTESTS)))$(PREFIX)$(notdir $(word 1,$(UNITTESTS)))$(SUFFIX))
|
|
$(eval mangle3=$(call MANGLE, $(UNITTESTS)))
|
|
@echo "variable declared within a recipe: "$(mangle2)
|
|
@echo "variable declared within a recipe using a canned recipe: "$(mangle3)
|
|
|
|
# Honestly still not sure what this directive does.
|
|
# It's an include directive, which processes all .d files that correspond to members of $(OBJ),
|
|
# with the hyphen in front meaning that it suppresses/ignores errors (from nonexistent .d files)
|
|
# Seems to be included under the stipulation that GNU make will auto-generate .d files based on
|
|
# a given file's #include directives?
|
|
# https://stackoverflow.com/questions/19114410/what-is-d-file-after-building-with-make
|
|
-include $(OBJ:.o=.d)
|