7
votes

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.

6

6 Answers

5
votes

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

3
votes

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]
1
votes

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.

1
votes

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)

0
votes

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.

0
votes

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;
}