Sterling
Sterling

Reputation: 4213

Makefile Error "File exists" when make -j2

Whenever I use just "make" to compile, my Makefile works fine. But when I use "make -j2", I get the error that

mkdir: cannot create directory `objects': File exists
make: *** [objects/robot_driver_agent.o] Error 1

This is the Makefile -

INCLUDE = -I/usr/include/X11 -I/usr/local/include -I/usr/local/include/FL/images -I/usr/include/freetype2

CC=g++ 
CFLAGS=-w -D LINUX -O3 -fpermissive 
OBJDIR=objects
SRCDIR=src

LDFLAGS= -L/usr/X11R6/lib$(LIBSELECT) -lpthread -lfltk -lXext -lXft -lfontconfig -lXinerama -lpthread -ldl -lm -lX11

SOURCES_RAW= robot_driver_agent.cpp robot_driver_position.cpp robot_driver_priorityqueue.cpp main.cpp robot_driver_tree.cpp robot_driver_stack.cpp robot_driver_grid.cpp robot_driver_path.cpp grid_analyzer.cpp tcpserver.cpp tcpclient.cpp servercontrol.cpp clientcontrol.cpp robot.cpp udpserver.cpp udpclient.cpp owncontrol.cpp guiwindow.cpp rs232.cpp

TARGET:= go
TARGETD:= go_d

OBJECTS:=$(SOURCES_RAW:.cpp=.o)
OBJECTS:=$(patsubst %.o, $(OBJDIR)/%.o, $(OBJECTS))

SOURCES:=$(SOURCES_RAW)
SOURCES:=$(patsubst %.cpp, $(SRCDIR)/%.cpp, $(SOURCES))

all: $(TARGET)

$(TARGET): $(OBJECTS)
    $(CC) -w -D LINUX $(INCLUDE) $^ -o $@ $(LDFLAGS)

$(OBJDIR)/%.o: src/%.cpp
    test -d $(OBJDIR) || mkdir $(OBJDIR)
    $(CC) -g -c $< $(CFLAGS) -o $@ 

debug: $(TARGETD)

$(TARGETD): $(OBJECTS)
    $(CC) -w -D LINUX $(INCLUDE) $^ -o $@ $(LDFLAGS)

%.o: $(SRCDIR)/%.cpp
    $(CC) -c -g $< $(CFLAGS)-o $@



.PHONY : clean
clean:
    rm -f $(OBJDIR)/*.o
    rm -f $(TARGET) $(TARGETD)

Can anyone tell me why using both of the processors with -j2 makes this error appear and how to fix it? Thank you for any help.

Upvotes: 1

Views: 2254

Answers (2)

Kaz
Kaz

Reputation: 58617

Use mkdir -p. It is idempotent (no problems if executed twice with the same argument, or even in parallel). And it makes all of the directories if you give a path name with multiple components.

Look at my Makefile here: http://www.kylheku.com/cgit/txr/tree/Makefile

Several instances of mkdir -p. Of course, I do see multiple mkdir -p jobs being issued when I run make -j, but it isn't a problem.

Another idea is to add the - on the mkdir command. (Just like what is used with rm in clean target rules). But that ignores a genuine error, not only EEXIST.

P.S. logic like if directory does not exist, then mkdir ... won't work because it has a race condition. The directory might not exist at the time the if is evaluated, but then by the time the mkdir is evaluated, it suddenly exists. In parallel make, you have to worry about races because writing rules for parallel make is a form of concurrent programming.

Upvotes: 0

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272667

Don't create directories like that; it's a race condition waiting to happen. Let Make handle the dependency resolution for you:

 $(OBJECTS): | $(OBJDIR)

 $(OBJDIR):
         mkdir $(OBJDIR)

This is taken directly from the order-only prerequisite example in the Make manual.

Upvotes: 3

Related Questions