bash completion of makefile target

MakefileBash Completion

Makefile Problem Overview


Suppose I have a simple makefile like:

hello:
   echo "hello world"

bye:
   echo "bye bye"

Then in bash I want something like:

> make h < tab >

so it can complete to

> make hello

I found a simple way like creating empty files hello and bye but I'm looking for something more sophisticated.

Makefile Solutions


Solution 1 - Makefile

Add this in your ~/.bash_profile file or ~/.bashrc file

complete -W "\`grep -oE '^[a-zA-Z0-9_.-]+:([^=]|$)' ?akefile | sed 's/[^a-zA-Z0-9_.-]*$//'\`" make

This searches for a target in your Makefile titled 'Makefile' or 'makefile' (note the capital ? wildcard in ?akefile) using grep, and pipes it over to the complete command in bash which is used to specify how arguments are autocompleted. The -W flag denotes that the input to the complete command will be a wordlist which is accomplished by passing the results of grep through sed which arranges it into the desirable wordlist format.

Caveats and gotchas:

  1. Your make file is named 'GNUMakefile' or anything else other than 'Makefile' or 'makefile'. If you frequently encounter such titles consider changing the regular expression ?akefile accordingly.

  2. Forgetting to source your ~/.bash_profile or ~/.bashrc file after making the changes. I add this seemingly trivial detail since, to the uninitiated it is unfamiliar. For any change to your bash files to take effect, source them using the command

     source ~/.bashrc
    

or

    source ~/.bash_profile

PS. You also now have the added ability to display the possible make targets by pressing [Tab] twice just like in bash completion. Just make sure you add a space after the command make before typing [Tab] twice.

Solution 2 - Makefile

Could this be what you're looking for?

http://freshmeat.net/projects/bashcompletion/

> make [Tab] would complete on all > targets in Makefile. This project was > conceived to produce programmable > completion routines for the most > common Linux/UNIX commands, reducing > the amount of typing sysadmins and > programmers need to do on a daily > basis.

Solution 3 - Makefile

There's a useful package called bash-completion available for most every OS. It includes Makefile completion.

(If you're using macOS and Homebrew, you can get this via brew install bash-completion.)

Solution 4 - Makefile

This seems to be default in at least Debian Lenny:

$ grep Makefile /etc/bash_completion
	# make reads `GNUmakefile', then `makefile', then `Makefile'
	elif [ -f ${makef_dir}/Makefile ]; then
		makef=${makef_dir}/Makefile
	# before we scan for targets, see if a Makefile name was
	# deal with included Makefiles

The header of this file states:

#   The latest version of this software can be obtained here:
#
#   http://bash-completion.alioth.debian.org/
#
#   RELEASE: 20080617.5

Solution 5 - Makefile

Here is a completion script that looks at the .PHONY: declaration.

_make_phony_words() {
  local opt_revert

  if [ -n "${BASH_VERSION:-}" ]; then
    shopt -q nullglob || {
      opt_revert=1 ; shopt -s nullglob ;
    }

  elif [ -n "${ZSH_VERSION:-}" ]; then
    [[ -o nullglob ]] || {
      opt_revert=1 ; setopt nullglob
    }
  fi

  for f in ./?akefile ./*.make ; do
    sed -nEe '/^.PHONY/ { s/^.PHONY:[ ]?// ; p ; } ' "$f" | tr ' ' $'\n' | sort -u
  done

  if [ -n "$opt_revert" ]; then

    [ -n "${ZSH_VERSION:-}" ] && unsetopt nullglob
    [ -n "${BASH_VERSION:-}" ] && shopt -u nullglob
  fi
  unset opt_revert

}

_make_phony_complete() {
  local cur="${COMP_WORDS[COMP_CWORD]}"

  COMPREPLY+=( $(compgen -W "$( _make_phony_words )" -- ${cur}) )

}
complete -F _make_phony_complete make

Solution 6 - Makefile

Makefile completion on steroids!

I had 2 problems with the normal completions:

Problem #1

Sometimes you have targets you want to call like make greet:hi and make greet:hola sort of like namespacing Makefile target names. So your Makefile ends up looking like:

greet\:hola:
   echo "hola world"

# OR a .PHONY target
.PHONY: greet\:hi
greet\:hi:
   echo "hi world"

In this case the auto-completions after : don't show up as it uses \: in the Makefile as shown above.

Problem #2

There wasn't a way to navigate through the list of all Makefile targets that match my input using arrow keys (or CTRL-p / CTRL-n) in my bash shell.

Basically, I wanted to use fuzzy search like approach on the targets (i.e. fzf). FZF Repo: https://github.com/junegunn/fzf

Solution

Install FZF Dependency
Using Homebrew

You can use Homebrew (on macOS or Linux) to install fzf.

brew install fzf
$(brew --prefix)/opt/fzf/install
Using Linux package managers
Package Manager Linux Distribution Command
APK Alpine Linux sudo apk add fzf
APT Debian 9+/Ubuntu 19.10+ sudo apt-get install fzf
Conda conda install -c conda-forge fzf
DNF Fedora sudo dnf install fzf
Nix NixOS, etc. nix-env -iA nixpkgs.fzf
Pacman Arch Linux sudo pacman -S fzf
pkg FreeBSD pkg install fzf
pkgin NetBSD pkgin install fzf
pkg_add OpenBSD pkg_add fzf
XBPS Void Linux sudo xbps-install -S fzf
Zypper openSUSE sudo zypper install fzf
FZF and : compatible auto-complete command

Put this in your .bashrc

complete -W "\`grep -oE '^[a-zA-Z0-9_.-]+[\\:]*[a-zA-Z0-9_.-]+:([^=]|$)' ?akefile | sort | uniq | sed 's/[^a-zA-Z0-9_.-]*$//' | sed 's/[\]//g' | fzf\`" make

Now just typing make and then hitting the key will work!

DEMO: in action!

Then you can use as following:

make using fzf

Solution 7 - Makefile

In Ubuntu 10.04, source the following file:

. /etc/bash_completion

or uncomment it in

/etc/bash.bashrc

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGuillaume Mass&#233;View Question on Stackoverflow
Solution 1 - MakefileCibin JosephView Answer on Stackoverflow
Solution 2 - MakefileKosView Answer on Stackoverflow
Solution 3 - MakefilePaul BissexView Answer on Stackoverflow
Solution 4 - MakefilemvdsView Answer on Stackoverflow
Solution 5 - MakefileAlissa HView Answer on Stackoverflow
Solution 6 - MakefileShahzad LoneView Answer on Stackoverflow
Solution 7 - MakefilephiltuxView Answer on Stackoverflow