5
votes

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);
4
Besides the fix shown in the answers, you should add the dependency to functions.h to your rules.juanchopanza
But it is working fine without it. Is there any specific reason to add dependency to functions.h? Because the place where I read this code, they not use dependency for functions.hJigyasa
It isn't really working fine. If you change functions.h and run make hello, you would want all the .o files to be re-built first.juanchopanza

4 Answers

7
votes

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
5
votes

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.

3
votes

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.

2
votes

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.