在编译时重命名符号而不以跨平台方式更改代码
Posted
技术标签:
【中文标题】在编译时重命名符号而不以跨平台方式更改代码【英文标题】:Renaming symbols at compile time without changing the code in a cross platform way 【发布时间】:2011-11-04 12:17:51 【问题描述】:在创建静态对象时,是否可以在编译时以跨平台方式重命名符号(不更改代码)?我最近推荐了 objcopy,但 linux 并不是唯一的目标平台,它也必须在 mac 上工作。我正在使用 gcc 进行编译,所以我希望有某种 gcc 选项。
我听说过 .def 文件,但这可能具有误导性,因为我发现的有关它们的信息似乎适用于 windows。
编辑: 我正在尝试更改 C 和 Fortran 函数的名称,特别是在它们前面加上“wrap”一词,以避免在链接时发生符号冲突。
【问题讨论】:
你能举个例子说明你想重命名什么样的符号,从什么到什么,为什么? 本质上是因为我包装了一些我不应该接触的代码,但我想更改一些符号以避免符号冲突。如果我不能更改代码,我想更改编译器输出的符号。至于什么 - 我想重命名函数,特别是在它们的符号名称前加上“wrap”这个词。 在这种情况下的另一种选择可能是在自己的进程中运行“untouchable”库,这样就没有冲突或其他丑陋,只需通过定义明确的接口公开其功能,可能通过套接字。 老实说,我对套接字一无所知,但这似乎是一种更慢的处理方式,这些函数的调用非常规律。目前最好的选择似乎是编辑代码并请求宽恕! 【参考方案1】:是否可以在编译时重命名符号
你也许可以用预处理器来实现它:
gcc -c foo.c -Dfoo=foo_renamed
【讨论】:
对不起,我错过了原始问题中的 fortran 标签。假设您的答案仅适用于 C 预处理器? 应该也适用于 Fortran:gcc.gnu.org/onlinedocs/gfortran/… 你为什么不直接尝试它? 是的,应该可以。只是一些需要解决的实施问题。首先,我要更改大量符号,因此 -Dfoo=bar 语法有点难看,但是我发现了 GCC 的 -include 标志,它可以让您包含文件。还有一个小问题是 fortran 不区分大小写,而预处理器不区分大小写。但是,小问题:)。 这似乎工作foo
需要足够独特以至于它不会在其他任何地方显示为子字符串。还要注意,对于固定形式的 fortran,如果新名称比原始名称长,您的预处理器子可能会使行太长。【参考方案2】:
您可以使用 gcc alias 属性来制作指向同一个函数的多个符号。
void name1() __attribute__((alias ("name2")));
我不确定 alias 属性是否适用于其他类型的符号(例如变量)。
【讨论】:
对不起,我之前错过了 fortran 标签。而且我相信这仅适用于C! :( 这也适用于 Fortran,但不会解决问题:您仍然拥有原始名称 1,并且仍然会导致冲突。您可以通过将 name1 设为静态来隐藏它。但这两者都需要更改源代码,而 OP 一开始就试图避免这种情况。 实际上查看gcc的文档也有__attribute__((weak))
,这意味着如果存在另一个全局符号,它将被使用。以上是关于在编译时重命名符号而不以跨平台方式更改代码的主要内容,如果未能解决你的问题,请参考以下文章