使用 CMake 编译 cpp-netlib + Boost 程序不工作

Compile cpp-netlib + Boost program with CMake not working

我正在尝试从 cpp-netlib site 编译 hello world 程序。代码如下。

#include <boost/network/protocol/http/client.hpp>
#include <iostream>

int main(int argc, char *argv[]) {
    using namespace boost::network;

    if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " [url]" << std::endl;
        return 1;
    }

    http::client client;
    http::client::request request(argv[1]);
    request << header("Connection", "close");
    http::client::response response = client.get(request);
    std::cout << body(response) << std::endl;

    return 0;
}

我的 CMakeLists.txt 文件如下

cmake_minimum_required(VERSION 2.8)

project(app_project)

add_executable(myapp main.cpp)

install(TARGETS myapp DESTINATION bin)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lboost_system -lboost_filesystem -lboost_thread -lcppnetlib-client-connections -lcppnetlib-uri -lcppnetlib-server-parsers -lcppnetlib-client-connections -lcppnetlib-uri -lboost_thread -lssl -lcrypt ")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lboost_system -lboost_filesystem -lboost_thread -lcppnetlib-client-connections -lcppnetlib-uri -lcppnetlib-server-parsers -lcppnetlib-client-connections -lcppnetlib-uri -lboost_thread -lssl -lcrypt ")

SET(ADDITIONAL_LIBS "")

find_package( Boost 1.58.0 )
if(Boost_FOUND)

    #set(Boost_USE_STATIC_LIBS        OFF)  # I've already tried ON
    #set(Boost_USE_MULTITHREADED      ON)
    #set(Boost_USE_STATIC_RUNTIME    OFF)

    include_directories(${Boost_INCLUDE_DIRS})
endif()

find_package(OpenSSL)
include_directories(${OpenSSL_INCLUDE_DIRS})
target_link_libraries ( myapp ${OpenSSL_INCLUDE_DIRS} )
LIST(APPEND ADDITIONAL_LIBS ${OpenSSL_LIBRARIES})

set ( CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} /data/dev/cpp/cpp-netlib-build )
find_package ( cppnetlib 0.11.0 REQUIRED )
include_directories ( ${cppnetlib_INCLUDE_DIRS} )
target_link_libraries ( myapp ${cppnetlib_LIBRARIES} )
LIST(APPEND ADDITIONAL_LIBS ${cppnetlib_LIBRARIES})

SET(CMAKE_REQUIRED_LIBRARIES ${ADDITIONAL_LIBS})

建造我 运行

mkdir build 
cd build
cmake --debug-output ..
make

