FASTBuild事始め
FASTBuildとはVisualC++で使えるIncrediBuild、distccのようなフリー(というかオープンソース)の分散ビルドツールです。
VisualStudioのプロジェクトも作成できるのでCMakeにも近いかも。
そんなFASTBuildですが日本語で解説しているページを見かけないのでやったことを書いてみることにしました。
FASTBuild自体を以下のページから落としてきます。
FASTBuild - High-Performance Build System
中にFBuild.exeとFBuildWorker.exeにLICENSE.TXTが入っています。
FBuild.exe、FBuildWorker.exeをパスの通るところにおいてください。
こいつでBuildするには定義ファイルを書かないといけないので分散ビルドの前に単純なビルドができるようなシンプルな定義ファイルを書きます。
ちなみに64ビットでの例なので32ビットでやりたい場合はコンパイラのパスを適宜修正してください。
またVCのパスは適宜自分の環境にあったものにしてください。
.VCBasePath = 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC' .Compiler = "$VCBasePath$\bin\amd64\cl.exe" .Librarian = "$VCBasePath$\bin\amd64\lib.exe" .Linker = "$VCBasePath$\bin\amd64\link.exe" ; ソースフォルダ、ファイルをここで指定 ObjectList( "hallo_obj" ) { .CompilerOptions = '%1 /Fo%2 /nologo /c' .CompilerInputPath = "src\" .CompilerOutputPath= "obj\" } ; 実行ファイル定義 Executable( "hallo" ) { .LinkerOptions = '/NOLOGO /OUT:%2 %1 /MACHINE:x64 /SUBSYSTEM:CONSOLE' .Libraries = { "hallo_obj" } .LinkerOutput = "bin/hallo.exe" } ; 引数省略時に実行される処理 Alias( "all" ) { .Targets = { "hallo" } }
事前にsrcフォルダ、objフォルダが入っているフォルダを用意します。
そこに上記の内容をテキストファイルに書き、fbuild.bffとして保存します。
srcフォルダにはコンパイルしたいソースを入れてください。
以下のような感じです。
・作業フォルダ(自分で作成)
┣ srcフォルダ(この中にソースを入れる)
┣ objフォルダ
┗ fbuild.bffファイル
コマンドプロンプトを開き、上記の作業フォルダに移動
"C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x64
と入力してください(ダブルクォーテーション含む)
次に
fbuild
と打ち込むことでビルドが始まります。
注意点として、FASTBuildのSampleを見てみるとLibrary( 'libA' )を使ってますが
これだとlibA.libができてさらにそれをリンクした実行バイナリができてしまいます。
単純な実行バイナリを作りたい場合は上記のObjectListを使います。
UltraVNCでrdr::Exception: rdr::EndOfStreamが出る。
UltraVNCを使用しているとうまくつながらない時があるのでlogを取ってみると
rdr::Exception: rdr::EndOfStream
とのエラーメッセージが出てました。
これを調べても、どうにも解決につながる情報が出てこなかったのですがこの前ようやく上記の症状がでなくなりました。
何をやったかというと、UltraVNCのバージョンをサーバ、クライアント共に最新に更新しただけです。
これだけで結構長期間苦しめられたこの問題があっさり直ってしまいました。
多分サーバ、クライアントのバージョンが合ってなかったのが良くなかったのかと。
困ったときは最新版にしよう、と思った出来事でした。
c++ 組み込み型のmove
右辺値参照の勉強中ですが以下気になったのでメモ
組み込み型(プリミティブ型)はmoveせず、lvalue参照と同様になるようです。
http://stackoverflow.com/questions/14679605/do-built-in-types-have-move-semantics
Singletonでのthread終了時にjoinで固まる
VisualStudio環境での話です(VS2012で確認)
gcc(4.9.2)環境では正常に動作します。
#include <thread> #include <atomic> #include <chrono> #include <iostream> class Hoge { public: static Hoge& get() { static Hoge hoge; return hoge; }; void run() { while( false == m_end ) { sleep(100); } } void stop() { m_end = true; } static void sleep(unsigned int ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } private: Hoge() : m_thread() , m_end(false) { m_thread = std::thread( &Hoge::run, this ); } virtual ~Hoge() { stop(); if ( m_thread.joinable() ) { m_thread.join(); } std::cout << "thread end" << std::endl; } Hoge(const Hoge& rhs); Hoge& operator=(const Hoge& rhs); std::thread m_thread; std::atomic<bool> m_end; }; int main() { Hoge::get(); Hoge::sleep(100); return 0; }
上記のコードを実行すると終了時に固まります。
何が起こっているかというと多分以下の通り
・mainが終了
・Hogeのデストラクタで動かしている子供スレッドの終了指示
・joinで子供スレッドが終わるのを待つ
・run関数自体は終わるが_Cnd_do_Broadcast_at_thread_exitでメインスレッドの終了待ちをしている?
・結果joinとメインスレッド終了待ちでデッドロック。
いまのところ、とりあえずjoinをdetachに変えてしのいでます。
if ( m_thread.joinable() ) { #if 0 m_thread.join(); #else m_thread.detach(); #endif }
ちなみに_Cnd_do_Broadcast_at_thread_exitを通るのを確認するために
ランタイムライブラリのオプションを/MTdにしてます。
Windows、linuxで共通のsleep
c++11限定だけど
#include <thread> #include <chrono> void sleep(unsigned int ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); }