是否有 GCC 编译器/链接器选项来更改 main 的名称?
我的软件有一个主要用于正常使用,另一个主要用于单元测试。 如果 gcc 有一个选项来指定要使用哪个“主”函数,我会很高兴的。
My software has one main for normal use and a different one for unit tests.
I would just love it if there was an option to gcc to specify which "main" function to use.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
这里的其他答案非常合理,但严格来说,您遇到的问题实际上并不是 GCC 的问题,而是 C 运行时的问题。您可以使用
ld
的-e
标志指定程序的入口点。我的文档说:这意味着您可以根据需要覆盖入口点,但您可能不想为打算在计算机上正常运行的 C 程序执行此操作,因为
start
可能会执行各种操作系统特定的操作这是你的程序运行之前所必需的。如果您可以实现自己的start
,您就可以做您想做的事情。The other answers here are quite reasonable, but strictly speaking the problem you have is not really one with GCC, but rather with the C runtime. You can specify an entry point to your program using the
-e
flag told
. My documentation says:That means you can override the entry point if you like, but you may not want to do that for a C program you intend to run normally on your machine, since
start
might do all kinds of OS specific stuff that's required before your program runs. If you can implement your ownstart
, you could do what you want.将它们放在单独的文件中,并指定一个.c 文件用于正常使用,一个.c 文件用于测试。
或者,使用测试构建在命令行上进行
#define
测试,并使用如下内容:Put them in separate files, and specify one .c file for normal use, and one .c file for testing.
Alternately,
#define
testing on the commandline using test builds and use something like:您可以使用宏将一个函数重命名为 main。
You can use macros to rename one function to main.
我假设您正在使用 Make 或类似的东西。我将创建两个包含 main 函数的不同实现的文件,然后在 makefile 中定义两个独立的目标,它们对其余文件具有相同的依赖关系,除了一个使用“单元测试 main”,另一个使用“正常 main” ”。像这样的事情:
只要“正常”目标更接近 makefile 的顶部,那么输入“make”就会默认选择它。您必须输入“make unittest”来构建您的测试目标。
I'm assuming that you're using Make or something similar. I would create two files that contain different implementations of the main function, then in the makefile, define two separate targets that have identical dependencies on the rest of your files, except one uses your "unit test main" and the other your "normal main". Something like this:
As long as the "normal" target is closer to the top of the makefile, then typing "make" will choose it by default. You would have to type "make unittest" to build your test target.
我倾向于使用不同的文件并进行测试和生产构建,但是如果您确实有一个文件,
那么
选择一个或另一个作为主要文件的编译器选项是
-Dtest_main=main
和-Dprod_main=mainI'd tend to use different files and make for testing and production builds, but if you did have a file with
and
then the compiler options to select one or the other as the main are
-Dtest_main=main
and-Dprod_main=main
我今天遇到了同样的问题:m1.c 和 m2.c 都有一个 main 函数,但需要链接并运行其中一个。
解决方案:用户 STRIP 在编译后但链接之前从其中一个删除主符号:
will run main from m2
will run main from m1
不带 strip:
I had the same problem today: m1.c and m2.c both had a main function but needed to be linked and run one of them.
Solution: user STRIP to remove the main symbol from one of them after compilation but before linking:
will run main from m2
will run main from m1
Without strip:
编辑:比利比我先找到答案,但这里有更多背景知识
更直接地说,main通常更多是标准库的函数。调用
main
的不是 C,而是标准库。操作系统加载应用程序,将控制权转移到库的入口点(GCC 中的_start
),库最终调用main
。这就是为什么 Windows 应用程序的入口点可以是WinMain
,而不是通常的入口点。嵌入式编程也可以有同样的事情。如果您没有标准库,则必须编写该库通常提供的入口点(除其他外),并且您可以将其命名为任何您想要的名称。在 GCC 工具链中,您还可以使用
-e
选项将库的入口点替换为您自己的入口点。 (就此而言,您也可以完全删除该库。)自己制作:
如果您不喜欢
ifdef
,那么编写两个仅包含 main 的主模块。链接一个用于单元测试,另一个用于正常使用。Edit: Billy beat me to the answer, but here's a bit more background
More directly, main is usually more a function of the standard library. The thing that calls
main
isn't C, but rather the standard library. The OS loads the application, transfers control to the library's entry point (_start
in GCC), and the library ultimately callsmain
. This is why the entry point for a windows application can beWinMain
, and not the usual. Embedded programming can have the same sort of thing. If you don't have a standard library, you have to write the entry point that the library normally provides (among other things), and you can name it whatever you want.In the GCC toolchain, you can also replace the library's entry point with your own by using the
-e
option. (For that matter, you can also remove the library entirely.)Make your own:
If you don't like
ifdef
, then write two main modules that contain only main. Link one in for unit tests and the other in for normal use.如果您使用
LD "-e symbol_name"
(当然,其中 symbol_name 是您的主函数),您还需要"-nostartfiles"
否则错误"undefined将生成对 main"
的引用。If you use into
LD "-e symbol_name"
(where symbol_name is your main function, of course) you need also"-nostartfiles"
otherwise error of"undefined reference to main"
will be produced.您可能必须单独运行
ld
才能使用它们,但ld支持脚本 定义输出文件的许多方面(包括入口点)。You may have to run
ld
separately to use them, but ld supports scripts to define many aspects of the output file (including the entry point).首先,在一个编译中不能有两个名为
main
的函数,因此要么源位于不同的文件中,要么您正在使用条件编译。无论哪种方式,你都必须获得两个不同的 .o 文件。因此,您不需要链接器选项;您只需将所需的 .o 文件作为参数传递即可。如果您不喜欢这样,您可以使用 dlopen() 做一些奇特的事情,从您动态命名的任何目标文件中提取
main
。我可以想象这可能有用的情况 - 例如,您采用系统方法进行单元测试,只需将它们全部放在一个目录中,然后您的代码遍历该目录,获取每个对象文件,动态加载它并运行其测试。但在开始之前,可能会指出一些更简单的东西。First of all, you can't have two functions named
main
in one compilation, so either the sources are in different files or you're using conditional compilation. Either way you've got to get two different .o files out. Therefore, you don't need a linker option; you just pass the .o file that you want in as an argument.If you don't like that, you can do fancy things with
dlopen()
to pullmain
from any object file you name dynamically. I can imagine circumstances where this might be useful—say, you take a systematic approach to unit tests, just put them all in a directory, and your code walks the directory, grabbing each object file, dynamically loading it, and running its tests. But to get started, something simpler is probably indicated.$ gcc -DTESTING=1 -o a.out filename.c #构建用于测试
$ gcc -UTESTING -o a.out filename.c #构建用于正常目的
< code>man gcc 向我展示了 -D 和 -U
$ gcc -DTESTING=1 -o a.out filename.c #building for testing
$ gcc -UTESTING -o a.out filename.c #building for normal purposes
man gcc
showed me the -D and -U