Я пытаюсь включить статическую библиотеку, созданную мной с помощью статического метода, но получаю следующую ошибку во время выполнения при попытке вызвать метод:
[ INFO] [1528271039.635221775]: Initializing nodelet with 4 worker threads. /opt/ros/kinetic/lib/nodelet/nodelet: symbol lookup error:/catkin_ws/devel/lib//libmission_manager_nodelet.so: undefined symbol: _ZN14my_commons10ConsoleLog6ROSLogEiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_
статическая библиотека имеет 2 файла: ConsoleLog.h:
#ifndef CONSOLE_LOG_H
#define CONSOLE_LOG_H
#include "ros/ros.h"
namespace my_commons
{
class ConsoleLog
{
public:
static void ROSLog(int type, std::string message,std::string taskName);
static void STDLog(int logType, std::string msg,std::string taskName);
};
} // namespace my_commons
#endif //CONSOLE_LOG_H
и ConsoleLog.cpp:
#include "ConsoleLog.h"
namespace my_commons
{
void ConsoleLog::ROSLog(int type, std::string message, std::string task)
{
switch (type)
{
case (0):
ROS_DEBUG_STREAM("########## " << task << " DEBUG: " << message << " ##########");
break;
case (1):
ROS_INFO_STREAM("########## " << task << " " << message << " ##########");
break;
case (2):
ROS_WARN_STREAM("########## " << task << " WARNNING: " << message << " ##########");
break;
case (3):
ROS_ERROR_STREAM("########## " << task << " ERROR: " << message << " ##########");
break;
}
}
void ConsoleLog::STDLog(int logType, std::string msg, std::string task)
{
std::cout << msg << std::endl;
}
} // namespace my_commons
CMakelist.txt:
cmake_minimum_required(VERSION 2.8.3)
project(my_commons)
set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}")
find_package(catkin REQUIRED COMPONENTS
roscpp
)
catkin_package(CATKIN_DEPENDS
INCLUDE_DIRS include)
include_directories(
${catkin_INCLUDE_DIRS}
include/
)
###########
## Build ##
###########
add_library(my_commons
src/ConsoleLog.cpp
)
## Specify libraries to link a library or executable target against
set_target_properties(my_commons PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(my_commons
${catkin_LIBRARIES}
${roscpp_LIBRARIES}
)
#add_dependencies(name_of_package_nodelet)
install(DIRECTORY include/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE)
# Install library
install(TARGETS my_commons
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
Редактировать:
Вот клиент CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.3)
project(my_mission_manager)
set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}")
find_package(catkin REQUIRED COMPONENTS
roscpp
nodelet
std_msgs
my_commons
message_runtime
std_srvs
)
catkin_package(
CATKIN_DEPENDS
message_runtime
std_msgs
my_commons
)
include_directories(
${catkin_INCLUDE_DIRS}
include/
)
###########
## Build ##
###########
add_library(my_mission_manager_nodelet
src/my_mission_manager_nodelet.cpp
)
## Specify libraries to link a library or executable target against
target_link_libraries( my_mission_manager_nodelet
${catkin_LIBRARIES}
${roscpp_LIBRARIES}
)
#add_dependencies(my_mission_manager_nodelet)
# Install library
install(TARGETS my_mission_manager_nodelet
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
# Install header files
install(DIRECTORY src/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
)
# Install launch files
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
)
# Install xml files
install(FILES nodelet_plugins.xml
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)
Что мне здесь не хватает?
Кстати, я могу использовать данные из файлов заголовков в my_commons (перечисления), проблема возникает при попытке добавить файл cpp и вызвать в нем статический метод.
Спасибо за помощь!
Добавлена недостающая строка ... вы можете попробовать еще раз? Спасибо вам за помощь.
Конечно, это не работает, потому что вы не предоставили никаких исходных файлов для своей библиотеки - следовательно, ваш проект даже не скомпилирован - поэтому у вас отсутствует символ. add_library(my_commons <here you should put sth like MyCommons.cpp>). set_target_properties(my_commons PROPERTIES LINKER_LANGUAGE CXX) - это своего рода взлом, а не хорошая практика. Ваши команды установки также немного взломаны. Чего вы вообще пытаетесь достичь?
Вы говорите, что у вас есть статическая библиотека, но я не вижу, где вы с ней связываетесь.
@ Ptaq666 Мне плохо с копированием сюда. добавил недостающую строку ...
@ Цыварев, что ты имеешь в виду? это библиотека, которую я пытаюсь использовать ... Я включаю ее в другой проект. Возможно, мне здесь не хватает чего-то фундаментального, так как я впервые пытаюсь создать статическую библиотеку C++, так что извините, если я не в курсе ...
О, так это CMakeLists.txt с строит библиотеку, а не с использует. Вы собираете библиотеку по стандарту c++0x ABI. Но у неопределенного символа есть подстрока __cxx11, поэтому кажется, что пользовательская библиотека скомпилирована по стандарту c++11. И могут возникнуть проблемы, когда вы попытаетесь объединить разные стандарты ABI в один исполняемый файл. См., Например, этот вопрос: stackoverflow.com/questions/33394934/…
@Tsyvarev Добавил клиентов Cmake. похоже, что это не так ...





