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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4623364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:58:11  来源:igfitidea点击:

"undefined reference" when linking against a static library

c++static-libraries

提问by ant2009

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

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

I have the following static library called sdpAPI.a. I am having problems trying to link it with my test application. Just wondering if I am doing something wrong. The static library has been built with g++;

我有以下名为 sdpAPI.a 的静态库。我在尝试将它与我的测试应用程序链接时遇到问题。只是想知道我是否做错了什么。静态库已经用 g++ 构建;

My directory is as follows:

我的目录如下:

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

My source code is this:

我的源代码是这样的:

#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;
}

And my Makefile is this:

我的 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) *~

These are the linker errors I am getting:

这些是我收到的链接器错误:

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

Many thanks for any suggestions,

非常感谢您的任何建议,

回答by paxdiablo

-Lspecifies the library path, not a specific library. You probably want -L sdp/lib -l sdpAPIto specify both the path andthe library name.

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

Although it will try to prefix and postfix your library name with liband either .aor .sl(or similar).

尽管它会尝试使用lib和或.a.sl(或类似的)前缀和后缀您的库名称。

So you may also need to rename your library to libsdpAPI.aas per the gcc manpage:

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

-l xyz
     The linker searches a standard list of directories for the library, which is actually a file named libxyz.a.

-l xyz
     链接器搜索库的标准目录列表,该库实际上是一个名为libxyz.a.



Also keep in mind that the order of things in the command line matters. By doing $(CC) $(CFLAGS) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET)(libraries before objects), there are no unresolved symbols at the point where you list the library, so nothing will be brought in from that library.

还要记住,命令行中的顺序很重要。通过这样做$(CC) $(CFLAGS) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET)(对象之前的库),在您列出库的位置没有未解析的符号,因此不会从该库中引入任何内容。

Then, when you finally bring in the objects (with their unresolved symbols), they stayunresolved because there are no libraries listed after that.

然后,当您最终引入对象(带有未解析的符号)时,它们保持未解析状态,因为之后没有列出任何库。

You should usually do libraries after objects:

你通常应该在对象之后做库:

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

to ensure all unresolved symbols are known before checking the libraries.

在检查库之前确保所有未解析的符号都是已知的。

This won't catch all problems (such as co-dependent libraries which can be fixed using other means) but it will ensure all unresolved symbols in the objectfiles are known about before looking at the libraries.

这不会捕获所有问题(例如可以使用其他方式修复的相互依赖的库),但它会确保在查看库之前了解目标文件中所有未解析的符号。

From the same section of the man page quoted above:

来自上面引用的手册页的同一部分:

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.osearches library zafter file foo.obut before bar.o. If bar.orefers to functions in z, those functions may not be loaded.

在命令中编写此选项的位置有所不同;链接器按照指定的顺序搜索和处理库和目标文件。因此,foo.o -lz bar.o搜索库z文件后,foo.o但在此之前bar.o。如果bar.o引用 中的函数z,则可能不会加载这些函数。

回答by icecrime

  • -Lis used to specify a library path:

    -LdirAdd directory dir to the list of directories to be searched for -l.

  • -lis what you need to specify which libraryto link against :

    -llibrarySearch the library named library when linking.

  • -L用于指定库路径

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

  • -l您需要指定要链接的

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

You probably need -L sdp/lib/ -l sdpAPI

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

回答by mna

How exactly the different options especially -l and -static worked confused me for a long time. Finally did a man gcc to get more details that I wasn't able to find online. Hope this helps someone else too

不同的选项,尤其是 -l 和 -static 究竟是如何工作的,让我困惑了很长时间。最后做了一个 man gcc 以获得更多我无法在网上找到的细节。希望这对其他人也有帮助

-llibrary -l library Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)

-llibrary -l library 链接时搜索名为 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 On systems that support dynamic linking, this prevents linking with the shared libraries. On other systems, this option has no effect.

-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 Add directory dir to the list of directories to be searched for -l.

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

回答by ArtificiallyIntelligence

Three flags you need to know:

你需要知道的三个标志:

-Ldir -lLIB -static

-Ldir -lLIB -static

Since you want to link with static library, you need the third flag. Otherwise, you will end up with linking with a dynamic library.

由于要与静态库链接,因此需要第三个标志。否则,您最终会链接到一个动态库。