Library Is Linked But Reference Is Undefined

library is linked but reference is undefined

From the gcc man page:

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

So try to specify the -lOpenCL after the file argument in your compile command.

You also search for symbols in libOpenCL.so, which is a shared library file. With your command you link your program agains a static library, in the format libOpenCL.a.

`ld` undefined reference error, but libraries are linked to by CMake and symbols exist

Fix /h3>

The cause of the linker errors was this statement:

if(LINUX)

The fix was to replace it with this:

if(UNIX AND NOT APPLE)

This commit fixes the problem:

Commit

Reference: https://stackoverflow.com/a/40152725/3405291

Strangely, CMake wasn't complaining about anything and just throwing random linker errors.

Linking C++ to static library; undefined reference errors

The library libEAPI.a contains object files compiled in C, not C++.
The symbols therefore have not been name-mangled and cannot serve to
resolve the name-mangled function references generated by your C++
code.

Run:

nm libEAPI.a | grep EApiFanDisable

and you will see no change.

Run:

nm main.o | grep EApiFanDisable

and you will see the mangled symbol, which is neither EApiFanDisable nor EApiFanDisable()
but something more like _Z14EApiFanDisablev, that the linker is actually trying
to resolve.

To avoid these linkage errors you must inform your C++ compiler, when it
compiles the header file(s) of libEAPI, that the declarations therein have
external C linkage, so it will emit unmangled references to the symbols declared: like so:

main.cpp

...
extern "C" {
#include "EAPI.h" // or whatever
}

...

BTW, this commandline:

g++  -o secoTest -lpthread  main.o  libEAPI.a

will fail to link libpthread on a Debian-based distro (Ubuntu et al)
more recent than Debian 6, as all libraries must be linked in dependency order since then:

g++  -o secoTest main.o  libEAPI.a -lpthread

Even better, do not use the non-portable -lpthread and pass the portable
option -pthread for both compilation and linkage. It means: Do whatever
is right to compile/link with Posix Threads support

How is linking failing: Undefined reference to library

You need to link the libraries in the right order - it sounds like Utilities.a needs to be linked last. I don't know how you do that in Qt but that's what you need to achieve.

Undefined references even though library is linking and it contains correct symbols

The fact that linker reports unresolved external symbols as ptp_usb_sendreq(_PTPParams*, _PTPContainer*) means that those symbols are mangled in C++ way (otherwise, function arguments would not be visible).

At the same time, nm reports the symbol as ptp_usb_sendreq, which means, it is not mangled.

Most likely solution: check and make sure your function signature (likely in a header file) is wrapped in extern "C" specifier.

Undefined reference to functions while linking to static library

do I need to include X.a only or do I need to include both libaries to my code?

You don't "include" libraries in your code, you link them in.

When you link against X.a, the linker copies used parts of the library into your executable.

When you link against a.so, the linker makes a note that a.so is required at runtime, and (if you are using versioned symbols) which versions of symbols from a.so must be present at runtime, but doesn't copy any code from a.so into your executable. However, a.so is still required on the link time.

