using .o files in makefile - c++

I've just learn something about makefile and here is my first question for it.I have main.cpp hello.cpp factorial.cpp and functions.h files
all: hello
hello: main.o factorial.o hello.o
g++ main.o factorial.o hello.o -o hello
main.o: main.cpp
g++ -c main.cpp
factorial.o: factorial.cpp
g++ -c factorial.cpp
hello.o: hello.cpp
g++ -c hello.cpp
clean:
rm -rf *o hello
In the code above, why files have an extention .o ? shouldnt be .cpp or what is the differences between using .cpp and .o

Building a C++ program is a two-stage process. First, you compile each .cpp file into a .o object file. Compiling converts the source code into machine code but doesn't resolve function calls from other source files (since they haven't been compiled yet).
main.o: main.cpp
g++ -c main.cpp
factorial.o: factorial.cpp
g++ -c factorial.cpp
hello.o: hello.cpp
g++ -c hello.cpp
Second, you link the object files together to create an executable. Linking resolves the external references in each object file.
hello: main.o factorial.o hello.o
g++ main.o factorial.o hello.o -o hello
By the way, there is a typo in the clean target. *o should be *.o.
clean:
rm -rf *.o hello

.o denote "object-files", these are files compiled from source but not yet linked into an executable or a library.
In your make-file, i.e.
main.o : main.cpp
says that main.o will be created from main.cpp using g++ -c main.cpp.
Eventually, all files with .o will create the executable hello as stated in
hello: main.o factorial.o hello.o
g++ main.o factorial.o hello.o -o hello

Related

Why do I write my .h file in the makefile if I never use it with g++?

# I understand this, it runs last as Term.o and main.o have to be created
main: Term.o main.o
g++ Term.o main.o -o run
# Why use Term.h here?
Term.o: Term.cpp Term.h
g++ -c Term.cpp
# and here?
main.o: main.cpp Term.h
g++ -c main.cpp
clean:
rm *.o
I am not using Term.h when I run g++ anyway, so is there really a purpose for having them there? Though it is needed as main.cpp includes Term.h

Makefile Creation Difficulty

I had to merge two codes (TestOne.cpp + TestTwo.cpp), one of them already has its makefile (TestOne.cpp), but the other has only .h included, each of these .h has no cpp, all the code is on the .h (TestTwo.cpp)
for the makefile it's like this , and it work:
CC = g++
CFLAGS = -std=c++11
test: main.o hung.o
$(CC) -o test main.o hung.o
hung.o: Hungarian.cpp Hungarian.h
$(CC) -c Hungarian.cpp -o hung.o
main.o: testMain.cpp Hungarian.h
$(CC) $(CFLAGS) -c testMain.cpp -o main.o
clean:
-rm main.o hung.o
and the other one (TestTwo.cpp) it's also work by compiling like that :
g++ TestTwo.cpp -o test `pkg-config opencv --libs`
I have to create a new makefile using the first and introducing the seconde commande g++ ... how should i do ?

This makefile only creates .o files

I'm trying to practice using Makefiles for a very simple program. The program files are:
main.cpp
other.cpp
other.h
I want the final executable to be Prog.
What happens when I run this is I get a main.o and other.o but no Prog.
What am I missing here?
## file Makefile
CXXOBJECTS= %.o
CXX= g++
CXXSOURCES= main.cpp other.cpp
CXXFLAGS= -std=c++11 -O2
Prog : main.o other.o
main.o : main.cpp
other.o : other.cpp other.h
## eof Makefile
You're almost there. You have the following:
Prog: main.o other.o ## these are your dependencies
g++ main.o other.o -o Prog
This should give you an executable called Prog. Though actually, a better makefile would be this:
CXXOBJECTS= %.o
CXX= g++
CXXSOURCES= main.cpp other.cpp
CXXFLAGS= -std=c++11 -O2
Prog: main.o other.o ## these are your dependencies
CXX main.o other.o -o Prog
main.o : main.cpp
CXX CXXFLAGS -c main.cpp
other.o : other.cpp
CXX CXXFLAGS -c other.cpp
Actually, you can make it even better, but I don't remember the syntactic sugar of makefiles off the top of my head (IDE's :P)

Linking not done in Makefile

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.

Problem with makefile making .gch files instead of.o files

So, I'm making a program to test the efficiency of certain data structures. I have all the .h files and I made a very terrible makefile that probably is wrong, although it seems to work up to a point. Instead of making .o files it makes .gch files, so when it tries to acces all the .o files they are not found. This is my makefile
prog1: main.o dsexceptions.o BinarySearchTree.o SplayTree.o RedBlackTree.o AvlTree.o
g++ -Wall -g -o prog1 main.o dsexceptions.h.gch BinarySearchTree.h.gch SplayTree.h.gch RedBlackTree.h.gch AvlTree.h.gch
main.o: main.cpp AvlTree.h RedBlackTree.h SplayTree.h BinarySearchTree.h dsexceptions.h
g++ -Wall -g -c main.cpp
#shape.o: shape.cpp shape.h grid.h
# g++ -Wall -g -c shape.cpp
dsexceptions.o: dsexceptions.h
g++ -Wall -g -c dsexceptions.h
BinarySearchTree.o: BinarySearchTree.h dsexceptions.h
g++ -Wall -g -c BinarySearchTree.h
SplayTree.o: SplayTree.h dsexceptions.h
g++ -Wall -g -c SplayTree.h
RedBlackTree.o: RedBlackTree.h dsexceptions.h
g++ -Wall -g -c RedBlackTree.h
AvlTree.o: AvlTree.h dsexceptions.h
g++ -Wall -g -c AvlTree.h
clean:
rm -f main main.exe main.o dsexceptions.o BinarySearchTree.o SplayTree.o RedBlackTree.o AvlTree.o *.gch
You don't want to feed your .h files to the compiler. Only compile the .cpp file, which should include your .h files. (The .gch files are precompiled headers.) You don't need .o files for your headers, just #include them in your .cpp file.
prog1: main.o
g++ -Wall -g -o prog1 main.o
main.o: main.cpp AvlTree.h RedBlackTree.h SplayTree.h BinarySearchTree.h dsexceptions.h
g++ -Wall -g -c main.cpp
clean:
rm -f prog1 main.o
You already have the solution from bstpierre, but just for fun here's my version of your makefile:
CC = g++ -Wall -g -o $#
MODULE = AvlTree BinarySearchTree RedBlackTree SplayTree
OBJECTS = $(addsuffix .o,$(MODULES))
prog1: main.o dsexceptions.o $(OBJECTS)
$(CC) $^
main.o: $(addsuffix .h,$(MODULES))
$(OBJECTS) main.o : %.cpp %.h dsexceptions.h
$(CC) -c $&lt
clean:
rm -f main main.exe *.o *.gch
And just for good measure, here is my SConstruct, because SCons's so much better :)
Program('main.cpp') # Yeah, it's that simple :)
You can look at SCons here.