#!/bin/bash # A quick-hack drop-in replacement for "make" which recursively # searches upwards in the dir hierarchy for a makefile, and runs the # real "make" from the first such directory. # # The problem this solves is: it's common for me to work in emacs in # source trees which don't have makefiles in every directory. Tapping # (ctrl-x m) to run make annoyingly (but rightfully) fails in such # directories. By mapping this script to emacs's compile-command var, # that problem disappears. i should have done this two decades ago :|. # Reminder: we can't find the real make with "which make" because that # might, depending on how this script is named, resolve to this # script. Thus we unfortunately hard-code the make path here: theMake=/usr/bin/make # According to the GNU make docs, it looks for makefiles with these # names in this order: # https://www.gnu.org/software/make/manual/html_node/Makefile-Names.html mfiles="GNUmakefile makefile Makefile" # Returns 0 if any file in the list of $mfiles is found in the current # directory, else returns non-0. function cwdHasMakefile(){ for f in $mfiles; do [[ -f "$f" ]] && return 0 done return 1 } prev= # previous directory while true; do if [[ "x/" = "x$prev" ]]; then # Interestingly, "cd .." from / does not fail, so we # check for that case here. break fi if cwdHasMakefile; then exec "$theMake" "$@" fi prev=${PWD} # If cd fails for any reason, simply bail. This can happen # if, e.g., /home is not accessible on a shared hoster. cd .. >/dev/null || break done echo "$0: no makefile found." 1>&2 exit 127