Search code examples
opengllinkerd

openGL program fails to link with LDC


I am trying to compile a simple program in D Language with ldc, but it seems that it can not link with openGL.

clang works fine:

clang `pkg-config --cflags --libs glu gl libglfw` triangle.c 

LDC info

LDC - the LLVM D compiler (trunk):
based on DMD v2.060 and LLVM 3.2svn
Default target: x86_64-apple-darwin12.2.1

and result of pkg-config

pkg-config --cflags --libs glu gl libglfw

-I/usr/local/include -I/opt/X11/include -L/usr/local/lib -L/opt/X11/lib -framework Cocoa -framework OpenGL -framework IOKit -lGLU -lGL -lglfw

CommandLine

$ ldc2 -L-lglfw -L-L/opt/X11/lib -L-lGL -L-lGLU -w triangle.d

Undefined symbols for architecture x86_64:
  "__D2gl10glVertex3fFfffZv", referenced from:
      __Dmain in triangle.o
  "__D2gl10glViewportFiiiiZv", referenced from:
      __Dmain in triangle.o
  "__D2gl12glClearColorFffffZv", referenced from:
      __Dmain in triangle.o
  "__D2gl12glMatrixModeFkZv", referenced from:
      __Dmain in triangle.o
  "__D2gl12glTranslatefFfffZv", referenced from:
      __Dmain in triangle.o
  "__D2gl14glLoadIdentityFZv", referenced from:
      __Dmain in triangle.o
  "__D2gl5glEndFZv", referenced from:
      __Dmain in triangle.o
  "__D2gl7glBeginFkZv", referenced from:
      __Dmain in triangle.o
  "__D2gl7glClearFkZv", referenced from:
      __Dmain in triangle.o
  "__D2gl9glColor3fFfffZv", referenced from:
      __Dmain in triangle.o
  "__D2gl9glRotatefFffffZv", referenced from:
      __Dmain in triangle.o
  "__D3glu14gluPerspectiveFddddZv", referenced from:
      __Dmain in triangle.o
  "__D3glu9gluLookAtFdddddddddZv", referenced from:
      __Dmain in triangle.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Error: /usr/bin/gcc failed with status: 1

Solution

  • How are you declaring the OpenGL functions? __D2gl10glVertex3fFfffZv is the symbol gl.glVertex3f, which is a D symbol in the module gl.

    The OpenGL functions in the libs have C linkage, so you need to use extern(C) when declaring them, e.g.

    extern(C) void glVertex3f(float, float, float);
    

    If you have all the declarations in a file then you can also use the {} notation:

    extern(C)
    {
        void glVertex3f(float, float, float);
        ...
    }
    

    When trying to fix linker errors, it can sometimes help to look at the symbols you are linking with. You can use the nm utility with grep to find how the symbol is mangled:

    % nm /System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib | grep glVertex3f
    0000000000003b13 T _glVertex3f
    0000000000003b2e T _glVertex3fv
    

    As you can see, the symbol is spelled _glVertex3f, not __D2gl10glVertex3fFfffZv, which is why it cannot be found. You can tell yours is a D symbol by the leading __D as well as all the extra mangling information (for example the fff at the end indicates the 3 float parameters). In general, the C symbols you find in most libraries are very simple, containing only a leading underscore following by the name.