32-bit & 64-bit OpenGL apps on 64-bit ubuntu linux

I have been developing a multiplatform (Linux and Windoze) 3D simulation/graphics/game engine for some time, and now need to be able to compile both 32-bit and 64-bit versions of the engine on 64-bit ubuntu linux, assuming that is possible.

I am somewhat confused about how the appropriate versions of include files, library files, and drivers all get matched properly. For example, when a 32-bit OpenGL application is running on a 64-bit Linux OS, where do 32-bit function calls cease and 64-bit function calls begin (to the driver, presumably)?

How do I make sure my programs include the appropriate include files (32-bit versus 64-bit)?

How do I make sure my programs link to the appropriate OpenGL and XWindows libraries (32-bit versus 64-bit)?

When I installed 64-bit ubuntu, it did not seem to install some of the OpenGL or X11 include files and library files. Do I need to explicitly install the nVidia drivers to make these install? Since the ubuntu package installation process appears to have installed the nvidia driver correctly (glxgears is fast), can I simply install these files manually (with the --extract-only option in the nvidia driver, then copy to the appropriate places)? This appears to save me from having to perform some kind of complex compilation process of one or more of the driver components.

If anyone can give me an overall description of the pieces of this puzzle, and where the 32-bit and 64-bit mismatch is taken care of, I’d greatly appreciate that. I hate not understanding what’s going on around me. I cannot get my programs to compile properly on 64-bit ubuntu linux (either as 32-bit or 64-bit programs). As 32-bit programs CodeBlocks compilation says it can’t find lX11 (during the link process, obviously). I’m not sure what makes CodeBlocks link in the appropriate libraries (32-bit versus 64-bit). I have -m32 and -m64 switches to the compiler and linker, hoping that tells them my intention, but who knows what else it might need (or whether my computer even has both 32-bit and 64-bit sets of every library my code requires (which is only rt, GL, X11 plus the standard C libraries at the moment).

Thanks for any help you can give!

I have a machine with Ubuntu 9.04 x86_64.

/usr/include/GL/gl.h comes from package nvidia-glx-180-dev

I don’t think there is a difference for the header files between 32 and 64 bit.

Regarding the libraries, if you look at /usr, you’ll see that there are lib64 and lib32 directories (lib64 is a symlink to lib).

A way to figure out what libraries are actually used is with ldd.

$ ldd which glxgears

gives me:

linux-vdso.so.1 =>  (0x00007fff0bfff000)
libGL.so.1 => /usr/lib/libGL.so.1 (0x00007f9703a3f000)
libm.so.6 => /lib/libm.so.6 (0x00007f97037ba000)
libc.so.6 => /lib/libc.so.6 (0x00007f9703448000)
libX11.so.6 => /usr/lib/libX11.so.6 (0x00007f9703141000)
libGLcore.so.1 => /usr/lib/libGLcore.so.1 (0x00007f9701e57000)
libnvidia-tls.so.1 => /usr/lib/tls/libnvidia-tls.so.1 (0x00007f9703d29000)
libXext.so.6 => /usr/lib/libXext.so.6 (0x00007f9701c45000)
libdl.so.2 => /lib/libdl.so.2 (0x00007f9701a41000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9703c31000)
libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007f9701825000)
libXau.so.6 => /usr/lib/libXau.so.6 (0x00007f9701622000)
libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007f970141d000)

Definitely. We do.

overlay’s got you covered on most things, but some of what he says isn’t completely standard across Linux distributions.

I think universally on 64-bit Linux, 64-bit libs go under …/lib64 instead of …/lib. e.g. /usr/lib64. So if you’re driving the linker directly, you’d -L/usr/lib64 -L/usr/local/lib64, etc. to get the 64-bit libs.

However, on SuSE at least, 32-bit libs go in …/lib as they always have for 32-bit Linux. 64-bit systems may be installed with or without 32-bit libs as well, so you can have a dev box that supports both for instance.

And as he said, the headers aren’t 32-bit or 64-bit specific, they’re generic, so nothing needs changing there.

As far as the libs go, you can simplify your life by just letting the compiler (gcc) link the appropriate libs for you. How? Well, if you just run “gcc” to compile and Link, it’ll compile/link libs for the version of Linux you’re running (32-bit on 32-bit Linux kernel, or 64-bit on 64-bit Linux kernel). And if/when you want to cross-compile a 32-bit binary on 64-bit Linux, you basically just add an “-m32” to the gcc (or g++ for C++ apps) command line: e.g. gcc -m32 … And it just links the right libs transparently.

If you use cmake or autotools, then this can be abstracted even further but trying to avoid overloading you. Try a compiling/cross-compiling a simple one-source-file program from the command line to get a feel and branch out/ask questions from there.

