Почему при связывании с архивом возникают ошибки «множественного определения»? - PullRequest
3 голосов
/ 03 февраля 2012

Я использую CppUTest для тестирования кода C, определенного в исходном файле fornol.c.Этот файл определяет основную производственную функцию main().

У меня также есть файл AllTests.cpp, который также имеет функцию main(), но этот main() должен использоваться только при выполнении модульных тестов..

AllTests.cpp компилируется в файл .o, тогда как fornol.c компилируется в архив libfornol.a.

Затем CppUTest пытается связать все вместе, но вот чтоВместо этого я получаю:

Linking fornol_tests
cc    -o fornol_tests objs/tests/AllTests.o objs/tests/FornolTests.o lib/libfornol.a ../../CppUTest/lib/libCppUTest.a ../../CppUTest/lib/libCppUTestExt.a -lstdc++ -lgcov
lib/libfornol.a(fornol.o): In function `main':
/home/dlindelof/Work/endor/nol/fornol/fornol.c:453: multiple definition of `main'
objs/tests/AllTests.o:/home/dlindelof/Work/endor/nol/fornol/tests/AllTests.cpp:4: first defined here
collect2: ld returned 1 exit status

Похоже, что функция main(), определенная в fornol.c и присутствующая в архиве libfornol.a, конфликтует с main(), определенным в AllTests.cpp.Но, насколько я понимаю, поиск файлов архива / библиотеки возможен только в том случае, если / когда на данный символ еще не было ссылки.Поэтому не должно быть проблемой, чтобы один и тот же символ определялся более одного раза, при условии, что все определения находятся в файлах архива / библиотеки.

Что я здесь не так делаю?

Ответы [ 2 ]

4 голосов
/ 03 февраля 2012

Вам необходимо удалить main() из AllTests.cpp и поместить его в собственный исходный файл.

Когда компоновщик связывается с библиотекой, он не может разбивать объектные файлы вбиблиотека; он должен либо связывать, либо опускать каждый объектный файл в библиотеке как единое целое.(Я знаю, что LLVM отличается, но это другая тема.) Вот почему, если вы посмотрите на источник для библиотеки, такой как glibc, каждая функция получит свой собственный исходный файл.

Итак, что с вами происходит,компоновщик должен извлечь объектный файл (fornol.o) из библиотеки (libfornol.a), чтобы удовлетворить зависимости, но этот объектный файл несет с собой дублированный символ (main).

Это прекрасноможно поместить тестовый код в библиотеку (мы обычно делаем это там, где я работаю), но храните его в собственных исходных файлах (мы традиционно используем main.cc).(В любом случае, это лучший тест, потому что тестовый код не должен иметь доступа к static -объявленным символам.)

0 голосов
/ 03 февраля 2012

Предполагается, что библиотека не имеет функции main (), так как это библиотека .

Вы должны удалить этот main () из fornol.c и скомпилировать его снова.

main () - это точка входа исходного кода исполняемого файла, поскольку библиотека (особенно статическая библиотека ".a") - это только предварительно скомпилированный исходный код, в ней нельзя использовать main.

Если вам нужна главная производственная точка входа вашей библиотеки, вы можете переименовать main () в fornol.c во что-то более явное и менее зарезервированное, например, например, в fornolMain ().

Статическая библиотека скомпилирована в вашем двоичном исполняемом файле и, таким образом, не ищется, только если загружен символ. Это точно так же, как компиляция fornol.c и компоновка fornol.o и вашего другого .o

...