Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make file warning, overriding commands for target

As part of the makefile i'd like to produce either a debug or release version of the target.

Functionally, everything is working, however, i am getting warnings when running make

 12 SRC := $(shell echo src/*.cpp)
 13 SRC += $(shell echo $(TEST_ROOT)/*.cpp)
 14 
 15 D_OBJECTS = $(SRC:.cpp=.o)       # same objects will need to be built differently
 16 R_OBJECTS = $(SRC:.cpp=.o)       # same objects will need to be built differently

 22 all: $(TARGET)
 23 
 25 $(TARGET): $(D_OBJECTS)
 26   $(CC) $(D_OBJECTS) -o $(TARGET)
 27 
 28 $(D_OBJECTS) : %.o: %.cpp                     # ----- run with debug flags 
 29   $(CC) $(COMMON_FLAGS) $(DEBUG_FLAGS) -c $< -o $@
 30 
 31 release: $(R_OBJECTS)
 32   $(CC) $(R_OBJECTS) -o $(TARGET)
 33 
 34 $(R_OBJECTS) : %.o: %.cpp                     # ----- run with release flags
 35   $(CC) $(COMMON_FLAGS) $(RELEASE_FLAGS) -c $< -o $@

When i make i get debug version, when i make release i get release version.

But i also get warnings:

Makefile:35: warning: overriding commands for target `src/Timer.o'
Makefile:29: warning: ignoring old commands for target `src/Timer.o'
Makefile:35: warning: overriding commands for target `test/TimerTest.o'
Makefile:29: warning: ignoring old commands for target `test/TimerTest.o'

With this 2 questions:

  1. Any way to ignore the warnings
  2. Am i doing things right? What changes are needed?
like image 240
James Leonard Avatar asked Aug 14 '12 18:08

James Leonard


3 Answers

Like the OP (James Leonard), I would like to suppress or avoid warnings about overriding Makefile targets. However, my situation and goals are different.

I want Makefile to include base.mk, and I want Makefile to be able to override targets from base.mk without any warning messages. I am using GNU Make.

The GNU Make documentation describes one way of doing this:

Create Makefile as follows:

foo:
        echo 'bar' > foo

%: force
        @$(MAKE) -f base.mk $@
force: ;

Source: https://www.gnu.org/software/make/manual/html_node/Overriding-Makefiles.html

The above method has the (potentially serious) disadvantage that it will invoke a separate instance of $(MAKE), meaning that (some or all?) variables may (will?) not be shared between the parent and child invocations of make.

Happily, I found a better solution, as outlined below:

Create base.mk as follows:

foo-default:
        echo  'foo-default'

bar-default:
        echo  'bar-default'

%:  %-default
        @  true

Create Makefile as follows:

include  base.mk

foo:
        echo  'foo  Makefile'

Example output:

$ make foo
echo  'foo  Makefile'
foo  Makefile

$ make bar
echo  'bar-default'
bar-default

Note that you need to be able to control the names of the targets in base.mk so that you can name them <target>-default. In other words, you cannot use this approach to extend arbitrary base makefiles. However, if you control both base.mk and Makefile, this approach will allow you to create one base.mk and then many customizations of it.

like image 115
mpb Avatar answered Nov 03 '22 23:11

mpb


One of the most common ways for doing this is to put the release objects and the debug objects in separate subdirectories. That way you don't get redefinitions for the rules for an object, since they will have different names. Something like this:

D_OBJECTS=$(SRC:%.cpp=debug/%.o)
R_OBJECTS=$(SRC:%.cpp=release/%.o)

RTARGET = a.out
DTARGET = a.out.debug

all : dirs $(RTARGET)

debug : dirs $(DTARGET)

dirs :
    @mkdir -p debug release

debug/%.o : %.c
    $(CC) $(DEBUG_CFLAGS) -o $@ -c $<

release/%.o : %.c
    $(CC) $(RELEASE_CFLAGS) -o $@ -c $<

$(DTARGET) : $(D_OBJECTS)
    $(CC) $(DEBUG_CFLAGS) -o $@ $(D_OBJECTS)

$(RTARGET) : $(R_OBJECTS)
    $(CC) $(RELEASE_CFLAGS) -o $@ $(R_OBJECTS)
like image 40
twalberg Avatar answered Nov 03 '22 23:11

twalberg


To avoid including the same file many times, you can use a C-style header 'directive':

ifeq ($(_MY_MAKEFILE_),)
_MY_MAKEFILE_ := defined

...

endif
  • ifeq here is just saying "is the value empty"
  • it's possible something similar can be done with ifndef but I got this working first
  • the value "defined" is just anything that isn't blank
like image 2
Dave Cousineau Avatar answered Nov 04 '22 01:11

Dave Cousineau