Problems with implicit rule in make - c++

I have the following directory structure
(root)
/ / \ \
/ | | \
src obj include bin
I would like to use an implicit rule to compile all the .cc files in root\src to .o files in root\obj.
This is my makefile so far:
basedir = .
incl = ${basedir}\include
obj = ${basedir}\obj
src = ${basedir}\src
lib = ${basedir}\lib
bin = ${basedir}\bin
CXX = gcc
LDLIBS = -lstdc++ -lmingw32 -lSDLmain -lSDL -lSDL_image -lchipmunk -lSDL_ttf \
-lSDL_mixer
LDFLAGS = -L${lib}
objects = $(addprefix ${obj}\, GameObject.o PhysicalObject.o \
Terrain.o Timer.o main.o ImageLoader.o Player.o )
sources = $(addprefix ${src}\, GameObject.cc PhysicalObject.cc \
Terrain.cc Timer.cc main.cc ImageLoader.cc Player.cc )
Cyborg : ${objects}
${CXX} ${objects} -o ${bin}\Cyborg.exe -L${lib} ${LDFLAGS} ${LDFLAGS}
${obj}\%.o : ${src}\%.c
${CXX} ${src}\$^ -c -o ${obj}\$#
.PHONY: clean
clean :
rm ${bin}\Cyborg.exe ${objects}
The error that I get is make: *** No rule to make target .\obj\GameObject.o, needed by Cyborg. Stop.
Any idea what's going wrong? I'm pretty new to makefiles so this might be terribly obvious.

Applying all of the ideas from the comments (and adding a couple trivial ones of my own), we get:
basedir = .
incl = ${basedir}/include
obj = ${basedir}/obj
src = ${basedir}/src
lib = ${basedir}/lib
bin = ${basedir}/bin
CXX = g++
LDLIBS = -lstdc++ -lmingw32 -lSDLmain -lSDL -lSDL_image -lchipmunk -lSDL_ttf \
-lSDL_mixer
LDFLAGS = -L${lib}
objects = $(addprefix ${obj}/, GameObject.o PhysicalObject.o \
Terrain.o Timer.o main.o ImageLoader.o Player.o )
sources = $(addprefix ${src}/, GameObject.cc PhysicalObject.cc \
Terrain.cc Timer.cc main.cc ImageLoader.cc Player.cc )
Cyborg : ${objects}
${CXX} ${objects} -o ${bin}/Cyborg.exe -L${lib} ${LDFLAGS} ${LDFLAGS}
${obj}/%.o : ${src}/%.c
${CXX} $^ -c -o $#
.PHONY: clean Cyborg
clean :
rm -f ${bin}\Cyborg.exe ${objects}
What does "make Cyborg" do with this Makefile?

This is probably going to take a few iterations.
Try some simple rules, in order of increasing complexity, and tell us the results:
./obj/GameObject.o : ./src/GameObject.cc
#echo trying to build $# from $<
./obj/GameObject.o : ./obj/%.o : ./src/%.cc
#echo trying to build $# from $<
$(objects) : ./obj/%.o : ./src/%.cc
#echo trying to build $# from $<
./obj/%.o : ./src/%.cc
#echo trying to build $# from $<

${obj}\%.o : ${src}\%.c --> ${obj}\%.o : ${src}\%.cc

I had similar problem with GNU make. Try making explisit rules for your objects:
$(obj)\GameObject.o: $(src)\GameObject.cc
$(obj)\PhysicalObject.o: $(src)\PhysicalObject.cc
# and so on for each object

Related

Makefile error in WSL Ubuntu : no rule to make target

