I can't get gcc in Ubuntu 11.10 to properly link in the google perftools -lprofiler.
The problem seems to be that the linker discards libraries which are not directly used in a program.
An example will help.
Let's call this main.cpp:
#include <math.h>
int main()
{
double value;
for (int i=0; i < 1000000; i++)
{
for (int j=0; j < 1000; j++)
value = sqrt(100.9);
}
return 0;
}
Compile using:
g++ -c main.cpp -o main.o
g++ main.o -o main -lm -lprofiler
Check the executable using ldd ./main:
linux-vdso.so.1 => (0x00007fff5a9ff000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f32bc1c9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f32bc593000)
Normally, I would run:
CPUPROFILE=/tmp/profile ./main
to produce profile output. But since the profile library is not linked in no profile output is generated.
I've made sure the profiler library is in my search path, and have tried directly linking against the shared library and static library.
The above test works fine on Ubuntu 10.04, Ubuntu 10.10, Ubuntu 11.04, SUSE 12.1, and Fedora 16.
Also, once I include function calls that use the profiler (such as ProfilerStart() and ProfilerStop()), then the profiler library gets linked into the executable.
Any ideas on how to get gcc to link in the profiler library?
Thanks.
g++ main.o -o main -lm -lprofiler
As another.anon.coward commented, you are likely falling victim of your g++
using --as-needed
linker flag. Try this instead:
g++ main.o -Wl,--no-as-needed -lprofiler -Wl,--as-needed
Notes:
g++
already adds -lm
, no need to add it again
- It is important to turn
--as-needed
back on. Not doing so will likely cause you to link to additional libraries that you don't really need.
In my case, the problem was that there was only a libprofiler.so.0
, and no libprofiler.so
in /usr/lib/
:
user@compy:/usr/include$ dpkg -L libgoogle-perftools4
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/libgoogle-perftools4
/usr/share/doc/libgoogle-perftools4/README.Debian
/usr/share/doc/libgoogle-perftools4/copyright
/usr/lib
/usr/lib/libprofiler.so.0.4.5
/usr/lib/libtcmalloc.so.4.2.6
/usr/lib/libtcmalloc_debug.so.4.2.6
/usr/lib/libtcmalloc_and_profiler.so.4.2.6
/usr/share/doc/libgoogle-perftools4/AUTHORS
/usr/share/doc/libgoogle-perftools4/TODO
/usr/share/doc/libgoogle-perftools4/README.gz
/usr/share/doc/libgoogle-perftools4/NEWS.gz
/usr/share/doc/libgoogle-perftools4/changelog.Debian.gz
/usr/lib/libtcmalloc.so.4
/usr/lib/libtcmalloc_and_profiler.so.4
/usr/lib/libprofiler.so.0
/usr/lib/libtcmalloc_debug.so.4
I don't know what the official fix to this is, but I simply created a symlink in /usr/lib:
user@compy:/usr/lib$ sudo ln -s libprofiler.so.0 libprofiler.so
This will make -lprofiler
work.
If you don't mind changing your Makefile you can alternatively specify -l:libprofiler.so.0
instead of -lprofiler
(note the extra colon) (source).
EDIT: The official way to get the .so
is apparently to install the libgoogle-perftools-dev
package as explained here:
user@compy:/usr/lib$ dpkg -S libprofiler.so
libgoogle-perftools-dev: /usr/lib/libprofiler.so
libgoogle-perftools4: /usr/lib/libprofiler.so.0.4.5
libgoogle-perftools4: /usr/lib/libprofiler.so.0
I understand that if you want to link to a certain lib, you should install the libx-dev
package, which will contain the /usr/lib/libx.so
. This file will only be a symlink to a specific version, such as /usr/lib/libx.so.1.2
. When you link against /usr/lib/libx.so
by specifying -lx
to your linker, you will actually create a link in your program against the specific version linked at the time by recording a SONAME of libx.so.1
(the last version number is stripped as oulined here). So when you run your program at a later point in time the dynamic linker will look only for /usr/lib/libx.so.1
, which is symlinked to /usr/lib/libx.so.1.2
, and no /usr/lib/libx.so
hence no dev
package needs to exist.
So the libx-dev
packages is for compiling and linking against libx
, and the libx
package is for running a precompiled program against libx
.