Ubuntu 11.10 linking perftools library

2019-05-05 21:17发布

问题:

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.

回答1:

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.


回答2:

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.