Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ubuntu 11.10 linking perftools library

Tags:

c++

c

ubuntu

linker

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.

like image 442
nkoenig Avatar asked Mar 06 '12 03:03

nkoenig


2 Answers

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:

  1. g++ already adds -lm, no need to add it again
  2. 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.
like image 57
Employed Russian Avatar answered Nov 04 '22 02:11

Employed Russian


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.

like image 33
Alexander Torstling Avatar answered Nov 04 '22 02:11

Alexander Torstling