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

15
задан Vadim Kotov 3 November 2017 в 08:10
поделиться

9 ответов

Поместите их в отдельные файлы и укажите один файл .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
}
9
ответ дан 1 December 2019 в 00:20
поделиться

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

-e имя_символа

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

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

14
ответ дан 1 December 2019 в 00:20
поделиться

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

#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[] ) { ... }
7
ответ дан 1 December 2019 в 00:20
поделиться

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

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

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

7
ответ дан 1 December 2019 в 00:20
поделиться

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

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

0
ответ дан 1 December 2019 в 00:20
поделиться

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

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

и

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

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

6
ответ дан 1 December 2019 в 00:20
поделиться
#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

0
ответ дан 1 December 2019 в 00:20
поделиться

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

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

2
ответ дан 1 December 2019 в 00:20
поделиться

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

0
ответ дан 1 December 2019 в 00:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: