2

下面的项目结构是一个简化的例子。

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

网络/CMakeLists.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)

链接 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 依赖于 NetWork 和 CommBase,如何在 DemoServer 中指定

4

1 回答 1

3

这里有一些问题,有些问题比其他问题更重要。大致按重要性排序:

  • add_library允许您将库定义为 STATICSHARED但不能同时定义。

  • 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)为了演示。

  • CMAKE_BUILD_TYPE通常由用户通过命令行(或 CMake GUI)设置。如果用户还没有这样做,或者它被设置为无效值,它可能应该只在 CMakeLists.txt 中设置。如果您设置或更改该值,最好通过message. 您可能不应该将它设置在 2 个不同的地方。

  • aux_source_directory不推荐作为收集源文件列表的方法。推荐的方法是将文件路径硬编码到 CMakeLists.txt 中,因此如果源列表更改,CMake 会自动重新运行。

  • link_directories很少需要,并且不应包含硬编码的绝对路径。

  • LIBRARY_OUTPUT_PATHEXECUTABLE_OUTPUT_PATH已弃用。

  • add_dependencies如果您已经通过target_link_libraries调用指定了这些依赖项,则不需要。

于 2013-10-01T03:33:59.397 回答