After recently using a new Ubuntu installation (was 11.04, is now 12.04), my project seems to fail linking correctly. I try to link to the API of LuxRender, an open-source rendering library. My code is written in C++ and compiled using g++.
I've already spent a lot of time on this problem and encountered a few solutions to problems with similar symptoms. However, I did not find a solution yet so I came here to ask for help.
The sample code, testmain.cc:
#include <lux_api.h>
int main (int argc, char* argv[]) {
lux_instance* lux = CreateLuxInstance("Test");
DestroyLuxInstance(lux);
return 0;
}
The problem
$ g++ -c -o testmain.o testmain.cc -Wall -g -pedantic -I/home/taz/lux/lux-build/lux/cpp_api -I/home/taz/lux/lux-build/lux/core -I/home/taz/lux/lux-build/lux/core/queryable
$ g++ -o testmain testmain.o -llux
testmain.o: In function `main':
/home/taz/Documents/msc/test/testmain.cc:4: undefined reference to `CreateLuxInstance'
/home/taz/Documents/msc/test/testmain.cc:5: undefined reference to `DestroyLuxInstance'
collect2: ld returned 1 exit status
Firstly, note that while other people have linking problems since Ubuntu 11.10, the link order is correct (-llux
after testmain.o
) so that's not the problem.
Secondly, the CreateLuxInstance and DestroyLuxInstance functions are exported using C-style naming (with extern "C"
) in lux_api.h. I include the header file where this happens so the compiler should be aware of it, right? (Checked the pre-processor output using g++ -E
.) The functions do correctly appear in the library so they should be available to the linker:
$ nm -s /usr/local/lib/liblux.so | grep LuxInstance
000000000008c440 t CreateLuxInstance
000000000008c4d0 t DestroyLuxInstance
Thirdly, I have compiled (and after upgrading, recompiled) this library from source using the maintainer's cmake files. But even when I grab a compiled version from their site, I get the same problems. In both cases, the library matches the included header(s).
Lastly, I know that the correct library file gets used by passing -Wl,--verbose
to see which library files the linker actually uses.
What am I missing here?
Some versions:
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.22
Copyright 2011 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ uname -a
Linux linuxtaz 3.2.0-24-generic #37-Ubuntu SMP Wed Apr 25 08:43:22 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -irc
Distributor ID: Ubuntu
Release: 12.04
Codename: precise
Edit:
The problem turned out to be in de LuxRender distribution when building luxShared, the shared library to be used with the Lux api. Why this problem turned up after an Ubuntu upgrade is still a mystery for me, but for others struggling with this problem, here is my "solution":
The distribution I wanted to build is v1.0-RC1. In the file cpp_api/export_defs.h
I added the following lines:
#ifdef LUX_DLL
#define CPP_API __attribute__ ((visibility ("default")))
#endif
The compiler complains about CPP_API being declared doubly but I ignored that. Now the library builds with publicly available API functions:
$ nm ./liblux.so | grep LuxInstance
000000000008c6c0 T CreateLuxInstance
000000000008c750 T DestroyLuxInstance