[Top][All Lists]

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

Re: How to: organize application files and get GNU make to put theoutpu

From: Paul Smith
Subject: Re: How to: organize application files and get GNU make to put theoutput files into the right place.
Date: Mon, 25 Jan 2010 17:03:33 -0500

On Mon, 2010-01-25 at 15:17 -0500, Ted Byers wrote:

>         Not sure what you mean by "standard"; if you mean by
>         "generally
>         available in GNU make", one option is to use target-specific
>         variables
>         (see the manual for details).  Do something like this:
> By "standard" I meant only commonly accepted, or commonly used,
> practice.

But, where?  In GNU make?  Or in all implementations of make?  Because
the target-specific variable thing is available only in GNU make and
Solaris make (that I know of).  If you want to really stick only to
features of make that are widely available, or "standard", across a
large variety of make implementations, then that's pretty restrictive.
If you just mean common among users of GNU make, that's quite different.

>                # By default, enable both optimization and debug
>                OPTFLAGS = -g -O2
>                CFLAGS += $(OPTFLAGS)
>                CXXFLAGS += $(OPTFLAGS)
>                debug: OPTFLAGS = -g
>                debug: all
>                production: OPTFLAGS = -O2
>                production: all
>                all: <whatever>
> Thanks.  This will be useful as a start.
> But here's a question about order of execution.  Above you show the
> contents of OPTFLAGS being added to whatever is in CFLAGS and
> CXXFLAGS.  When is that executed when make is invoked with either
> debug or production?  Before the target specific values are defined or
> after?

You can check the manual, which hopefully explains this fairly well, but
basically each target level adds a new "scope" to the variable value,
and that scope hides any less specific version of the variable.  Because
we are assigning CFLAGS with "=" and not ":=", those values aren't
expanded until they are used (when the command is about to be invoked).

So, as long as you don't use ":=" to assign variables, basically you can
do the assignment in any order.

> And a point of clarification.  We don't want to mix debug and
> non-debug binaries.  So, I have clean and realclean targets defined
> that remove intermediate binaries or all binaries.  Therefore, I need
> to ask, is there a well defined order in which targets that have been
> specified are made?  For example, is realclean guaranteed to be done
> before all if I specify:
> debug: realclean all

There is... sort of.  Make will always try to build prerequisites
starting with the first one and continuing on with the next, etc.

HOWEVER!  If someone invokes make with parallelism (-j), then make will
try to build more than one target at a time.  In that situation, in the
above case, it could quite well be that both realclean and all are being
run by make at the same time.

The only way to avoid this is to declare a prerequisite relationship
between them, which is obviously not something you want to do all the
time.  You can do something like this:

        all: $(filter realclean,$(MAKECMDGOALS))

which will expand to "realclean" only if it was specified on the make
command line.

Of course, even this is not really enough, because if you have:

        all: $(filter realclean,$(MAKECMDGOALS)) foo bar

then realclean is run before all, but NOT before foo or bar (in the face
of parallelism).  Really, it's hard to get this working: to be 100%
correct you need to mark realclean as a prerequisite on every object
that it might clean, to be sure it runs before all of them.

In this case a better solution is to use recursion:

                $(MAKE) realclean
                $(MAKE) all

and if you do this, you can not worry about target-specific variables at
all; just run:

                $(MAKE) realclean
                $(MAKE) all OPTFLAGS=-g

> So the implication is that I'd do something similar to what MS VC++
> does (different locations for debug and release versions of a given
> project).  I can live with that for the time being.

There are basically two ways to do it: either use separate directories,
or else use separate target names (foo.c -> dbg_foo.o / opt_foo.o or
whatever).  I've seen both used.  I prefer the separate directory myself
but others do not.

> For the "much more flexible environment that allows you to build
> multiple output types from the same set of source" system, can you
> point me to a document or tutorial that shows how to do this?

Hm.  I don't know of one offhand.  There is nothing built into make,
IMO, that makes one option a lot better than other options, so people
really tend to do their own thing.  I've seen some posts to the list
from folks who have created templates like this but I don't have
pointers handy and I haven't reviewed them myself.

reply via email to

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