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.
Related
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)
I am writing my first second makefile because I need to understand them before I can actually start my C++ project. Here's the files I'm trying to link:
/storage/emulated/0/cpptest/test.h
#ifndef TEST_H_DEF
#define TEST_H_DEF
class Test {
private:
int value;
public:
Test(int);
operator int();
Test operator + (Test);
};
#endif
/storage/emulated/0/cpptest/test.cpp
#include "test.h"
Test::Test(int new_value):
value(new_value) {}
Test::operator int() {
return value;
}
Test Test::operator + (Test other) {
return Test(value + int(other));
}
/storage/emulated/0/cpptest/main.cpp
#include <iostream>
#include "test.h"
int main() {
Test o1(12);
Test o2(18);
std::cout << int(o1) << '\n';
std::cout << int(o2) << '\n';
std::cout << int(o1 + o2) << std::endl;
}
And here's my attempt at a (maintainable) makefile:
CC = g++
default: test
#I'm actually using four spaces here on SO
test: main.o test.o
$(CC) -o test main.o test.o
#my issue starts here: what does main.o depends on? My guess is main.cpp only (which is really /storage/emulated...main.cpp)
main.o: main.cpp
$(CC) -o main.o /storage/emulated/0/cpptest/main.cpp
#same with test.o
test.o: test.cpp
$(CC) -o test.o /storage/emulated/0/cpptest/test.cpp
And then? Am I fine now? How do I handle the issue of test.h being updated without make knowing about it?
Also did I get the usage of .h and .cpp files right while writing my files?
gcc can generate dependencies for you. So rather than manually typing out what all dependencies your source files have (which will inevitably be wrong or incomplete), use the compiler:
default: test
.PHONY : default
compiler := g++
objects := main.o test.o
depends := $(objects:.o=.d)
# include the depends rules if they exist
-include $(depends)
# test depends on all the objects, compiled together
test : $(objects)
$(compiler) -o $# $^
# each object depends on its source file
# the recipe here will both compile the source file and generate its dependencies
%.o : %.cpp
$(compiler) -o $# -c $< -MP -MMD -MF $(#:.o=.d)
This will generate files for you named main.d and test.d which will contain makefile rules with the actual dependencies of main.cpp and test.cpp.
Whenever you're in doubt about the validity of your makefiles, it's always helpful to run make -pn and examine everything that's printed there. That will help make sure your dependencies are entirely the way they should be.
For example, the first time you compile, the *.d files won't exist, so the include $(depends) command will fail (silently because of -include), and this makefile creates a dependency graph that looks like:
You should read this as any node needs to have its recipes rerun if any of its children have been updated (I filled in default blue because it's a phony rule.). So main.o needs to be recompiled whenever main.cpp gets updated. Note that there is no dependency on test.h! This may seem like a mistake, but we have to recompile everything anyway, so we're not missing out. After we compile the first time, we'll have generated the *.d files and then we bring those into our include, and the new dependency graph looks like:
which is exactly what we want.
The dependency of test.h is for both test.cpp and main cpp:
CC = g++
default: test
test: main.o test.o
$(CC) -o test main.o test.o
main.o: main.cpp test.h
$(CC) -o main.o /storage/emulated/0/cpptest/main.cpp
test.o: test.cpp test.h
$(CC) -o test.o /storage/emulated/0/cpptest/test.cpp
The idea is that if something changes within test.h both test.o and main.o must be remade.
Let's say, compiling hello.c requires car.c and water.c.
But main.c requires hello.c.
When I say requires, I mean that the compiled output would differ if the things it requires is modified in any way.
So, if car.c or water.c is changed, then hello.c would need recompiling.
Then, would this be the correct Makefile?
main: main hello.o
gcc main.c hello.c -o main
hello.o: water.c, car.c
gcc water.c car.c -o hello.o
Otherwise, if it's not correct, can someone explain to me why it is wrong and give me an example?
Thank you!
Let's say, compiling hello.c requires car.c and water.c. But main.c requires hello.c.
This statement doesn't make a lot of sense. The only thing it could mean is that either these aren't C or C++ source files, rather some other language that uses these names confusingly, or they contain #include directives that include those other files.
In that latter case (which is rare, and a poor design), there's no need to specify the included files on the command line, since gcc will include them for you. You just need to specify the dependencies in the Makefile:
main: main.c hello.c car.c water.c
gcc -o main main.c
since main.c has #include "hello.c" and hello.c has #include "car.c" and #include "water.c", only the one compile gets everything.
If these are some other language, and you mean something completely different, its likely that gcc can't understand (or compile) them at all...
What you're doing is a little strange, but I guess not incorrect. Don't have a recursive dependency on main and compile hello.o as an object file.
main: main.c hello.o
gcc main.c hello.o -o main
hello.o: hello.c water.c car.c
gcc hello.c water.c car.c -c hello.o
I would re-write it as:
SRC := hello.c main.c water.c
OBJS := $(patsubt %.c,%.o,$(SRC))
main: $(OBJS)
$(CC) -o $# $^
This makefile works because there is an implicit rule for compiling C files. This will mean that when $(OBJS) is expanded to hello.o, main.o, and water.o, each of those .o files will be built by "$(CC) -o hello.o -c hello.c".
Note that if you use the GCC -c flag to only compile the file, but not link it, you will not need to be worried that hello.c relies on car.c and water.c.
EDIT:
Note that in your original makefile, the line "main: main hello.o" is incorrect. A target cannot depend on itself.
In general, with Make, you want to specify dependencies, but not the implementation of making those dependencies, if you can help it. It is much cleaner to say "I need this" versus "do these steps". In a lot of cases, Make is smart enough that if you say "I need this," it will "do the right thing."
In your makefile there are entities of the following type:
final executable program: main
compiled objects (relocatable ELFs linked into the main executable). I can see hello.o, but I cannot find water.o, car.o and main.o (since each *.c compilation unit is generally converted by the compiler to a *.o compiled object).
the source files (compilations units): main.c, hello.c, water.c and car.c. These are used as inputs by the compiler to generate the corresponding *.o files.
So, based on the above, the appropriate Makefile would look like this (tested):
main.o:
gcc -c main.c
hello.o:
gcc -c hello.c
water.o:
gcc -c water.c
car.o:
gcc -c car.c
main: hello.o water.o car.o main.o
gcc hello.o water.o car.o main.o -o main
The shortened versioned, using makefile text functions and automatic variables (tested):
%.o:
gcc -c $(addsuffix .c, $(basename $#))
main: hello.o water.o car.o main.o
gcc $^ -o main
Another approach (tested):
SRC := hello.c water.c car.c main.c
OBJ := $(addsuffix .o, $(basename $(SRC)))
main: $(OBJ)
gcc $^ -o main
I have made a Makefile for my CMSC 202 course project, 'Blackjack'. It does everything I need it to and it works perfectly. You may be asking why I posted here then, this is because I have no idea how it works and I didn't use any other resources but myself to create it.
Here is my Makefile code.
# Object files to either reference or create
OBJECTS = Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
# The executable file that will be created at the end
EXEC = Proj2.out
# The flags to use for compilation
FLAGS = -Wall
# The code compiler to use for compilation
CC = g++
# Perform action on all object files (May or may not exist)
all: $(OBJECTS)
$(CC) $(FLAGS) -o $(EXEC) $(OBJECTS)
Here is the terminal output when I call make in the terminal.
g++ -c -o Proj2.o Proj2.cpp
g++ -c -o Blackjack.o Blackjack.cpp
g++ -c -o Deck.o Deck.cpp
g++ -c -o Card.o Card.cpp
g++ -c -o Hand.o Hand.cpp
g++ -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Can anyone tell me how the .o files are being compiled? It does not look like they are being prompted to be compiled with that g++ -c -o $.o $.cpp command anywhere in the Makefile. Nor did I state to use any .cpp files.
Thank you in advance for your help.
Edit
Thanks to all your great help, this is now the terminal output I receive when using make.
g++ -Wall -c -o Proj2.o Proj2.cpp
g++ -Wall -c -o Blackjack.o Blackjack.cpp
g++ -Wall -c -o Deck.o Deck.cpp
g++ -Wall -c -o Card.o Card.cpp
g++ -Wall -c -o Hand.o Hand.cpp
g++ -Wall -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Thank you so much to all of you who have contributed.
Make has a set of implicit rules (see here for a reference). For instance
Compiling C++ programs
`n.o' is made automatically from `n.cc' or `n.C' with a command of the form
`$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)'.
Most make's will also use this rule for .cpp files.
When make sees there's a x.o requirement for one of your targets, it will try to see if it can generate x.o using implicit rules, and in your case find it can do it starting from a .cpp file.
This Makefile uses implicit rules which are a great way to reduce duplication.
By default the first target will be built, here all. It depends on a number
of object files listed in a variable $OBJECTS, e.g. Proj2.o who's
dependencies aren't listed in the Makefile. Now if make sees an input file in the current directory
with a matching name, e.g. Proj2.cpp it will try
to build Proj2.o from it (there are other implicit rules for sources in
other languages). Proj2.o would then be built by default with the command
$(CXX) $(CXXFLAGS) -c -o Proj2.o
where $(CXX) the name of the C++ compiler (g++ in your case).
The explicit build step for all assembles all the object files into the
target executable.
Looking at above build command you'll notice a small problem in your Makefile. Since the flags to the C++ compiler are given in a variable FLAGS and not the standard CXXFLAGS no warnings will be emitted when building the object files. Using the standard name would fix this (you do want warnings, maybe even more than -Wall gives you).
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