-1

I use CMake 3.5.2. When trying to build my C++ code I get the following error:

[100%] Linking CXX executable SomeExecutable
CMakeFiles/SomeExecutable.dir/Common/src/FunctionOne.cpp.o: In function `FunctionOne::FunctionOne(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double, double, unsigned int, bool)':
FunctionOne.cpp:(.text+0x490): undefined reference to `Helper::initLevel(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)'

The program doesn't find Helper::initLevel() in myLib.so. How do I fix it?

CMakeLists.txt: (shortened for brevity)

cmake_minimum_required(VERSION 3.0)
project(ProjectName)

add_definitions(-std=c++11)
add_definitions(-Wall)
add_definitions(-O2)

link_directories(/usr/local/lib)    

add_executable(SomeExecutable SomeExecutable.cpp ${FunctionOne} ${FunctionTwo})
target_link_libraries(SomeExecutable -pthread -lboost_thread ${Boost_LIBRARIES} myLib armadillo)

File structure (shortened for brevity):

├── bin
├── CMakeCache.txt
├── cmake_install.cmake
├── CMakeLists.txt
├── Common
│   ├── include
│   │   ├── dataContainer.h
│   │   ├── FunctionOne.h
│   │   ├── FunctionTwo.h
│   └── src
│       ├── FunctionOne.cpp
│       └── FunctionTwo.cpp
├── SomeExecutable.cpp
├── myLib
│   ├── example.cpp
│   ├── include
│   │   ├── Config.h
│   │   ├── Helper.h
│   ├── libmyLib.so

UPDATE:

myLib/include/Config.h:

Namespace Helper {
[...]
    Level* initLevel(const std::string& jsonLvlPath, bool twiceSpatPts =        false);
[..]
}

UPDATE 2:

kepj@laptop:~/ProjectName$ make VERBOSE=1
/usr/bin/cmake -E cmake_link_script CMakeFiles/SomeExecutable.dir/link.txt --verbose=1
/usr/bin/c++      CMakeFiles/SomeExecutable.dir/SomeExecutable.cpp.o CMakeFiles/SomeExecutable.dir/Common/src/FunctionOne.cpp.o CMakeFiles/SomeExecutable.dir/Common/src/FunctionTwo.cpp.o SomeExecutable  -L/usr/local/lib -rdynamic -pthread -lboost_thread -lboost_system -lboost_filesystem -lmyLib -lsymbolicc++ -lmatio -larmadillo -Wl,-rpath,/usr/local/lib 
CMakeFiles/SomeExecutable.dir/Common/src/FunctionTwo.cpp.o: In function `FunctionTwo::FunctionTwo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double, double, unsigned int, bool)':
FunctionTwo.cpp:(.text+0x490): undefined reference to `Helper::initLevel(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)'
collect2: error: ld returned 1 exit status
CMakeFiles/SomeExecutable.dir/build.make:174: recipe for target 'SomeExecutable' failed
make[2]: *** [SomeExecutable] Error 1
make[2]: Leaving directory '/home/kepj/ProjectName'
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/SomeExecutable.dir/all' failed
make[1]: *** [CMakeFiles/SomeExecutable.dir/all] Error 2
make[1]: Leaving directory '/home/kepj/ProjectName'
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
kepj
  • 3
  • 1
  • 5

1 Answers1

1

So there is technically still not enough information about this issue to answer this question with certainty, but I am going to share how I would debug this isssue, only knowing what is in the question, explaining each step along the way.

Make sure you are linking to the correct myLib.so

This one is pretty explanatory, and would be my best guess as to the root of this problem.

Relevant compiler flags: -L/usr/local/lib -lmyLib

When trying to find the library you specified with the -l argument to your compile command, there is a series of steps that the linker takes: 1. It sees if the argument passed to -l was an absolute path (entire path to the library, ie starting with / on *nix computers or a drive letter on Windows) or just a name. If it is a absolute path, then it knows where it is. In this case, it is just a name, so continue on to step 2. 2. The next place to look is in the paths specified in -L arguments. In this case the only -L argument is to /usr/local/lib so it looks there. This may or may not be where it is found for this specific case. Look in your filesystem to see if the file /usr/local/lib/libmyLib.so exists, and if so make sure that is the version that is most recenpt. 3. Now it searches in configured linker paths. Use the same steps as in step 2 for each of these paths.

This is my guess because there is no reference to your myLib folder in your linker arguments, yet you claim it is in that folder, so I think it is using an out of date myLib.so.

Make sure the .so or .a file actually has the symbol that is undefined

On linux, you can list the symbols defined in a .so file. Make sure the symbol that is resolving to undefined is in there.

If they aren't there, here are the possible causes:

  1. You aren't using all the C++ source files (.cpp) to create your library.
  2. The definition and the declaration don't match:
    1. You forgot to enter namespace Helper before defining the function
    2. You misspelled the function name
    3. The arguments/return type don't match
    4. For member functions, you forgot to include MyClass:: before the function name.

ABI mismatch

(thanks to n.m in the comments for pointing this out)

Because there are multiple implementations (and versions) of the C++ standard library, it is possible that you have an ABI Mismatch.

This means that the standard library that myLib was compiled with is not compatable with the one you are trying to compile your executable with. For example, when you compile myLib with libstdc++ on linux, then go to mac and try to compile your executable, where the standard library is libc++ you will get errors. Why? The signature for anything, for example std::string is not the same. They are different classes entirely, and will cause a signature mismatch while linking.

Community
  • 1
  • 1
Russell Greene
  • 2,141
  • 17
  • 29