MinGWでBoost 1.48.0を使う

ビルドが必要なboost::threadやboost::regexを使いたい時にはまったので私的メモ、
試したOSはWindows7

環境

gcc 4.6.1(MinGW)(※リンクはTopページ)
Boost 1.48.0

当然ながらMinGWのbinにはパスを通しておく。

手順

解凍したboostのパスにて、以下のコマンドでビルド用のbjam.exeを作る

bootstrap.bat gcc


生成されたbjam.exeを使い、ライブラリをビルドする

bjam.exe -sTOOLS=mingw --toolset=gcc --stagedir="boostのパス\stage\mingw" --without-python --without-mpi --build-type=complete variant=debug,release link=static threading=multi runtime-link=static release debug stage -j4

※ビルドするのは静的リンクのみ、理由は後述
※-jnでビルド時の並列処理数を記述、この辺はビルドを行うマシンのスペックと相談


次にboost::threadをincludeした時にwarningが出ないように、以下のパッチを施す、
参考にしたのはここ
ファイルのパスは boostへのパス\boost\thread\win32\thread_heap_alloc.hpp
行数は59行目辺り

//        inline BOOST_THREAD_DECL void* allocate_raw_heap_memory(unsigned size)
        inline void* allocate_raw_heap_memory(unsigned size)
    	{
            void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
            if(!heap_memory)
            {
                boost::throw_exception(std::bad_alloc());
            }
            return heap_memory;
        }

//        inline BOOST_THREAD_DECL void free_raw_heap_memory(void* heap_memory)
        inline void free_raw_heap_memory(void* heap_memory)
        {
            BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
        }

ここまでで準備完了。


次にboost::threadを使ったサンプルをBoostライブラリを静的リンクでビルドして実行してみる。
ソースは、以前書いたSleep Sortのソースを使おう。
sleepsort.cpp

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind/bind.hpp>


#define BOOST_SLEEP(n) boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds((n)))

std::vector<int> SleepSort(std::vector<int> v)
{
    boost::mutex m;
    std::vector<int> ret;

    std::function<void(int)> f = [&](int n) {
        BOOST_SLEEP(n * 100);

        {
            boost::mutex::scoped_lock lock(m);
            ret.push_back(n);
        }
    };


    boost::thread_group group;

    std::for_each(v.begin(), v.end(), [&](int n) {
        group.create_thread(boost::bind(f, n));
    });

    group.join_all();

    return ret;
}

int main()
{
    int a[] = {3, 1, 8, 7, 2, 4, 9, 6, 0, 5};
    int n = sizeof(a) / sizeof(a[0]);
    std::vector<int> v(a, a + n);

    v = SleepSort(std::move(v));

    std::for_each(v.begin(), v.end(), [](int n) {
        std::cout << n << " ";
    });

    return 0;
}


ビルドする時は以下のコマンド

g++ sleepsort.cpp -o sleepsort.exe -std=c++0x -DBOOST_THREAD_USE_LIB -Iboostのincludeパス -Lboostのlibパス -lboost_thread-mgwXX-mt-s-X_XX

MinGWではVisual Studioの時とは違い、-lオプションで明示的にライブラリを指定する必要がある(参考)
※静的リンクなので、 libファイル(MinGWでは.a)はmt-s-X_XXのようになっているのに注意
※静的リンクの時には、 -DBOOST_THREAD_USE_LIB オプションを付加する


これでsleepsort.exeを実行すれば実行結果が確認できる。

はまった事

Boostライブラリをビルドする際、動的リンク用も生成するように

bjam -sTOOLS=mingw --toolset=gcc --stagedir="boostのパス\stage\mingw" --without-python --without-mpi --build-type=complete variant=debug,release link=static,shared threading=multi runtime-link=static,shared release debug stage -j4

とすると、Boostライブラリの静的リンク用を使ってサンプルをビルドする際に
MinGWのld.exeがboost_thread-mgwXX-mt-s-X_XXが見つからないというエラーを出した。
なのでBoostライブラリを静的リンクで使う際には、Boostライブラリは静的リンク用だけビルドした方がいいかもしれない。