2016-06-23 3 views
-1

Я использую CMake 3.5.2. При попытке построить мой C++ код я получаю следующее сообщение об ошибке:CMake: undefined ссылка на

[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)' 

Программа не находит Helper :: initLevel() в myLib.so. Как это исправить?

CMakeLists.txt: (сокращен для краткости)

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) 

Файловая структура (сокращенный для краткости):

├── 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 

ОБНОВЛЕНИЕ:

MYLIB/include/Config.h:

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

UPDATE 2:

[email protected]:~/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 
+0

Итак, в каком файле находится 'Helper :: initLevel'? И на что это похоже? –

+1

Я предполагаю, что есть 'Helper.cpp', который вы забыли включить в CMake, не может быть окончательным без дополнительных данных, хотя –

+0

' initLevel' объявлен в Config.h, но где он определен? Кажется, что отсутствует в вашем скомпилированном источнике, или определение имеет другую подпись. –

ответ

0

Так что технически все еще не хватает информации об этой проблеме, чтобы ответить на этот вопрос с уверенностью, но я собираюсь поделиться тем, как я бы отладить этот isssue , только зная, что находится в вопросе, объясняя каждый шаг на этом пути.

Убедитесь, что вы ссылаетесь на правильный myLib.so

Это один довольно толковый, и будет моя догадка, чтобы корень этой проблемы.

Соответствующие флаги компилятора: -L/usr/local/lib -lmyLib

При попытке найти библиотеку, указанный с -l аргументом в вашу команду компиляции, существует целый ряд шагов, которые компоновщик принимает: 1. видит, если аргумент передается до -l был абсолютным путем (весь путь к библиотеке, то есть начиная с / на компьютерах * nix или буквой диска в Windows) или просто с именем. Если это абсолютный путь, то он знает, где он. В этом случае это просто имя, поэтому переходите к шагу 2. 2. Следующее место для поиска - это пути, указанные в аргументах -L. В этом случае аргумент -L равен /usr/local/lib, поэтому он выглядит там. Это может быть или не быть там, где оно найдено для этого конкретного случая. Посмотрите в свою файловую систему, чтобы увидеть, существует ли файл /usr/local/lib/libmyLib.so, и если да, убедитесь, что это самая последняя версия. 3. Теперь он ищет в configured linker paths. Используйте те же шаги, что и на шаге 2 для каждого из этих путей.

Это мое предположение, потому что в ваших аргументах компоновщика нет ссылки на вашу папку myLib, но вы утверждаете, что она находится в этой папке, поэтому я думаю, что она использует устаревшую версию myLib.so.

Убедитесь, что файл .so или .a на самом деле имеет символ, который не определен

В Linux, вы можете list the symbols defined in a .so file. Убедитесь, что символ, который разрешает неопределенное, находится там.

Если их нет, вот возможные причины:

  1. Вы не используете все ++ исходные файлы C (.cpp), чтобы создать свою библиотеку.
  2. Определение и объявление не совпадают:
    1. Вы забыли ввести namespace Helper перед определением функции
    2. опечатку имени функции
    3. Аргументов/типа возвращаемого значения не совпадает
    4. Для функций-членов вы забыли указать MyClass:: перед именем функции.

ABI несовпадение

(спасибо нм в комментариях указывают на это)

Поскольку существует множество реализаций (и версии) по стандартной библиотеки C++, то возможно, что у вас есть ABI Несоответствие.

Это означает, что стандартная библиотека, которую myLib была скомпилирована с , не совместима с тем, с которой вы пытаетесь скомпилировать свой исполняемый файл. Например, когда вы компилируете myLib с libstdC++ на linux, переходите к mac и пытаетесь скомпилировать ваш исполняемый файл, где стандартная библиотека libC++ вы будет получить ошибки. Зачем? Подпись для чего угодно, например std::string - это не то же самое. Они совершенно разные классы и вызовут несоответствие подписи при связывании.

+1

Вы забыли наиболее вероятную причину этой ошибки: * C++ ABI несоответствие * (если вы видите __cxx11 что-то yadda yadda, вы можете быть достаточно уверены, что это ABI). –

+0

Да, позвольте мне добавить, что –

Смежные вопросы