2013-09-28 5 views
1

Структура проекта ниже - упрощенный пример.Ошибка компоновки CMake (collect2: ld возвращен 1 статус выхода)

├── CMakeLists.txt 
├── debug 
├── CommBase 
│ ├── Task.h 
│ ├── Task.cpp 
│ ├── Thread.h 
│ ├── Thread.cpp 
│ └── CMakeLists.txt 
├── NetWork 
│ ├── TSocket.h 
│ ├── TSocket.cpp 
│ ├── Stream_Channel.h 
│ ├── Stream_Channel.cpp 
│ └── CMakeLists.txt 
├── MessageDispatch 
│ ├── Channel_Manager.h 
│ ├── Channel_Manager.cpp 
│ ├── Message_Facade.h 
│ ├── Message_Facade.cpp 
│ └── CMakeLists.txt 
└── DemoServer 
    ├── CMakeLists.txt 
    └── main.cpp 

./CMakeLists.txt

PROJECT(DDLIB) 
CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 

MESSAGE(STATUS "This is PROJECT_BINARY_DIR dir "${PROJECT_BINARY_DIR}) 
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) 
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) 
ADD_SUBDIRECTORY(CommBase) 
ADD_SUBDIRECTORY(NetWork) 
ADD_SUBDIRECTORY(DemoServer) 

CommBase/CMakeLists.txt

AUX_SOURCE_DIRECTORY(. LIB_SRC_LIST) 
ADD_LIBRARY(CommBase SHARED STATIC ${LIB_SRC_LIST}) 

INCLUDE_DIRECTORIES(../boost) 
INSTALL(TARGETS CommBase CommBase 
LIBRARY DESTINATION lib 
ARCHIVE DESTINATION lib) 

SET(CMAKE_BUILD_TYPE Debug) 
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") 
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") 

Сеть/СМ akeLists.txt

AUX_SOURCE_DIRECTORY(. LIB_SRC_LIST) 
ADD_LIBRARY(NetWork SHARED STATIC ${LIB_SRC_LIST}) 

INCLUDE_DIRECTORIES(../boost) 
INSTALL(TARGETS NetWork NetWork 
LIBRARY DESTINATION lib 
ARCHIVE DESTINATION lib) 
TARGET_LINK_LIBRARIES(NetWork CommBase) 
SET(CMAKE_BUILD_TYPE Debug) 
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") 
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") 

MessageDispatch/CMakeLists.txt

AUX_SOURCE_DIRECTORY(. LIB_SRC_LIST) 
ADD_LIBRARY(MessageDispatch SHARED STATIC ${LIB_SRC_LIST}) 

INCLUDE_DIRECTORIES(../boost) 
INCLUDE_DIRECTORIES(../CommBase) 
INCLUDE_DIRECTORIES(../NetWork) 
ADD_DEPENDENCIES(MessageDispatch CommBase NetWork) 
LINK_DIRECTORIES(/home/cl/server/ddsvn/debug) 
TARGET_LINK_LIBRARIES(MessageDispatch CommBase NetWork) 
INSTALL(TARGETS MessageDispatch MessageDispatch 
LIBRARY DESTINATION lib 
ARCHIVE DESTINATION lib) 

DemoServer/CMakeLists.txt

PROJECT(DDLIB) 
CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 
MESSAGE(STATUS "This is PROJECT_BINARY_DIR dir "${PROJECT_BINARY_DIR}) 
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) 
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) 
AUX_SOURCE_DIRECTORY(. SRC_LIST) 
ADD_EXECUTABLE(DemoServer ${SRC_LIST}) 
INCLUDE_DIRECTORIES(../boost) 
INCLUDE_DIRECTORIES(../CommBase) 
INCLUDE_DIRECTORIES(../NetWork) 
INCLUDE_DIRECTORIES(../MessageDispatch) 
ADD_DEPENDENCIES(DemoServer CommBase NetWork MessageDispatch) 
LINK_DIRECTORIES(/home/cl/server/ddsvn/debug) 
TARGET_LINK_LIBRARIES(DemoServer CommBase NetWork MessageDispatch) 

Linking CXX исполняемого DemoServer

