|
Home > Archive > Unix Programming > June 2007 > GNUMake - emulating nested for loops
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
GNUMake - emulating nested for loops
|
|
| dadapapa@googlemail.com 2007-06-21, 1:25 pm |
| Dear all,
it is not easy to find a simple subject for the thing I am trying to
achieve.
I use GNU Make to automate the creation of file from a parameterized
script. I successfully used the following contruct:
arguments = 1 2 3 4 5 5
result_files = ${arguments:%=arg_%.dat}
aggregated.dat : aggregation_script ${result_files}
sh $< > $@
arg_%.dat : myscript
sh $^ $* > $@
clean ::
rm -f ${result_files}
cleanall :: clean
rm -f aggregated.dat
So basically, arguments is a list of parameters I want to iterate
over. For each parameter, myscript is called with the stem of the
condition (the parameter) as command line argument. the Makefile
emulates a for loop in the sense that it
will generate all result_files when asked to generate aggregated_data.
This works
pretty well.
Now I want to emulate nested for loops, i.e. an outer join. Consider I
have
arg1 = 1 2 3 4 5 6
arg2 = a b c d e f
Now, I want to start myscript with any combination of arg1 and arg2. I
can use
the function join to generate the names of result_files similar to the
solution
above:
result_files = $(join ${arg1:%=arg1_%},${arg2:%=_arg2_%.dat})
But is there any good way to get the separate parameters back in from
the stem
of an implicit loop? The only way I find is to use
arg1_%.dat : myscript
sh $^ $$(echo $* | cut -f'_' -d 1) $$(echo $* | cut -f'_' -d3) >$@
but this usage of cut strikes me as really ugly. Are there any means
to define
and use two stems in an implicit rule? Or is there any other prefered
way to
achieve this sort of cartesian product / outer join / nested loop ?
I read through the GNU Make documentation but could not find anything.
Any help is appreciated.
- harold -
| |
| dadapapa@googlemail.com 2007-06-21, 1:25 pm |
| Unfortunately, my previous solution is not only ugly, but also wrong,
since the
join does not do the outer join / cartesian product, but simply zips
together the
elements of the two lists
> result_files = $(join ${arg1:%=arg1_%},${arg2:%=_arg2_%.dat})
resolving to
result_files = arg1_1_arg2_a.dat arg1_2_argb_a.dat
arg1_3_arg2_c.dat ...
So back to docs .. 
- harold -
| |
| Mark Holland 2007-06-21, 7:24 pm |
|
<dadapapa@googlemail.com> wrote in message
news:1182434202.210379.7070@p77g2000hsh.googlegroups.com...
> Unfortunately, my previous solution is not only ugly, but also
> wrong,
> since the
> join does not do the outer join / cartesian product, but simply zips
> together the
> elements of the two lists
>
>
> resolving to
>
> result_files = arg1_1_arg2_a.dat arg1_2_argb_a.dat
> arg1_3_arg2_c.dat ...
>
> So back to docs .. 
>
> - harold -
Almost there, there's just a few more manipulations you need to do...
I have produced a working Makefile below. Just copy it and alter as
you see fit.
This works by using a combination of the addprefix, and foreach
functions. Add prefix will add a prefix to each of the items in a
list. By adding every item of arg1 to the front of arg2, you get the
cartesian product as desired. You can then add any additional text as
you wish. I added the ".dat" suffix in the example.
arg1 = 1 2 3 4 5 6
arg2 = a b c d e f
args = $(addsuffix .dat,$(foreach foo,$(arg1),$(addprefix
$(foo),$(arg2))))
default: $(args)
%.dat:
@echo $@
|
|
|
|
|