【问题标题】:How to determine which object files are actually necessary for linking?如何确定链接实际需要哪些目标文件?
【发布时间】:2010-07-09 01:29:09
【问题描述】:

我必须修改一些开源代码才能在 C 项目中使用。我不想从修改后的代码构建一个库,而是从我自己的源代码与修改后的开源代码相结合来编译和构建一个可执行文件。目标是拥有一个可以分发的独立包。我可以使用 GNU 构建工具让它正常工作,并成功构建了我的可执行文件。

现在我想减少我正在构建和链接的代码量。有没有一种简单的方法可以确定我实际需要编译哪些开源文件?比如说,开源包中有 40 个 .c 文件。我猜我的代码只使用(或导致使用)这些文件中的 20 个。目前我正在编译所有这些并将所有内容都扔给链接器。必须有一种聪明(且简单?)的方法来确定我真正需要哪些,对吧?

如果有帮助,我很乐意提供更多详细信息。提前致谢。

【问题讨论】:

  • 这样做的目的是什么?链接器已自动删除未使用的代码。只是为了让您的构建更快吗?
  • 我希望我的包裹更紧凑(没有双关语!)。最终我将分发此代码并希望删除不必要的文件。

标签: c linker compilation


【解决方案1】:

当遇到这种情况时,我要么简单地使用最终链接命令删除所有对象,然后重新添加直到它工作,要么处理 nm 命令的输出。

工作示例:

查看nm的输出:

$ nm *.o

a.o:
00000000 T a
         U aa

b.o:
00000000 T b

t.o:
         U a
         U b
00000000 T main

ua.o:
00000000 T ua

ub.o:
00000000 T ub

所以我创建了以下 awk 脚本

# find-unused.awk
BEGIN {req["main"]="crt"}

/\.o\:$/{
    gsub(/\:/,"");
    modulename=$0;
}

$1=="U"{
    req[$2] = modulename;
}

/[0-9,a-f].* T/{
    def[$3] = modulename;
}

END{
    print "modules referenced:"
    for (i in req)
    {
        if (def[i] != "")
            print "    "def[i];
    }

    print "functions not found"
    for (i in req)
    {
        if (def[i] == "")
            print "    "i;
    }
}

然后这样称呼它;

$ nm *.o|awk -f find-unused.awk

它告诉我:

modules referenced:
    t.o
    a.o
    b.o
functions not found
    aa

哪个是正确的 - 因为上面示例中的 ua & ub 函数没有被使用。

【讨论】:

  • 这个脚本非常方便。感谢您的详细回答。脚本中唯一的问题是它列出了该 .o 中每个函数的 .o 文件。我只是使用'sort -u'来获得唯一的.o并得到我的答案。结果我使用了 115 个 .o 中的 105 个。所以我不会删除任何文件。再次感谢。
  • 这只是一个快速脚本 - 可能会有所改进 - 但我很高兴它很有用。
【解决方案2】:

看看您是否可以让您的死代码剥离器告诉您它在链接期间消除了哪些功能/符号。然后您将知道可以安全删除哪些源代码。 GNU 链接器的-map 选项在这方面可能很有用。例如,您可以在没有死代码剥离的情况下链接一次,然后再次链接死代码剥离并比较输出映射文件。

如果最多只有 40 个源文件,这种优化真的值得您花时间吗?

【讨论】:

  • 我认为避免分发中的无关文件是值得的。显然不会破坏交易,但如果有一个更干净的包装会很好。
猜你喜欢
  • 2018-06-25
  • 2011-09-26
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
  • 2012-05-02
相关资源
最近更新 更多