1

A part of my makefile is as follow:

list1:          all
                for f in \
                `less fetch/list1.txt`; \
                do \
                    ...
                    ./$(BIN) $$f & \
                    ...
                done

list2:          all
                for f in \
                `less fetch/list2.txt`; \
                do \
                    ...
                    ./$(BIN) $$f & \
                    ...
                done

fetch/list1.txt and fetch/list2.txt contains two lists of files (path+filename), and make list1 and make list2 will respectively go through the 2 lists and run $(BIN) again the files. This works fine.

The problem is that, I have a couple of file lists as list1 and list2, and the process of the make is always the same. Does anyone know how to simplify makefile such that make listA, make list4, etc. does what they are supposed to do?

ceving
  • 21,900
  • 13
  • 104
  • 178
SoftTimur
  • 5,630
  • 38
  • 140
  • 292
  • 2
    `for f in `less fetch/list2.txt``???? are you feeling alright? – gniourf_gniourf Nov 09 '13 at 22:22
  • I don't see where is the problem... That does work... – SoftTimur Nov 09 '13 at 22:40
  • Definitely an unorthodox use of `less` which is intended to display a file to your terminal page by page. But it works because the command in the command substitution backticks does not have a terminal, and thus less degenerates to displaying the file in one go, which I think is what you want. More regular usage would be something like `$(cat fetch/list1.txt)`. Also note `$()` generally preferred over backticks http://stackoverflow.com/questions/9405478/command-substitution-backticks-or-dollar-sign-paren-enclosed – Digital Trauma Nov 09 '13 at 22:44
  • I tried `for f in $(cat fetch/$@.txt)`, that returns nothing... – SoftTimur Nov 09 '13 at 23:10
  • 1
    You need to escape the `$` in the make body so the shell gets it. That is you need `$$(cat ...)`. – Etan Reisner Nov 10 '13 at 15:02

3 Answers3

1

You can use a Pattern Rule:

all:
    @echo "The all recipe"

list%: all
    @echo "This recipe does something with $@.txt"

Output is:

$ make list1
The all recipe
This recipe does something with list1.txt
$ make list256
The all recipe
This recipe does something with list256.txt
$ 
Digital Trauma
  • 15,475
  • 3
  • 51
  • 83
0

I do not recommend performing scripting within makefiles. It will very often lead to arbitrary, inconsistent bugs, and other forms of frustration.

Use Make for execution control with dependencies, (as in, determining what gets executed when) but write your actual primitives (scripts or other programs) seperately, and call them from within Make.

bar:    foo1 foo2 foo3

# bar is the make target.  Foo1, 2, and 3 are sub-targets needed to make bar.

foo1:
    fooscript1    # Written as an individual script, outside Make.
    fooscript2
petrus4
  • 616
  • 4
  • 7
0

How about:

all:
        @echo "All"

action_%:
    @./$(BIN) $*

ACTION=$(patsubst %,action_%,$(shell cat $(ACT_FILE)))

actionList:
    @make $(ACTION)

list%:  all
    @make ACT_FILE=fetch/list$*.txt actionList

Supports all list :-)

Rather than allow infinite parallelism (you were using ./$(BIN) fileName &). You can control actual parallelism using Make's built in features.

 make -j8 list1
 #      ^  Parallelism set to 8
Martin York
  • 257,169
  • 86
  • 333
  • 562