Ниже приведен рабочий пример правильного проекта CMake:
Структура каталогов:
ROOT
|
+--inc
| +--ConsoleLog.hpp
+--src
| +--ConsoleLog.cpp
| +--main.cpp
+CMakeLists.txt
Ваш исходный и заголовочный файлы остаются неизменными (я только изменил * .h на * .hpp -> после всего, что вы пишете на C++, а не на C).
main.cpp:
#include "ConsoleLog.hpp"
int main() {
my_commons::ConsoleLog log;
log.ROSLog(1, "xxx", "yyy");
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.11)
project(my_commons)
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
find_package(catkin REQUIRED COMPONENTS roscpp)
add_library(my_commons STATIC src/ConsoleLog.cpp)
target_include_directories(my_commons PUBLIC inc ${roscpp_INCLUDE_DIRS})
target_link_libraries(my_commons ${catkin_LIBRARIES} ${roscpp_LIBRARIES})
add_executable(MyExec src/main.cpp)
target_link_libraries(MyExec my_commons)
Результат казни:
./MyExec
[ INFO] [1528280295.971205050]: ########## yyy xxx ##########
Я использую более новую версию CMake, чтобы иметь возможность использовать target_include_directories, потому что мне нравится эта функция. Я изменил флаги вашего компилятора, чтобы включить стандарт C++ 11, потому что, видимо, вы его используете. Я также удалил правила INSTALL CMake, потому что они не имеют отношения к вопросу. Сообщите мне, подходит ли вам этот ответ.
=============== РЕДАКТИРОВАТЬ (чтобы ответить на комментарий OP) ==============
Что ж, у меня нет проблем с встраиванием этой библиотеки в другую структуру проекта. Полученная ошибка означает, что ваша структура каталогов неверна (каталог my_commons не существует). Дерево вашего проекта должно выглядеть так:
ROOT
|
+--MyCommonsLib (this is the root of your my_commons library)
|
+--src
| +--main.cpp
+CMakeLists.txt
А CMakeLists.txt вашего проекта может выглядеть так:
cmake_minimum_required(VERSION 2.8.11)
project(SomeSimpleProjectUsingMyCommonsLib)
add_subdirectory(MyCommonsLib)
add_executable(MyExec src/main.cpp)
target_link_libraries(MyExec my_commons)
Просто не забудьте удалить инструкцию add_executable с вашего MyCommonLib/CMakeLists.txt. Также main.cpp должен быть таким:
#include "ConsoleLog.hpp"
int main() {
my_commons::ConsoleLog::ROSLog(1, "xxx", "yyy");
return 0;
}
Извините, раньше я не замечал, что ROSLog объявлен статичным.
Привет @ Ptaq666, спасибо за ответ! Обязательно ли иметь main в статической библиотеке? все дело в том, чтобы создать класс статических методов, которые я могу использовать в разных проектах ... Вдобавок, поскольку у меня есть больше проектов с такими же флагами компилятора, я пока не хочу менять его на более новую версию .. .
Нет, конечно, не надо. Я включил только основной исполняемый файл, чтобы доказать, что решение работает. Вы можете просто встроить вашу библиотеку my_commons в CMakeLists.txt вашего проекта, вызвав add_subdirectory. Если вы хотите установить свой my_commons системно и найти его с find_package - это более сложно, потому что вам нужно создать my_commonsConfig.cmake, что еще больше усложняет вашу задачу. Как это сделать правильно - другая тема (хотя и не такая уж сложная).
Дело в том, что я могу использовать данные из файлов заголовков в библиотеке my_common. Проблема возникает только при добавлении cpp статическими методами ... при попытке add_subdirectory получил: Ошибка CMake в my_mission_manager / CMakeLists.txt: 27 (add_subdirectory): add_subdirectory для данного источника "my_commons", который не является существующим каталогом.
Это означает, что каталога my_commons не существует. Я отредактировал ответ и объяснил, как именно вы должны встроить свою библиотеку в проект.
спасибо за помощь ... Кажется, что иерархия правильная, но все равно не работает. Однако, когда я попытался переместить код из файла cpp в файл заголовка, все сработало нормально. так что теперь я запутался :)
Это невозможно (при нормальных обстоятельствах). Я уверен, что предоставленная мной структура и CMakeLists верны. Если проблема существует, это либо связано с конфигурацией системы (возможно, я не знаю об этом, и я не могу здесь помочь), либо это какой-то другой исходный файл, вызывающий проблему. Например, реализация шаблонных методов.
Позвольте нам продолжить обсуждение в чате.
Он успешно компилируется. он вылетает во время выполнения.