List goals/targets in GNU make that contain variables in their definition

MakefileGnu Make

Makefile Problem Overview


I have a fairly large makefile that creates a number of targets on the fly by computing names from variables. (eg foo$(VAR) : $(PREREQS)). Is there any way that gnu make can be convinced to spit out a list of targets after it has expanded these variables?

I'd like to be able to get the targets for an aribitrary makefile. I'm trying to write a completion function for my shell.

Makefile Solutions


Solution 1 - Makefile

make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'     

Taken from the make arg completion, which works like a charm.

Solution 2 - Makefile

Can you parse the output from make -pn (i.e. make --print-data-base --dry-run)? It prints out all the variables, rules, implicit rules and which commands will be run in laborious detail.

Solution 3 - Makefile

I'm not sure if this is only a gnu make thing, but this works well:

make help

Solution 4 - Makefile

Several responders have suggested using make -pn, which will print the database of rules but not execute anything -- more or less. The problem with this approach is that -n does still invoke all recursive makes, and it does still do a lot more work than necessary, because it prints out every command that it would have invoked in a regular build. A more efficient solution would be to create a trivial makefile, dummy.mk, with these contents:

__all_targets__: ; #no-op

Now invoke make as make -p -f Makefile -f dummy.mk __all_targets__. On any substantial build, the difference in the amount of output generated by make is significant. For example:

$ gmake -pn | wc
 138985 2632330 69612711
$ gmake -f Makefile -f /tmp/dummy.mk -pn __all_targets__ | wc
  21673   93437  878985

Execution time was dramatically better as well -- 2.063s for the first version, 0.059s for the second.

Solution 5 - Makefile

Check out bash completion for make on GitHub.

Solution 6 - Makefile

Edit: FYI the debian bash completion git repository in another answer now incorporates an enhanced version of this script tailored to bash completion use cases.

#!/bin/bash

SCRIPT='
  /^# Make data base/,/^# Files/d             # skip until files section
  /^# Not a target/,+1          d             # following target isnt
  /^\.PHONY:/                   d             # special target
  /^\.SUFFIXES:/                d             # special target
  /^\.DEFAULT:/                 d             # special target
  /^\.PRECIOUS:/                d             # special target
  /^\.INTERMEDIATE:/            d             # special target
  /^\.SECONDARY:/               d             # special target
  /^\.SECONDEXPANSION/          d             # special target
  /^\.DELETE_ON_ERROR:/         d             # special target
  /^\.IGNORE:/                  d             # special target
  /^\.LOW_RESOLUTION_TIME:/     d             # special target
  /^\.SILENT:/                  d             # special target
  /^\.EXPORT_ALL_VARIABLES:/    d             # special target
  /^\.NOTPARALLEL:/             d             # special target
  /^\.ONESHELL:/                d             # special target
  /^\.POSIX:/                   d             # special target
  /^\.NOEXPORT:/                d             # special target
  /^\.MAKE:/                    d             # special target

