Mokus
Mokus

Reputation: 10400

Undefined reference during compilation

I would like to write a make file, but I'm quit newbie. I have the main file where I include the l_mpc.h helper.h written by me, also I'm using the gnuplot, because of this I need the gnuplot_i.hpp.

This is my make file

CPPFLAGS=-I /usr/local/include/eigen3

dc_motor_main.out : dc_motor_main.o 
    g++ -o main.out dc_motor_main.o

dc_motor_main.o: l_mpc.o helper.o 
    g++ $(CPPFLAGS) -c dc_motor_main.cpp l_mpc.o helper.o 

gnuplot_i.o: gnuplot_i.hpp
    g++ $(CPPFLAGS) -c gnuplot_i.hpp 

l_mpc.o: l_mpc.cpp l_mpc.h
    g++ $(CPPFLAGS) -c l_mpc.cpp

helper.o: helper.cpp helper.h
    g++ $(CPPFLAGS) -c helper.cpp

clean:
    rm *.o dc_motor_main.out

and the output is the following:

g++ -I /usr/local/include/eigen3 -c l_mpc.cpp
g++ -I /usr/local/include/eigen3 -c helper.cpp
g++ -I /usr/local/include/eigen3 -c dc_motor_main.cpp l_mpc.o helper.o 
g++: warning: l_mpc.o: linker input file unused because linking not done
g++: warning: helper.o: linker input file unused because linking not done
g++ -o main.out dc_motor_main.o
dc_motor_main.o: In function `main':
dc_motor_main.cpp:(.text+0x3ab3): undefined reference to `SysMat::SysMat()'
dc_motor_main.cpp:(.text+0x40fa): undefined reference to `SysMat::calcMPCFi(int)'

The SysMat::SysMat() is in the l_mpc.h, Where do I make the mistake?

This is my header files: main.cpp

#include <iostream>
#include <Eigen/Dense>
#include <sys/time.h>

#include "gnuplot_i.hpp"
#include "l_mpc.h"
#include "helper.h"

#define DEBUG 1

int main( int argc, char* argv[])
{   ....

helper.h

#include <iostream>
#include <Eigen/Dense>
#include <sys/time.h>
#include "gnuplot_i.hpp"

using namespace Eigen;

double now();
void plot_x(MatrixXd, Gnuplot *);
void plot_x(MatrixXd, float, Gnuplot *);
void plot_xy(MatrixXd, MatrixXd,  Gnuplot *);
void plot_xy(MatrixXd, Gnuplot *);

template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}

l_mpc.h

#include <iostream>
#include <Eigen/Dense>
#include <sys/time.h>
#include "gnuplot_i.hpp"


using namespace Eigen;

class SysMat
{
    public:
        MatrixXd Fi;
        MatrixXd Ga;
        MatrixXd C;
        MatrixXd Er;
    private:    
        MatrixXd MPCFi;
        MatrixXd MPCGa;
        MatrixXd MPCGy;     
    public:
        SysMat(MatrixXd, MatrixXd, MatrixXd);
        SysMat();
        ~SysMat();
        void calcMPCFi(int);
        void calcMPCGa(int);
        void calcMPCGy(int, int);
        MatrixXd calcContSig(MatrixXd, MatrixXd, MatrixXd);
        MatrixXd calcError(MatrixXd, MatrixXd, MatrixXd);
};

Upvotes: 0

Views: 406

Answers (2)

john
john

Reputation: 8027

The mistake looks to be here

dc_motor_main.out : dc_motor_main.o 
    g++ -o main.out dc_motor_main.o

dc_motor_main.o: l_mpc.o helper.o 
    g++ $(CPPFLAGS) -c dc_motor_main.cpp l_mpc.o helper.o 

should be

main.out : dc_motor_main.o l_mpc.o helper.o 
    g++ -o main.out dc_motor_main.o l_mpc.o helper.o

dc_motor_main.o: l_mpc.o helper.o 
    g++ $(CPPFLAGS) -c dc_motor_main.cpp

assuming that you want your executable file to be called main.out.

When you use the g++ -c option you are compiling only. The final step without -c is called linking, that should link together all the *.o files you have created by compiling each *.cpp file.

As Olaf says in his answer there are various ways you can make this less repetitive, but what is above is the basic steps however you do it.

Upvotes: 3

Olaf Dietsche
Olaf Dietsche

Reputation: 74008

Make already knows how to build object files out of appropriate sources. So, most of the time you need only define the dependencies and you can simplify the Makefile to

CPPFLAGS=-I /usr/local/include/eigen3
LDFLAGS = # insert linker flags, if needed
LDLIBS = # insert needed libraries here

OBJS = \
dc_motor_main.o  \
gnuplot_i.o \
l_mpc.o \
helper.o \

dc_motor_main.out: $(OBJS)
    g++ $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)

gnuplot_i.o: gnuplot_i.hpp

l_mpc.o: l_mpc.h

helper.o: helper.h

clean:
    rm $(OBJS) dc_motor_main.out

Keep in mind, that the commands must be prefixed by a tab character. Don't insert spaces instead.

Upvotes: 1

Related Questions