Подтвердить что ты не робот

"undefined ссылка" при связывании с статической библиотекой

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()'

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

4b9b3361

Ответ 1

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

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

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

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


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

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

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

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

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

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

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

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

Ответ 2

  • -L используется для указания пути к библиотеке:

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

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

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

Вам, вероятно, потребуется -L sdp/lib/ -l sdpAPI

Ответ 3

Как точно разные варианты, особенно -l и -static, смутили меня в течение длительного времени. Наконец, человек 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          Добавить каталог каталога в список каталогов для поиска -l.

Ответ 4

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

-ldir -lLIB -static

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