链接器和依赖关系 [英] Linker and dependencies

查看:155
本文介绍了链接器和依赖关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

pre $ //头文件
#ifndef OSHELPER_H
#define OSHELPER_H
size_t GetConsoleWidth();
uint32_t GetMillisecondCounter();
#endif

// ---------------------------------- -------
//代码文件
#includecommonincludes.h
#includeoshelper.h

size_t GetConsoleWidth()
{
struct winsize ws = {};
ioctl(0,TIOCGWINSZ,& ws);
返回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的未解析引用。这显然是通过传递给g ++来修复的。然后ldd server显示librt.so.1仍然是运行时依赖项。因此,与clock_gettime的链接显然没有得到优化。



但是,当我将GetConsoleWidth的实现分离为独立源文件时libcommon.a的一部分),链接器停止抱怨对clock_gettime的未解决引用,并且不再强调我传递 -lrt

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



这是怎么回事?



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

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

g ++ server.cpp -lcommon -lpthread -o服务器
g ++ client.cpp -lcommon -lrt -o客户端


解决方案

没有特殊的命令,一个.o链接在一起,因此他所有的依赖您需要在库中使用编译器标志构建编译单元,这些编译器标志将所有符号放在不同的部分中,然后使用垃圾收集部分,以便只有直接或间接从主(也可能是ctors / dtors)引用的代码被链接到。



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

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

解决方案

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)

这篇关于链接器和依赖关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