如何将可执行入口点的名称从 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
功能要求的选项:
- 使用
main
符号创建单独的 object 文件(即通过 gcc -c
),它只是(声明和)调用(即包装)您的自定义入口点(可能通过通过 argc
和 argv
调用参数)。这将使链接器满意并且就像添加单个 makefile 规则一样简单。
- 将您的程序编译为
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
有些东西可能需要更多的调整,但我希望你明白这个想法。
我正在尝试在 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
功能要求的选项:
- 使用
main
符号创建单独的 object 文件(即通过gcc -c
),它只是(声明和)调用(即包装)您的自定义入口点(可能通过通过argc
和argv
调用参数)。这将使链接器满意并且就像添加单个 makefile 规则一样简单。 - 将您的程序编译为
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
有些东西可能需要更多的调整,但我希望你明白这个想法。