# The stuff above here describes lines that are not
#  explicit targets or not targets other than special ones
# The stuff below here decides whether an explicit target
#  should be output.

  /^[^#\t:=%]+:([^=]|$)/ {                    # found target block
    h                                         # hold target
    d                                         # delete line
  }
  /^# File is an intermediate prerequisite/ { # nope
    s/^.*$//;x                                # unhold target
    d                                         # delete line
  }
  /^([^#]|$)/ {                               # end of target block
    s/^.*$//;x                                # unhold target
    s/:.*$//p                                 # write current target
    d                                         # hide any bugs
  }
'

make -npq .DEFAULT 2>/dev/null | sed -n -r "$SCRIPT" \
  | sort | uniq

This is a much more complete script than the debian bash completion script because it provides results for generated rules which is what the question asks for and the top voted answer (debian bash completion script at the debian git server) doesn't go far enough.

This is not the original script that I linked to but it is much simpler and is a touch faster.

Solution 7 - Makefile

This is the code for alias based on Todd Hodes solution

alias mtargets='make -qp | awk -F":" "/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split(\$1,A,/ /);for(i in A)print A[i]}"'

Solution 8 - Makefile

This will give a nice output:

make -pn | perl -F: -ane 'print "$F[0]\n" if /^\w+\s*:/' | sort

Solution 9 - Makefile

There is a very nice solution with some sed and egrep magic here: https://gist.github.com/pvdb/777954

Solution 10 - Makefile

Guess I'm a little late to this party, but if you're looking for a specific command you could try

make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'

This mostly works, although it might still include some non-target stuff like a vpath directive. If you don't depend on make's built-in rules, you can use make -qpR as the first command in the pipeline.

Solution 11 - Makefile

Ruby solution:

`make -qp`.split("\n").select{|l| l =~ /^\w/ && l !~ /=/}.map{|l| l.sub(/:.*/,'')}

Solution 12 - Makefile

Im working on solaris 10 anda turbo C shell. The given solution doesn´t work for my makefile project. even after altering the command line above to tcsh syntax. However, I found out you can get an easy solution using

remake --tasks | grep -v "clean some static output or just grep tabs on start of line" | awk ´{print $1}´

remake version:

remake --version

is

GNU Make 3.82+dbg0.8
Built for sparc-sun-sparc2-9

and some other unimportant version data

Solution 13 - Makefile

I went looking for the same question and came up with this spin:

make -pn | sed -rn '/^[^# \t\.%].*:/p'

This removes all comment lines, pattern rules (lines beginning with tabs), all the intrinsics (example .c.o and %.o: %.c patterns).

Solution 14 - Makefile

Found this solution in another thread:

sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\""

You can also add it to your Makefile:

list:
	sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\\""

And execute make list.

Solution 15 - Makefile

Sure, but when do you want it to spit them out?

To report the name of the target when it runs the rule, put a line in the rule:

foo$(VAR): $(PREREQS)
    @echo now making the foo target: $@
    do_other_stuff...

To spit them all out at once, you could make a separate PHONY target:

.PHONY: show_vars
show_vars:
    @echo foo$(VAR)
    @echo bar$(PARAM) blah$(FLAG)
    # and so on

And this can be made a prerequisite of your default target:

all: show_vars
    ...

EDIT:
You want a way to show all possible targets of an arbitrary makefile, which I suppose means non-intrusively. Well...

To do it exactly, and be able to cope with sophisticated makefiles, e.g. involving rules constructed by eval statements, you'd have to write something close to a Make emulator. Impractical.

To see the targets of the simple rules, you could write a makefile that would act as a makefile scanner, operating on an arbitrary makefile:

  1. Get all the target names from the makefile using sed.
  2. include the makefile in order to use it to expand variables.
  3. Use show_%: ; echo $$* to print all the targets
This would be an impressive piece of work. Are you sure the goal is worth the effort?

Solution 16 - Makefile

grep ^[a-z].*\:$ Makefile | sed s,:,,g

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
QuestionBitShifterView Question on Stackoverflow
Solution 1 - Makefiletodd hodesView Answer on Stackoverflow
Solution 2 - MakefileJack KellyView Answer on Stackoverflow
Solution 3 - MakefileZdenikView Answer on Stackoverflow
Solution 4 - MakefileEric MelskiView Answer on Stackoverflow
Solution 5 - Makefilejs.View Answer on Stackoverflow
Solution 6 - MakefilecodeshotView Answer on Stackoverflow
Solution 7 - MakefileNguyễn Minh VũView Answer on Stackoverflow
Solution 8 - MakefileAndorView Answer on Stackoverflow
Solution 9 - MakefileAtilla FilizView Answer on Stackoverflow
Solution 10 - MakefileDGradyView Answer on Stackoverflow
Solution 11 - MakefilegdubView Answer on Stackoverflow
Solution 12 - MakefileAvivView Answer on Stackoverflow
Solution 13 - MakefileJamieView Answer on Stackoverflow
Solution 14 - MakefilethisismydesignView Answer on Stackoverflow
Solution 15 - MakefileBetaView Answer on Stackoverflow
Solution 16 - MakefileWillian BragaView Answer on Stackoverflow