Jigyasa
Jigyasa

Reputation: 186

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);

Upvotes: 5

Views: 10865

Answers (4)

Jigyasa
Jigyasa

Reputation: 186

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.

Upvotes: 2

nogard
nogard

Reputation: 9716

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.

Upvotes: 5

loentar
loentar

Reputation: 5249

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.

Upvotes: 3

David Schwartz
David Schwartz

Reputation: 182837

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

Upvotes: 7

Related Questions