如何将可执行入口点的名称从 main 更改为其他名称?

How to change the name of executable entry point from main to something else?

我正在尝试在 Ubuntu Linux (12.04 x64) 上使用 gcc 4.8 编译第三方源代码,其中包含许多实用程序和测试应用程序,其中未调用可执行入口点 main。不要问我为什么-我不知道答案。

链接器当然会抱怨:

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

是否可以强制链接器使用另一种方法作为入口点?我尝试将这些链接器选项与 gcc 一起使用,但它们都不起作用: -Wl,-eWhatever-Wl,--entry=Whatever-Wl,-e,Whatever。都以同样的错误结束。

按照 C 标准,托管环境(我猜是你的情况 as/if 你想使用标准库 headers*)迫使你与 main 功能保持一致。来自 C11 §5.1.2.2.1/p1(强调我的):

The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

int main(void) { /* ... */ }

or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

int main(int argc, char *argv[]) { /* ... */ }

or equivalent;10) or in some other implementation-defined manner.

在您的情况下,我可以想到两个绕过 main 功能要求的选项:

  1. 使用 main 符号创建单独的 object 文件(即通过 gcc -c),它只是(声明和)调用(即包装)您的自定义入口点(可能通过通过 argcargv 调用参数)。这将使链接器满意并且就像添加单个 makefile 规则一样简单。
  2. 将您的程序编译为 gcc -DWhatever=main。这基本上用 main 替换了 Whatever 预处理标记的每个实例,因此链接器将 Whatever 视为 "proper" 主函数。

* 一些 headers 也必须在独立环境中可用,例如 <stddef.h><float.h>,请参阅 §4/p6 以获取它们的完整列表。

这是这两个选项的一些基本说明。每个假设 foo.c 如下:

foo.c

#include <stdio.h>

void foo(void)
{
    printf("foo\n");
}

第一种方法:

main.c

/* declare an entry point */
void foo(void);

/* define main as wrapper function */
int main(void)
{
    foo();

    return 0;
}

编译 & 运行:

$ gcc -c main.c
$ gcc foo.c main.o
$ ./a.out
foo

第二种方法:

$ gcc -Dfoo=main foo.c 
$ ./a.out
foo

有些东西可能需要更多的调整,但我希望你明白这个想法。