11

Is there a way to flag some targets in a Makefile so that they don't appear at all in the shell when the user types make and then presses Tab ? I am having a Makefile with too many recipes and I don't want them all to appear in the shell autocompletion when a users presses Tab looking for targets.

1
  • @derobert bash, added tag Commented Sep 10, 2014 at 16:45

4 Answers 4

11

After studying the problem and coming up with a solution that I wrote in the first answer, I realized that there is another very simple way.

Just start the target's names you don't want to show beginning with a dot.

Example:

.PHONY: foo .hiddentarget
foo: foo.x .hiddentarget
foo.x: foo.c
        touch foo.x
.hiddentarget: foo.x
        echo foo.x ok, I believe

And that's all you need!

I came to this idea after trying to figure out how to prevent a target named .HIDDENGOALS being called by mistake and run all hidden goals. :)

Warning Although I don't see any, I'm not sure if there isn't any side effect on using target names like this ".targetname" (starting with a dot).

4
  • Doesn't seem to work for nested hidden files, i.e. foo/.hidden: ..., bar/.hidden: ..., .hidden: foo/.hidden bar/.hidden; these will still show up, so some additional gymnastics is required. Commented Mar 31, 2015 at 9:19
  • I'm not sure if I followed you @FilipDupanović. This is for hiding targets, not files. Commented Jun 15, 2016 at 13:11
  • 1
    That time when you google and find your own answer.... :D Commented Jan 27, 2020 at 0:45
  • I feel you - happened a few times to me too but more often where I was asking the question ;) One problem/missing feature of this approach, I think, is that you can't hide goals that are actually file names which always show up(?) So in your example it's not possible to hide the foo.x goal. Commented Sep 17, 2020 at 1:41
1

To hide some targets, you'd need to hack the autocompletion function of your shell. bash uses /etc/bash_completion and /etc/bash_completion.d/*for that.

Can't recall how tcsh does it.

0
1

I've observed that this also works by starting the target with an underscore

_hiddentarget:
    @echo "Running hidden target" 
0

EDITED Best to read the other answer (target name starting with a dot). But I'll let this answer here, as the programming part may help other similar issues.

Ok, it took me some time to come up with a solution. This is a (good) draft, and hopefully it will do the job right.

You must edit the file /usr/share/bash-completion/completions/make (for Debian Wheezy, or some similar to your system)

In my current version, line numbers 70 to 73 have the code:

70         COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
71             awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
72             {split($1,A,/ /);for(i in A)print A[i]}' )" \
73             -- "$cur" ) )

Replace then for the foloowing code:

 70         HIDDENGOALS="$(make -qp | grep '^\.HIDDENGOALS:' | cut -d' ' -f2- | sed 's/ /\\|/g')"
 71         if [[ "$HIDDENGOALS" == "" || "$HIDDENGOALS" == ".HIDDENGOALS:" ]]; then
 72             COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
 73                 awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
 74                 {split($1,A,/ /);for(i in A)print A[i]}' )" \
 75                 -- "$cur" ) )
 76         else
 77             COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
 78                 awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
 79                 {split($1,A,/ /);for(i in A)print A[i]}' \
 80                 | grep -ve "$HIDDENGOALS" )" \
 81                 -- "$cur" ) )

Now inside your makefile you can use the following special target to hide goals from bash autocompletion:

 .HIDDENGOALS: somegoal anothergoal goalstohide

much like a .PHONY special target (there are some differences).

Careful:

(I) As this solution works through a grep -ev, the special target isn't quite so. It will use anything in the line to match just the way a Regular Expression does.

So, if you have a target, say, copy2, and another copy, writting

 .HIDDENGOALS: copy

will hide both goals!

I let the solution to this behavior as an exercise to the reader! ;)

(II) Another thing to notice, the : is hardcoded to be next to .HIDDENGOALS:, meaning that although targets allow spaces like .PHONY :, this special hack doesn't.

(III) I think it would be better to edit a local file instead of /usr/share/bash-completion/completions/make, to avoid losing the information when an upgrade comes. But I did not tested any options. If you know, please comment and I'll update this answer.

(IV) There is a slight chance of a curious run the very target .HIDDENGOALS with a make .HIDDENGOALS. That would run all hidden goals. And autocompleting the name wasn't possible, which lead me to the other quite simple answer!

1
  • 2
    What are the odds that you would end up googling some problem years later just to find out that the guy who gives you the answer is yourself? :) Commented Mar 7, 2017 at 3:44

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.