Reputation: 4213
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
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
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