2017-02-08 10 views
1

я написал такой код в моей системе Ubuntu:неопределенная ссылка при компоновке динамической библиотеки в системе Ubuntu

my.h

#include <stdio.h> 
int a; 
int set(void); 

lib.c

#include "my.h" 
int set(void) { 
    a = 100; 
    return 0; 
} 

main.c

#include "my.h" 

int main(void){ 
    set(); 
    printf("a = %d\n", a); 
    return 0; 
} 

, а затем я использую следующие команды для создания их:

gcc -shared -fPIC -o libmy.so -I. lib.c 

gcc -L. -lmy -I. -o test main.c 

, когда я построить тест, я получаю информацию об ошибке:

main.c:(.text+0x5):undefined reference to 'set' 
collect2: error: ld returned 1 exit status 

но когда я использую один и тот же код, выполняемый в Fedora23 и Fedora24, он работает хорошо.

, так что я хочу знать, почему это может произойти? есть ли какие-либо ограничения в системе Ubuntu?

ответ

1

Вы потеряли разницу между соглашениями о связи Сборки GCC Fedora и сборки GCC от Debian/Ubuntu.

При вызове gcc выполнить связывание с C исполняемым это в свою очередь вызывает системный компоновщик ld, передавая ему параметры командной строки сцепления и тихо добавляет к их большое количество «шаблонных» вариантов сцепления, которые являются инвариантными для ссылок на языке C (аналогично для ссылок g++ и языка C++).

Эти параметры инвариантной связи определяются вашим дистрибутивом и настроены в их сборку GCC. Таким образом, это не инвариант через дистрибутивы.

Debian/Ubuntu GCC тихо добавляет --as-needed к параметрам связи в позиции перед вашими входными файлами и библиотеками. Fedora GCC этого не делает.

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

Это различие является разницей политики связей между дистрибутивами. Что это такое означает, что для успешной ссылки на Ubuntu ваша командная строка связи должна указывать на любую библиотеку после любого объектного файла или другой библиотеки, которая зависит от этого .И если вы компилируете-и-ссылку в одной команде, то вы должны указать любую библиотеку после любой исходный файл, соответствующий объектный файл зависит от этой библиотеки. Итак, на ubuntu, ваша проблема командной строки должна быть:

gcc -I. -o test main.c -L. -lmy 

, чтобы добиться успеха. Это, конечно же, будет работать для Fedora.

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

+0

благодарю вас. он решает мою проблему. И я хочу знать, могу ли я изменить флаги LD по умолчанию, чтобы для каждой библиотеки свойство по умолчанию было «--no-as-needed», как в FEDORA. Откуда возникают аргументы ссылки по умолчанию? благодаря! – pakade

+0

@pakade Вы не можете изменить это поведение, не создавая свою собственную привязку GCC. В Ubuntu - , как в Fedora - лучше привыкнуть к правилам, чем сражаться с ними. В некоторых странах вы едете слева от дороги, в других вы едете справа. Большинство linux devs сегодня даже не знают, что возможно связать совместно используемые библиотеки , к которым вы привыкли. Если вы действительно хотели сделать это на Ubuntu, вы бы использовали , например. 'gcc -Wl, - no-as-needed -L. -lmy -I. -o test main.c -Wl, - по мере необходимости. Но кто-то предпочел бы «gcc -I. -o test main.c -L. -lmy' –