链接器和依赖项

时间:2011-08-20 09:12:39

标签: gcc linker g++

对于Linux / g ++项目,我有一个帮助库(“libcommon.a”),我编写了两个不同的程序(“客户端”和“服务器”)。其中一个特定的源文件oshelper.cpp具有一组不相关的实用程序函数:

// 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);
}

两个程序都链接到包含这些函数的库(libcommon.a或-lcommon)。

“client”程序调用GetConsoleWidth和GetMillisecondCounter函数。由于GetMillisecondCounter最终依赖于对“clock_gettime”的调用,因此 -lrt 是链接器的必需参数,以便链接librt。这是预期的。

“server”只调用GetConsoleWidth。它从不调用GetMillisecondCounter。但是如果没有传递“-lrt”,链接器会抱怨未解析的clock_gettime引用。通过将-lrt传递给g ++显然可以解决这个问题。然后“ldd server”显示librt.so.1仍然是运行时依赖项。因此,与clock_gettime的联系显然没有得到优化。

但是当我将GetConsoleWidth的实现分离为单独的源文件(但仍然是libcommon.a的一部分)时,链接器停止抱怨未解析的对clock_gettime的引用,并且不再坚持我通过了在 -lrt

就好像g ++链接器只能剔除未使用的目标文件,而不是未使用的函数调用。

这里发生了什么?

更新:编译器和链接器命令行是最基本的:

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

1 个答案:

答案 0 :(得分:1)

如果没有特殊命令,.o就会完全链接,因此所有依赖项都是必需的。

您需要使用编译器标志在库中构建编译单元,这些标志将所有符号放在单独的部分中,然后使用“垃圾收集”部分的选项调用链接器,以便只使用直接或间接引用的代码(并且可能是ctors / dtors)。

我不完全知道命令,但是搜索gcc参数,例如-ffunction-sections -fdata-sections -fvtable-gc和-gc-section(s)