help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Make: Filtering prerequisites


From: Smirnov Dmitry
Subject: RE: Make: Filtering prerequisites
Date: Fri, 7 Apr 2006 19:53:18 +0400

Thanks, Paul for your explanations. I really new to make and my
experience is not enough.

But the idea I'm trying to implement is simple:
Suppose I'm having the list of source files. These files can be located
anywhere.
All I need is to compile each source file and place the result (.o) into
some specific directory.

So, I had tried to implement the simplest approach: since in general I
cannot restore the source file path I just trying to filter the list of
the sources with the name of the file (let's suppose sources have
different file names, i.e. there no dir1/file1 and dir2/file1)

Probably this solution is not optimal or even not feasible in make. But
I'm just a C programmer and trying to implement the ideas from that
world :-) 
If make will have arrays, I would just create a 2 column array
(source<->dest)

Unfortunately, I cannot upgrade to 3.81 since it is a company policy now
to use 3.80. But probably I could try to convince others that we need
3.81. 

Dmitry


-----Original Message-----
From: Paul Smith [mailto:address@hidden On Behalf Of Paul D. Smith
Sent: Friday, April 07, 2006 7:11 PM
To: Smirnov Dmitry
Cc: address@hidden
Subject: Re: Make: Filtering prerequisites

%% "Smirnov Dmitry" <address@hidden> writes:

  sd> $(TARGETS): dir3/subdir3/% : $(foreach src,$(SOURCES),$(if
$(findstring $(notdir $(src)),%),$(src), Notfound)

I really don't understand what you're trying to accomplish here.

It helps if you back up a few steps and provide your overall goal before
delving into details.

  sd> For example, if I write 

  sd> $(TARGETS): $(filter %$$(@F), anystring/$$(@F) anystring2/$$(@F))

  sd> it works,

... No, it doesn't.

  sd> But it fails if I replace it with 

  sd> $(TARGETS): $(filter %$$(@F), $(SOURCES) )

Your examples show a common confusion: you are not clear on when
expansion happens.  In make, variables (and functions, which have
exactly the same rules as variables) can be expanded at various times.
Knowing when they will be expanded in every context is critical if you
want to write a makefile of any complexity.

There's a section of the GNU make manual dedicated to this, called "How
make Reads a Makefile".  You should read that section before anything
else.

The important point to pick up from that for your purposes is that when
parsing targets and prerequisites, variable are expanded _immediately_,
as the makefile is read in, before any other processing is done.  That
includes any pattern substitution.  So your first example above:

 > $(TARGETS): dir3/subdir3/% : $(foreach src,$(SOURCES),$(if
$(findstring $(notdir $(src)),%),$(src), Notfound)

The variables and functions are expanded before the "%" is replaced, and
your $(findstring ...,%) is looking for $(notdir $(src)) in the actual
literal string "%", which of course will never be true.

Similarly, here:

> $(TARGETS): $(filter %$$(@F), $(SOURCES) )

The $$(@F) is deferred (but in GNU make 3.81 you'll have to add a
special target to get this to work: see the NEWS file for that release),
but none of the other expansions are deferred... which means the
$(filter ...) is not deferred!  So, filter is looking for patterns
matching '%$(@F)'--or, words ending with the literal string '$(@F)', not
the expansion of $(@F)--in the $(SOURCES) variable, and of course it
doesn't exist.  So, the filter returns the empty string.


In this example you are getting the results you want, but by accident:

> $(TARGETS): $(filter %$$(@F), anystring/$$(@F) anystring2/$$(@F))

As above you're looking for words ending in the literal string '$(@F)',
but it so happens that both of the words in your match list _DO_ end in
the literal '$(@F)' so they both match.

  sd> If such filtering is impossible, could you please advice the
  sd> method to implement my goal...

What is your goal?  That's where you need to start.

If you upgrade to GNU make 3.81 there are some very powerful features
that will let you do what you are trying to do above (with some slightly
modified syntax).

However, that power is only needed 1% of the time; the other 99% of the
time there are much simpler and more straightforward solutions.  But
without any idea of what you're trying to do we can't suggest them.

-- 
------------------------------------------------------------------------
-------
 Paul D. Smith <address@hidden>          Find some GNU make tips at:
 http://www.gnu.org                      http://make.paulandlesley.org
 "Please remain calm...I may be mad, but I am a professional." --Mad
Scientist




reply via email to

[Prev in Thread] Current Thread [Next in Thread]