Binding not done in makefile

I tried to create a Makefile using the main.cpp, factorial.cpp, hello.cpp and function.h files. Typing "make" in the Linux command prompt 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 doing a makefile for the first time. Please give advice, what could be the problem? The Makefile contains the 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 contents of a single file, if you want to see it: 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); 
+4
source share
4 answers

The -c for g++ indicates that it does not bind:

-c Compile or compile source files, but do not link them. The linking step simply fails. The end result is presented as an object file for each source file.

You definitely don't want -c here:

 hello: main.o factorial.o hello.o g++ -c -o hello main.o factorial.o hello.o 
+7
source

You can also use rules and patterns to make it more general:

 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 advantages:

  • Easy to use: you specify the source files once, and you do not care about processing each object file: the task is performed according to one rule.

  • Additional support: every time you need to change the compiler or linker settings, you do this in one rule, and not for each translation unit.

+5
source

There is an error in this line:

  g++ -c -o hello main.o factorial.o hello.o 

man gcc says: ... the -c option says not to run the linker.

This parameter is used only for creating object files. When it passes, gcc will not start the linker to create an executable or shared library.

+3
source

As you can see from all of the above answers, due to the use of -c in g++ -c -o hello main.o factorial.o hello.o , this prevents binding. After creating the object files from the corresponding .cpp or .h etc files, you need to link them. Without binding, since each file is part of a complete program that can perform some task, nothing useful can be done, since this file depends. So, we need to link these dependent parts in order to run our full program.

One basic video tutorial to easily learn how to create a Makefile in two methods — dependencies and templates — is here . It takes an example of the dependency method and then introduces the template rules as the best approach for creating a long Makefile.


To find out the difference between compilation and binding, this link may be useful.

+2
source

Source: https://habr.com/ru/post/1496503/


All Articles