ldaphotos/Makefile
Sandy Mossgrave 980784ea29 Works.
Now accepts argument '-f', for which the argument is a file path.
Opens file, then reads input from it.
If file is not provided or fopen() fails, ldaphotos defaults to reading message from standard input.
2023-05-21 23:05:39 +00:00

129 lines
4.7 KiB
Makefile

#NEWPROJECT requires refactor.sh sources
# 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.
PREFIX :=
SUFFIX :=
SRCDIR := sources
MAINDIR := $(SRCDIR)/main
INCDIR := $(SRCDIR)/include
OBJDIR := objects
MAINOD := $(OBJDIR)/main
BINDIR := build
INSTDIR := /usr/local/bin
REFACTOR := refactor.h
TESTCFLAGS:= $(pkg-config --cflags criterion)
TESTLIBS := $(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$(abspath $(INCDIR)) -MMD -MP -DUSE_LIBNOTIFY -DUSE_SYSLOG
CFLAGS := -Wall -Werror -Wpedantic $(shell pkg-config --cflags libnotify) -ggdb
LDFLAGS := #-Lmath or whatever
LDLIBS := $(shell pkg-config --libs libnotify libcrypto) #-lm or whatever
define MANGLE =
$(dir $(1))$(PREFIX)$(notdir $(1))$(SUFFIX)
endef
.PHONY: all clean
all: $(TARGETS) $(UNITTESTS)
@echo "Executables built: " $^
refactor:
./refactor.sh
$(UNITTESTS): $(OBJECTS) $(TESTOBJS) | $(BINDIR) $(OBJDIR) $(TESTOD)
@echo "Linking unit tests..."
@echo "Object files for tests is " $(TESTOBJS)
$(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) -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)