并得到以下错误输出

  Running with debug output on.
  -- The C compiler identification is GNU 4.8.4
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeDetermineCCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- The CXX compiler identification is GNU 4.8.4
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeDetermineCXXCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Check for working C compiler: /usr/bin/cc
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Check for working C compiler: /usr/bin/cc -- works
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Detecting C compiler ABI info
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Detecting C compiler ABI info - done
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Check for working CXX compiler: /usr/bin/c++
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeTestCXXCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Check for working CXX compiler: /usr/bin/c++ -- works
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeTestCXXCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Detecting CXX compiler ABI info
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeTestCXXCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Detecting CXX compiler ABI info - done
  Called from: [2]  /usr/share/cmake-2.8/Modules/CMakeTestCXXCompiler.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Boost version: 1.58.0
  Called from: [2]  /usr/share/cmake-2.8/Modules/FindBoost.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Found OpenSSL: /usr/lib/x86_64-linux-gnu/libssl.so;/usr/lib/x86_64-linux-gnu/libcrypto.so (found version "1.0.1f") 
  Called from: [2]  /usr/share/cmake-2.8/Modules/FindOpenSSL.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Found cppnetlib: /usr/local/lib/x86_64-linux-gnu/libcppnetlib-client-connections.a;/usr/local/lib/x86_64-linux-gnu/libcppnetlib-server-parsers.a;/usr/local/lib/x86_64-linux-gnu/libcppnetlib-uri.a (Required is at least version "0.11.0") 
  Called from: [2]  /usr/share/cmake-2.8/Modules/Findcppnetlib.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Found cppnetlib in /usr/local/include:/usr/local/lib/x86_64-linux-gnu/libcppnetlib-client-connections.a;/usr/local/lib/x86_64-linux-gnu/libcppnetlib-server-parsers.a;/usr/local/lib/x86_64-linux-gnu/libcppnetlib-uri.a
  Called from: [2]  /usr/share/cmake-2.8/Modules/Findcppnetlib.cmake
        [1] /data/dev/cpp/tuto/CMakeLists.txt
  -- Configuring done
  -- Generating /data/dev/cpp/tuto/build
  -- Generating done
  -- Build files have been written to: /data/dev/cpp/tuto/build
  Scanning dependencies of target myapp
  [100%] Building CXX object CMakeFiles/myapp.dir/main.cpp.o
  Linking CXX executable myapp
  CMakeFiles/myapp.dir/main.cpp.o: In function `__static_initialization_and_destruction_0(int, int)':
  main.cpp:(.text+0x2d1): undefined reference to `boost::system::generic_category()'
  main.cpp:(.text+0x2dd): undefined reference to `boost::system::generic_category()'
  main.cpp:(.text+0x2e9): undefined reference to `boost::system::system_category()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::system::error_code::error_code()':
  main.cpp:(.text._ZN5boost6system10error_codeC2Ev[_ZN5boost6system10error_codeC5Ev]+0x17): undefined reference to `boost::system::system_category()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::thread_exception::thread_exception(int, char const*)':
  main.cpp:(.text._ZN5boost16thread_exceptionC2EiPKc[_ZN5boost16thread_exceptionC5EiPKc]+0x14): undefined reference to `boost::system::system_category()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::condition_error::condition_error(int, char const*)':
  main.cpp:(.text._ZN5boost15condition_errorC2EiPKc[_ZN5boost15condition_errorC5EiPKc]+0x14): undefined reference to `boost::system::system_category()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::detail::thread_data_base::thread_data_base()':
  main.cpp:(.text._ZN5boost6detail16thread_data_baseC2Ev[_ZN5boost6detail16thread_data_baseC5Ev]+0x24): undefined reference to `vtable for boost::detail::thread_data_base'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::detail::interruption_checker::interruption_checker(pthread_mutex_t*, pthread_cond_t*)':
  main.cpp:(.text._ZN5boost6detail20interruption_checkerC2EP15pthread_mutex_tP14pthread_cond_t[_ZN5boost6detail20interruption_checkerC5EP15pthread_mutex_tP14pthread_cond_t]+0x16): undefined reference to `boost::detail::get_current_thread_data()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::condition_variable::wait(boost::unique_lock<boost::mutex>&)':
  main.cpp:(.text._ZN5boost18condition_variable4waitERNS_11unique_lockINS_5mutexEEE[_ZN5boost18condition_variable4waitERNS_11unique_lockINS_5mutexEEE]+0x8b): undefined reference to `boost::this_thread::interruption_point()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::system::make_error_code(boost::future_errc)':
  main.cpp:(.text._ZN5boost6system15make_error_codeENS_11future_errcE[_ZN5boost6system15make_error_codeENS_11future_errcE]+0xd): undefined reference to `boost::future_category()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::thread::start_thread()':
  main.cpp:(.text._ZN5boost6thread12start_threadEv[_ZN5boost6thread12start_threadEv]+0x15): undefined reference to `boost::thread::start_thread_noexcept()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::thread::~thread()':
  main.cpp:(.text._ZN5boost6threadD2Ev[_ZN5boost6threadD5Ev]+0x15): undefined reference to `boost::thread::detach()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::thread::get_id() const':
  main.cpp:(.text._ZNK5boost6thread6get_idEv[_ZNK5boost6thread6get_idEv]+0x18): undefined reference to `boost::thread::native_handle()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::thread::join()':
  main.cpp:(.text._ZN5boost6thread4joinEv[_ZN5boost6thread4joinEv]+0x6d): undefined reference to `boost::thread::join_noexcept()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::network::uri::uri::parse()':
  main.cpp:(.text._ZN5boost7network3uri3uri5parseEv[_ZN5boost7network3uri3uri5parseEv]+0x6a): undefined reference to `boost::network::uri::detail::parse(__gnu_cxx::__normal_iterator<char const*, std::string>, __gnu_cxx::__normal_iterator<char const*, std::string>, boost::network::uri::detail::uri_parts<__gnu_cxx::__normal_iterator<char const*, std::string> >&)'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::asio::error::get_system_category()':
  main.cpp:(.text._ZN5boost4asio5error19get_system_categoryEv[_ZN5boost4asio5error19get_system_categoryEv]+0x5): undefined reference to `boost::system::system_category()'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::asio::detail::posix_thread::~posix_thread()':
  main.cpp:(.text._ZN5boost4asio6detail12posix_threadD2Ev[_ZN5boost4asio6detail12posix_threadD5Ev]+0x26): undefined reference to `pthread_detach'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::asio::detail::posix_thread::join()':
  main.cpp:(.text._ZN5boost4asio6detail12posix_thread4joinEv[_ZN5boost4asio6detail12posix_thread4joinEv]+0x2b): undefined reference to `pthread_join'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::asio::detail::posix_thread::start_thread(boost::asio::detail::posix_thread::func_base*)':
  main.cpp:(.text._ZN5boost4asio6detail12posix_thread12start_threadEPNS2_9func_baseE[_ZN5boost4asio6detail12posix_thread12start_threadEPNS2_9func_baseE]+0x29): undefined reference to `pthread_create'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::network::http::impl::connection_delegate_factory<boost::network::http::tags::http_async_8bit_udp_resolve>::new_connection_delegate(boost::asio::io_service&, bool, bool, boost::optional<std::string>, boost::optional<std::string>, boost::optional<std::string>, boost::optional<std::string>)':
  main.cpp:(.text._ZN5boost7network4http4impl27connection_delegate_factoryINS1_4tags27http_async_8bit_udp_resolveEE23new_connection_delegateERNS_4asio10io_serviceEbbNS_8optionalISsEESB_SB_SB_[_ZN5boost7network4http4impl27connection_delegate_factoryINS1_4tags27http_async_8bit_udp_resolveEE23new_connection_delegateERNS_4asio10io_serviceEbbNS_8optionalISsEESB_SB_SB_]+0x9c): undefined reference to `boost::network::http::impl::normal_delegate::normal_delegate(boost::asio::io_service&)'
  CMakeFiles/myapp.dir/main.cpp.o: In function `boost::detail::thread_data<boost::_bi::bind_t<unsigned long, boost::_mfi::mf0<unsigned long, boost::asio::io_service>, boost::_bi::list1<boost::_bi::value<boost::asio::io_service*> > > >::~thread_data()':
  main.cpp:(.text._ZN5boost6detail11thread_dataINS_3_bi6bind_tImNS_4_mfi3mf0ImNS_4asio10io_serviceEEENS2_5list1INS2_5valueIPS7_EEEEEEED2Ev[_ZN5boost6detail11thread_dataINS_3_bi6bind_tImNS_4_mfi3mf0ImNS_4asio10io_serviceEEENS2_5list1INS2_5valueIPS7_EEEEEEED5Ev]+0x1f): undefined reference to `boost::detail::thread_data_base::~thread_data_base()'
  CMakeFiles/myapp.dir/main.cpp.o:(.rodata._ZTIN5boost6detail11thread_dataINS_3_bi6bind_tImNS_4_mfi3mf0ImNS_4asio10io_serviceEEENS2_5list1INS2_5valueIPS7_EEEEEEEE[_ZTIN5boost6detail11thread_dataINS_3_bi6bind_tImNS_4_mfi3mf0ImNS_4asio10io_serviceEEENS2_5list1INS2_5valueIPS7_EEEEEEEE]+0x10): undefined reference to `typeinfo for boost::detail::thread_data_base'
  collect2: error: ld returned 1 exit status
  make[2]: *** [myapp] Error 1
  make[1]: *** [CMakeFiles/myapp.dir/all] Error 2
  make: *** [all] Error 2

