是否有 GCC 编译器/链接器选项来更改 main 的名称?

发布于 2024-09-06 15:37:56 字数 69 浏览 3 评论 0原文

我的软件有一个主要用于正常使用,另一个主要用于单元测试。 如果 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

北方。的韩爷 2024-09-13 15:37:56

这里的其他答案非常合理,但严格来说,您遇到的问题实际上并不是 GCC 的问题,而是 C 运行时的问题。您可以使用 ld-e 标志指定程序的入口点。我的文档说:

<代码>-e 符号名称

指定主可执行文件的入口点。默认情况下,条目名称为“start”,可在 crt1.o 中找到,其中包含需要设置和调用 main() 的粘合代码。

这意味着您可以根据需要覆盖入口点,但您可能不想为打算在计算机上正常运行的 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 to ld. My documentation says:

-e symbol_name

Specifies the entry point of a main executable. By default the entry name is "start" which is found in crt1.o which contains the glue code need to set up and call main().

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 own start, you could do what you want.

笔芯 2024-09-13 15:37:56

将它们放在单独的文件中,并指定一个.c 文件用于正常使用,一个.c 文件用于测试。

或者,使用测试构建在命令行上进行 #define 测试,并使用如下内容:

int main(int argc, char *argv[])
{
#ifdef TESTING
    return TestMain(argc, argv);
#else
    return NormalMain(argc, argv);
#endif
}

int TestMain(int argc, char *argv[])
{
    // Do testing in here
}

int NormalMain(int argc, char *argv[])
{
    //Do normal stuff in here
}

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:

int main(int argc, char *argv[])
{
#ifdef TESTING
    return TestMain(argc, argv);
#else
    return NormalMain(argc, argv);
#endif
}

int TestMain(int argc, char *argv[])
{
    // Do testing in here
}

int NormalMain(int argc, char *argv[])
{
    //Do normal stuff in here
}
你曾走过我的故事 2024-09-13 15:37:56

您可以使用宏将一个函数重命名为 main。

#ifdef TESTING
#define test_main main
#else
#define real_main main
#endif

int test_main( int argc, char *argv[] ) { ... }
int real_main( int argc, char *argv[] ) { ... }

You can use macros to rename one function to main.

#ifdef TESTING
#define test_main main
#else
#define real_main main
#endif

int test_main( int argc, char *argv[] ) { ... }
int real_main( int argc, char *argv[] ) { ... }
风追烟花雨 2024-09-13 15:37:56

我假设您正在使用 Make 或类似的东西。我将创建两个包含 main 函数的不同实现的文件,然后在 makefile 中定义两个独立的目标,它们对其余文件具有相同的依赖关系,除了一个使用“单元测试 main”,另一个使用“正常 main” ”。像这样的事情:

normal: main_normal.c file1.c file2.c
unittest: main_unittest.c file1.c file2.c

只要“正常”目标更接近 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:

normal: main_normal.c file1.c file2.c
unittest: main_unittest.c file1.c file2.c

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.

陌伤浅笑 2024-09-13 15:37:56

我倾向于使用不同的文件并进行测试和生产构建,但是如果您确实有一个文件,

int test_main (int argc, char*argv[])

那么

int prod_main (int argc, char*argv[])

选择一个或另一个作为主要文件的编译器选项是 -Dtest_main=main和-Dprod_main=main

I'd tend to use different files and make for testing and production builds, but if you did have a file with

int test_main (int argc, char*argv[])

and

int prod_main (int argc, char*argv[])

then the compiler options to select one or the other as the main are -Dtest_main=main and -Dprod_main=main

爱人如己 2024-09-13 15:37:56

我今天遇到了同样的问题:m1.c 和 m2.c 都有一个 main 函数,但需要链接并运行其中一个。
解决方案:用户 STRIP 在编译后但链接之前从其中一个删除主符号:

gcc -c m1.c m2.c;  strip --strip-symbol main m1.o; gcc m1.o m2.o; ./a.out

will run main from m2

gcc -c m1.c m2.c;  strip --strip-symbol main m2.o; gcc m1.o m2.o; ./a.out

will run main from m1

不带 strip:

gcc - m1.c m2.c
m2.o: In function `main':
m2.c:(.text+0x0): multiple definition of `main'
m1.o:m1.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status

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:

gcc -c m1.c m2.c;  strip --strip-symbol main m1.o; gcc m1.o m2.o; ./a.out

will run main from m2

gcc -c m1.c m2.c;  strip --strip-symbol main m2.o; gcc m1.o m2.o; ./a.out

will run main from m1

Without strip:

gcc - m1.c m2.c
m2.o: In function `main':
m2.c:(.text+0x0): multiple definition of `main'
m1.o:m1.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
今天小雨转甜 2024-09-13 15:37:56

编辑:比利比我先找到答案,但这里有更多背景知识

更直接地说,main通常更多是标准库的函数。调用 main 的不是 C,而是标准库。操作系统加载应用程序,将控制权转移到库的入口点(GCC 中的_start),库最终调用main。这就是为什么 Windows 应用程序的入口点可以是 WinMain,而不是通常的入口点。嵌入式编程也可以有同样的事情。如果您没有标准库,则必须编写该库通常提供的入口点(除其他外),并且您可以将其命名为任何您想要的名称。

在 GCC 工具链中,您还可以使用 -e 选项将库的入口点替换为您自己的入口点。 (就此而言,您也可以完全删除该库。)


自己制作:

int main(int argc, char *argv[])
{
#if defined(BUILD_UNIT_TESTS)
    return main_unittest(argc, argv);
#endif
#if defined(BUILD_RUNTIME)
    return main_run(argc, argv);
#endif
}

如果您不喜欢 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 calls main. This is why the entry point for a windows application can be WinMain, 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:

int main(int argc, char *argv[])
{
#if defined(BUILD_UNIT_TESTS)
    return main_unittest(argc, argv);
#endif
#if defined(BUILD_RUNTIME)
    return main_run(argc, argv);
#endif
}

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.

又怨 2024-09-13 15:37:56

如果您使用 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.

伪装你 2024-09-13 15:37:56

可能必须单独运行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).

蓝天 2024-09-13 15:37:56

首先,在一个编译中不能有两个名为 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 pull main 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.

两人的回忆 2024-09-13 15:37:56
#ifdef TESTING

int main()

{

/* testing code here */

}

#else

int main()

{

/* normal code here */

}

#endif

$ gcc -DTESTING=1 -o a.out filename.c #构建用于测试

$ gcc -UTESTING -o a.out filename.c #构建用于正常目的

< code>man gcc 向我展示了 -D 和 -U

#ifdef TESTING

int main()

{

/* testing code here */

}

#else

int main()

{

/* normal code here */

}

#endif

$ 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文