Maxpm
Maxpm

Reputation: 25652

GNU make Not Deleting Intermediate Files

My makefile is as follows:

# The names of targets that can be built.  Used in the list of valid targets when no target is specified, and when building all targets.
TARGETS := libAurora.a libAurora.so

# The place to put the finished binaries.
TARGET_DIRECTORY := ./Binaries

# The compiler to use to compile the source code into object files.
COMPILER := g++

# Used when compiling source files into object files.
COMPILER_OPTIONS := -I. -Wall -Wextra -fPIC -g -O4

# The archiver to use to consolidate the object files into one library.
ARCHIVER := ar

# Options to be passed to the archiver.
ARCHIVER_OPTIONS := -r -c -s

SOURCE_FILES := $(shell find Source -type f -name *.cpp)
OBJECT_FILES := $(SOURCE_FILES:.cpp=.o)

.PHONY: Default # The default target, which gives instructions, can be called regardless of whether or not files need to be updated.
.INTERMEDIATE: $(OBJECT_FILES) # Specifying the object files as intermediates deletes them automatically after the build process.

Default:
    @echo "Please specify a target, or use \"All\" to build all targets.  Valid targets:"
    @echo "$(TARGETS)"

All: $(TARGETS)

lib%.a: $(OBJECT_FILES)
    $(ARCHIVER) $(ARCHIVER_OPTIONS) $(TARGET_DIRECTORY)/$@ $(OBJECT_FILES)

lib%.so: $(OBJECT_FILES)
    $(ARCHIVER) $(ARCHIVER_OPTIONS) $(TARGET_DIRECTORY)/$@ $(OBJECT_FILES)  

%.o:
    $(COMPILER) $(COMPILER_OPTIONS) -c -o $@ $*.cpp

As you can see, the .o files are specified as intermediates via the .INTERMEDIATE target. However, they are not deleted as expected after compilation finishes. Instead, they remain where they were created, cluttering up my source directory.

The strange thing is that it works perfectly on another machine. This leads me to believe it's a different version of make, but man make still shows it as the "GNU make utility."

Why won't make delete the intermediate files?

EDIT: make -v reports version 3.81.

EDIT: After manually deleting the .o files (i.e., a clean slate), make All produces the following output:

g++ -I. -Wall -Wextra -fPIC -g -O4 -c -o Source/File/File.o Source/File/File.cpp
g++ -I. -Wall -Wextra -fPIC -g -O4 -c -o Source/Timer/Timer.o Source/Timer/Timer.cpp
ar -r -c -s ./Binaries/libAurora.a Source/File/File.o Source/Timer/Timer.o
ar -r -c -s ./Binaries/libAurora.so Source/File/File.o Source/Timer/Timer.o

Upvotes: 5

Views: 6334

Answers (2)

Dan
Dan

Reputation: 12705

So I copied this onto my machine and managed to reproduce both your problem and the solution.

Notice that in your .INTERMEDIATE target, you use $(OBJECT_FILES) as a prerequisite, but for the rule that makes .o files you use a pattern rule. This confuses make and it doesn't recognize that the both refer to the same thing. There are two solutions to this problem:

  1. Change the prerequisites of .INTERMEDIATE from $(OBJECT_FILES) to %.o, so it looks like

    .INTERMEDIATE: %.o
    
  2. Change the rule for making .o files to

    $(OBJECT_FILES): $(SOURCE_FILES)
        $(COMPILER) $(COMPILER_OPTIONS) -c $< -o $@
    

    or something like it.

I recommend the first solution, as it's less likely to cause weird problems with compilation if you have several source files.

More info on the intermediate target can be found here.

Upvotes: 4

Thomas Berger
Thomas Berger

Reputation: 1870

Make sure, that the files are not there before you start building the project. The doc says clearly:

Therefore, an intermediate file which did not exist before make also does not exist after make.

If this is not the problem, you should post some debug output from make.

Upvotes: 4

Related Questions