There are ways to link an executable without a.so, but they are best left to experts (there are too many possible gotcha's with that approach).

Undefined reference in transitive library linking

CMake has no issue with circular dependencies between static libraries. Just declare the actual dependencies and CMake will take care of the rest. Here is my revised CMakeLists.txt:

cmake_minimum_required(VERSION 3.22)
project(config)

set(CMAKE_CXX_STANDARD 11)

add_library(A STATIC A/A.cpp)
target_include_directories(A PUBLIC "${CMAKE_CURRENT_LIST_DIR}/A")
target_link_libraries(A PRIVATE B)

add_library(B STATIC B/B.cpp)
target_include_directories(B PUBLIC "${CMAKE_CURRENT_LIST_DIR}/B")
target_link_libraries(B PRIVATE A)

add_library(C STATIC C/C.cpp)
target_include_directories(C PUBLIC "${CMAKE_CURRENT_LIST_DIR}/C")
target_link_libraries(C PRIVATE B)

add_executable(main main.cpp)
target_link_libraries(main PRIVATE C)

Using your exact sources, I can build and run like so:

$ cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=Release
...
$ cmake --build build --verbose
[1/8] /usr/bin/c++ -I/path/to/B -I/path/to/A -O3 -DNDEBUG -std=gnu++11 -MD -MT CMakeFiles/B.dir/B/B.cpp.o -MF CMakeFiles/B.dir/B/B.cpp.o.d -o CMakeFiles/B.dir/B/B.cpp.o -c /path/to/B/B.cpp
[2/8] /usr/bin/c++ -I/path/to/A -I/path/to/B -O3 -DNDEBUG -std=gnu++11 -MD -MT CMakeFiles/A.dir/A/A.cpp.o -MF CMakeFiles/A.dir/A/A.cpp.o.d -o CMakeFiles/A.dir/A/A.cpp.o -c /path/to/A/A.cpp
[3/8] : && /usr/bin/cmake -E rm -f libB.a && /usr/bin/ar qc libB.a CMakeFiles/B.dir/B/B.cpp.o && /usr/bin/ranlib libB.a && :
[4/8] : && /usr/bin/cmake -E rm -f libA.a && /usr/bin/ar qc libA.a CMakeFiles/A.dir/A/A.cpp.o && /usr/bin/ranlib libA.a && :
[5/8] /usr/bin/c++ -I/path/to/C -O3 -DNDEBUG -std=gnu++11 -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /path/to/main.cpp
[6/8] /usr/bin/c++ -I/path/to/C -I/path/to/B -O3 -DNDEBUG -std=gnu++11 -MD -MT CMakeFiles/C.dir/C/C.cpp.o -MF CMakeFiles/C.dir/C/C.cpp.o.d -o CMakeFiles/C.dir/C/C.cpp.o -c /path/to/C/C.cpp
[7/8] : && /usr/bin/cmake -E rm -f libC.a && /usr/bin/ar qc libC.a CMakeFiles/C.dir/C/C.cpp.o && /usr/bin/ranlib libC.a && :
[8/8] : && /usr/bin/c++ -O3 -DNDEBUG CMakeFiles/main.dir/main.cpp.o -o main libC.a libB.a libA.a libB.a libA.a && :
$ ./build/main
Config ID: 2

As you can see, the final link line produces C B A B A. The latter two don't hurt anything since they'll never actually be searched.


If you want to break the cycle, you can break off the part of B that A needs into another library and make both of them depend on it.

Now I have the following files:

// A/A.cpp
#include "common.hpp"

Config MY_CONFIG = {
.id=2
};
// common/common.hpp

typedef struct Config {
int id;
} Config;
// B/B.cpp

#include "B.hpp"
#include "common.hpp"

extern Config MY_CONFIG;

int get_config_id () {
Config work = MY_CONFIG;
return work.id;
}
// B/B.hpp

int get_config_id ();

The build is then adjusted like so:

cmake_minimum_required(VERSION 3.22)
project(config)

set(CMAKE_CXX_STANDARD 11)

add_library(common INTERFACE)
target_include_directories(common INTERFACE "${CMAKE_CURRENT_LIST_DIR}/common")

add_library(A STATIC A/A.cpp)
target_include_directories(A PUBLIC "${CMAKE_CURRENT_LIST_DIR}/A")
target_link_libraries(A PRIVATE common)

add_library(B STATIC B/B.cpp)
target_include_directories(B PUBLIC "${CMAKE_CURRENT_LIST_DIR}/B")
target_link_libraries(B PRIVATE common A)

add_library(C STATIC C/C.cpp)
target_include_directories(C PUBLIC "${CMAKE_CURRENT_LIST_DIR}/C")
target_link_libraries(C PRIVATE B)

add_executable(main main.cpp)
target_link_libraries(main PRIVATE C)

and when we build, we see that the link order is correct and the duplicated libraries have disappeared:

$ cmake --build build --verbose
[1/8] /usr/bin/c++ -I/path/to/A -I/path/to/common -O3 -DNDEBUG -std=gnu++11 -MD -MT CMakeFiles/A.dir/A/A.cpp.o -MF CMakeFiles/A.dir/A/A.cpp.o.d -o CMakeFiles/A.dir/A/A.cpp.o -c /path/to/A/A.cpp
[2/8] /usr/bin/c++ -I/path/to/B -I/path/to/common -I/path/to/A -O3 -DNDEBUG -std=gnu++11 -MD -MT CMakeFiles/B.dir/B/B.cpp.o -MF CMakeFiles/B.dir/B/B.cpp.o.d -o CMakeFiles/B.dir/B/B.cpp.o -c /path/to/B/B.cpp
[3/8] : && /usr/bin/cmake -E rm -f libA.a && /usr/bin/ar qc libA.a CMakeFiles/A.dir/A/A.cpp.o && /usr/bin/ranlib libA.a && :
[4/8] : && /usr/bin/cmake -E rm -f libB.a && /usr/bin/ar qc libB.a CMakeFiles/B.dir/B/B.cpp.o && /usr/bin/ranlib libB.a && :
[5/8] /usr/bin/c++ -I/path/to/C -O3 -DNDEBUG -std=gnu++11 -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /path/to/main.cpp
[6/8] /usr/bin/c++ -I/path/to/C -I/path/to/B -O3 -DNDEBUG -std=gnu++11 -MD -MT CMakeFiles/C.dir/C/C.cpp.o -MF CMakeFiles/C.dir/C/C.cpp.o.d -o CMakeFiles/C.dir/C/C.cpp.o -c /path/to/C/C.cpp
[7/8] : && /usr/bin/cmake -E rm -f libC.a && /usr/bin/ar qc libC.a CMakeFiles/C.dir/C/C.cpp.o && /usr/bin/ranlib libC.a && :
[8/8] : && /usr/bin/c++ -O3 -DNDEBUG CMakeFiles/main.dir/main.cpp.o -o main libC.a libB.a libA.a && :

**Undefined reference** error while linking two libraries referring to one-another

Libraries must be listed in the order their symbols are needed.

The command cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1 tells the linker to first use the func2 library to resolve any pending references in the executable it is building and then to use the func1 library.

Since the linker processes func2 first, and, at the time it does so, there is no pending reference to print2, the linker does not include the module with print2 in the executable.

Later, when the linker is processing func1, it includes the module with print1 in the executable because main uses it. That module print1 uses print2, so including that module adds a new reference to print2. Then, when the linker is done processing func1, it has an unresolved reference. The linker does not go back to func2 to check it again.

Since the func1 library depends on func2, change the link command to cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc1 -lfunc2.

(If the func2 library also depends on func1, that is a bad design and should be reconsidered. If it is not changed, asking the linker to reconsider the libraries multiple times, as with -lfunc1 -lfunc2 -lfunc1, might fix the immediate problem, but others can arise.)



Related Topics



Leave a reply



Submit