To tell what kind of executable/object file/etc. you’ve got, use “file”. e.g. “file myexec”. You’ll see something like one of the below:

  • myexec: ELF 64-bit LSB executable …
  • myexec: ELF 32-bit LSB executable …

If you want to see what specific dynamic libs an executable or shared library would link with if you ran it, use ldd. e.g. “ldd myexec”.

The library it’s specifically complaining it can’t find is a X/Windows system shared library file called libX11.so. If you’re compiling a 32-bit executable, then this should live in /usr/lib32/libX11.so or /usr/lib/libX11.so, depending on your distro (I don’t think any distros stuff this in /usr/X11*/lib anymore…)

This specific filename is typically a symbolic link to the actual library name with a version number at the end (e.g. libX11.so.1), so first look for libX11.so* and if it already exists, just create the symlink. e.g.:

cd /usr/lib
ln -s libX11.so.6 libX11.so

and try another link. If there’s no libX11.so* there at all, then you’ll need to install the 32-bit Xlib libraries package, whatever it’s called on ubuntu. Here on SuSE 11.1 64-bit, it’s called: xorg-x11-libX11-32bit.

Thanks for the great replies from both of you! I am still trying to digest some of your information. First off, let me post the output of “ldd /usr/bin/glxgears” on my system in case it tells you something important.

linux-vdso.so.1 => (0x00007fff94bfe000)
libGL.so.1 => /usr/lib/libGL.so.1 (0x00007fdb8c6d6000)
libm.so.6 => /lib/libm.so.6 (0x00007fdb8c451000)
libc.so.6 => /lib/libc.so.6 (0x00007fdb8c0df000)
libX11.so.6 => /usr/lib/libX11.so.6 (0x00007fdb8bdd8000)
libGLcore.so.1 => /usr/lib/libGLcore.so.1 (0x00007fdb8aaee000)
libnvidia-tls.so.1 => /usr/lib/tls/libnvidia-tls.so.1 (0x00007fdb8c9c9000)
libXext.so.6 => /usr/lib/libXext.so.6 (0x00007fdb8a8dc000)
libdl.so.2 => /lib/libdl.so.2 (0x00007fdb8a6d8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fdb8c8c8000)
libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007fdb8a4bc000)
libXau.so.6 => /usr/lib/libXau.so.6 (0x00007fdb8a2b9000)
libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007fdb8a0b4000)

Some addresses are different (not surprising), but the set of files appears to be the same… so we’re on the same page.

It makes sense they’d have only one set of include files for both 32-bit and 64-bit — that’s what I do too via conditional includes (and by me defining either CPU32 or CPU64). However, if those header files contain any conditional includes, I’m not sure what names they might adopt to specify 32-bit versus 64-bit. I don’t see off hand how -m32 or -m64 on the compile or link lines can selectively include parts of include files.

ubuntu64 9.04 does indeed have /usr/lib32 and /usr/lib64 directories, with /usr/lib64 linked to /usr/lib on this 64-bit OS.

You ask whether I “drive the linker directly”. I’m not sure how to answer that question. The CodeBlocks IDE requires we fill in project settings for each project, including the following (this set is for the build-option we call “linux32_debug”):

compiler settings
compiler flags (the following are checked)

produce debugging symbols [-g]
in C mode, support all ISO C90 programs (in C++ mode, remove GNU extensions that conflict with ISO C++) [-ansi]
enable all compiler warnings (overrides every other setting) [-Wall]
AMD Athlon64 (x86-64 instruction set) [-march=athlon64]

NOTE: They do not have any Phenom or Phenom2 switches, but hopefully that doesn’t matter.

other options

-O0 (-O2 or more aggressive on release builds)
-m32 (-m64 on 64-bit builds)


CPU32 (CPU64 on 64-bit builds)
LINUX (versus WINDOZE on win32 builds)
DEBUG (versus RELEASE on release builds)

linker settings
link libraries


other linker options

-m32 (not sure this is necessary, but we have this entered for sake of our ASM files)

search directories


That’s pretty much everything, I think. The main point is, we do not specify any directories for standard/system C function libraries (not for include .h files and not for static/shared libraries either). We didn’t need these on ubuntu32 8.04 which was our previous development linux platform (winxp64 is our windoze development platform).

I assume we need not add the following entries: (-L/usr/lib64 -L/usr/local/lib64), because we specify the “rt”, “GL”, “X11” link libraries, which presumably get searched for in “/usr/lib/” by default). Oh wait! That’s wrong, isn’t it? Since we want to develop (and test) both 32-bit and 64-bit versions of our application on our current ubunbu64 OS, we probably DO need to explicitly specify explicit “/usr/lib32” and “/usr/lib64” linker search directories in the 32-bit and 64-bit build specifications, huh? Otherwise we’d always link to the 64-bit libraries via the presumable default “/usr/lib”. Related question: If we do enter those search directories, will they always be searched BEFORE the default “/usr/lib”? If not, we need to disable those default search paths!