I get the following error :
make : *** no rule to make target obj/Divers.o, needed by main. Stop
Here is what my makefile look like :
IDIR = include
ODIR = obj
SDIR = src
BDIR = bin
CC = g++
CFLAGS = -g -Wall -Wextra -std=c11 -I$(IDIR)
PROG = main
_DEP = Divers.h ArbresSyntaxiques.h
DEP = $(patsubst %,$(IDIR)/%,$(_DEP))
_OBJ = Divers.o ArbresSyntaxiques.o Main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
.PHONY: run all remake clean delete
all: $(PROG)
run : all
./$(PROG)
$(PROG) : $(OBJ)
$(CC) $(CFLAGS) -o $# $^ -lm
$(ODIR)/%.o : $(SDIR)/%.c $(DEP)
$(CC) $(CFLAGS) -c -o $# $<
clean :
rm -f $(ODIR)/*.o
delete : clean
rm $(PROG)
Finally my folder is structured like this :
include :
ArbresSyntaxiques.h
Divers.h
obj : (Empty)
src :
AbresSyntaxiques.cpp
Divers.o
Main.o
makefile

Makefile to compile a list of sources to custom directory

I have this makefile:
IDIR = include
SDIR = src
ODIR = obj
BDIR = build
DEPS = $(shell find $(IDIR)/ -name '*.hpp')
SRCS = $(shell find $(SDIR)/ -name '*.cpp')
OBJS = $(patsubst %.cpp,$(ODIR)/%.o,$(notdir $(SRCS)))
BIN = main
CPPC = g++
CFLAGS = -Wall -c
all: dir $(BDIR)/$(BIN)
#echo Finished compiling $(BIN)
dir:
mkdir -p $(BDIR)
mkdir -p $(ODIR)
$(BDIR)/$(BIN): $(OBJS)
$(CPPC) $^ -o $#
$(OBJS): $(SRCS)
$(CPPC) $(CFLAGS) $^ -o $#
clean:
rm -rf $(BDIR) $(ODIR)
When I try to make, I get the following error:
mkdir -p build
mkdir -p obj
g++ -Wall -c src/sdk/tcp/Tcp.cpp src/sdk/socket/Socket.cpp src/Main.cpp -o obj/Tcp.o
g++: fatal error: cannot specify ‘-o’ with ‘-c’, ‘-S’ or ‘-E’ with multiple files
compilation terminated.
make: *** [Makefile:27: obj/Tcp.o] Error 1
My question is, is it possible to achieve what I am trying with this makefile? Going through each source file in $(SRCS), and compile the object file directly inside the obj directory with just the basename. An example of obj directory after a successful compilation:
obj
/ | \
/ | \
Tcp.o Socket.o Main.o
Your $(OBJS) rule is wrong.
There are (at least) two ways to do this.
You could write a pattern rule and use vpath to locate the sources:
vpath %.cpp $(dir $(SRCS))
$(OBJS): obj/%.o: %.cpp
$(CPPC) $(CFLAGS) $^ -o $#
Or you could generate a rule for each object:
define template
$(patsubst %,obj/%.o,$(notdir $(1))): $(addsuffix .cpp,$(1))
echo $(CPPC) $(CFLAGS) $$^ -o $$#
endef
$(foreach src,$(SRCS),$(eval $(call template,$(basename $(src)))))

make: unable to locate user-defined header file that is included?

When I run make, I get the following error:
make: *** No rule to make target Menu.h', needed by Menu.o'. Stop.
Here is my Makefile:
PROG = sim
CURR_PATH = ~/Projects/restaurant/cpp/
CC = g++
CPPFLAGS = -g -v -Wall $(LOCAL_INCLUDES) -I$(BOOST_ROOT)
ODIR = ./bin
SDIR = ./src
LOCAL_INCLUDES = $(patsubst %,-I$(CURR_PATH)src/%,$(PKG_DIRS))
PKG_DIRS = $(shell ls $(SDIR))
FIND_SRC_FILES = $(notdir $(wildcard $(SDIR)/$(pkg)/*.cpp))
SRC_FILES = $(foreach pkg,$(PKG_DIRS),$(FIND_SRC_FILES))
OBJ_FILES = $(patsubst %.cpp,%.o,$(SRC_FILES))
MAIN_OBJ = main.o
.PHONY : prog
prog : $(PROG)
all : ; $(info $$CPPFLAGS is [${CPPFLAGS}])#echo Hello world
$(PROG) : $(OBJ_FILES)
$(CC) $(CPPFLAGS) -o $(PROG) $(MAIN_OBJ)
%.o : %.cpp
$(CC) $(CPPFLAGS) -c $< -o $#
$(OBJ_FILES) : %.o : %.h
$(CC) $(CPPFLAGS) -c $(patsubst %.h,%.cpp,$<) -o $#
BTW, in case you're wondering what LOCAL_INCLUDES looks like, the output for the 'all' recipe is the following:
$CPPFLAGS is [-g -v -Wall -I~/Projects/restaurant/cpp/src/concurrent -I~/Projects/restaurant/cpp/src/containers -I~/Projects/restaurant/cpp/src/data -I~/Projects/restaurant/cpp/src/loader -I~/Projects/restaurant/cpp/src/main -I~/Projects/restaurant/cpp/src/people -I~/Projects/restaurant/cpp/src/sim -I/usr/local/boost_1_72_0]
Hello world
Sorry for the single line output, I am unaware of how to format in a more readable fashion. But as you can see, the directory data, which contains Menu.h, is being properly included. But for some reason, make is unable to find it. What could possibly be going wrong here?
Let me know if you need more information.
Cheers
The compiler knows how to find that header file. Make does not know how to find it, and Make is the one producing that error message.
I suggest you make this modification:
INCLUDE_DIRS = $(addprefix $(CURR_PATH)src/,$(PKG_DIRS))
LOCAL_INCLUDES = $(addprefix -I,$(INCLUDE_DIRS))
vpath %.h $(INCLUDE_DIRS)
(P.S. Your use of CURR_PATH and . is confusing, and data/ is a terrible place to put header files.)
EDIT:
All right, let's take this in stages. Step 1, try this makefile:
OBJ_FILES = Menu.o
INCLUDE_DIRS = ~/Projects/restaurant/cpp/src/data
vpath %.h $(INCLUDE_DIRS)
Menu.o:
$(OBJ_FILES) : %.o : %.cpp %.h
#echo building $# from $^
and tell us what happens. (If it doesn't work, tell us what happens.)
As aforementioned, make's vpath did not like the absolute path that it was being given. See below for my modified Makefile:
PROG = sim
CURR_PATH = ~/Projects/restaurant/cpp/
CC = g++
CPPFLAGS = -g -v -Wall $(LOCAL_INCLUDES) -I$(BOOST_ROOT)
ODIR = bin
# vpath only needs SDIR and PKG_DIRS!
SDIR = src
PKG_DIRS = $(shell ls $(SDIR))
INCLUDE_DIRS = $(addprefix $(CURR_PATH)src/,$(PKG_DIRS))
LOCAL_INCLUDES = $(addprefix -I,$(INCLUDE_DIRS))
FIND_SRC_FILES = $(notdir $(wildcard $(SDIR)/$(pkg)/*.cpp))
SRC_FILES = $(foreach pkg,$(PKG_DIRS),$(FIND_SRC_FILES))
OBJ_FILES = $(patsubst %.cpp,%.o,$(SRC_FILES))
MAIN_OBJ = main.o
vpath %.h $(addprefix $(SDIR)/,$(PKG_DIRS))
.PHONY : all
prog : $(PROG)
all : ; $(info $$CPPFLAGS is [${CPPFLAGS}])#echo Hello world
$(PROG) : $(OBJ_FILES)
$(CC) $(CPPFLAGS) -o $(PROG) $(MAIN_OBJ)
%.o : %.cpp
$(CC) $(CPPFLAGS) -c $< -o $#
$(OBJ_FILES) : %.o : %.h
$(CC) $(CPPFLAGS) -c $(patsubst %.h,%.cpp,$<) -o $#
I hope this helps other people that come across similar issues.

Makefile source in multiple directories

I have seen some examples of using makefile with multiple source directories but still could not implement it to my makefile.
Currently I have all source files at /src/ folder and I would like to be able compile subfolders in /src/ such as /src/modules.
I am using:
NAME = 'AI'
SRC = src
TGT = obj
PRG = application
INCLUDES = -Iinclude ...
LIBRARIES = -L ...
CXXFLAGS = -O2 -std=c++0x $(INCLUDES) $(LIBRARIES)
SOURCES = $(wildcard $(SRC)/*.cpp)
ENDFLAGS = -ljvm -lcurl
NOWARNINGS = -Wno-unused-variable -Wno-unused-result
OBJS = $(addprefix $(TGT)/, $(notdir $(SOURCES:.cpp=.o)))
$(TGT)/%.o: $(SRC)/%.cpp
$(CXX) $(CXXFLAGS) -c $< -o $# $(NOWARNINGS)
$(PRG)/$(NAME): $(OBJS)
$(CXX) $(LIBRARIES) $(OBJS) -o $# $(ENDFLAGS) $(NOWARNINGS)

No rule to make target ***

I am currently trying to build Face Tracker (by Jason Saragih) with "make" in my Windows 7 x64, but all I'm getting is: "No rule to make target src/lib/IO.o, needed by bin/face_tracker".
Does anyone have any idea of what is happening, please?
This is the makefile (also available in Jason Saragih's page):
# Paths
OPENCV_PATH=/OpenCV246/
# Programs
CC=
CXX=g++
# Flags
ARCH_FLAGS=-arch x86_64
CFLAGS=-Wextra -Wall -pedantic-errors $(ARCH_FLAGS) -O3
LDFLAGS=$(ARCH_FLAGS)
DEFINES=
INCLUDES=-I$(OPENCV_PATH)/include -Iinclude/
LIBRARIES=-L$(OPENCV_PATH)/lib -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_objdetect
# Files which require compiling
SOURCE_FILES=\
src/lib/IO.cc\
src/lib/PDM.cc\
src/lib/Patch.cc\
src/lib/CLM.cc\
src/lib/FDet.cc\
src/lib/PAW.cc\
src/lib/FCheck.cc\
src/lib/Tracker.cc
# Source files which contain a int main(..) function
SOURCE_FILES_WITH_MAIN=src/exe/face_tracker.cc
# End Configuration
SOURCE_OBJECTS=$(patsubst %.cc,%.o,$(SOURCE_FILES))
ALL_OBJECTS=\
$(SOURCE_OBJECTS) \
$(patsubst %.cc,%.o,$(SOURCE_FILES_WITH_MAIN))
DEPENDENCY_FILES=\
$(patsubst %.o,%.d,$(ALL_OBJECTS))
all: bin/face_tracker
%.o: %.cc Makefile
## Make dependecy file
$(CXX) -MM -MT $# -MF $(patsubst %.cc,%.d,$<) $(CFLAGS) $(DEFINES) $(INCLUDES) $<
## Compile
$(CXX) $(CFLAGS) $(DEFINES) $(INCLUDES) -c -o $# $<
-include $(DEPENDENCY_FILES)
bin/face_tracker: $(ALL_OBJECTS)
$(CXX) $(LDFLAGS) $(LIBRARIES) -o $# $(ALL_OBJECTS)
.PHONY: clean
clean:
#echo "Cleaning"
#for pattern in '*~' '*.o' '*.d' ; do \
find . -name "$$pattern" | xargs rm ; \
done
Thanks,
Fabio