/usr/bin/cmake -E cmake_link_script CMakeFiles/DemoServer.dir/link.txt --verbose=1 
/usr/bin/c++  -fPIC CMakeFiles/DemoServer.dir/stdafx.cpp.o CMakeFiles/DemoServer.dir/DemoServer.cpp.o -o DemoServer -rdynamic -lCommBase -lNetWork -lMessageDispatch 
/usr/local/lib/libMessageDispatch.a(Message_Facade.cpp.o): In function `Message_Facade::stop()': 
/home/cl/server/ddsvn/MessageDispatch/Message_Facade.cpp:80: undefined reference to `Timer_Queue::instance()' 
/home/cl/server/ddsvn/MessageDispatch/Message_Facade.cpp:80: undefined reference to `Timer_Queue::stop()' 
/usr/local/lib/libMessageDispatch.a(Message_Facade.cpp.o): In function `Message_Facade::wait()': 
/home/cl/server/ddsvn/MessageDispatch/Message_Facade.cpp:87: undefined reference to `Task::wait()' 
/home/cl/server/ddsvn/MessageDispatch/Message_Facade.cpp:88: undefined reference to `Task::wait()' 
/usr/local/lib/libMessageDispatch.a(Acceptor_Manager.cpp.o): In function `Stream_Acceptor': 
/home/cl/server/ddsvn/MessageDispatch/../NetWork/Stream_Accecptor.h:40: undefined reference to `vtable for Stream_Acceptor' 
/usr/local/lib/libMessageDispatch.a(Channel_Manager.cpp.o): In function `Channel_Manager': 
/home/cl/server/ddsvn/MessageDispatch/Channel_Manager.cpp:81: undefined reference to `Channel_Handler::~Channel_Handler()' 
/usr/local/lib/libMessageDispatch.a(Channel_Manager.cpp.o): In function `~Channel_Manager': 
/home/cl/server/ddsvn/MessageDispatch/Channel_Manager.cpp:86: undefined reference to `Channel_Handler::~Channel_Handler()' 
/home/cl/server/ddsvn/MessageDispatch/Channel_Manager.cpp:86: undefined reference to `Channel_Handler::~Channel_Handler()' 
/usr/local/lib/libMessageDispatch.a(Channel_Manager.cpp.o): In function `Channel_Handler': 
/home/cl/server/ddsvn/MessageDispatch/../NetWork/Channel_Handler.h:14: undefined reference to `vtable for Channel_Handler' 
/usr/local/lib/libMessageDispatch.a(Channel_Manager.cpp.o):(.rodata._ZTI15Channel_Manager[typeinfo for Channel_Manager]+0x28): undefined reference to `typeinfo for Channel_Handler' 
/usr/local/lib/libMessageDispatch.a(Message.cpp.o): In function `Message': 
/home/cl/server/ddsvn/MessageDispatch/Message.cpp:49: undefined reference to `Binary_Stream::Binary_Stream(int)' 
/home/cl/server/ddsvn/MessageDispatch/Message.cpp:98: undefined reference to `Binary_Stream::~Binary_Stream()' 
/home/cl/server/ddsvn/MessageDispatch/Message.cpp:100: undefined reference to `Binary_Stream::Binary_Stream(int)' 
/usr/local/lib/libMessageDispatch.a(Message.cpp.o): In function `Message::resize(int)': 
/home/cl/server/ddsvn/MessageDispatch/Message.cpp:187: undefined reference to `Stream_Base::resize(int)' 
/home/cl/server/ddsvn/MessageDispatch/Message.cpp:196: undefined reference to `Stream_Base::resize(int)' 
/usr/local/lib/libMessageDispatch.a(Message.cpp.o): In function `~Message': 
/home/cl/server/ddsvn/MessageDispatch/Message.cpp:203: undefined reference to `Binary_Stream::~Binary_Stream()' 
/home/cl/server/ddsvn/MessageDispatch/Message.cpp:203: undefined reference to `Binary_Stream::~Binary_Stream()' 
/usr/local/lib/libMessageDispatch.a(Message.cpp.o):(.rodata._ZTV7Message[vtable for Message]+0x20): undefined reference to `Stream_Base::clone_stream()' 
/usr/local/lib/libMessageDispatch.a(Message.cpp.o):(.rodata._ZTI7Message[typeinfo for Message]+0x10): undefined reference to `typeinfo for Binary_Stream' 
/usr/local/lib/libMessageDispatch.a(Connector_Manager.cpp.o): In function `Stream_Connector': 
/home/cl/server/ddsvn/MessageDispatch/../NetWork/Stream_Connector.h:42: undefined reference to `vtable for Stream_Connector' 
/usr/local/lib/libMessageDispatch.a(Context.cpp.o): In function `Context': 
/home/cl/server/ddsvn/MessageDispatch/Context.cpp:15: undefined reference to `Dispatch_Thread::Dispatch_Thread()' 
/usr/local/lib/libMessageDispatch.a(Context.cpp.o): In function `Context::initialize()': 
/home/cl/server/ddsvn/MessageDispatch/Context.cpp:113: undefined reference to `Timer_Queue::instance()' 
/home/cl/server/ddsvn/MessageDispatch/Context.cpp:113: undefined reference to `Timer_Queue::start()' 
/home/cl/server/ddsvn/MessageDispatch/Context.cpp:116: undefined reference to `Task::activate(int, int*)' 
/home/cl/server/ddsvn/MessageDispatch/Context.cpp:121: undefined reference to `Task::activate(int, int*)' 
/usr/local/lib/libMessageDispatch.a(Re_Connect_Handler.cpp.o): In function `Re_Connect_Handler::process_re_connect(Context&, int)': 
/home/cl/server/ddsvn/MessageDispatch/Re_Connect_Handler.cpp:23: undefined reference to `Timer_Queue::instance()' 
/home/cl/server/ddsvn/MessageDispatch/Re_Connect_Handler.cpp:23: undefined reference to `Timer_Queue::schedule_timer(Smart_Ptr<Timer_Handler>, Time_Value const&, Smart_Ptr<Ref_Object>, EDispatchType, Dispatch_Thread*)' 
/usr/local/lib/libMessageDispatch.a(IO_Thread.cpp.o): In function `IO_Thread': 
/home/cl/server/ddsvn/MessageDispatch/IO_Thread.cpp:4: undefined reference to `Task::Task()' 
/home/cl/server/ddsvn/MessageDispatch/IO_Thread.cpp:7: undefined reference to `Task::~Task()' 
/usr/local/lib/libMessageDispatch.a(IO_Thread.cpp.o): In function `~IO_Thread': 
/home/cl/server/ddsvn/MessageDispatch/IO_Thread.cpp:12: undefined reference to `Task::~Task()' 
/home/cl/server/ddsvn/MessageDispatch/IO_Thread.cpp:12: undefined reference to `Task::~Task()' 
/usr/local/lib/libMessageDispatch.a(IO_Thread.cpp.o):(.rodata._ZTI9IO_Thread[typeinfo for IO_Thread]+0x10): undefined reference to `typeinfo for Task' 
collect2: ld returned 1 exit status 
make[2]: *** [DemoServer] Error 1 
make[2]: Leaving directory `/home/cl/server/ddsvn/DemoServer/Debug' 
make[1]: *** [CMakeFiles/DemoServer.dir/all] Error 2 
make[1]: Leaving directory `/home/cl/server/ddsvn/DemoServer/Debug' 
make: *** [all] Error 2 

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

NetWork зависит от CommBase, MessageDispatch зависит от сети и CommBase, как я могу указать в DemoServer

+0

Прочитать ваше сообщение об ошибке: Ссылка на исполняемый файл CXX. ;;/usr/bin/ld: невозможно открыть выходной файл.: Является ли каталог. Вы каким-то образом настроили точку как имя приложения или библиотеки, и, конечно, линкер не может сгенерировать файл с этим именем. –

+0

Вы не должны искать библиотеки, созданные сами, просто передайте имена своих целей в 'target_link_library'. – arrowd

+0

Чтобы увидеть, что действительно происходит, вы можете вызвать 'make VERBOSE = 1', который выводит фактические команды компилятора и компоновщика и конкретные аргументы, которые генерирует cmake. – mars

ответ

0

Есть несколько вопросов здесь, некоторые более критично, чем другие. Примерно в порядке важности:

  • add_library позволяет определить библиотеку как либоSTATIC или SHARED, но не оба.

  • target_link_libraries связывает зависимости в порядке их появления в команде. Вы должны указывать их от наиболее зависимых до наименее. Таким образом, в вашем DemoServer CMakeLists.txt, он должен быть

    TARGET_LINK_LIBRARIES(DemoServer MessageDispatch NetWork CommBase) 
    

    Однако, из документации: зависимостей

    Библиотека транзитивны по умолчанию. Когда эта цель связана с другой целью, библиотеки, связанные с этой целью, появятся и на линии ссылок для другой цели.

    Другими словами, вы должны иметь TARGET_LINK_LIBRARIES(NetWork CommBase) в NETWORK (вы уже делаете), TARGET_LINK_LIBRARIES(MessageDispatch NetWork) в MessageDispatch и просто TARGET_LINK_LIBRARIES(DemoServer MessageDispatch) для Demo.

  • CMAKE_BUILD_TYPE обычно устанавливается пользователем через командную строку (или CMake GUI). Вероятно, он должен быть установлен только внутри CMakeLists.txt, если пользователь еще этого не сделал, или если он установлен на недопустимое значение. Если вы установите или измените значение, было бы полезно сообщить пользователю через message. Вероятно, вы не должны устанавливать его в двух разных местах.

  • aux_source_directory не рекомендуется в качестве средства для сбора списков исходных файлов. Рекомендуемый способ состоит в том, чтобы жестко закодировать пути к файлам в вашем CMakeLists.txt, поэтому, если исходный список изменяется, CMake автоматически перезапускается.

  • link_directories редко требуется и не должен содержать строго кодированный абсолютный путь.

  • LIBRARY_OUTPUT_PATH и EXECUTABLE_OUTPUT_PATH устарели.

  • add_dependencies не требуется, если вы уже указали эти зависимости посредством вызова target_link_libraries.

+0

и синтаксическая ошибка в статической библиотеке^^ спасибо A lots – nemo

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