Как правильно связать в C, чтобы символы не были удалены? - PullRequest
4 голосов
/ 02 октября 2011

У меня возникли проблемы с правильной связью с библиотеками в C.

Я уверен, что это одно из тех загадочных правил связывания C, которые я не до конца понимаю, но не могу понять.

У меня есть библиотека libn, которую я компилирую в статическую библиотеку, libn.a

nm libn показывает:

doug@ninja:~/projects/libnw/build$ nm ../../libn/build/libn.a |grep nIndex
00000034 T nIndex
00000000 D nIndex_
00000026 T nIndex_finalize
00000013 T nIndex_init
00000000 T nIndex_map

У меня также есть библиотека libnw, которая зависит от libn,nm на libnw показывает:

doug@ninja:~/projects/libnw/build$ nm libnw.a |grep Index
         U nIndex

Однако, когда я компилирую программирование, связанное с libnw и libn, я получаю:

doug@ninja:~/projects/libnw/build$ make
[ 70%] Built target nw
[ 80%] Built target test-template
Scanning dependencies of target test-Core
[ 85%] Building C object tests/nw/mvc/Core/CMakeFiles/test-Core.dir/Tests.c.o
[ 90%] Building C object tests/nw/mvc/Core/CMakeFiles/test-Core.dir/test.c.o
Linking C executable test-Core
../../../../libnw.a(Impl.c.o): In function `nwCore__Impl_init':
/home/doug/projects/libnw/src/nw/mvc/Core/Impl.c:76: undefined reference to `nIndex'
collect2: ld returned 1 exit status
make[2]: *** [tests/nw/mvc/Core/test-Core] Error 1
make[1]: *** [tests/nw/mvc/Core/CMakeFiles/test-Core.dir/all] Error 2
make: *** [all] Error 2

Причина вполне понятна.Когда Tests.c -> Tests.co, он не выбирает nIndex как символ, который необходимо сохранить:

doug@ninja:~/projects/libnw/build$ nm tests/nw/mvc/Core/CMakeFiles/test-Core.dir/Tests.c.o 
         U MyController
000005a4 T Tests
00000000 D Tests_
00000125 T Tests_can_attach_controller
00000080 T Tests_can_create_core
000003d3 T Tests_can_handle_native_event
000001c8 T Tests_can_set_controller
00000322 T Tests_can_update
00000000 t Tests_core_factory
0000056c T Tests_finalize
000005c0 T Tests_getType
0000048c T Tests_init
         U nFactory
         U nTest
         U nType_nalloc
         U nType_nfree
         U nwCore
         U nwDummyContext_getType
         U nwDummyEvents_getType
         U nwDummyRender_getType
         U nwIContext_getType
         U nwIEvents_getType
         U nwIRender_getType

(обратите внимание на полное отсутствие U nIndex в объектном файле tests).

Итак, я могу легко это исправить, добавив вызов nIndex () в моем скрипте тестов, но это не решает основной проблемы:

Программа зависит от liba, зависит от libb, liba имеетпропущенные символы из libb нужно устранить, но программа не имеет ссылок на эти символы, поэтому они, похоже, удаляются.

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

(Да, ясборка с использованием cmake и в зависимости от статически построенных версий libn и libnw).

Редактировать:

Теперь со строкой компоновщика:

/usr/bin/gcc  -std=c99 -g   CMakeFiles/test-Core.dir/Tests.c.o \
      CMakeFiles/test-Core.dir/test.c.o \
      CMakeFiles/test-Core.dir/helpers/MyController.c.o \
      CMakeFiles/test-Core.dir/helpers/MyModel.c.o \
      -o test-Core -rdynamic \
      /home/doug/projects/tapspin-android/source/deps/libn/build/libn.a \
      ../../../../libnw.a 

Ответы [ 3 ]

5 голосов
/ 02 октября 2011

Я не вижу вашей линии связи, поэтому мне сложно сказать наверняка, но похоже, что это может быть проблемой упорядочения.

Если все символы, необходимые для libb, находятся в liba, затем вы должны сначала перечислить libb, чтобы они были перечислены как символы, которые необходимо разрешить, а при посещении libb они будут разрешены.Это не само по себе удаление, оно просто не включает (то есть это упущение, а не активное удаление, я расщепляю волосы? Может быть)

Кроме того, иногда, если есть циклическая зависимость (liba потребностинекоторым символам из libb и libb нужны символы из liba) нужно несколько раз перечислить libs (это не ответ cmake, так как я не использую cmake, но для многих использовал линкерыгода, это обычная ошибка).

Обратите внимание, что в отличие от символов из библиотек, все символы из объектных файлов связаны

Самый простой способ исправить это сначала поменять местами порядок двух библиотек

1 голос
/ 26 ноября 2014

Чтобы найти правильный порядок зависимых библиотек, можно использовать следующий конвейер команд * nix:

lorder libA.a libB.a ... | tsort

Если получено сообщение об ошибке циклической ссылки, то, хотя вышеупомянутый GCC Kludge используетstart-group и --end-group будут работать, или просто перечислять нарушающие библиотеки во второй раз, действительно нужно исправить библиотеки, чтобы они не имели циклических зависимостей.

1 голос
/ 18 июня 2013

Поскольку проблема связывания заказа является проблемой, вы также можете решить ее с помощью

- старт-группа

- конец группы

GCC: каковы параметры командной строки --start-group и --end-group?

Это работает, пока мы говорим о статических библиотеках / архивных файлах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...