Подтвердить что ты не робот

Есть ли опция компилятора/компоновщика GCC для изменения имени основного?

У моего программного обеспечения есть один основной для нормального использования, а другой - для модульных тестов. Мне просто понравилось бы, если бы была опция gcc, чтобы указать, какую "главную" функцию использовать.

4b9b3361

Ответ 1

Поместите их в отдельные файлы и укажите один файл .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

Другие ответы здесь вполне разумны, но, строго говоря, проблема, которую вы имеете, на самом деле не имеет отношения к GCC, а скорее к запуску C. Вы можете указать точку входа в свою программу, используя флаг -e для ld. В моей документации говорится:

-e symbol_name

Указывает точку входа основного исполняемого файла. По умолчанию имя записи "start", которое находится в crt1.o, которое содержит код клея, необходимо настроить и вызвать main().

Это означает, что вы можете переопределить точку входа, если хотите, но вы можете не захотеть сделать это для программы на C, которую вы намереваетесь нормально запускать на своем компьютере, поскольку start может выполнять все виды специфичных для ОС материалов перед запуском вашей программы. Если вы можете реализовать свой собственный start, вы можете делать то, что хотите.

Ответ 3

Я предполагаю, что вы используете Make или что-то подобное. Я бы создал два файла, которые содержат различные реализации основной функции, а затем в make файле определяют две отдельные цели, которые имеют одинаковые зависимости от остальных ваших файлов, за исключением того, что использует ваш "unit test main", а другой ваш "обычный" главный". Что-то вроде этого:

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

Пока "нормальная" цель ближе к верхней части make файла, тогда набрав "make", выберете его по умолчанию. Вам нужно будет ввести "make unittest" для создания тестовой цели.

Ответ 4

Вы можете использовать макросы для переименования одной функции в основную.

#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

У меня была та же проблема сегодня: m1.c и m2.c оба имели основную функцию, но должны были быть связаны и запускать одну из них. Решение: пользовательский STRIP для удаления основного символа из одного из них после компиляции, но перед связыванием:

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

будет работать main из m2

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

будет запускаться main из 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

Ответ 6

Я бы использовал разные файлы и делал для тестирования и сборки, но если у вас есть файл с

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

и

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

тогда параметры компилятора для выбора одного или другого в качестве основного являются -Dtest_main=main и -Dprod_main=main

Ответ 7

Изменить: Билли победил меня до ответа, но вот немного больше фона

Более непосредственно, основная функция обычно больше зависит от стандартной библиотеки. Вещь, которая вызывает main, не является C, а скорее стандартной библиотекой. ОС загружает приложение, передает управление в точку входа библиотеки (_start в GCC), и библиотека в конечном итоге вызывает 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. Свяжите один для модульных тестов, а другой для нормального использования.

Ответ 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

Ответ 9

Возможно, вам придется запускать ld отдельно, чтобы использовать их, но ld поддерживает скрипты для определения многих аспектов выходного файла (в том числе точка входа).

Ответ 10

Прежде всего, вы не можете иметь две функции с именем main в одной компиляции, поэтому либо источники находятся в разных файлах, либо вы используете условную компиляцию. В любом случае вы должны получить два разных файла .o. Поэтому вам не нужен вариант компоновщика; вы просто передаете файл .o, который вы хотите использовать в качестве аргумента.

Если вам это не нравится, вы можете делать причудливые вещи с помощью dlopen(), чтобы вытащить main из любого объектного файла, который вы назвали динамически. Я могу представить себе обстоятельства, когда это может быть полезно. Например, вы применяете системный подход к модульным тестам, просто помещаете их в каталог, а ваш код ходит по каталогу, захватывает каждый объектный файл, динамически загружает его и запускает его тесты. Но чтобы начать, возможно, что-то более простое.

Ответ 11

Если вы используете в LD "-e symbol_name" (где, конечно, имя_файла - ваша основная функция), вам также нужно "-nostartfiles", иначе будет произведена ошибка "undefined reference to main".