g++ -I duplicating libraries

2019-08-30 07:43发布

I'm learning to program C++ in Linux, and I have the following problem:

I have 4 files: main.cpp, model.cpp, view.cpp and controller.cpp, each (except main) with their own header files. main.cpp includes model.h, view.h and controller.h, and view.h includes other libraries that are only relevant to it (necessary to run the graphic library). Those libraries are in different folders and have other dependencies on their own (that's why I don't want to move them). So, my makefile looks as follows:

model: model.cpp model.h
  g++ -c model.cpp

view: view.cpp view.h
  g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c view.cpp

controller: controller.cpp
  g++ -c controller.cpp

main: main.cpp
  g++ -c main.cpp

and also a line to link all the files together (I didn't added it because I'm writing this on my Mac and copying it from the screen of my Raspberry Pi).

My problem is that when I try to compile them, all of them work, except for main, it tells me the following:

In file included from main.cpp:6:0:
view.h:4:23: fatal error: VG/openvg.h: No such file or directory
compilation terminated.
make: *** [main] Error 1

From what I can understand, when I compile view with "make view", it can find the files included without problem, because it has the paths in which it must look, but since "make main" doesn't have those paths, it doesn't know where to look for openvg.h. The problem is that if I add the paths to main, it tells me that there's multiple definitions for what's inside the library... Any help?

3条回答
来,给爷笑一个
2楼-- · 2019-08-30 08:11

here are my files, the code seems to run fine if in main.cpp I include view.cpp instead of view.h, but I don't think that's what I'm supposed to be doing:

main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include "model.h"
#include "view.h"
#include "controller.h"

using namespace std;

int main() {
  int n;
  View view;
  view.initialize();
  view.drawBackground();
  view.show();
      std::cin >> n;
}

view.h:

#ifndef VIEW_H
#define VIEW_H

#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"

class View{
private:
    int width, height;

public:
    View();
    int getWidth();
    int getHeight();
        void drawBackground();
        void initialize();
        void show();
};

#endif

view.cpp

#include "view.h"

View::View(){
int width, height;
    VGfloat w2, h2, w;
}

int View::getWidth(){
return width;
}

int View::getHeight(){
return height;
}

void View::drawBackground(){

Background(0,0,0);
Stroke(255,255,255,1);
Fill(255,0,0,1.0);
Circle(width/2, height/2, 100);
}

void View::initialize(){
init(&width, &height);
Start(width, height);
}

void View::show(){
End();
}
查看更多
Rolldiameter
3楼-- · 2019-08-30 08:17

The #include VG/openvg.h is in /opt/vc/include and is included from view.h

When you make view you are including it from view.cpp which is compiled with -I/opt/vc/include

When you make main you are including it from main.cpp which is compiled without flags so it can't find the file.

You need to add the flags

main: main.cpp
        g++ -c -I/opt/vc/include main.cpp

You may need the other flags as well, depending on what view.h includes.

The multiple definitions are caused by $(OPENVGLIBDIR)/fontinfo.h

which contains

Fontinfo SansTypeface, SerifTypeface, MonoTypeface;

so if you include that file in more than one object file and link them (main.o and view.o in this case) you will get multiple definitions.

Change it to

extern Fontinfo SansTypeface, SerifTypeface, MonoTypeface;

I then got Background etc undefined as libshapes is a C library. To get round this I changed

#include "fontinfo.h"
#include "shapes.h"

in view.h to

extern "C" {
#include "fontinfo.h"
#include "shapes.h"
}

and it builds for me (with references to model and controller removed).

In your makefile, the view/model/controller/main targets are making the .o files so they should be .o too. When you make test when no .o exists, it is looking for the .o target. If there isn't one in your makefile it will use the default which is a straight g++ -c.

Your make file should be like this:

test: model.o view.o controller.o main.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)/oglinit.o
    g++ -o test view.o main.o model.o controller.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)oglinit.o -L/opt/vc/lib -L/opt/vc/include -lGLES -ljpeg

view.o: view.cpp
    g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c view.cpp

main.o: main.cpp
    g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c main.cpp view.cpp

model.o: model.cpp
    g++ -c model.cpp

controller.o: controller.cpp
    g++ -c controller.cpp
查看更多
祖国的老花朵
4楼-- · 2019-08-30 08:18

Thanks A LOT for your help man! I've been fighting with this for the last couple of days (that's what I get for getting used to automatic compiling/linking). It's somewhat based on that example. I can make it run if I make each object by itself and then link them all together like this:

test: model.o view.o controller.o main.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)/oglinit.o
    g++ -o test view.o main.o model.o controller.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)oglinit.o -L/opt/vc/lib -L/opt/vc/include -lGLES -ljpeg

view: view.cpp
    g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c view.cpp

main: main.cpp
    g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c main.cpp view.cpp

model: model.cpp
    g++ -c model.cpp

controller: controller.cpp
    g++ -c controller.cpp

if I do "make view" "make main" and then "make test" everything goes fine, but if I try "make test" without any object created prior to that I get fatal error: VG/openvg.h: No such file or directory when it's trying to compile view.cpp

查看更多
登录 后发表回答