Oh no, wait. You address this. You are saying the -m32 or -m64 option to the compiler will be passed to the linker to force the linker to link our executable to static/shared libraries in “/usr/lib32” or “/usr/lib64”. Very convenient!

I am not familiar with cmake or autotools, because I prefer to develop in IDEs like CodeBlocks and VisualStudio. I know that’s a bad habit in many ways, but ever since I created a compiler/debugger/IDE in 1988… I’ve acquired that nasty habit for software development. Bad, bad boy!

I am still getting an error message from ld (the linker, I presume) “can’t find -lX11”. That probably means the 32-bit libraries for X11 are not installed. For some strange reason I don’t see separate libx11 files listed in the synaptic IDE. What is does show installed already is “libx11-data”, “libx11-dev” and “libx11-6”. None say “64-bit” or “32-bit” so I assume these are 64-bit versions. How do I find and install the 32-bit packages in a way that absolutely, positively cannot accidentally overwrite my default 64-bit libraries? I also wonder why the synaptic package manager IDE doesn’t even list them. BTW, the installed versions are shown as “2:”.

We installed package ai32-libs, and that seems to solve the -lX11 error. Unfortunately, now we get the following error:

ld cannot find -lstdc++

My wild guess is, installing “build-essentials” only installs the 64-bit versions of whatever is part of that package, but does not install the 32-bit versions. I don’t find a separate 32-bit stdc++ or libstdc++ listed in the synaptic package manager list of “all available applications”. In fact, all I see listed with a name like that is libstdc++6-4.3-doc (which is installed).

So, how do I stop the above error from appearing when trying to compile a 32-bit executable on 64-bit ubuntu 9.04? Thanks.

You’ve probably already figured this out, but the library it’s missing is libstdc++.so. Here on 64-bit SuSE the package base names are fairly intuitive:

> rpm -qf /usr/lib64/libstdc++.so.6
> rpm -qf /usr/lib/libstdc++.so.6

So look for a 32-bit package in your package manager tool that has stdc++, gcc, or something in the package name.

cd /usr/lib32
ls -la libst*


lrwxrwxrwx 1 root root 18 2009-06-04 19:41 libstdc++.so.5 -> libstdc++.so.5.0.7
-rw-r–r-- 1 root root 737192 2008-05-09 23:18 libstdc++.so.5.0.7
lrwxrwxrwx 1 root root 19 2009-06-04 19:41 libstdc++.so.6 -> libstdc++.so.6.0.10
-rw-r–r-- 1 root root 950424 2009-03-16 18:03 libstdc++.so.6.0.10

To me, that indicates the “stdc++” library is installed in the correct path. I assume “stdc++” and “libstdc++” refer to the same package, right?

I’m at a loss. This is one of those problems that will probably appear obvious — in retrospect. Unfortunately, I’m not there yet.

Ah! Do this (as root):

cd /usr/lib32
ln -s libstdc++.so.6 libstdc++.so

That’ll do it. Then retry that compile you were doing that couldn’t find stdc++.

To me, that indicates the “stdc++” library is installed in the correct path.

Yep. The guy the cooked the package just goofed and forgot to include the libstdc++.so symlink in it. When you try to link a lib X, it goes looking for a libX.so.

I assume “stdc++” and “libstdc++” refer to the same package, right?

Same library, yes.

Ah! Do this (as root):

cd /usr/lib32
ln -s libstdc++.so.6 libstdc++.so

That’ll do it. Then retry that compile you were doing that couldn’t find stdc++.
Yup, that did it. I should have suspected that myself. Presumably most applications don’t link against a specific version, and therefore expect the library without the version suffix.

Yikes! I just looked in the /usr/lib64 directory, and the “libstdc++.so” symbolic link is missing from that directory too. I better add it before I forget! Is this “oversight” something that somebody should be informed of (I have no idea what package this library is part of)? Or is everyone else less dense than me?


Good deal. At least some applications don’t link against a specific version, but it depends on the method you use to link. The simplest is to just use the c++ compiler to link (e.g. “g++ -o exec … -lstuff1 -lstuff2 …”) and in that case yeah, it just goes looking for the .so (e.g. libstuff1.so, libstuff2.so, etc.)

Yikes! I just looked in the /usr/lib64 directory, and the “libstdc++.so” symbolic link is missing from that directory too. I better add it before I forget! Is this “oversight” something that somebody should be informed of

No, that’s OK. Mine doesn’t either. Apparently when g++ links it in automagically, it goes and finds the library name with the version in it.

(I have no idea what package this library is part of)?

I happen to know, but it’s not something you really need to know. It contains a lot of the C++ standard library stuff (try nm -D /usr/lib64/libstdc++.so.6 | grep " T ").