C/C++ compilation. Having trouble with simple makefile for a project - c++

I been working on this makefile for hours and it seems like no changes are working, but it seems totally fine to me. Maybe I am missing something fundamental?
Here is how the directory looks:
project
makefile
\obj
checkInput.cpp
olend.cpp
\include
checkInput.h
Here is makefile:
I_DIR = include
OBJ_DIR = obj
CXX = g++
CXXFLAGS = -I$(I_DIR)
MAIN = olend
SRCS = checkInput.cpp
OBJ_SRCS = $(subst .cpp, .o, $(SRCS)), $(MAIN).o
OBJS = $(patsubst %, $(OBJ_DIR)/%, $(OBJ_SRCS))
DEP_SRCS = $(subst .cpp,.h,$(SRCS))
DEPS = $(patsubst %,$(I_DIR)/%,$(DEP_SRCS))
all: $(MAIN)
$(MAIN): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(MAIN) $(OBJS)
$(OBJ_DIR)/%.o: %.cpp $(DEPS)
$(CXX) $(CXXFLAGS) -o $# $<
.PHONY: clean
clean:
rm -f $(OBJ_DIR)/*.o $(MAIN)
I'm looking to get an executable "olend", and the error I am currently getting is,
"No rule to make target 'obj/olend.o,', needed by `olend'. Stop."
Which is very straight forward error, but I don't understand how that could be happening,
$(OBJ_DIR)/%.o
should include obj/olend.o as a target. Any help would be greatly appreciated!

If you look closely at the error message, it says that the target it can't find is 'obj/olend.o,' - notice the extra comma at the end. This comes from the way you defined your OBJ_SRCS variable. It should look like this:
OBJ_SRCS = $(subst .cpp,.o, $(SRCS)) $(MAIN).o
Notice there is no space before .o (this caused it to generate filenames like checkInput .o) and there is no comma before the $(MAIN) part (this caused it to generate something like this: checkInput.o, olend.o).

Related

How can I avoid circular dependency in my Makefile compiling obj file with g++ and gcc?

I tried to create a makefile for a project that use c++ and c.
I need to compile those file in order to make de .o file, but when I compile using make I have circular dependency that is dropped.
I don't know why this error occurs as I tried to separate the building of .o files that comes from .c and .o files that comes froms .cpp files.
Here is my makefile :
SRC = $(wildcard *.c)
SRC++ = $(wildcard *.cpp)
OBJ = $(SRC++:.cpp=.o) $(SRC:.c=.o)
DEP = $(SRC:.c=.d) $(SRC++:.cpp=.d)
CC=gcc
CXX=g++
CFLAGS = -Wall
CXXFLAGS = -Wall
all: $(OBJ)
%.c : %.o
$(CC) -c $(CFLAGS) $< -o $#
%.cpp : %.o
$(CXX) -c $(CXXFLAGS) $< -o $#
# Clean the project
clean:
#rm -f $(OBJ) $(DEP)
-include $(DEP)
Do you have any idea of what I am doing wrong ?
The rules you wrote are %.cpp : %.o and %.c : %.o. You wrote those rules the wrong way around. The target being built must be to the left of the colon, and the things it depends on must be to the right.
The error message tells you about a circular dependency because GNU Make defines an implicit rule where the dependencies are defined in the correct direction.

Error when executing make

I am trying to create a makefile for my project, but i seem to run into some errors, as I am testing new things. My file structure is as such:
~/main #root project folder
~/main/include #header files (mostly class headers)
~/main/src #source files
~/main/src/obj #object files
Makefile
(Makefile is in the root project folder)
Makefile:
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
CFLAGS=-Wall -std=c++11 -I$(IDIR)
$(OBJS): $(SRCS) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
all: $(OBJS)
gcc -o run $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(OBJS)
For testing purposes I have a single main.cpp in src folder and a random header file in include folder. The error I am getting when running the simple make command is the following:
make: *** No rule to make target `src/obj/%.o', needed by `all'. Stop.
EDIT : With the help of the guys below i came up with the solution
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
CFLAGS=-Wall -std=c++11 -I$(IDIR)
_DEPS = yo.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
_SRC = main.cpp
SRC = $(patsubst %,$(SDIR)/%,$(_SRC))
$(ODIR)/%.o: $(SRC) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
all: $(OBJ)
$(CC) -o run $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(OBJS)
There is a difference in using % in your two cases. When you write:
$(ODIR)/%.o : $(SDIR)/%.cpp $(IDIR)/%.h
that will do pattern substitution, and create a bunch of rules like:
$(ODIR)/foo.o : $(SDIR)/foo.cpp $(SDIR)/foo.h
So it's fine there, although you should use the % explicitly there so it's clear to see what the rule is doing.
But when you use it here:
all : $(ODIR)/%.o
That is literally looking for the target $(ODIR)/%.o for which you don't have a rule. There's no substitution. And you don't have a rule to make that target - hence the error. What you meant to do was have all depend on all the actual objects, for which you'll want to use the wildcard function:
SOURCES = $(wildcard $(SDIR)/*.cpp)
OBJECTS = $(SOURCES:$(SDIR)/%.cpp=$(ODIR)/%.o)
all : $(OBJECTS)
gcc -o run $^ $(CFLAGS)
When you use
OBJS=$(ODIR)/%.o
The %.o part does not expand to anything meaningful. It just remains as the literal value %.o. Same problem exists for DEPS and SRCS as well.
You need to use the wildcard and patsub functions. Instead of
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
use
DEPS=$(wildcard $(IDIR)/*.h)
SRCS=$(wildcard $(SDIR)/*.cpp)
OBJS=$(patsub %.cpp,%.o,$(SRCS))

Error: "Mixed implicit and static pattern rules" in my Makefile

I had a working Makefile for small C++ applications that just had a couple of source code files inside a single folder that was also the output folder. Now I am trying to separate source and object files and ran into a problem. This is how my makefile looks right now, I'll go into detail where the problem occurs below.
CC = gcc
CXX = g++
RM = del
TARGET = plox.exe
CFLAGS = -Wall -ggdb -O3 $(INCLUDE)
CXXFLAGS = -std=c++11 -Wall -ggdb -O3 $(INCLUDE)
LDFLAGS = $(LIB) -lglfw3 -lopengl32 -lglu32 -lgdi32
INCLUDE = -I$(GLFW_INC) -I$(GLAD_INC)
LIB = -L$(GLFW_LIB)
SRC_DIR = src
BUILD_DIR = build
GLFW_DIR = d:/external/glfw-3.1
GLFW_INC = $(GLFW)/include
GLFW_LIB = $(GLFW)/lib64
GLAD = d:/external/glad-c
GLAD_INC = $(GLAD)/include
CXX_SOURCES = $(SRC_DIR)/%.cpp
CXX_OBJS = $(addprefix $(BUILD_DIR)/, $(CXX_SOURCES:.cpp=.o))
OBJS = $(CXX_OBJS) $(BUILD_DIR)/glad.o
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) -o $# $^ $(LDFLAGS)
$(CXX_OBJS): %.o: $(SRC_DIR)%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
$(BUILD_DIR)/glad.o: src/glad.c
$(CC) -c $(CFLAGS) -c -o $(BUILD_DIR)/glad.o $(SRC_DIR)/glad.c
.PHONY: clean
clean:
$(RM) $(TARGET) $(OBJS)
The problem is in the line:
$(CXX_OBJS): %.o: $(SRC_DIR)/%.cpp
Before my changes, it looked like this:
$(CXX_OBJS): %.o: %.cpp
A friend helped gave me a template and I never really knew what that line really does. In another thread I learned that this is a static pattern rule so I guess this is where I made the mistake. But writing it down just now, I think the error could be earlier already. I might have made a mistake when defining $(CXX_OBJS). Could it be that the objects in that list are of the form build/src/test.o instead of build/test.o?
But how can I fix the addprefix line to produce the correct output? And where does the error in the title come from; where am I mixing those? I thought it could be about the $(SRC_DIR) in the static pattern rule because I probably misunderstood how it worked, but omitting it doesn't make the error go away. Moreover (assuming CXX_OBJS is working correctly later), if the static pattern rule checks every file in the list $(CXX_OBJS) for a match with %.o, and then has a dependency on the same file with ending .cpp, then that is also not correct because of the build folder prefix.
All in all, I'm very confused about how to handle the folder prefixes correctly and any advice is greatly appreciated!
In a static pattern rule, the words in the first section (the targets) have to be real files. None of them can contain patterns (%). You have:
CXX_SOURCES = $(SRC_DIR)/%.cpp
CXX_OBJS = $(addprefix $(BUILD_DIR)/, $(CXX_SOURCES:.cpp=.o))
$(CXX_OBJS): %.o: $(SRC_DIR)%.cpp
So CXX_OBJS is $(BUILD_DIR)/$(SRC_DIR)/%.o, which contains a pattern, so this is illegal.
I don't really know what you're trying to do with CXX_SOURCES. Maybe you wanted:
CXX_SOURCES := $(wildcard $(SRC_DIR)/*.cpp)
instead?
In addition to MadScientist's correct answer, there was another error in my Makefile introduced by renaming variables: mingw32-make couldn't find the -lglfw3 part because I used $(GLFW) in the definition of GLFW_INC and GLFW_LIB, but didn't define it. I wanted to have $(GLFW_DIR) instead.

Makefile pattern rule with mixed dependencies

I've coded the following lines in my Makefile:
PROJECTS = ExamsGenerator ExercisesImporter
VERSION = .v0.0
EXTENSION = .Exe
BINDIR = ../bin
CONFDIR = ../config
DATADIR = ../data
DOCDIR = ../doc
INCDIR = ../include
LIBDIR = ../lib
OBJDIR = ../obj
SRCDIR = ../src
INCDIRS = $(INCDIR:%=-I%)
CC = g++
CCVAR = -D__DATADIR__=\"$(DATADIR)\"
CFLAGS = -g -Wall $(shell root-config --cflags) $(INCDIRS)
LDFLAGS = -g -Wall $(shell root-config --ldflags)
LDLIBS = $(shell root-config --glibs)
MEG_DEP = Functions.h Parser.h Test.h
MEG_DEPS = $(patsubst %,$(INCDIR)/%,$(MEG_DEP))
MEI_DEP = Functions.h Parser.h Exercise.h
MEI_DEPS = $(patsubst %,$(INCDIR)/%,$(MEI_DEP))
MEG_OBJ = mainExamsGenerator.o Parser.o Test.o
MEG_OBJS = $(patsubst %,$(OBJDIR)/%,$(MEG_OBJ))
MEI_OBJ = mainExercisesImporter.o Parser.o Exercise.o
MEI_OBJS = $(patsubst %,$(OBJDIR)/%,$(MEI_OBJ))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(MEG_DEPS) $(MEI_DEPS)
#echo "\nCreating object: $#"
$(CC) $(CCVAR) $(CFLAGS) -c -o $# $<
all: $(PROJECTS)
#echo "\n"
ExamsGenerator: $(MEG_OBJS)
#echo "\nLinking $#"
$(CC) $(CCVAR) $(CFLAGS) $(LDLIBS) -o $(BINDIR)/$(#)$(VERSION)$(EXTENSION) $^
ExercisesImporter: $(MEI_OBJS)
#echo "\nLinking $#"
$(CC) $(CCVAR) $(CFLAGS) $(LDLIBS) -o $(BINDIR)/$(#)$(VERSION)$(EXTENSION) $^
.SILENT:
.PHONY: clean
clean:
\rm -f $(BINDIR)/*$(EXTENSION) $(OBJDIR)/*.o *~ $(INCDIR)/*~ $(SRCDIR)/*~
I'm a Makefile newbie so I've picked up hints from several places and I'm probably not writing it in the most elegant way. I have few questions to improve them:
Do I really need to add $(OBJDIR)/%.o into the dependencies ?
Written in this way Parser.h is listed twice. Is it possible to rewrite this pattern rule to avoid it ? E.g., I don't want to recompile MEG stuff if Exercise.h is modified. New dependencies will be added and I'd like to manage them in a smart way.
Any other suggestion?
Thanks in advance for any help.
Bye...
No, you don't need (and don't want) to list a target as its own prerequisite. That doesn't make sense and cannot work.
$(patsubst %,prefix/%,$(var)) can be written as $(addprefix prefix,$(var)).
You might want to read Auto-Dependency Generation for a method to automatically generate the correct dependencies for .o files. It will help solve some of your problems.
If, however, you don't want to get that fancy then what you need to remember is that you need to list, for each target, all the files that that target depends on and no other files.
So
Parser.o presumably depends on (at least) Parser.h
So add $(OBJDIR)/Parser.o: $(INCDIR)/Parser.h
Exercise.o presumably depends on (at least) Exercise.h (and possibly also Parser.h?)
So add $(OBJDIR)/Exercise.o: $(INCDIR)/Exercise.h (or possibly $(OBJDIR)/Exercise.o: $(INCDIR)/Exercise.h $(INCDIR)/Parser.h)
etc...
Note that prerequisites combine from wherever they are found so the above suggested lines will combine with a $(OBJDIR)/%.o: $(SRCDIR)/%.cpp rule to form a full set of prerequisites for the given .o file.

How to build library and link it with sources with Make

I'm still quite new to make. I am trying to compile a project in which maketest.cpp and maketest.hpp rests on Users/wen/Projects/maketest with the Makefile itself. Problem is, I want to also compile and link the source files (.cc and .hh) in Users/wen/Projects/include/bigint.
# Macros
INCLUDE = -I/Users/wen/Projects/include/bigint
LIBS =
CC = g++
override FLAGS += -O2
HEADERS= $(wildcard *.hpp) $(wildcard Users/wen/Projects/include/bigint/*.hh)
# EXE Name
INSTALL = maketest
CC_FILES = %.cpp Users/wen/Projects/include/bigint/%.cc
OBJ_FILES = maketest.o $(wildcard Users/wen/Projects/include/bigint/*.o)
# Rules
$(INSTALL): $(OBJ_FILES)
$(CC) $(FLAGS) $^ -o $# $(LIBS)
%.o: $(CC_FILES) $(HEADERS)
$(CC) $(FLAGS) $(INCLUDE) -c $< -o $#
# Installation types
install: $(INSTALL)
release:
#echo "Re-run with parameter:"
#echo "FLAGS=-D_RELEASE"
debug:
#echo "Re-run with parameter:"
#echo "FLAGS=-D_DEBUG"
# Cleaning up
clean:
rm -f $(OBJ_FILES) $(INSTALL)
The code compiles maketest.cpp and links it, but not bigint.
What will be the right way to build and link the files from Users/wen/Projects/include/bigint? Many thanks!
I figured it out at the end, thank you Jay. The problem was I forgot a slash at the front of Users/wen/Projects/include/bigint, so it was not searching from root but instead the project folder. Now it works!
Try explicitly specifying one of the files from bigint in OBJ_FILES (perhaps "bigint.o" ?). I don't think your wildcard is getting what you want.