tags:

views:

204

answers:

6

This is either trivial or runs counter to the philosophy of how make should be used, but I'd like to have a command line that reads as "make debug" rather than "make DEBUG=1". I tried creating a phony target called debug that did nothing except set the DEBUG variable, but then there was a difference between "make debug build" and "make build debug"--namely that in one case, the variable got set after the build happened.

Is there a way to give certain targets precedence?

Thanks for your help.

A: 

If your debug will only be used with the build target, you might as well make debug call build so you can just type make debug or make build, where make build would be non-debug.

But as for your actual question, I'm not familiar enough with makefiles to answer it.

jonathanasdf
+1  A: 

you can write the following:

.PHONY: debug
debug:
        $(MAKE) -$(MAKEFLAGS) build DEBUG=1

build:
        echo makeflags='$(MAKEFLAGS)' debug=${DEBUG}

This will at least work with GNU Make, BSD Make and Interix Make. I didn't try all the other implementations.

Roland Illig
Portability at the cost of recursive evaluation of the make file.
dmckee
+3  A: 

See 'Target-specific variable values' in this page.

bmargulies
No harm mentioning you just have to do `target: DEBUG=1` for a target versus pointing him to the documentation... right?
xyld
He needs to read the rest of the doc to know what's he's getting into with this. Plus, he gets the bonus of all those other obscure features.
bmargulies
Doesn't this not solve the problem that "make build debug" is not equivalent to "make debug build"? This particular feature is exactly what I tried.
leo grrr
In retrospect, I can see how that matches your question, but you didn't make it clear. Make targets are *always* ordered, so I think you're on an impossible mission.
bmargulies
In that case, that's exactly what I needed to know. Thanks!
leo grrr
A: 

One approach is to set up the dependencies and build rules in both the build and debug targets, but add the your debugging options to the debug target. A simple example:

Makefile

program:        program.c
                gcc -o program program.c
debug:          program.c
                gcc -D DEBUG -o program program.c

Program.c

#include <stdio.h>
int main(void) {
#ifdef DEBUG
  printf("DEBUG on!\n");
#endif
  printf("in the program\n");
  return 0;
}
GreenMatt
+1  A: 

One thing you can do with GnuMake is use macros that expand to rules with the foreach builtin. Something like:

TARGETS := build all foo bar baz

define DEBUG_TARGET_RULE
$(1).debug:
        $$(MAKE) DEBUG=1 $(1)
debug.$(1):
        $$(MAKE) DEBUG=1 $(1)
endef

$(foreach target,$(TARGETS),$(eval $(call DEBUG_TARGET_RULE,$(target))))

This will allow you to type make debug.foo or make foo.debug and it will automatically turn into make DEBUG=1 foo, and it works for any target you put in $(TARGETS)

Chris Dodd
Not exactly what I was looking for, but cool workaround that also demonstrates a useful feature of make.
leo grrr
A: 

You can also do it by looking at the MAKECMDGOALS variable

ifneq "$(findstring debug, $(MAKECMDGOALS))" ""
DEBUG = 1
endif

build:
    @echo build and DEBUG is [$(DEBUG)]

debug:

This is what happens when you call it:

$ make build
build and DEBUG is []
$ make build debug
build and DEBUG is [1]
make: Nothing to be done for `debug'.
$ make debug build
make: Nothing to be done for `debug'.
build and DEBUG is [1]
jake