已修复。

注:

  • 我已将 cppnetlib 安装到与您不同的目录中 - 这反映在我对 cmake 的命令行调用中。我已经将 boost 和 cppnetlib 构建到 $HOME/include/... 和 $HOME/lib...
  • 大写变量CPPNETLIB_xxxx
  • 很好地使用 CMAKE find_package(...) 变量,这样您的脚本就不会被讨厌的黑客弄得乱七八糟。
  • 我从 find_package(Boost) 中删除了版本需求,因为我使用的是 1.57 版本

这是脚本:

$ more ~/play/netlib/CMakeLists.txt 

cmake_minimum_required(VERSION 2.8)

project(app_project)

add_executable(myapp main.cpp)

install(TARGETS myapp DESTINATION bin)

find_package( Boost REQUIRED COMPONENTS thread system)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(myapp ${Boost_LIBRARIES})

find_package(OpenSSL)
include_directories(${OpenSSL_INCLUDE_DIRS})
target_link_libraries ( myapp ${OpenSSL_LIBRARIES} )

find_package ( cppnetlib 0.11.0 REQUIRED )
include_directories ( ${CPPNETLIB_INCLUDE_DIRS} )
target_link_libraries ( myapp ${CPPNETLIB_LIBRARIES} )

调用(从干净的目录):

$ mkdir ~/play/mk-netlib
$ cd ~/play/mk-netlib/
$ CMAKE_PREFIX_PATH=$HOME CMAKE_CXX_FLAGS="c++11" cmake ../netlib/
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Boost version: 1.57.0
-- Found the following Boost libraries:
--   thread
--   system
-- Found OpenSSL: /usr/lib/x86_64-linux-gnu/libssl.so;/usr/lib/x86_64-linux-gnu/libcrypto.so (found version "1.0.1f")
-- Configuring done
-- Generating done
-- Build files have been written to: /home/xxxx/play/mk-netlib

$ make
Scanning dependencies of target myapp
[100%] Building CXX object CMakeFiles/myapp.dir/main.cpp.o
Linking CXX executable myapp
[100%] Built target myapp

$ ./myapp
Usage: ./myapp [url]

如您所见,它运行良好。

$ uname -a
Linux tp-dev-1 3.16.0-38-generic #52~14.04.1-Ubuntu SMP Fri May 8 09:43:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

$ c++ --version
c++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.