¿Existe una opción de comstackdor / enlazador GCC para cambiar el nombre de main?

Mi software tiene uno principal para uso normal y otro diferente para pruebas unitarias. Me encantaría que hubiera una opción para gcc para especificar qué función “principal” usar.

Póngalos en archivos separados, y especifique un archivo .c para uso normal, y un archivo .c para prueba.

Alternativamente, #define testing en la línea de comandos usando comstackciones de prueba y usa algo como:

 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 } 

Las otras respuestas aquí son bastante razonables, pero estrictamente hablando, el problema que tiene no es realmente uno con GCC, sino con el tiempo de ejecución de C. Puede especificar un punto de entrada a su progtwig usando la -e para ld . Mi documentación dice:

-e symbol_name

Especifica el punto de entrada de un ejecutable principal. Por defecto, el nombre de la entrada es “inicio”, que se encuentra en crt1.o, que contiene el código de pegamento necesario para configurar y llamar a main ().

Eso significa que puede anular el punto de entrada si lo desea, pero es posible que no quiera hacer eso para un progtwig en C que pretende ejecutar normalmente en su máquina, ya que start puede hacer todo tipo de cosas específicas del sistema operativo que se requieren antes de que se ejecute su progtwig. Si puede implementar su propio start , podría hacer lo que quiera.

Supongo que estás usando Make o algo similar. Me gustaría crear dos archivos que contengan diferentes implementaciones de la función principal, luego, en el makefile, defina dos objectives separados que tengan dependencias idénticas en el rest de sus archivos, excepto que uno usa su “prueba de unidad principal” y el otro su “principal principal”. “. Algo como esto:

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

Siempre que el objective “normal” esté más cerca de la parte superior del archivo de make, al escribir “make” lo elegirá de forma predeterminada. Tendría que escribir “make unittest” para construir su objective de prueba.

Puedes usar macros para cambiar el nombre de una función a 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[] ) { ... } 

Tendría a usar diferentes archivos y hacer pruebas y comstackciones de producción, pero si tuviera un archivo con

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

y

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

luego las opciones del comstackdor para seleccionar una u otra como main son -Dtest_main=main y -Dprod_main=main

Hoy tuve el mismo problema: m1.c y m2.c tenían una función principal, pero necesitaban estar vinculados y ejecutar una de ellas. Solución: el usuario STRIP elimina el símbolo principal de uno de ellos después de la comstackción pero antes de vincular:

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

correrá principal desde m2

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

correrá principal desde m1

Sin tira

 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 

Edit: Billy me ganó la respuesta, pero aquí hay un poco más de fondo

Más directamente, main suele ser más una función de la biblioteca estándar. Lo que se llama main no es C, sino la biblioteca estándar. El sistema operativo carga la aplicación, transfiere el control al punto de entrada de la biblioteca ( _start en GCC), y la biblioteca finalmente llama main . Es por esto que el punto de entrada para una aplicación de Windows puede ser WinMain , y no el habitual. La progtwigción integrada puede tener el mismo tipo de cosas. Si no tiene una biblioteca estándar, tiene que escribir el punto de entrada que la biblioteca proporciona normalmente (entre otras cosas), y puede nombrarlo como desee.

En la cadena de herramientas de GCC, también puede reemplazar el punto de entrada de la biblioteca con el suyo mediante la opción -e . (Para el caso, también puede eliminar la biblioteca por completo).


Haz lo tuyo:

 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 } 

Si no te gusta ifdef , escribe dos módulos principales que contengan solo main. Conecte uno para pruebas de unidad y el otro para uso normal.

Es posible que tenga que ejecutar ld separado para usarlos, pero ld admite scripts para definir muchos aspectos del archivo de salida (incluido el punto de entrada).

En primer lugar, no puede tener dos funciones denominadas main en una comstackción, por lo que las fonts están en archivos diferentes o está usando una comstackción condicional. De cualquier manera tienes que sacar dos archivos .o diferentes. Por lo tanto, no necesita una opción de vinculador; simplemente pasa el archivo .o que desea como argumento .

Si no te gusta eso, puedes hacer cosas extravagantes con dlopen() para extraer main de cualquier archivo de objeto que nombre dinámicamente. Puedo imaginar circunstancias en las que esto podría ser útil; digamos, toma un enfoque sistemático de las pruebas unitarias, solo las pone en un directorio y su código recorre el directorio, toma cada archivo de objetos, lo carga dinámicamente y ejecuta sus pruebas. Pero para empezar, probablemente se indique algo más simple.

Si usa LD "-e symbol_name" (donde symbol_name es su función principal, por supuesto) también necesita "-nostartfiles" contrario se "-nostartfiles" error de "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 #building for testing

$ gcc -UTESTING -o a.out filename.c #building for normal purposes

man gcc me mostró la -D y -U