“undefined reference” when linking against a stati

2020-02-09 00:40发布

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++;

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:

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,

4条回答
▲ chillily
2楼-- · 2020-02-09 00:45

Three flags you need to know:

-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.

查看更多
Evening l夕情丶
3楼-- · 2020-02-09 00:45

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

-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.)

       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.

       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.

查看更多
男人必须洒脱
4楼-- · 2020-02-09 00:51

-L specifies the library path, not a specific library. You probably want -L sdp/lib -l sdpAPI to specify both the path and the library name.

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

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

-l xyz
     The linker searches a standard list of directories for the library, which is actually a file named 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.

Then, when you finally bring in the objects (with their unresolved symbols), they stay unresolved 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 object files 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.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.

查看更多
smile是对你的礼貌
5楼-- · 2020-02-09 00:58
  • -L is used to specify a library path :

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

  • -l is what you need to specify which library to link against :

    -l library Search the library named library when linking.

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

查看更多
登录 后发表回答