6

I wrote a program on Ubuntu 11.04 that uses freeglut. It worked fine. Then I got another computer and tried to run the program on a fresh install of Ubuntu 11.04. Doesn't work. So I installed

sudo apt-get install freeglut3 freeglut3-dev libglew1.5 libglew1.5-dev libglu1-mesa libglu1-mesa-dev libgl1-mesa-glx libgl1-mesa-dev mesa-common-dev gcc

and tried to run the program, which imports



    #include <GL/freeglut.h>
    #include <GL/gl.h>
    #include <GL/glu.h>

using the command

g++ -lGL -lGLU -lglut Driver.cpp -o a

However the linker or whatever spits out like 200 errors of the form:



    Driver.cpp:(.text+0x3c6b): undefined reference to `glutSolidSphere'
    Driver.cpp:(.text+0x3c75): undefined reference to `glEnable'
    Driver.cpp:(.text+0x3c9a): undefined reference to `glColor4f'
    Driver.cpp:(.text+0x3cb5): undefined reference to `glRotatef'
    Driver.cpp:(.text+0x3d02): undefined reference to `glutSolidSphere'
    Driver.cpp:(.text+0x3d07): undefined reference to `glutSwapBuffers'

What is the cause of the problem?

comp sci balla
  • 823
  • 2
  • 13
  • 29
  • 1
    Why your source file is named .cpp if you compile with gcc? If it is C++, you must compile with g++, if it is C, it must be called something.c . – lvella Apr 03 '12 at 20:32
  • Typo in the posting. I was using g++ – comp sci balla Apr 03 '12 at 20:34
  • What is this Driver.cpp? Are you including it from program.cpp? – lvella Apr 03 '12 at 20:35
  • 4
    Try putting the libraries _after_ your source file in your compile. – Mat Apr 03 '12 at 20:36
  • Another typo in the posting. Keen eye. – comp sci balla Apr 03 '12 at 20:37
  • @Mat +1, on Linux it's needed for some reason (on non-Linux [iOS, Mac, even AVR] it works... *sigh GCC*), and you always have to make sure that your C functions are declared `extern "C"` or C++ name mangling will break things. –  Apr 03 '12 at 20:40
  • @Mat. That worked. Would you put that as an answer so I can mark it as best answer – comp sci balla Apr 03 '12 at 20:41
  • @H2CO3: there's a reason why the behavior might appear inconsistent - this is very related to the linker, and different platforms have different linker behaviors/requirements (like the fat binaries/libraries things I think exist on Mac). There's also the `--as-needed` thing that comes in the way... – Mat Apr 03 '12 at 20:56
  • @Mat yes, I know that it's a matter of platform, but even then... I'd expect a good compiler to work out-of-the-box. –  Apr 04 '12 at 04:58

1 Answers1

16

The order in which you specify the objects you want to link to (including static and dynamic libraries) can matter.

Try with:

g++ Driver.cpp -lGL -lGLU -lglut  -o a

(Not sure about the order of the libs, but that looks ok.)

The idea when you build your command line is that if a requires a symbol from b, b must appear after a in the command line.

The link order problem happens (or not) with GCC/ld for shared libraries depending on (most likely among other things - I'm no expert here) whether the --as-needed link flag is set or not. (See for instance the before-last item in Gentoo's as-needed transition guide.)
The linking process eliminates un-needed symbols ASAP when --as-needed is active, which causes problems if the link order is not "correct". This is done to reduce the number of un-necessary dependencies present in final executables.
This doesn't happen (or less so) if --as-needed is not active - all symbols are kept in that case, and link order doesn't matter as much (more or less - again, I'm no expert.)

Since different distributions use different defaults for that flag, the behavior of GCC might seem inconsistent, but that's just an impression.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • That is usually an issue with statically linked libraries. I don't know what could have caused the problem with shared libraries, which are the case. – lvella Apr 03 '12 at 20:47