9

Suppose I have the following Makefile:

RM = rm -f
FLAGS =  -Cr -O1 -gv -gw -g -vw
builddir = ./build/
TD = ./tasks/

all: example1 example3 example5

example1:  

    fpc 01_Kreisumfang.pas $(FLAGS) -o$(builddir)01_Kreisumfang

example3:

    fpc 03_EuroBetrag3.pas $(FLAGS) -o$(builddir)03_EuroBetrag3

example5:

    fpc 05_Dreiecke.pas $(FLAGS) -o$(builddir)05_Dreieck

clean:

    $(RM) $(builddir)*

At a certain point my Makefile grows to example112 ..., is there a way to define all automatically with out needing to type in all the targets? I don't want to do this:

all: example1 example3 example5 ... example112

Can I do something like this?

all: (MAGIC to Exclude clean)?

So instead of having to type all the targets, I want make to detect all the targets and exclude a certain list.

update:

I found the following possible hint:

 make -rpn | sed -n -e '/^$/ { n ; /^[^ ]*:/p }' |egrep -v -E '(all|clean)' 

I don't know how to make this a target by itself, I tried with:

TARGETS =: $(shell make -rpn | sed -n -e '/^$$/ { n ; /^[^ ]*:/p }' |egrep -v -E '(all|clean)')

But it seems to be wrong. Not only it is wrong, it will cause a silly recursion.

So this solution is only available as a shell command, not within the Makefile itself.

Well, make seems to be just cryptic here. The most reasonable solution I found is to create a script and use that:

$ cat doall.sh 
#!/bin/bash
for i in `make -rpn | sed -n -e '/^$/ { n ; /^[^ ]*:/p }' | sed -e 's/://' | egrep -v -E '(all|clean)'`; 
    do make $i; 
done

It seems impossible to create it as a make target, or that the ROI on this is very low ...

oz123
  • 27,559
  • 27
  • 125
  • 187
  • possible duplicate of [How do you get the list of targets in a makefile?](http://stackoverflow.com/questions/4219255/how-do-you-get-the-list-of-targets-in-a-makefile) – Shimon Rachlenko Sep 29 '13 at 09:40
  • You need to duplicate any literal dollar sign inside a Makefile. – tripleee Sep 29 '13 at 13:17
  • @tripleee, even if I change that, there is still no way around make calling it's self ... How would you do it? – oz123 Sep 29 '13 at 13:22

2 Answers2

1

I tried this out using a for loop. Check if this simple example works for you. Took the command from this post.

RM = rm -f
FLAGS =  -Cr -O1 -gv -gw -g -vw
builddir = ./build/
TD = ./tasks/
SHELL := /bin/bash

targets=$(shell for file in `find . -name '*.pas' -type f -printf "%f\n" | sed 's/\..*/\.out/'`; do echo "$$file "; done;)

all: $(targets)

%.out:%.pas
  fpc $< $(FLAGS) -o (builddir)$@

clean:
    $(RM) $(builddir)*
Community
  • 1
  • 1
el_tenedor
  • 644
  • 1
  • 8
  • 19
  • you are assuming all my targets are called example. Which is fine for now, how would it be when I start having other names? – oz123 Sep 29 '13 at 10:36
  • it will try to execute the files themselves. – oz123 Sep 29 '13 at 10:51
  • Sorry, my fault. I think now I got the problem. Check the new edit. – el_tenedor Sep 29 '13 at 11:07
  • you are searching for .h files, I am trying to compile .pas files. Why are you adding the word .targets? and finally, it just echoing a list of the files but it does not execute the compiler – oz123 Sep 29 '13 at 11:13
  • el_tenedor, your solution now makes it easy to compile many pascal programs in one make file , thanks! – oz123 Sep 29 '13 at 11:46
0

I've been using

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

(Saved as make-t) to list all targets.

If you want to build all real targets, then get a listing of all targets that aren't phony:

make -qp | grep -P '^[.a-zA-Z0-9][^$#\/\t=]*:([^=]|$)' |
tee >(cut -d: -f1 ) >(grep '^\s*\.PHONY\s*:' |cut -d: -f2) >/dev/null|
tr ' ' '\n' | sed '/^\s*\./ d; /^\s*$/ d' |sort |uniq -u

should do the job (this assumes no target names with spaces in them).

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142