1

For a Linux/g++ project, I have a helper library ("libcommon.a") that I wrote that is used in two different programs ("client" and "server"). One particular source file among several, oshelper.cpp, has a set of unrelated utility functions:

// header file
#ifndef OSHELPER_H
#define OSHELPER_H
    size_t GetConsoleWidth();
    uint32_t GetMillisecondCounter();
#endif

// -----------------------------------------
// Code file
#include "commonincludes.h"
#include "oshelper.h"

size_t GetConsoleWidth()
{
    struct winsize ws = {};
    ioctl(0, TIOCGWINSZ, &ws);
    return ws.ws_col;
}

uint32_t GetMillisecondCounter()
{
    timespec ts={};
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return (uint32_t)(ts.tv_nsec / 1000000 + ts.tv_sec * 1000);
}

Both programs link to the library that contains these functions (libcommon.a or -lcommon).

"client" program calls both the GetConsoleWidth and GetMillisecondCounter function. And since GetMillisecondCounter ultimately depends on a call to "clock_gettime", -lrt is a required parameter to the linker such that librt is linked in. This is expected.

"server" just calls GetConsoleWidth. It never calls GetMillisecondCounter. But without "-lrt" being passed, the linker complains about the unresolved reference to clock_gettime. Which is obviously fixed by passing -lrt to g++. And then "ldd server" shows that librt.so.1 is still a runtime dependency. So the linkage to clock_gettime clearly did not get optimized away.

But when I separate the implementation of GetConsoleWidth into a seperate source file (but still part of libcommon.a), the linker stops complaining about the unresolved reference to clock_gettime and no longer insists that I pass in -lrt.

It's as if the g++ linker can only cull out unused object files, but not unused function calls.

What's going on here?

Update: the compiler and linker command lines are as basic as they can get:

g++ -c oshelper.cpp
g++ -c someotherfile.cpp
etc...
ar -rv libcommon.a oshelper.o someotherfile.o ...

g++ server.cpp -lcommon -lpthread -o server
g++ client.cpp -lcommon -lrt -o client
selbie
  • 100,020
  • 15
  • 103
  • 173
  • Can you show your compile and link commands? (Not reproducing this here.) – Mat Aug 20 '11 at 09:25
  • @Mat - Compiler and linker commands are as basic as it gets. But I updated the above to reference just that. – selbie Aug 20 '11 at 09:38

1 Answers1

1

Without special commands an .o is linked in its entirety, and thus all he dependencies are required.

You need to build the compilation units in the library with compiler flags that put all symbols in separate sections, and then call the linker with an option that "garbage collects" sections, so that only code referenced directly or indirect from main (and maybe ctors/dtors) is linked in.

I don't know the commands exactly but search for gcc parameters like -ffunction-sections -fdata-sections -fvtable-gc and -gc-section(s)

Marco van de Voort
  • 25,628
  • 5
  • 56
  • 89