Skip to content

Instantly share code, notes, and snippets.

@ericpruitt
Created July 25, 2016 03:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericpruitt/32f3f8b6c3df903d03f5e95ed8ba3428 to your computer and use it in GitHub Desktop.
Save ericpruitt/32f3f8b6c3df903d03f5e95ed8ba3428 to your computer and use it in GitHub Desktop.
Makefile
DMENU_REPOSITORY = http://git.suckless.org/dmenu
DMENU_REVISION = 3c91eed
DWM_REPOSITORY = http://git.suckless.org/dwm
DWM_REVISION = 56a31dc
SLOCK_REPOSITORY = http://git.suckless.org/slock
SLOCK_REVISION = 65b8d52
ST_REPOSITORY = http://git.suckless.org/st
ST_REVISION = 235b438
PREFIX = $(HOME)
BINARIES = del dmenu dwm st
SUPERUSER_PREFIX = /usr/local
SUPERUSER_BINARIES = slock
SCRIPTS = mediacontrol screenshot window-screenshot
# For some targets, an if/wildcard combination ensures that a directory is only
# considered a dependency if it does not already exist. This ensures changing
# directory timestamps don't result in unnecessary recompiles. In other
# targets, wildcard expansion is used so that certain files are only added as
# dependencies if they already exist. Without using the wildcard function, the
# recipes fail when the files did not exist because there's no recipe for them
# in this Makefile. I attempted to use order-only prerequisites for *-src
# folders, but I ran into some problems with dependency chains; deleting
# "app-src" after creating the binary "app" then running "make" would only
# generate the config.h symlink; in order to rebuild th binary, "make" would
# have to be run again.
all: $(BINARIES) $(SUPERUSER_BINARIES)
reset: reset-dmenu reset-dwm reset-slock reset-st
# Dependency function for suckless projects. This accepts the project's name as
# its only argument e.g. $(call suckless,app) would gemerate a dependency list
# for the suckless project "app".
sucklessdeps = \
$(1)-src/config.h \
$(wildcard $(1)-src/*.[ch] $(1)-*.[ch] patches/$(1)-*.diff) \
$(if $(wildcard $(1)-src),,$(1)-src)
# Generic target for fetching upstream Git repositories: given the target
# "app-src", this recipe will clone the URL specified by $(APP_REPOSITORY) into
# the folder "app-src" and attempt to reset the repository to the revision
# specified by $(APP_REVISION) if it is non-empty string.
%-src:
@echo "bin" "*-src" | tr ' ' '\n' > .git/info/exclude
git clone $($(shell echo $(subst -src,,$@) | tr a-z A-Z)_REPOSITORY) $@
@revision=$($(shell echo $(subst -src,,$@) | tr a-z A-Z)_REVISION); \
if [ -n "$$revision" ]; then \
cd $@ && git reset --hard $$revision; \
fi
# Generic target for resetting for a repository: given the target "reset-app",
# this recipe will run "git --reset --hard $(APP_REVISION)" inside "app-src"
# followed by "make clean".
reset-%:
@set -e; \
dir=$(subst reset-,,$@)-src; \
test ! -e $$dir && return; \
cd $$dir; \
git reset -q --hard \
$($(shell echo $(subst reset-,,$@) | tr a-z A-Z)_REVISION); \
$(MAKE) -s clean > /dev/null
# Generic target for applying patches to a repository: given the target
# "patched-app", this recipe will apply all patches matching the shell glob
# "patches/app-*.diff" to the contents of the folder "app-src".
patched-%:
@prefix=$(subst patched-,,$@); \
echo "Applying patches to $$prefix:"; \
for patch in patches/$$prefix-*.diff; do \
echo "- $$patch"; \
if ! patch -d $$prefix-src -s < $$patch; then \
exit 1; \
fi; \
done
# Generic target for suckless config.h files: given the target
# "app-src/config.h", this recipe will symlink "app-config.h" into the folder
# "app-src".
%-src/config.h: %-config.h | %-src
@if ! [ -e $@ ]; then \
ln -v -s ../$< $@; \
fi
bin/dmenu: $(call sucklessdeps,dmenu)
@cd dmenu-src && $(MAKE) -s dmenu
@mv dmenu-src/dmenu $@
dmenu: bin/dmenu
bin/dwm: $(call sucklessdeps,dwm)
@if (cd dwm-src && git diff --quiet -- *.c *.h); then \
$(MAKE) -s patched-dwm; \
else \
echo "WARNING: dwm tree is dirty; no patches will be applied."; \
fi
@ln -s -f ../dwm-build.mk dwm-src/config.mk
@cd dwm-src && $(MAKE) -s
@mv dwm-src/dwm $@
dwm: bin/dwm
slock-src/slock: $(call sucklessdeps,slock)
@cd slock-src && $(MAKE) -s
slock: slock-src/slock
bin/st: $(call sucklessdeps,st)
@cd st-src && $(MAKE) -s
@mv st-src/st $@
st: bin/st
bin/%: utilities/%.c
@command=$$(sed -n -e 's/.*\(\<cc\>.*\)/\1/p;/\<cc\>/q;/^$$/q' $^); \
if [ -z "$$command" ]; then \
echo "Could not extract compilation command from $^"; >&2 \
exit 1; \
fi; \
sh -c "INPUT=$^; OUTPUT=$@; echo $$command && exec $$command"
del: bin/del
$(SUPERUSER_PREFIX)/bin/slock: slock-src/slock
sudo install -m 4755 -g root -o root $^ $(SUPERUSER_PREFIX)/bin
$(PREFIX)/bin/%: $(PWD)/bin/%
@if [ -h $@ ]; then \
rm -v $@; \
fi
ln -s $^ $@
install: $(addprefix $(PREFIX)/bin/,$(BINARIES)) \
$(addprefix $(SUPERUSER_PREFIX)/bin/,$(SUPERUSER_BINARIES))
@if [ ! -e ~/.del ]; then \
echo st > ~/.del; \
echo "del -u" && exec del -u; \
fi
clean:
rm -f *-src/config.h bin/*
cleaner:
rm -rf *-src bin/*
.PHONY: all clean cleaner install preinstall reset sanity
.PRECIOUS: %-src
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment