链接静态库时的“未定义引用”

时间:2011-01-07 07:24:44

标签: c++ static-libraries

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 个答案:

答案 0 :(得分:43)

-L指定库路径,而不是特定的库。您可能希望-L sdp/lib -l sdpAPI指定路径库名称。

虽然它会尝试使用lib以及.a.sl(或类似)来为您的图书馆名称添加前缀和后缀。

因此,根据gcc联机帮助页,您可能还需要将库重命名为libsdpAPI.a

  

-l xyz
  链接器搜索库的标准目录列表,该列表实际上是名为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中的函数,则可能无法加载这些函数。

答案 1 :(得分:10)

  • -L用于指定库路径

      

    - Ldir 将目录dir添加到要搜索-l的目录列表中。

  • -l是指定要链接的所需的内容:

      

    -l library 在链接时搜索名为library的库。

您可能需要-L sdp/lib/ -l sdpAPI

答案 2 :(得分:2)

特别是-l和-static的不同选项究竟是如何使我困惑了很长时间的。最后做了一个男人gcc来获取我无法在网上找到的更多细节。希望这也有助于其他人

-llibrary -l库            链接时搜索名为library的库。 (第二            作为单独参数的库的替代方案仅适用于            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。

答案 3 :(得分:0)

你需要知道三个标志:

-Ldir -llib -static

由于您想要与静态库链接,因此需要第三个标志。否则,您将最终使用动态库进行链接。