I'm learning how to use makefile however after a few hours of research and still being stuck I just can not manage to resolve what is wrong with my makefile:
output: main.o module.o
g++ main.o module.o -o output
main.o: module.cpp module.h
g++ -c module.cpp
module.o: module.cpp module.h
g++ -c main.cpp
my main.cpp file has #include "module.cpp"
my module.cpp file has #include "module.h"
after attempting to execute my makefile i get lots of "multiple definitions of" and "undefined references"
help will be highly appreciated
p.s code in codeblocks works flawlessly, that's why i am so confused. i am using mingw32-make
You are getting "multiple definition errors" becasue you are linking module.o and main.o together but your main.cpp already includes module.cpp. Do not include module.cpp in main.cpp (i.e.: remove the #include "module.cpp directive inside main.cpp). Since main.o won't depend then on module.cpp, you should remove that prerequisite from the main.o rule as well.
Also, consider using GNU Make's automatic variables instead of hard-coded filenames and predefined variables (i.e.: CXX) instead of hard-coded commands (i.e.: g++):
output: main.o module.o
$(CXX) $^ -o $#
main.o: main.cpp module.h
$(CXX) -c $<
module.o: module.cpp module.h
$(CXX) -c $<
Or even better, rely on the predefined pattern rule for generating .o files from .cpp files:
output: main.o module.o
$(CXX) $^ -o $#
main.o: module.h
module.o: module.h
Note that failing to provide the last two lines will cause main.o and module.o to be still up-to-date (i.e.: not being rebuilt) even though module.h changes.
Thanks to implicit rules in Makefiles, this should be enough:
output: main.o module.o
g++ main.o module.o -o output
The implicit rules allows make to know how to create .o files from .cpp files.
But this could be even simpler:
output: main.o module.o
$(CXX) -o $# #^
$(CXX) is your C++ compiler, usually g++
$# is an automatic variable of the target (value before the colon)
#^ is an automatic variable of the prerequisites (values after the colon)
Related
Every question I've seen on here is dealing with much more complicated use cases than I am.
I'm in a first year programming course and just can't understand what I am doing incorrectly. When running make I just get a Circles is up to date message.
I have three files:
main.cpp => entry point for the program
CircleDriver.cpp => an implementation file
circle.h => a header file containing the header class.
main.cpp depends on CircleDriver.cpp and circle.h, CircleDriver.cpp depends on circle.h
Currently my Makefile looks like this:
Circles: main.o
g++ -std=c++11 -g -Wall main.o -o Circles
main.o: main.cpp
g++ -std=c++11 -g -Wall -c main.cpp CircleDriver.cpp
clean:
rm *.o Circles
I read that you don't need to include header files in the compile command, but adding the other .cpp file did not solve my issue.
I'm sure this is a simple issue, but about 30 minutes of Googling yielded no results.
Thank you in advance.
I usually do something like this for my Makefile:
%.o: %.cpp
g++ -c -o $# $< -std=c++11 -Wall
Circles: main.o CircleDriver.o
g++ -o $# $^ -std=c++11 -Wall
clean:
rm *.o *~
This will create object files for each .cpp file and then use the object files to make Circles.
#use g++ for everything
CC= g++
# include debugging symbols in object files,
# and enable all warnings
FLAGS= -g -Wall -std=c++11
BSTHPP= BST.hpp BSTNode.hpp BSTIterator.hpp
all: main
bst: testBST.o $(BSTHPP)
$(CC) $(FLAGS) -o bst testBST.o $(BSTHPP)
main: main.o $(BSTHPP)
$(CC) $(FLAGS) -o main main.o $(BSTHPP)
main.o: $(BSTHPP)
$(CC) $(FLAGS) -c main.cpp
testBST.o: testBST.cpp
$(CC) $(FLAGS) -c testBST.cpp
clean:
$(RM) main bst *.o
I changed the BST.hpp file and then run make bst. But I debug for several times and find out firstly I need to make clean, then recompile. But why? Could anyone explain it to me?
It's the .o files that need to depend on the .hpp, not the executable (which should also not mention them in its recipe).
I recently started a small project in C++. I created a simply Makefile:
output: main.o google_api.o
g++ main.o google_api.o -o output
rm *.o
clear
./output
main.o: main.cpp
g++ -c main.cpp
test.o: google_api.cpp google_api.h
g++ -c google_api.cpp
And when I compile my code I get the next error -
non-aggregate type 'vector' cannot be initialized
with an initializer list
I am check for this issue and find that I need to add -std=c++11 support to my makefile to fix the problem. I add this command to the code:
g++ -std=c++11 main.o google_api.o -o output
But this is not make any change. I would love if someone can help me to fix this problem. Thanks
change this:
main.o: main.cpp
g++ -c main.cpp
to:
main.o: main.cpp
g++ -std=c++11 -c main.cpp
You may as well use something like this as basis for your Makefile:
CXX=g++
CXXFLAGS=-g -Wall -MMD -std=c++11
LDLIBS=-lm # list libs here
output: main.o google_api.o
clean:
$(RM) *.o *.d output
-include $(wildcard *.d)
There are also similar questions on stackoverflow: Makefile c++11 support
I currently have the following makefile (I am using an example of an online tutorial) which works however I have a few questions regarding this:
# *****************************************************
# Variables to control Makefile operation
CXX = g++
CXXFLAGS = -Wall -g
test: main.o car.o student.o house.o
$(CXX) $(CXXFLAGS) -o test main.o car.o student.o house.o
objcopy --only-keep-debug test test.debug
main.o: student.h house.h main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp
car.o: car.h
student.o: student.h car.h
house.o: house.h
clean:
rm -rf *.o test *.debug
Here is my understanding of what is going on here please correct me if I am wrong. When initially test target is called it looks for the first dependency main.o This could either be a file or a target. Since there is no file called main.o it will look for main.o as a target. Once main.o as a target is found it looks for dependencies student.h house.h main.cpp since these exist as a file make then executes the recipe (command) which is $(CXX) $(CXXFLAGS) -c main.cpp. Now here is the part that I dont understand. When the second dependency car.o turn comes up make looks for car.h and finds it but there is no command that tells it to generate the .o file. How is the .o file being generated here ?
make contains several implicit rules. That means that make has built-in knowledge about how to create a .o file from a .cpp file without you telling it explicitly how to do that.
From the documentation:
Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or
n.C with a recipe of the form ‘$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c’. We
encourage you to use the suffix ‘.cc’ for C++ source files instead of
‘.C’
You may think of this as make having a built-in rule that looks quite like:
%.o : %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
Read more about these implicit rules here and here.
There is a built in rule for generating an .o file from a .cpp file.
You have told it that is has an extra dependency of car.h, but not how to make car.o so it falls back on the built in rule, with car.h as an added dependency.
You could change
main.o: student.h house.h main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp
to
main.o: student.h house.h
and it would build it too using the built in rule. Its documented here.
You could also use a built in rule to make your test binary, were you not also running the objcopy command.
Instead of
test: main.o car.o student.o house.o
$(CXX) $(CXXFLAGS) -o test main.o car.o student.o house.o
You could just use
test: main.o car.o student.o house.o
Most make (and similar) programs pre-define implicit rules for things like converting a source file (with any of a number of common extensions) to object file (using their default extension).
Typically that'll be equivalent to something like this:
.c.o:
$(CC) $(CFLAGS) -o $*.o -c $*.c
.cc.o:
$(CXX) $(CXXFLAGS) -o $*.o -c $*.cc
...with more for other common extensions, so it'll not only know how to compile most typical extensions (.c, .cc, .cpp, .C, etc.) to .o files, but also implicitly pick up the content of some variable you can specify as the set of flags to pass to the compiler when it does so.
As for the details of these rules: a rule like .cc.o: is an implicit rule--it basically says "if you have a .cc file you can create a .o file from it using this rule". These get used as kind of a backstop--if you have an explicit rule telling how to create some specific .o file, make will use that by preference--but if there isn't an explicit rule, it can fall back on the implicit rule instead.
The $* is a built-in macro, that expands to the base name (without the extension) of the source file. There are a number of them for just the base name of the source ($*) and the full name of the source file ($<). There are a number of other automatic variables like this, but from what I've seen most people using them rarely enough that they have to look them up when they need to use them.
I tried to make a Makefile using files main.cpp, factorial.cpp, hello.cpp and function.h
On typing 'make' on Linux command window, it shows:
g++ -c -o hello main.o factorial.o hello.o
g++: main.o: linker input file unused because linking not done
g++: factorial.o: linker input file unused because linking not done
g++: hello.o: linker input file unused because linking not done
I am making the Makefile for first time. Please give suggestions what can be the problem?
The Makefile contains following code->
hello: main.o factorial.o hello.o
g++ -c -o hello main.o factorial.o hello.o
main.o: main.cpp
g++ -c -o main.o main.cpp
factorial.o: factorial.cpp
g++ -c -o factorial.o factorial.cpp
hello.o: hello.cpp
g++ -c -o hello.o hello.cpp
The individual file contents if you want to see are:
1) main.cpp
#include<iostream>
#include"functions.h"
using namespace std;
int main()
{
print_hello();
cout << endl;
cout << "The factorial of 5 is " << factorial(5) << endl;
return 0;
}
2) hello.cpp
#include<iostream>
#include "functions.h"
using namespace std;
void print_hello()
{
cout << "Hello World!";
}
3) factorial.cpp
#include "functions.h"
int factorial(int n)
{
if(n!=1)
{
return(n * factorial(n-1));
}
else return 1;
}
4) function.h
void print_hello();
int factorial(int n);
The -c parameter to g++ tells it not to link:
-c Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
You definitely don't want the -c here:
hello: main.o factorial.o hello.o
g++ -c -o hello main.o factorial.o hello.o
You could also use rules and patterns to make it more generic:
SRC_DIR = ./src
OBJ_DIR = ./bin/obj
BIN_DIR = ./build/bin
# List all the sources
SRCS = A.cpp B.cpp
# Define the rule to make object file from cpp
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
g++ -o $# $(INCLUDES) $(CPPFLAGS) -c $^
TARGET_BIN = $(BIN_DIR)/test
all : make_dirs $(TARGET_BIN)
$(TARGET_BIN) : $(SRCS:%.cpp=$(OBJ_DIR)/%.o)
g++ $(LDFLAGS) -o $# $^ $(LDLIBS)
make_dirs :
mkdir -p $(OBJ_DIR)
mkdir -p $(BIN_DIR)
With this approach you have several benefits:
Easy to use: you specify source files once, and you don't care about processing of each object file: the job is done by a single rule.
More maintainable: every time you need to change the compiler or linker options you do it in the single rule, not for each translation unit.
You have an error in that line:
g++ -c -o hello main.o factorial.o hello.o
man gcc says: ... the -c option says not to run the linker.
This option is used to produce objects files only. When it passed, gcc will not start linker to produce executable file or shared library.
As clear from all above answers, because of using -c in g++ -c -o hello main.o factorial.o hello.o, it is preventing from linking. After creating the object files from corresponding .cpp or .h etc files, these need to be linked. Without linking, as each file is a part of a complete program that can perform some task, nothing useful can be done as these file are dependent. So, we have to link these dependent parts to run our complete program.
One basic video tutorial for easy learning of making a Makefile in the two methods viz dependencies and pattern rules is here.
It takes example of method of dependencies and then introduce pattern rules as a better approach for making a long Makefile.
To know the difference between compilation and linking, this link can be useful.