## -*-makefile-*- all:: .SECONDEXPANSION: #sorry ###-------------------------------------------------------------------------- ### Utilities. ## quote = '$(subst ','\'',$1)'#' ## Suss out how to print stuff. print = printf "%s" $(call quote,$1) ## Looking configuration things up. mdw-conf = $(shell bin/mdw-conf "$1" "$2") ## Checking symlink targets. symlink-ok-p = $(shell \ case $$(readlink 2>/dev/null $1) in ($2) echo t ;; esac) ## Silent rules machinery. V = 0 V_AT = $(V_AT_$V) V_AT_0 = @ v_print = $(call v_print_$V,$1,$2) v_print_0 = \ printf " %-8s %s\n" "$1" $(call quote,$(patsubst $(HOME)/%,~/%,$2)); v_tag = $(V_AT)$(call v_print_$V,$1,$@) ## Hack. relax = ###-------------------------------------------------------------------------- ### Configuration. ## Figure out where I am. HERE := $(shell pwd) ## Decide on how to fetch things from URLs. ifeq ($(shell (curl >/dev/null 2>&1 --version || [ $$? -eq 2 ]) && echo t),t) get-url = curl -fs -o $1 $2 else get-url = wget -q -O $1 $2 endif ## Which Emacs should I use? EMACS := $(shell \ emacs=nil; \ for i in emacs24 emacs23 emacs22 emacs21 emacs; do \ if type >/dev/null 2>&1 $$i; then emacs=$$i; break; fi; \ done; \ echo $$emacs) ## Whence to obtain externally hosted stuff. REPO = https://ftp.distorted.org.uk/u/mdw/profile ## Additional local configuration. -include local.mk ###-------------------------------------------------------------------------- ### Some utility rules. _force: .PHONY: _force ###-------------------------------------------------------------------------- ### Emacs. ifneq ($(EMACS),nil) EMACSLIB = $(HOME)/lib/emacs EMACS_VERSION := $(shell $(EMACS) 2>&1 -Q --batch --eval \ '(message "%s %s" emacs-major-version emacs-minor-version)' | \ tail -n1) emacs-version-p = $(shell set -- $(EMACS_VERSION); \ if [ $$1 -gt $1 ] || ([ $$1 -eq $1 ] && [ $$2 -ge $2 ]); then \ echo t; \ fi) ELISP += make-regexp ew-hols ELISP += mdw-gnus-patch ELISP += mdw-multiple-cursors ELISP += git git-blame vc-git stgit quilt ifeq ($(call emacs-version-p,24,3),t) ELISP += bracketed-paste endif ELISP += dot-emacs dot-emacs_DEPS = make-regexp SCRIPTLINKS += emacsclient-hack movemail-hack sendmail-hack SCRIPTLINKS += aspell-hack emerge-hack %.elc: %.el $$(foreach e, $$($$*_DEPS), $$(DEP_$$e)) $(call v_tag,EMACS)if ! $(EMACS) >$*.build-log 2>&1 \ -L el/ -L $(EMACSLIB) \ --batch --no-site-file \ --eval '(byte-compile-file "$<")'; then \ cat $*.build-log; exit 2; \ fi LOCAL_ELISP = $(filter $(notdir $(wildcard el/*.el)), \ $(addsuffix .el, $(ELISP))) $(foreach e, $(LOCAL_ELISP), \ $(eval DEP_$(basename $e) = $(EMACSLIB)/$(e:.el=.elc))) $(addprefix $(EMACSLIB)/, $(LOCAL_ELISP)): $(EMACSLIB)/%: el/% $(call v_tag,SYMINK)mkdir -p $(EMACSLIB) && \ rm -f $@.new && \ ln -s $(HERE)/$< $@.new && \ mv $@.new $@ REMOTE_ELISP = $(filter-out $(notdir $(wildcard el/*.el)), \ $(addsuffix .el, $(ELISP))) $(foreach e, $(REMOTE_ELISP), \ $(eval DEP_$(basename $e) = $(if $(shell \ if $(EMACS) >/dev/null 2>&1 --no-site-file -q --batch \ --eval ' \ (progn \ (kill-emacs (condition-case nil \ (progn (load-library "$e") 0) \ (error 1))))'; then \ echo t; \ fi),, $(EMACSLIB)/$(e:.el=.elc)))) $(addprefix $(EMACSLIB)/, $(REMOTE_ELISP)): $(EMACSLIB)/%: $(call v_tag,FETCH)mkdir -p $(EMACSLIB) && \ $(call get-url,$@.new,$(REPO)/$*) && \ mv $@.new $@ DOTLINKS += .emacs .emacs-calc .vm .gnus.el .ercrc.el all:: $(foreach e, $(ELISP), $(DEP_$e)) $(foreach e, $(ELISP), $(eval _emacs.$e: $(EMACSLIB)/$e.elc)) endif ###-------------------------------------------------------------------------- ### Other simpler things. $(HOME)/.mdw.conf: $(call v_tag,COPY)cp mdw.conf $@.new && mv $@.new $@ ## Utility packages. PACKAGES += mlib checkpath mlib_CHECK = crc-mktab checkpath_CHECK = tmpdir checkpath_DEPS = mlib ## Packaging machinery. SCRIPTLINKS += mdw-build mdw-sbuild mdw-sbuild-server SCRIPTLINKS += update-buildable-branch ## Shells. DOTLINKS += .profile .shell-rc .shell-logout DOTLINKS += .shrc DOTLINKS += .zprofile .zshrc .zlogout .zshenv DOTLINKS += .bash_profile .bash_completion .bash_logout DOTLINKS += .bashrc .inputrc .bash_profile_SRC = bash-profile .bash_completion_SRC = bash-completion .bash_logout_SRC = shell-logout .zlogout_SRC = shell-logout all:: $(V_AT)if [ $(HOME)/.zcompdump -ot dot/zshrc ]; then \ $(call v_print,ZAP,$(HOME)/.zcompdump)rm -f $(HOME)/.zcompdump; \ fi ## The Plan 9 `rc' shell. This needs special hacking, because the Linux port ## and Plan 9 From User Space have incompatible syntax. DOTLINKS += lib/profile lib/profile_SRC = rcrc all:: $(HOME)/.rcrc $(HOME)/.rcrc: dot/rcrc $(call v_tag,SED)sed 's/; if not/else/' $< >$@.new && mv $@.new $@ ## Git. DOTSUBST += .gitconfig SCRIPTLINKS += git-copyright-dates DOTLINKS += .cgrc .tigrc .gitconfig_SUBSTS = \ $(call substvar,releasekey,$(call mdw-conf,release-key,481334C2)) $(HOME)/.gitconfig: $(HOME)/.mdw.conf ## PulseAudio. DOTLINKS += .pulse/daemon.conf DOTSUBST += .pulse/default.pa .pulse/daemon.conf_SRC = pulse-daemon.conf .pulse/default.pa_SRC = pulse-default.pa.in ## Other editors. DOTLINKS += .vimrc .mg .zile ## Mail. DOTLINKS += .mailrc .signature .muttrc ## Lisp. DOTLINKS += .cmucl-init.lisp .sbclrc .clisprc.lisp .eclrc .cmucl-init.lisp_SRC = lisp-init.lisp .sbclrc_SRC = lisp-init.lisp .clisprc.lisp_SRC = lisp-init.lisp .eclrc_SRC = lisp-init.lisp DOTLINKS += .swank.lisp ## IPython. DOTLINKS += .ipython/profile_default/ipython_config.py DOTLINKS += .ipython/profile_default/startup/50-key-bindings.py .ipython/profile_default/ipython_config.py_SRC = ipython-config.py .ipython/profile_default/startup/50-key-bindings.py_SRC = ipython-key-bindings.py ## Other languages. DOTLINKS += .guile DOTLINKS += .tclshrc .wishrc .tclshrc_SRC = tclshrc .wishrc_SRC = tclshrc ## Random scripts. SCRIPTLINKS += mdw-editor mdw-pager SCRIPTLINKS += mdw-conf SCRIPTLINKS += svnwrap SCRIPTLINKS += guest-console SCRIPTLINKS += hyperspec ## Random odds and ends. DOTLINKS += .infokey .sqliterc DOTLINKS += .gdbinit .toprc .aspell.conf DOTLINKS += .dircolors .colordiffrc .screenrc .tmux.conf DOTLINKS += .cvsrc .indent.pro .ditz-config DOTLINKS += .lftp/rc .lftp/rc_SRC = lftp-rc DOTSUBST += .mykermrc SCRIPTLINKS += lesspipe.sh SCRIPTLINKS += run-with-shell-env SCRIPTLINKS += start-ssh-agent start-ssh-pageant SCRIPTLINKS += add-ssh-keys SCRIPTLINKS += hacks/ssh/ssh hacks/ssh/ssh_SRC = hacks/ssh DOTLINKS += .w3m/config .elinks/elinks.conf .w3m/config_SRC = w3m-config .elinks/elinks.conf_SRC = elinks.conf DOTLINKS += .mc/ini .mc/panels.ini .mc/ini_SRC = mc-ini .mc/panels.ini_SRC = mc-panels.ini DOTLINKS += .parallel/config .parallel/config_SRC = parallel-config all:: $(HOME)/.less $(HOME)/.less: dot/lesskey $(V_AT)rm -f $(HOME)/.lesskey $(call v_tag,LESSKEY)lesskey -o$@ $< ###-------------------------------------------------------------------------- ### X11 configuration. ifeq ($X,t) PACKAGES += xtoys xtoys_CHECK = xatom xtoys_DEPS = mlib DOTLINKS += .xinitrc .xsession .xmodmap .vncrc .vncsession DOTLINKS += .fonts.conf DOTLINKS += .stalonetrayrc DOTLINKS += .putty/sessions/Default%20Settings .putty/sessions/Default%20Settings_SRC = putty-defaults DOTLINKS += .config/gnome-session/sessions/mdw.session .config/gnome-session/sessions/mdw.session_SRC = mdw.session DOTLINKS += .Eterm/themes/Eterm/theme.cfg DOTLINKS += .enlightenment/keybindings.cfg DOTLINKS += .enlightenment-vnc/keybindings.cfg DOTLINKS += .e16/bindings.cfg .Eterm/themes/Eterm/theme.cfg_SRC = eterm-theme.cfg .enlightenment/keybindings.cfg_SRC = e-keybindings.cfg .enlightenment-vnc/keybindings.cfg_SRC = evnc-keybindings.cfg .e16/bindings.cfg_SRC = e16-bindings DOTLINKS += .gtkrc-2.0 DOTLINKS += .config/gtk-3.0/gtk.css DOTLINKS += .config/gtk-3.0/settings.ini .config/gtk-3.0/gtk.css_SRC = gtk3.css .config/gtk-3.0/settings.ini_SRC = gtk3-settings.ini SCRIPTLINKS += xinitcmd lock-screen xshutdown SCRIPTLINKS += un-backslashify-selection SCRIPTLINKS += xpra-start-xdummy SCRIPTLINKS += play-rawk SCRIPTLINKS += media-keys SCRIPTLINKS += disorder-notify DOTCPP += .Xdefaults Xdefaults_DEFS = -DEMACSWD=$(call mdw-conf,emacs-width,77) $(HOME)/.Xdefaults: $(HOME)/.mdw.conf ifeq ($(shell case $${DISPLAY-nil} in (:[0-9]*) echo t ;; (*) echo nil ;; esac),t) dotfile-hook/.Xdefaults = \ $(call v_tag,XRDB)xrdb -override $< endif endif ###-------------------------------------------------------------------------- ### Processing dotfiles. dotfile-source = $(HERE)/dot/$(or $($1_SRC), $(1:.%=%)$2) ## Easiest: just make symlinks. dotlink-ok-p = \ $(call symlink-ok-p,$(HOME)/$1,$(call dotfile-source,$1)) all:: $(addprefix $(HOME)/, $(DOTLINKS)) $(addprefix $(HOME)/, $(subst %,\%,$(DOTLINKS))): $(HOME)/%: \ $$(if $$(call dotlink-ok-p,$$*),,_force) $(call v_tag,SYMLINK)mkdir -p $(dir $@) && \ rm -f $@.new && \ ln -s $(call dotfile-source,$*) $@.new && \ mv $@.new $@ $(dotfile-hook/$*) ## Hack with the C preprocessor. all:: $(addprefix $(HOME)/, $(DOTCPP)) $(addprefix $(HOME)/, $(subst %,\%,$(DOTCPP))): $(HOME)/%: \ $$(call dotfile-source,$$*) Makefile $(call v_tag,CPP)mkdir -p $(dir $@) && \ rm -f $@.new && \ cpp -P -o$@.new $($*_DEFS) $< && \ mv $@.new $@ $(dotfile-hook/$*) ## Hack by making simple substitutions. substvar = -e $(call quote,s@$1@$2g) SUBSTS += $(call substvar,home,$(HOME)) SUBSTS += $(call substvar,profile,$(HERE)) all:: $(addprefix $(HOME)/, $(DOTSUBST)) $(addprefix $(HOME)/, $(subst %,\%,$(DOTSUBST))): $(HOME)/%: \ $$(call dotfile-source,$$*,.in) Makefile $(call v_tag,SUBST)mkdir -p $(dir $@) && \ rm -f $@.new && \ sed -e "1i\ $(relax)### generated by $(HERE)/Makefile; do not edit!" \ $(SUBSTS) $($*_SUBSTS) \ $(call dotfile-source,$*,.in) >$@.new && \ mv $@.new $@ $(dotfile-hook/$*) ###-------------------------------------------------------------------------- ### Processing script links. script-source = $(HERE)/bin/$(or $($1_SRC), $1) ifeq ($(prefix-shebang-p),t) all:: $(addprefix $(HOME)/bin/, $(SCRIPTLINKS)) $(addprefix $(HOME)/bin/, $(SCRIPTLINKS)): $(HOME)/bin/%: \ $$(call script-source,$$*) Makefile $(call v_tag,SHEBANG)mkdir -p $(dir $@) && \ rm -f $@.new && \ sed "1s\(#! *\)/\1$(SHEBANG_PREFIX)/" \ $(call script-source,$*) >$@.new && \ chmod --reference=$(call script-source,$*) $@.new && \ mv $@.new $@ $(script-hook/$*) else scriptlink-ok-p = \ $(call symlink-ok-p,$(HOME)/bin/$1,$(call script-source,$1)) all:: $(addprefix $(HOME)/bin/, $(SCRIPTLINKS)) $(addprefix $(HOME)/bin/, $(SCRIPTLINKS)): $(HOME)/bin/%: \ $$(if $$(call scriptlink-ok-p,$$*),,_force) $(call v_tag,SYMLINK)mkdir -p $(dir $@) && \ rm -f $@.new && \ ln -s $(call script-source,$*) $@.new && \ mv $@.new $@ $(script-hook/$*) endif all:: $(addprefix $(HOME)/bin/, $(SCRIPTLINKS)) ###-------------------------------------------------------------------------- ### Building packages from source tarballs. SRCDIR = $(HOME)/src/profile pkg-builddir = $(SRCDIR)/$1/build pkg-stamp = $(call pkg-builddir,$1)/$2-stamp $(foreach p, $(PACKAGES), $(eval DEP_$p = $(if $(shell \ if $($p_CHECK) >/dev/null 2>&1 --version; then echo t; fi),, \ $(call pkg-stamp,$p,install)))) $(PACKAGES:%=$(SRCDIR)/%.tar.gz): $(SRCDIR)/%.tar.gz: $(call v_tag,FETCH)mkdir -p $(SRCDIR) && \ rm -f $@.new && \ $(call get-url,$@.new,$(REPO)/$*.tar.gz) && \ mv $@.new $@ $(foreach p, $(PACKAGES), $(call pkg-stamp,$p,unpack)): \ $(call pkg-stamp,%,unpack): $(SRCDIR)/%.tar.gz $(call v_tag,EXTRACT)rm -rf $(SRCDIR)/$* && \ mkdir $(SRCDIR)/$*.tmp-unpack && \ cd $(SRCDIR)/$*.tmp-unpack && \ gzip -cd ../$*.tar.gz | tar xf - && \ mv * ../$* && \ cd .. && \ rmdir $*.tmp-unpack && \ mkdir $*/build && \ touch $*/build/unpack-stamp $(foreach p, $(PACKAGES), $(call pkg-stamp,$p,configure)): \ $(call pkg-stamp,%,configure): \ $(call pkg-stamp,%,unpack) \ $$(foreach p, $$($$*_DEPS), $$(DEP_$$p)) $(call v_tag,CONFIG)cd $(dir $@) && \ ../configure --prefix=$(HOME) \ PKG_CONFIG_PATH=$(HOME)/lib/pkgconfig \ $($*_CONFIG) >>buildlog 2>&1 && \ touch configure-stamp $(foreach p, $(PACKAGES), $(call pkg-stamp,$p,build)): \ $(call pkg-stamp,%,build): \ $(call pkg-stamp,%,configure) $(call v_tag,BUILD)cd $(dir $@) && \ $(MAKE) $($*_MAKEFLAGS) >>buildlog 2>&1 && \ touch build-stamp $(foreach p, $(PACKAGES), $(call pkg-stamp,$p,install)): \ $(call pkg-stamp,%,install): \ $(call pkg-stamp,%,build) $(call v_tag,INSTALL)cd $(dir $@) && \ $(MAKE) $($*_MAKEFLAGS) install >>buildlog 2>&1 && \ touch install-stamp $(package-hook/$*) all:: $(foreach p, $(PACKAGES), $(DEP_$p)) $(foreach p, $(PACKAGES), $(eval _pkg.$p: $(call pkg-stamp,$p,install))) ###----- That's all, folks --------------------------------------------------