cmakeでboostライブラリのリンク順を指定


3日程悩んだのでメモ

はじめに

boost::asioで coroutineを使った際に、Linux環境でビルドすると
下記のエラーが出ました

/usr/local/lib/libboost_coroutine.a(stack_traits.o): 関数 `void boost::call_once<void (*)(rlimit*), rlimit*>(boost::once_flag&, void (*)(rlimit*), rlimit*) [clone .constprop.156]' 内:
stack_traits.cpp:(.text+0x3a): `boost::thread_detail::enter_once_region(boost::once_flag&)' に対する定義されていない参照です
/usr/local/lib/libboost_coroutine.a(stack_traits.o): 関数 `boost::coroutines::pagesize()' 内:
stack_traits.cpp:(.text+0x7a): `boost::thread_detail::enter_once_region(boost::once_flag&)' に対する定義されていない参照です
stack_traits.cpp:(.text+0x99): `boost::thread_detail::commit_once_region(boost::once_flag&)' に対する定義されていない参照です
/usr/local/lib/libboost_coroutine.a(stack_traits.o): 関数 `boost::coroutines::stacksize_limit()' 内:
stack_traits.cpp:(.text+0xba): `boost::thread_detail::enter_once_region(boost::once_flag&)' に対する定義されていない参照です
stack_traits.cpp:(.text+0xd7): `boost::thread_detail::commit_once_region(boost::once_flag&)' に対する定義されていない参照です
/usr/local/lib/libboost_coroutine.a(stack_traits.o): 関数 `boost::coroutines::stack_traits::is_unbounded()' 内:
stack_traits.cpp:(.text+0xfa): `boost::thread_detail::enter_once_region(boost::once_flag&)' に対する定義されていない参照です
stack_traits.cpp:(.text+0x117): `boost::thread_detail::commit_once_region(boost::once_flag&)' に対する定義されていない参照です
/usr/local/lib/libboost_coroutine.a(stack_traits.o): 関数 `boost::coroutines::stack_traits::page_size()' 内:
stack_traits.cpp:(.text+0x13a): `boost::thread_detail::enter_once_region(boost::once_flag&)' に対する定義されていない参照です
stack_traits.cpp:(.text+0x159): `boost::thread_detail::commit_once_region(boost::once_flag&)' に対する定義されていない参照です
/usr/local/lib/libboost_coroutine.a(stack_traits.o): 関数 `boost::coroutines::stack_traits::default_size()' 内:
stack_traits.cpp:(.text+0x17a): `boost::thread_detail::enter_once_region(boost::once_flag&)' に対する定義されていない参照です
stack_traits.cpp:(.text+0x197): `boost::thread_detail::commit_once_region(boost::once_flag&)' に対する定義されていない参照です
/usr/local/lib/libboost_coroutine.a(stack_traits.o): 関数 `boost::coroutines::stack_traits::maximum_size()' 内:
stack_traits.cpp:(.text+0x20a): `boost::thread_detail::enter_once_region(boost::once_flag&)' に対する定義されていない参照です
stack_traits.cpp:(.text+0x227): `boost::thread_detail::commit_once_region(boost::once_flag&)' に対する定義されていない参照です
/usr/local/lib/libboost_coroutine.a(stack_traits.o): 関数 `void boost::call_once<void (*)(rlimit*), rlimit*>(boost::once_flag&, void (*)(rlimit*), rlimit*) [clone .constprop.156]' 内:
stack_traits.cpp:(.text+0x69): `boost::thread_detail::commit_once_region(boost::once_flag&)' に対する定義されていない参照です
/usr/local/lib/libboost_coroutine.a(coroutine_context.o): 関数 `boost::coroutines::detail::coroutine_context::coroutine_context(void (*)(long), boost::coroutines::stack_context const&)' 内:
coroutine_context.cpp:(.text+0x3d): `make_fcontext' に対する定義されていない参照です
/usr/local/lib/libboost_coroutine.a(coroutine_context.o): 関数 `boost::coroutines::detail::coroutine_context::jump(boost::coroutines::detail::coroutine_context&, long, bool)' 内:
coroutine_context.cpp:(.text+0x9c): `jump_fcontext' に対する定義されていない参照です
clang: error: linker command failed with exit code 1 (use -v to see invocation)

CMakeListsは下記

CMakeLists.txt
cmake_minimum_required(VERSION 2.8.4)
project(hoge)

set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)

set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DDEBUG")
#set(CMAKE_OSX_ARCHITECTURES "x86_64")

file(GLOB_RECURSE SOURCE_FILES "*.cpp"  )

find_package(Boost 1.57.0 COMPONENTS thread filesystem system context coroutine chrono container)
if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR})
    add_executable(hoge ${SOURCE_FILES})
    target_link_libraries(hoge ${Boost_LIBRARIES} pthread)
endif()

色々とエラーの原因を探るとどうやら、ライブラリのリンク順ではないかと。

libboost_contextの前にlibboost_coroutineをリンクする必要がありそうです

一見、CMakeLists.txtの find_packageで contextとcoroutineを入れ替えれば
リンク順を換えれそうですが
入れ替えても 結果は変わりませんでした

対処法

正しい対処法知っている人が居たら教えて下さい。

CMakeよくわからないので愚直に、リンクに記述しました

CMakeLists.txt
cmake_minimum_required(VERSION 2.8.4)
project(hoge)

set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)

set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DDEBUG")
#set(CMAKE_OSX_ARCHITECTURES "x86_64")

file(GLOB_RECURSE SOURCE_FILES "*.cpp"  )

find_package(Boost 1.57.0 COMPONENTS thread filesystem system coroutine context chrono container)
if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR})
    add_executable(hoge ${SOURCE_FILES})
    target_link_libraries(hoge boost_coroutine ${Boost_LIBRARIES} pthread)
endif()

target_link_librariesに愚直に boost_coroutineを先に入れました

以上、つまんない事で3日悩んだのでメモ