«неопределенная ссылка» при связывании со статической библиотекой - PullRequest
25 голосов
/ 07 января 2011

g ++ (Ubuntu / Linaro 4.4.4-14ubuntu5) 4.4.5

У меня есть следующая статическая библиотека с именем sdpAPI.a. У меня возникают проблемы при попытке связать его с моим тестовым приложением. Просто интересно, делаю ли я что-то не так. Статическая библиотека была собрана с помощью g ++;

Мой каталог выглядит следующим образом:

/projects/unit_test/main.c
/projects/unit_test/sdp/inc/sdpAPH.h
/projects/unit_test/sdp/lib/sdpAPI.a

Мой исходный код такой:

#include <stdio.h>

#include "sdpAPI.h"

int main(void)
{
    printf("----- TEST SDP ------\n");

    try {
        sdpSessionDescription sdp;
        sdp.clear();
    }
    catch(...) {
        printf("----- TEST FAILED --------\n");
        return 0;
    }

    printf("------ TEST SUCCESSFULL ------\n");

    return 0;
}

А мой Makefile такой:

OBJECT_FILES = main.o
CC = g++
CFLAGS = -Wall -Wextra -Wunreachable-code -ggdb -O0
TARGET = sdp_demo

INC_PATH = -I sdp/inc
LIB_PATH = -L sdp/lib/sdpAPI.a

$(TARGET): $(OBJECT_FILES)
 $(CC) $(CFLAGS) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET)

main.o: main.c
 $(CC) $(CFLAGS) $(INC_PATH) $(LIB_PATH) -c main.c

clean:
 rm -f $(TARGET) $(OBJECT_FILES) *~

Вот ошибки компоновщика, которые я получаю:

undefined reference to `sdpSessionDescription::sdpSessionDescription()'
undefined reference to `sdpSessionDescription::clear()'
undefined reference to `sdpSessionDescription::~sdpSessionDescription()'
undefined reference to `sdpSessionDescription::~sdpSessionDescription()'

Большое спасибо за любые предложения,

Ответы [ 4 ]

44 голосов
/ 07 января 2011

-L указывает библиотеку путь , а не конкретную библиотеку. Возможно, вы хотите, чтобы -L sdp/lib -l sdpAPI указывал и путь , и имя библиотеки.

Хотя он попытается добавить префикс и постфикс к имени вашей библиотеки с помощью lib и либо .a, либо .sl (или аналогичного).

Так что вам также может понадобиться переименовать вашу библиотеку в libsdpAPI.a согласно man-странице gcc:

-l xyz
Компоновщик ищет стандартный список каталогов для библиотеки, который на самом деле является файлом с именем libxyz.a.


Также имейте в виду, что порядок вещей в командной строке имеет значение. Делая $(CC) $(CFLAGS) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET) (библиотеки перед объектами), в точке, где вы перечисляете библиотеку, нет неразрешенных символов, поэтому из этой библиотеки ничего не будет выведено.

Затем, когда вы наконец вводите объекты (с их неразрешенными символами), они остаются неразрешенными, поскольку после этого нет библиотек.

Обычно вы должны делать библиотеки после объектов:

$(CC) $(CFLAGS) $(INC_PATH) $(OBJECT_FILES) $(LIB_PATH) -o $(TARGET)

для проверки всех неразрешенных символов перед проверкой библиотек.

Это не решит все проблемы (например, создание зависимых библиотек, которые могут быть исправлены с помощью других средств), но обеспечит известность всех неразрешенных символов в файлах object перед просмотром библиотек. .

Из того же раздела справочной страницы, указанной выше:

Имеет значение, где в команде вы пишете эту опцию; компоновщик ищет и обрабатывает библиотеки и объектные файлы в указанном порядке. Таким образом, foo.o -lz bar.o ищет библиотеку z после файла foo.o, но до bar.o. Если bar.o относится к функциям в z, эти функции могут не загружаться.

10 голосов
/ 07 января 2011
  • -L используется для указания библиотеки path :

    - Ldir Добавить каталог dir в список каталоговдля поиска - l.

  • -l - это то, что вам нужно указать, какую библиотеку связать с:

    -l library Поиск библиотеки с именем library при связывании.

Возможно, вам нужно -L sdp/lib/ -l sdpAPI

2 голосов
/ 19 августа 2013

Как именно работают разные опции, особенно -l и -static, меня долго смущало. В конце концов сделал man gcc, чтобы получить больше деталей, которые я не смог найти в Интернете. Надеюсь, это поможет кому-то еще

-llibrary -l библиотека Поиск библиотеки по имени библиотеки при связывании. (Второй Альтернатива с библиотекой в ​​качестве отдельного аргумента предназначена только для Соответствие POSIX и не рекомендуется.)

       It makes a difference where in the command you write this option;
       the linker searches and processes libraries and object files in the
       order they are specified.  Thus, foo.o -lz bar.o searches library z
       after file foo.o but before bar.o.  If bar.o refers to functions in
       z, those functions may not be loaded.

       The linker searches a standard list of directories for the library,
       which is actually a file named liblibrary.a.  The linker then uses
       this file as if it had been specified precisely by name.

       The directories searched include several standard system
       directories plus any that you specify with -L.

       Normally the files found this way are library files---archive files
       whose members are object files.  The linker handles an archive file
       by scanning through it for members which define symbols that have
       so far been referenced but not defined.  But if the file that is
       found is an ordinary object file, it is linked in the usual
       fashion.  The only difference between using an -l option and
       specifying a file name is that -l surrounds library with lib and .a
       and searches several directories.

-static В системах, которые поддерживают динамическое связывание, это предотвращает связывание с общие библиотеки. В других системах этот параметр не действует.

       This option will not work on Mac OS X unless all libraries
       (including libgcc.a) have also been compiled with -static.  Since
       neither a static version of libSystem.dylib nor crt0.o are
       provided, this option is not useful to most people.

-ldir Добавить каталог dir в список каталогов для поиска -l.

0 голосов
/ 18 июня 2016

Три флага, которые нужно знать:

-ldir -lLIB -static

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

...