我的软件有一个主函数,用于正常使用,还有一个不同的主函数,用于单元测试。 如果有一种方法可以通过gcc指定要使用哪个“主”函数,那就太棒了。
我的软件有一个主函数,用于正常使用,还有一个不同的主函数,用于单元测试。 如果有一种方法可以通过gcc指定要使用哪个“主”函数,那就太棒了。
-e
标志将入口点指定为ld
来指定程序的入口点。我的文档上写着:
这意味着您可以覆盖入口点,但如果您想在计算机上正常运行C程序,则可能不希望这样做,因为
-e symbol_name
指定主可执行文件的入口点。默认情况下,入口名称为“start”,该名称在crt1.o中找到,其中包含设置和调用main()所需的粘合代码。
start
可能会执行各种特定于操作系统的操作,这些操作在运行程序之前是必需的。如果您能够实现自己的start
,那么您就可以按照自己的意愿进行操作。-nostartfiles
,否则crt1.o
中的main
将未定义,因此无法链接2)必须使用显式的exit()
退出,否则返回到未知位置将导致段错误3)argv
不会为您设置。 - Ciro Santilli OurBigBook.comint 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
}
-DTESTING
添加到gcc的参数列表中即可。 - Marc Bollinger#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[] ) { ... }
我假设你正在使用Make或类似工具。我建议创建两个文件,分别包含不同的主函数实现,然后在makefile中定义两个独立的目标,这两个目标都依赖于除了一个使用“单元测试主函数”和另一个使用“普通主函数”之外的相同文件。示例如下:
normal: main_normal.c file1.c file2.c
unittest: main_unittest.c file1.c file2.c
我倾向于在测试和生产环境中使用不同的文件和构建方式,但如果你确实有一个包含
testing
和
production
代码的文件,你可以使用条件语句来区分它们。
int test_main (int argc, char*argv[])
并且
int prod_main (int argc, char*argv[])
然后选择一个作为主要的编译器选项是-Dtest_main=main
和-Dprod_main=main
今天我也遇到了同样的问题:m1.c和m2.c都有一个main函数,但需要将它们链接并运行其中之一。 解决方法:在编译之后但在链接之前,使用STRIP从其中一个文件中删除main符号:
gcc -c m1.c m2.c; strip --strip-symbol main m1.o; gcc m1.o m2.o; ./a.out
将从m2运行主程序
gcc -c m1.c m2.c; strip --strip-symbol main m2.o; gcc m1.o m2.o; ./a.out
将从m1中运行主函数
不去除标签:
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
main
的不是C,而是标准库。操作系统加载应用程序,将控制权转移到库的入口点(GCC中的_start
),最终库调用main
。这就是为什么Windows应用程序的入口点可以是WinMain
而不是通常的main
。嵌入式编程也可能有类似的情况。如果没有标准库,您必须编写库通常提供的入口点(以及其他内容),并且可以按任意名称命名它。-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
,那么可以编写两个仅包含主函数的主模块。其中一个用于单元测试,另一个用于正常使用。
LD "-e symbol_name"
(其中symbol_name是您的主函数,当然),您还需要"-nostartfiles"
,否则将会产生"undefined reference to main"
的错误。#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 #正常目的编译
man gcc
告诉我关于 -D 和 -U 的信息
main
函数的代码放在一个 define
中... 一些 IDE 的语法高亮会将所有测试代码变灰(因为它通常不被定义),这可能会变得非常烦人。 - Billy ONeal你 可能 需要单独运行 ld
来使用它们,但是 ld 支持 脚本 来定义输出文件的许多方面(包括入口点)。
main
不是入口点(至少在大多数系统上不是)。 - Carl Norum