代码之家  ›  专栏  ›  技术社区  ›  Arthur Ulfeldt

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

  •  15
  • Arthur Ulfeldt  · 技术社区  · 14 年前

    我的软件有一个主要用于正常使用和一个不同的单元测试。

    11 回复  |  直到 7 年前
        1
  •  9
  •   Billy ONeal IS4    14 年前

    将它们放在不同的文件中,并指定一个.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
    }
    
        2
  •  15
  •   Carl Norum    14 年前

    这里的其他答案是相当合理的,但严格来说,您遇到的问题并不是GCC的问题,而是C运行时的问题。可以使用 -e ld . 我的文件上说:

    -e symbol_name

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

    start 在你的程序运行之前,你可能会做各种特定于操作系统的事情。如果你能实现你自己的 ,你可以做你想做的事。

        3
  •  7
  •   Paul    14 年前

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

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

    只要“normal”目标更接近makefile的顶部,那么默认情况下键入“make”将选择它。您必须键入“makeunittest”来构建测试目标。

        4
  •  7
  •   drawnonward    14 年前

    可以使用宏将一个函数重命名为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[] ) { ... }
    
        5
  •  6
  •   Pete Kirkham    14 年前

    我倾向于使用不同的文件,并使测试和生产构建,但如果你有一个与

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

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

    然后选择其中一个作为主编译器的编译器选项是 -Dtest_main=main -Dprod_main=main

        6
  •  5
  •   jand    11 年前

    我今天遇到了同样的问题:m1.c和m2.c都有一个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
    

    无带:

    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
    
        7
  •  2
  •   mschaef    14 年前

    编辑:

    更直接地说,main通常更像是标准库的一个函数。打电话的东西 main _start . 这就是为什么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的主模块。一个用于单元测试,另一个用于正常使用。

        8
  •  1
  •   Piotr Sobiegraj    12 年前

    LD "-e symbol_name" (当然,符号名称是您的主要功能)您还需要 "-nostartfiles" 否则错误 "undefined reference to main" 将会产生。

        9
  •  0
  •   Jerry Coffin    14 年前

    可以 ld 单独使用,但ld支持 scripts 定义输出文件的许多方面(包括入口点)。

        10
  •  0
  •   Norman Ramsey    14 年前

    首先,不能有两个名为 main 在一个编译中,要么源代码在不同的文件中,要么使用条件编译。不管是哪种方式,你都得拿出两个不同的.o文件。因此,您不需要链接器 ; 你只需要把你想要的.o文件作为 论点

    dlopen() 主要的 从任何动态命名的对象文件。我可以想象这样做可能有用的情况,比如说,对单元测试采取系统化的方法,将它们全部放在一个目录中,然后代码遍历目录,获取每个对象文件,动态加载它,并运行它的测试。但首先,可能会指出一些更简单的方法。

        11
  •  0
  •   Delgan    8 年前
    #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 给我看了-D和-U