2016年12月29日木曜日

2016年総括

さて、2016年も残りわずかですが、いかがお過ごしでしょうか?
私は今日で仕事納めでございます。そう、ついさっきまで仕事してました…疲れた…orz
それはまぁ置いといて…

このブログもこれで2016年ラストです。
今年は 55 記事を投稿しました。これを入れて 56 なので、目標である週一ペースは守れたといって良いでしょう。

なんだかんだで Jenkins
今年の Jenkins 関連記事は全部で 16 ありました。以外と書いたなーという感想。
もう殆ど Jenkins 使ってないんですけどね。

ただ、今年は Jenkins 2.0 が出たり、勉強会で発表したりしたので、こうなったのかなと思います。

来年は使ってみたい CI サービスでまだ手をつけられてないのがいくつかあるので、そっちをやりたいなーと思いつつ、ローカル Jenkins のパイプライン化も終わらせたいと思っているので、また何個か書くと思います。

2016年に読んだ本

ブログズミ: 2015年最後の下書き供養

去年読み残した本はそのままに、今年も何冊か買って、そしてまだ読みきれてないです…あぁぁ…orz
増えた本はこちら。





Effective Modern C++ は1回だけ読書会に参加しただけで、それからあんまり読み進められてないです。
ブログズミ: 「Effective Modern C++読書会 vol.3」に行ってきた
(余裕があれば読書会にはもっと行きたかったんですが…)

カンバン仕事術は、大阪で読書会やってたり、繋がりのある人達が読んでたりしたので、読み始めました。
実践もしてます。だいたい2ヶ月くらいになりましたね。
本も読み進めて、改善していきたいですね。

さて、来年どうなるかはわかりませんが、再び下書きのタイトルを「2017年に読んだ本」に変更しました!
今年と同じ結果にならぬよう、終わらせることを始めていこうと思います。

初収益
ブログを始めて約6年、初めてアドセンスの振込があった年でもありました。
ブログズミ: このブログのアドセンス収益が最小支払額に到達しました
些細なことではありますが、嬉しいことです。
2017年もこのペースを維持して頑張っていこうと思います。

To Be 2017
2017年といえば C++17 ですよね。来年はもうちょっと C++ に触れたらいいなぁ~と思ってます。
あとは溜まってることをゆっくり消化したいと思います。

では、良いお年を。





2016年12月26日月曜日

PowerShell を使って「ネットワークドライブ上の」バッチファイルを管理者権限で実行する

「ブログズミ: PowerShell を使ってバッチファイルを管理者権限で実行する」 の補足記事です。
上記との違いは「ネットワークドライブ上の」バッチファイルである点です。
以下がそのバッチ



前回と異なる点は、 PowerShell で自分自身を起動する前に net use でトライブ割当をしている点です。
管理者権限のユーザーに移動すると、割当ていたネットワークドライブが見えない場合があるので、このような対応をしています。

参考

2016年12月15日木曜日

「第8回大阪Jenkins勉強会」で発表してきた

タイトルのとおり、「第8回大阪Jenkins勉強会」で発表してきました。

発表資料はこちら




補足
いやーとっても緊張しました。スライドは結構うまくできたかなーと思ってたのですが、やっぱり1回は話す練習しとかないと言いたいこと言いそびれますね。。。
というわけで、補足。

CI サービスの特徴
質問で特徴について聞かれて、あんまり特徴がない…と答えたものがありましたが、iutest 開発での利用範囲ではあまり特徴に差がないということです。
特にデプロイ関係はノータッチなので、ご了承ください。

Groovy 使えばなんでもデキル
狂ったように Groovy 推ししてましたが、職人技で難解な Jenkins を作ることを推してるわけじゃないです。
なんかあったら Groovy 使って解決できるから大丈夫。という心の余裕を持てるようになって欲しいという点と、(新人・後輩に)全能感を味わってもらうことで Jenkins 仲間に引きずり込もうという考えです。

テーマ
気づいた方もいるかと思いますが、スライドテーマは BlueOcean をイメージして作りました。
スライド自体は reveal.js を使っているのですが、それ用の theme です。
もし使いたい方がいれば、ご自由に使ってください。
github から取ってこれます。

最後に
前回に引き続き、今回も超絶面白勉強会でした。
他の方の発表はどれも、すごいなぁと思ったり、なるほどと思ったり、そしてクソ笑えたり、
いやー濃いですね。


ともあれ、自分はもっとうまく話せるようにならないとダメだなぁと思いました。
来年も挑戦できたらいいなぁ~

というところで、以上。
では、またどこかで。

2016年12月9日金曜日

iutest v1.16.0 をリリースしました

C++ テスティングフレームワーク iutest v1.16.0 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.jp/projects/iutest/releases/66838

変更点は以下の通りです。
  • 追加
    • iuwandbox で複数ソースファイルのビルドに対応
    • 例外アサーションで構造化例外(SEH)もキャッチできるように対応
  • 変更
    • --iutest_filter のルールを Google Test 互換に修正
  • 修正
    • バグ修正

今回、--iutest_filter の仕様を変更しています。
今までは Google Test と少し異なるルールでした(というか勘違いしてた)が、Google Test と同様の仕様になりましたので、ご注意ください。

では。

2016年11月30日水曜日

[iutest] iutest.min.hpp の圧縮

※下書きしたまま公開するのを忘れてました。
iutest v1.15.2 が既にリリースされていますが、以下は v1.15.1 のときの結果になります。ご了承ください。



iutest v1.15.0 のときには、824,858 byte ありましたが、これをさらにコンパクトにして 573,897 byte にまで小さくしました。
こんな感じだったのが、
namespace iutest
{
class TestInfo
: public detail::iu_list_node<TestInfo>
{
public:
TestInfo(detail::iuITestCaseMediator* testcase,const char* name,detail::iuFactoryBase* factory)
: m_testname(name)
,m_factory(factory)
,m_testcase(testcase)
,m_should_run(true)
,m_ran(false)
,m_disable(false)
,m_skip(false)
,m_matches_filter(true)
{
m_mediator.SetPointer(this);
if( detail::IsStringForwardMatching(name, "DISABLED_")
|| (strstr(name, "/DISABLED_") != NULL) )
{
m_disable = true;
}
}
public:
const char* test_case_name(void) const { return m_testcase->test_case_name(); }
こんな感じになりました。
namespace iutest{class TestInfo: public detail::iu_list_node<TestInfo>{public: TestInfo(detail::iuITestCaseMediator* testcase,const char* name,detail::iuFactoryBase* factory): m_testname(name),m_factory(factory),m_testcase(testcase),m_should_run(true),m_ran(false),m_disable(false),m_skip(false),m_matches_filter(true){m_mediator.SetPointer(this);if(detail::IsStringForwardMatching(name,"DISABLED_")||(strstr(name,"/DISABLED_")!=NULL)){m_disable=true;}}public: const char* test_case_name()const{return m_testcase->test_case_name();}const char* name()const{return m_testname.c_str();}bool should_run()const IUTEST_CXX_NOEXCEPT_SPEC{return m_should_run;}bool is_ran()const IUTEST_CXX_NOEXCEPT_SPEC{return m_ran;}bool is_disabled_test()const IUTEST_CXX_NOEXCEPT_SPEC{return m_disable;}bool is_skipped()const IUTEST_CXX_NOEXCEPT_SPEC{return m_skip||m_test_result.Skipped();}bool is_reportable()const IUTEST_CXX_NOEXCEPT_SPEC{return m_matches_filter;}TimeInMillisec elapsed_time()const{return m_test_result.elapsed_time();}const TestResult* result()const IUTEST_CXX_NOEXCEPT_SPEC{return &m_test_result;}const char* value_param()const{return m_value_param.empty()?NULL:m_value_param.c_str();}const char* type_param()const{return m_testcase->type_param();}::std::string testcase_name_with_default_package_name()const{return TestEnv::AddDefaultPackageName(test_case_name());}public: bool HasFatalFailure()const{return m_test_result.HasFatalFailure();}bool HasNonfatalFailure()const{return m_test_result.HasNonfatalFailure();}bool HasFailure()const{return m_test_result.Failed();}bool Passed()const{if(is_skipped()){return false;}return m_test_result.Passed();}public: ::std::string test_full_name()const{::std::string fullname=test_case_name();fullname+=".";fullname+=name();return fullname;}::std::string test_name_with_where()const{::std::string str=m_testname;if(value_param()!=NULL){str+=", where GetParam() = ";str+=m_value_param;}return str;}public: static bool ValidateTestPropertyName(const ::std::string& name){const char* ban[] ={"name","status","time","classname","type_param","value_param"};
大きな変更は、同じヘッダーが2つ分含まれていたバグの修正と改行コード、空白の削減をしています。
iutest.min.hpp は Wandbox や paiza.IO のようなオンラインコンパイラーを使うときに使用をしていますので、サイズが小さくなることにメリットはあるわけです。

paiza.IO
さて、paiza.IO での実行は以前も記事に書いたように Too long 、ソースコードサイズが大きすぎて実行できませんでした。
ブログズミ: paiza.IO の API を使ってみた

iutest.min.hpp のサイズが小さくなりましたが、paiza.IO の制限 10,000 byte からはまだまだ大きすぎます。
そこで、paiza.IO 向けに更に削減するようにしてみました。
paiza.IO はコンパイラーが決まっているので、ある程度プリプロセスをかけるようにした感じです。

具体的には __clang__ や __has_include, __has_feature などをプリプロセスして、#if を削減しています。
また、Google Test 互換用のヘッダーファイルを除外するようにしています。

これで、テストコードを含めて 388,831 byte まで減らすことができました。
けど、まだまだ足りませんね。。。

ただ、API では無理ですが、ブラウザからは実行できるくらいに収まったようです。


まだ API からは実行できませんが、ここまででキリにしたいと思います。
それでは。

2016年11月22日火曜日

ソースコード中の単語からの略語/スペルミス検出に挑戦

ブログズミ: TreeTagger を使ってソースコード中の単語をリストアップしてみた」の続きです。
今回は抽出した単語が略語、もしくはスペルミスなどがないかチェックします。

なぜ、こんなものを作ったのか?それは


ということです。

今回作成したものはそのうちの一つで、「許可された略語以外は禁止」という規約に対して、その発見を"補助"するものです。
(あくまで補助でこれをかけて何も検出されなかったら OK というわけではありません。でも、人間が一語一語確認するものでもないので、これでも十分かなぁーっと思ってます。)

できたもの
最初に出来上がったものを紹介したいと思います。
ソースコードはこちらで公開しています。

usage: abbreviation.py [-h] [-v] [-g FILE] [-w FILE] [-e EXCLUDE]
                       [-a ABBREVIATION] [--glosbe] [--dejizo] [--cache]
                       [--load-cache NAME] [--cache-dir DIR] [--list-all]
                       FILE/DIR [FILE/DIR ...]

positional arguments:
  FILE/DIR              source code file/dir

optional arguments:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit
  -g FILE, --gene FILE  exlude word
  -w FILE, --whitelist FILE
                        whitelist file
  -e EXCLUDE, --exclude EXCLUDE
                        exlude word
  -a ABBREVIATION, --abbreviation ABBREVIATION
                        abbreviation word
  --glosbe              use online translation service (glosbe)
  --dejizo              use online service (dejizo)
  --cache               online translation cache enable
  --load-cache NAME     load translation cache
  --cache-dir DIR       translation cache directory
  --list-all            list up all location

試しに iutest のソースコードを調べてみました。


設計としては、抽出した単語を辞書(オンライン/オフライン)から検索して、辞書にあれば問題なし(辞書に略語として登録されている場合は×)、辞書になかった場合に疑わしい単語として警告する設計です。

以下で詳しく説明していきます。

単語の抽出
「ソースコード中の単語」の抽出は libclang などを利用してやるほうが正しいとは思うのですが、
ブログズミ: TreeTagger を使ってソースコード中の単語をリストアップしてみた」でやったように形態素解析ツールの TreeTagger を使ってやりました。


オンライン辞書サービスを利用する
Glosbe
Glosbe Api
英単語の日本語訳をプログラム内やターミナル内で取得する - roombaの日記

いいね~いいね~とコーディングしていたら、いつの間にかエラーに…
Too many queries, your IP has been blocked

    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 429 Client Error:  for url: https://glosbe.com/gapi/translate?dest=ja&phrase=incg&from=en&pretty=true&format=json
というわけで、制限を超えてしまったようです…

ドキュメントによれば、「ブロックするリクエスト数は明確には決まってないけど、人間じゃなくてロボットだと判断したらブロックするよ」と書いてあります。

ロボットなのでしょうがないですね…
開発者でブロックされたら連絡してねとありますが、別のサービスを探すことにしました。
(一応、1日経つとブロック解除されています。今のところ)

WORDS API
WORDS API
無料プランでも 2,500 Requests/Day でよさそうだったんですが、クレジットの登録が必要だったので今回は保留としました。
(V-プリカとか使えば良いんですけど、めんどくさいので…)
(制限オーバーしたら請求が発生する感じに見えたのも保留した理由の1つ…)

デ辞蔵
デ辞蔵 オンラインでもオフラインでも使える電子辞書
続いて目をつけたのがこちら。
(SOAP ってなんだろ?って思ったんですが、そういうのがあったんですね)

こちらは特に制限がないのですが、注意事項として
・短時間にアクセスが集中するような呼び方(1秒間に20回以上の呼び出しなど)
・定常的に一定のアクセスが続くような呼び方(数秒ごとに自動的に呼び出すなど)
とありました。→「BizPal - デ辞蔵Tech よくある質問と回答
あと無償版は動作保証なし。

英和辞書で使えるのは、EDICT和英辞典(EJdict) と 三省堂 デイリーコンサイス英和辞典 試用版(DailyEJL)の2つあったので、両方を検索するようにしてます。ただし、 Glosbe よりも辞書の単語数は少ない印象
秒間20リクエストは場合によっては超えてるかもしれないので、ゴメンナサイm(__)m

その他
この記事も早く公開したいし、組み込みはこの辺で一旦終わりにしておきます。
その他の辞書サービスがあれば使ってみたいと思います。
あとは、翻訳サービス使う方法もありなのかも。

オンライン辞書のヒット結果をキャッシュする
さて、オンライン辞書から単語を引いてくることができるようになりましたが、リクエスト制限のことを考えなければいけません。というわけで、なるべくリクエストを投げないようにするために、一度検索ヒットした単語をローカルにキャッシュする仕組みを入れました。

今回 iutest を解析したときのキャッシュがリポジトリに入ってます。
このキャッシュはサービスごとに記録し、どんどん追記していく仕組みです。

また、キャッシュは2種類あります。
辞書には「略語」として単語登録されているものもありますので、ヒットしたけど略語だった場合はブラックリストに登録しています。
(※この略語判定が大変だった。特に EDICT は統一性がないのでかなり妥協…)

オフライン辞書を利用する
ソースコード中の単語で、外部に出したくないものもあると思います。(コードネームとか製品名とか?)
そこで、オフラインの辞書にも対応しています。

辞書は3つのタイプが利用可能です。

--whitelist FILE
単純な形式で単語を1行ずつ読み込みます。

--gene FILE
オープンしたファイルから、 '^[a-zA-Z][a-z]+$' にマッチするものを単語として読み込みます。
(これは GENE95 を想定して用意しているので、それ以外には使わないかもしれませんが…)

--cache-load XXX
オンライン辞書でキャッシュしたファイルを読み込みます。
XXX の部分にはオンライン辞書のオプション名を入れます。(現状、glosbe と dejizo のみ対応)
形式はホワイトリスト+ブラックリストになっています。

オンライン辞書では、場合によって "ver" などが "version" の略語として単語登録されている場合がありますので、
そのような単語はブラックリストとしてキャッシュしています。
(ホワイトリストの形式 --whitelist で読み込めるファイルと同じですので、これだけを --whitelist で読み込むことも可能です。)


使ってみた結果
当初は略語の検出を目的に作成しましたが、どちらかと言うと typo 、誤字脱字の方がよく検出される結果となりました。
(恥ずかしいのでちゃんと直しました。 > https://github.com/srz-zumix/iutest/commit/6c767630c810ef27b92bfca856a657209945433c

使ってみたい方、github で公開してますのでご自由にお使いください。




2016年11月14日月曜日

%HOMEPATH%\.nuget の場所を変更する

.nuget フォルダが C ドライブを圧迫してたので、場所を変えたくて調べました。

package - .nuget Folder in User space - Stack Overflow

こちらの方法通り、%APPDATA%\NuGet\NuGet.Config に以下を追記しました。
<config>
    <add key="globalPackagesFolder" value="d:\.nuget" />
  </config>

これで場所が変わりました。


2016年10月31日月曜日

FindFirstFile にルートパスを指定した場合の挙動について

FindFirstFile(FindFirstFileEx) 関数の lpFileName にルートパスは指定できません。
MSDN でそのように記載されています。
FindFirstFile 関数
FindFirstFile の lpFileName パラメータでは、最後に円記号(\)を付けるかどうかにかかわりなく、ルートディレクトリを指定することはできません。




指定できないのはわかりましたが、実際に指定してしまった場合にどうなるのか検証したところ、厄介な挙動だったので備忘録として残しておきます。

検証にしようしたコードはこちら。



これを実行するとこのような出力になります。

カレントディレクトリがルートパスでない場合

このように INVALID_HANDLE ではなく Find が成功し、しかもなぜかカレントディレクトリ名が取得できます。


これが、カレントディレクトリがルートパスだった場合

期待?通り INVALID_HANDLE が返ります。


ちなみに、FindFirstFileExTest がコメントアウトされていますが、FindFirstFileEx でも同じ挙動を示しました。
(Windows 10 HOME version 1607 build 14393.321)
古い OS での検証はできていないので、もしかしたら挙動が異なるかもしれません。

2016年10月26日水曜日

[Cppcheck] 結果を CSV で出力してエクセルで確認する

なぜそんなことが必要か?
Jenkins で xml を集計している場合は、視覚的に確認ができます。
Visual Studio などから利用した場合も、--template vs で出力ウィンドウからジャンプできますし、拡張機能もあります。
これらの組み合わせを使っている場合は、まったくもって問題ないのですが、スタンドアロンで解析して結果を確認したい場合に、視覚的に確認できる方法が欲しかったので、表題にあるような対応をしました。

方法

出力ログフォーマットを以下のように指定します。
--template={file},{line},{severity},{id},\"{message}\"

あとは、stderr を .csv にリダイレクトすれば OK
(message にたまに "" が含まれている場合があるので、そこだけセルが別れちゃいますが…)


実際にこの方法で確認してみると結構便利だということがわかりました。
ぜひ一度お試しあれ


2016年10月17日月曜日

Bitbucket などから「SourceTree にクローン」をしても SourceTree が起動しない場合にすること

Bitbucket の WEB ページなどからクローンしたりするアレ。


これが無反応だったり、ストアアプリを検索させられたり、うまく動作してなかったので調べました。



そもそもどういう仕組み?
なんか便利な機能程度にしか認識してなかったのですが、ちゃんと調べるとそんなのできたんだーと勉強になりました。
これは、URI Association というものだそうです。
ストアアプリとやり取りしたりするのに使ったりもするようです。

SourceTree のオプションから設定
さて、本題です。
SourceTree の URI Association がなぜか無効になっていることがわかったので(インストール時に設定されないのかな?)、オプションから設定してあげます。

「ツール」>「オプション」を開き、「全般」の上のほうにある「Use this version of SourceTree for URI association」にチェックをいれます。

これで完了です。

おまけ
URI Association はレジストリの HKEY_CLASS_ROOT に以下のような構成で記録されます。


2016年10月13日木曜日

[Cppcheck] 1.76 で Visual Studio プロジェクトファイルの読み込みに対応



--project=     Run Cppcheck on project. The  can be a Visual
                     Studio Solution (*.sln), Visual Studio Project
                     (*.vcxproj), or compile database
                     (compile_commands.json). The files to analyse,
                     include paths, defines, platform and undefines in
                     the specified file will be used.


プロジェクトファイルもしはソリューションファイルを指定すると、その定義に従って解析できるようになりました。
これを待っていた!
(あと cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON で出力できる compile_commands.json にも対応)


iutest で試してみました。


--verbose オプションをつけているので、Define とか Include がどう設定されているのかわかると思いますが、
ちゃんとプロジェクトの設定に従って、しかもすべての構成で解析してくれています!
最高やーん!

みんなも今すぐバージョンアップ!!
ダウンロードはこちらから→ Cppcheck - A tool for static C/C++ code analysis

2016/10/14 追記
Version 1.76 にはハングアップバグがあったようで、その修正バージョンとして 1.76.1 がリリースされていました。

2016年10月11日火曜日

TreeTagger を使ってソースコード中の単語をリストアップしてみた

ちょっと入用で、ソースコード中の単語をリストアップしてみました。
お仕事で MeCab を使って日本語テキストを解析して、「とあること」の検出ができないかなーと試したことがあったのですが、今回はソースコードの単語を抽出して「とあること」をしようと思いついたので、やってみました。

ソースコードからの単語検出ということで、英語の形態素解析ツールを使うことにしました。
今回使ったのは TreeTagger です。
環境は Windows + TreeTagger + Python です。



TreeTagger のインストール
WIndows にインストールする場合の手順はこちら
tree-tagger-windows-X.X.zip (筆者ダウンロード時は 3.2)をダウンロードしたら展開し、INSTALL.txt に従ってインストールします。
要約すると、Perl のインストールと、必要なパラメーターファイルを .par 拡張子に変えて lib に置くことと、C:\TreeTagger に配置して bin フォルダを PATH に通せば OK。
※ C:\TreeTagger なのは bat ファイルにパスがベタ書きされているため。別にここである必要はないです。
※ Perl も今回は Python から呼び出すのでなくても問題ない

今回、言語は英語を使います。こちらからパラメーターファイル(English parameter file)をダウンロードしました。
http://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/#Linux

TreeTagger を Python から使う
検索して一番最初に出てきた treetaggerwrapper を使用することにしました。
最初に書いた参考URLではダウンロードしてインストールしていましたが、pip からインストールできるようだったのでそちらでインストールしました。
pip install treetaggerwrapper
pip install six

※ six は treetaggerwrapper が使ってるので、なければインストール

treetaggerwrapper.py は english.par を要求するので、TreeTagger のインストールでダウンロードしてきたパラメーターファイルをコピーリネームしておきます。

試しに以下のサンプルを実行します。
import treetaggerwrapper
import os

tagdir = os.getenv('TREETAGGER_ROOT')
tagger = treetaggerwrapper.TreeTagger(TAGLANG='en',TAGDIR=tagdir)
tags = tagger.TagText(u"Save the time of the reader. SAMPLETEST. SampleTest.")
for tag in tags:
    print tag

TAGDIR には TreeTagger のインストールディレクトリを指定しますが、bin に PATH が通っていれば空で問題ないようです。

ソースコード中の単語のリストアップ
とりあえず、コメント行(// で始まる行、/**/ や行末コメントは非対応)除いてリストアップしてみました。
対象のソースコードは iutest の実装全部入り(fused-src/iutest.hpp)です。


C++ のキーワードを除外するとこんな感じ。


圧倒的に iutest が多いですね。(当たり前か)

リストアップに使用したソースコードは github で公開しています。
https://github.com/srz-zumix/taggertool

2016年10月7日金曜日

Visual Studio "15" Preview 5

Announcing Visual Studio “15” Preview 5 | The Visual Studio Blog
Visual Studo 15 Preview 5 がリリースされたのでインストールしました。
実は Preview 4 のときはトラブってかなり苦労したので(結局あきらめた)、今回も…と思ったのですが、
あっさりインストールできてしまいました。



Preview 4 のときはインストールが失敗して苦労したんですよね…




そのころメモってブログにあげようと思ってたのが以下。
(このまま消すのもあれなので、アップしちゃう)


「Visual Studio "15" Preview 4 のインストールが「this directory is not empty」で失敗する」

https://blogs.msdn.microsoft.com/visualstudio/2016/08/22/visual-studio-15-preview-4/#comment-203695

こちらに同様の質問があります。
"Program Files (x86)\Microsoft Visual Studio\VS15Preview" を削除しろと回答があります。
該当のフォルダが残っていたので削除、インストールできたと思ったら別のエラー。。。

2016-08-28T23:04:11 : Verbose : Getting installed product. [installerId: SetupEngine, installationId: 9c96d633, productId: Microsoft.VisualStudio.Product.Enterprise]
2016-08-28T23:11:33 : Warning : Installation package warnings:
Package 'Microsoft.VisualC.RuntimeDebug.14' failed to install
Package 'Microsoft.VisualC.RuntimeDebug.14' failed to install
2016-08-28T23:11:33 : Error : Failed to update product. [installerId: SetupEngine, productId: Microsoft.VisualStudio.Product.Enterprise, installationPath: 'C:\Program Files (x86)\Microsoft Visual Studio\VS15Preview', error: Package 'Microsoft.VisualC.RuntimeDebug.14' failed to install;Package 'Microsoft.VisualC.RuntimeDebug.14' failed to install at Error: Package 'Microsoft.VisualC.RuntimeDebug.14' failed to install;Package 'Microsoft.VisualC.RuntimeDebug.14' failed to install
    at SetupEngineAdapter.handleError (C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\lib\Installer\Adapters\SetupEngineAdapter.js:316:31)
    at C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\lib\Installer\Adapters\SetupEngineAdapter.js:154:45
    at process._tickCallback (internal/process/next_tick.js:103:7)]
2016-08-28T23:11:34 : Verbose : Getting product summaries. [installerId: SetupEngine]
2016-08-28T23:11:34 : Verbose : Getting installed product summaries. [installerId: SetupEngine]
2016-08-28T23:11:34 : Verbose : Getting product. [installerId: SetupEngine, productId: Microsoft.VisualStudio.Product.Enterprise].
2016-08-28T23:11:35 : Verbose : Getting installed product. [installerId: SetupEngine, installationId: 9c96d633, productId: Microsoft.VisualStudio.Product.Enterprise]

https://blogs.msdn.microsoft.com/visualstudio/2016/08/22/visual-studio-15-preview-4/#comment-203435

We will have this issue fixed in the next release of Visual Studio. For now you can ignore the error and the debugger will still work fine.

エラー出るものの使えるみたいです。

しかし、なんとも気持ちが悪いので、上のリンク先にも書いてある vc_runtimeDebug*.msi をアンインストールしてから、再度インストールしました。



一応大丈夫そうです。たぶん。

2016年10月5日水曜日

無料で使える CI サービス比較(定期実行編)

SCM との連携で更新タイミングで CI が実行されるサービスがほとんどですが、ちょっと定期的に実行させたいことがあり調べたのでまとめました。

以前まとめた情報はこちら
※まとめた時期が結構前なのでもう腐った情報になってるかもしれませんので注意!
ブログズミ: 無料で使える CI サービス比較
ブログズミ: 無料で使える CI サービス比較(Artifacts)

AppVeyorCircle CICodeshipdrone.ioMagnum CIsemaphoreShippableSnap CITravis CIWercker
定期実行 × ×

Appveyor
Build configuration - AppVeyor
Syntax はこちら Crontab Expression · atifaziz/NCrontab Wiki
Jenkins と同じ感じです。


Circle CI
Circle CI では定期実行する仕組みはありませんが、外部から実行開始することができます。
Nightly Builds - CircleCI
なので、何かしらの cron サービスと組み合わせれば定期実行は可能というわけです。

実際に定期実行させた例が Qiita にありました。

Codeship
API | Codeship Documentation
API が用意されていて、リスタートはできそうなのですが、新規に実行する方法が?だったので×にしました。

Magnum CI
Circle CI と同様に外部から実行開始できるので △ にしました。
https://magnum-ci.com/docs/integration

Semaphore
Project Settings に Build Scheduler があります。
Scheduling builds - Semaphore


Shippable
API を利用して外部から実行開始できるので △ にしました。
Shippable API for Projects - Shippable Docs

Snap CI
Scheduling and skipping builds | Snap CI Documentation, FAQ, and Troubleshooting
プロジェクトのページに「Build Schedule」があるので、そこから設定できます。



Travis CI
Cron Jobs - Travis CI
Please note that cron jobs are not enabled by default. Set “Build pushes” to on in your settings, then ask us to unlock this feature for your repository: support@travis-ci.com
デフォルトでは使えません。サポートチームに連絡する必要があるようです。

Wercker
Introducing Cronetes
こちらにやり方が書いてあります。が、ちょっと面倒くさそう。

最後に
ここで×としたサービスもただ単に機能を見逃しているだけで使えるかもしれません。
また、この情報記事投稿前の情報です。今後サービスは拡充していくと思いますので、公式ページで最新の情報を確認するようにお願いします。


さて、これで一旦調べ終わったので、どこかで定期実行ジョブを作りたいと思います。
では、今回は以上。

2016年9月26日月曜日

[Visual C++] lambda を使った構造化例外と C++ 例外の処理

VC++ には構造化例外処理(Structured Exception Handling、通称SEH)があります。
これは C++ の try - catch とは別に __try - __except で処理することができます。

さて、この独自拡張で問題になること、というかメンドクサイことナンバーワンは、
1つの関数で try と __try を同時に使えないことではないでしょうか?

つまり、こういうことです。
void f()
{
    try {
        __try {  // error C2713: 関数ごとに許されている例外ハンドルのフォームは 1 つです。
        } __except(EXCEPTION_EXECUTE_HANDLER) {
        }
    } catch(...) {
    }
}

void g()
{
    __try {
    } __except(EXCEPTION_EXECUTE_HANDLER) {
    }

    try { // error C2713: 関数ごとに許されている例外ハンドルのフォームは 1 つです。
    } catch(...) {
    }
}
void fa()
{
    __try {
    } __except(EXCEPTION_EXECUTE_HANDLER) {
    }
}
void fb()
{
    try {
        fa(); // OK
    } catch(...) {
    }
}

lambda があるじゃない
Visual Studio でも lambda が使えるようになってます。これ使えばわざわざ関数にしなくても済みます!

void f()
{
    try {
        []() {
            __try {}
      __except(EXCEPTION_EXECUTE_HANDLER) {}
        }();
    } __except(EXCEPTION_EXECUTE_HANDLER) {
    }
}

やったね!

とはならない…

VS2012/2013 でエラー
上記コードは VS2015 なら問題なくビルドできます
しかし、VS2012/2013 ではエラーとなってしまいます。
(エラー内容は lambda 使う前と同じ、「error C2713: 関数ごとに許されている例外ハンドルのフォームは 1 つです。」)

もう少し詳しく書くと、こう。

void f()
{
    __try {
        []() {
            try {}
            catch( ... ) {}
        }();
    } __except( EXCEPTION_EXECUTE_HANDLER ) {
    }
}

void g()
{
    try {
        []() {
            __try {} // error C2713: 関数ごとに許されている例外ハンドルのフォームは 1 つです。
            __except( EXCEPTION_EXECUTE_HANDLER ) {}
        }();
    } catch( ... ) {
    }
}

void h()
{
    auto x = []() {
        __try {}
        __except( EXCEPTION_EXECUTE_HANDLER ) {}
    };
    try {
        x();
    } catch( ... ) {
    }
}

__try の中に try がある場合は OK
try の中に __try があるのは NG
lambda が try の外で定義されいれば OK

という感じでした。

まとめ
Visual Studio 2015 を使おう!

2016年9月20日火曜日

GO!!

ポケモンGO みんなやってますね。
自分は今のところやる予定がないのですが(端末の買い替えしないと無理)、周りが Go Go うるさい言ってるのでなんかせねばと…そこでこのネタですよ…何番煎じでしょうね…


ともあれ、
Go は今まで使ったことなかったので、いい機会なので私も Go をやってみました。



まずはオンラインコンパイラーで始める
とりあえず、オンラインコンパイラーを使って始めるのが一番簡単だと思います。
私が知っている Go言語 対応しているオンラインコンパイラーは以下があります。
Go Playground
Paiza.IO

今回はたまーに使ってる Paiza.IO でやってみたいと思います。
package main
import "fmt"
func main() {
  fmt.Println(" ʕ ◔ϖ◔ʔ  ゲットだぜ!")
}





あ、はい。なんかすみません。
もう遅いですよね…まじめにやります。

マスコットキャラクター
さて、上で某キャラになっていたのは、GO言語のマスコットキャラクターです。

What is "Go" Gopher?





うーん。まだ私には魅力がわからないようです。
次。
Windows での環境構築
ここからはローカル環境で Go言語 を使えるようにしていきたいと思います。
ダウンロード
まずは、こちら(https://golang.org/dl/)からインストーラーをダウンロードします。
ダウンロードしたら、インストールします。特別なにか対応する必要はなく、手順に沿ってインストールすれば大丈夫です。

Hello,world
まず、Hello.go ファイルを作成します。Go言語の拡張子は .go のようです。
Hello.go に以下のコードを記入して保存します。
package main

import fmt "fmt"

func main() {
    fmt.Printf("Hello world.");
}

ビルドします。
go build Hello.go
とすると、実行ファイル Hello.exe ができます。
これを実行すると以下のような出力がでるはずです。


はい。できましたね。

それでは次は何かしら作ってみたいと思います。
が、それはまた次回ということにしたいと思います。

最後に
さて、これでビンゴカードの穴を1つあけることができました。








2016年9月12日月曜日

[Jenkins] BlueOcean beta 版がプラグイン管理に登場

公開されてました。
https://wiki.jenkins-ci.org/display/JENKINS/Blue+Ocean+Plugin
プラグイン管理からインストールできます。



(スクリーンショットは beta 3 ですが、既に beta 5 がリリースされてます。)

以前、ソースコードからビルドしてインストールする方法を紹介しましたが、
これからは単純にインストールするだけで良さそうです。
ブログズミ: [Jenkins] Blue Ocean を試してみる

2016年9月5日月曜日

git master ブランチの更新を svn trunk にコミットする CI 環境構築

先日 Jenkins で svn から git に commit / push するジョブの紹介をしました。
今回はその逆 git から svn に commit できるようにしましたので、そちらを紹介したいと思います。

環境
  • Git repo (github)
  • SVN repo (OSDN)
  • 適当な CI サービス(今回は Codeship を使用)
  • アクセス用公開鍵(Codeship 発行)

手順
  1. git/svn ともに公開鍵を登録しておく
  2. svn からチェックアウト
    svn co svn+ssh://path/to/trunk svn
  3. git からもクローンする(別フォルダ)
    git clone git@github.com:srz-zumix/iutest.git git-svn
    
  4. .svn フォルダを git のフォルダにコピー、 .git フォルダを削除し、svn 作業ディレクトリにする
    cp -r svn/.svn git-svn
    rm -rf git-svn/.git
  5. cd git-svn
  6. 削除されたファイルを svn delete する
    if `svn st | grep -q '^!'` ; then svn st | grep '^!' | awk '{print $2}' | xargs svn delete; fi
  7. 追加されたファイルを svn add する
    svn add * --force
  8. svn の HEAD からログを取得し、対応する git commit id を取得する
    これは svn のコミットメッセージを構築するときに使用します。
    export PREVCOMMIT=
    if `svn log . -l 1 | grep -q 'git@[0-9a-zA-Z]*'` ; then export PREVCOMMIT=`svn log . -l 1 | grep 'git@[0-9a-zA-Z]*' | head -1 | sed -e 's/.*git@\([0-9a-zA-Z]*\).*/\1/g'`; fi
    e 's/.*git@\([0-9a-zA-Z]*\).*/\1/g'`; fi
    echo $PREVCOMMIT
  9. git の HEAD ($CI_COMMIT_ID) からログを取得し、svn のコミットメッセージ用にファイル出力する
    git log $CI_COMMIT_ID -n 1 --pretty="%B%ngit@%H%nhttps://github.com/srz-zumix/iutest/commit/%H" > ../svn.msg
  10. PREVCOMMIT があれば、そのコミットから HEAD までのログもコミットメッセージに追加する
    if [ -n "$PREVCOMMIT" ]; then git --no-pager log $PREVCOMMIT..$CI_COMMIT_ID^ --pretty="---------------%n%B%ngit@%H%n" >> ../svn.msg; fi
  11. svn commit する
    svn commit --file ../svn.msg

実際に動作しているところを見てもらいたいところですが、Codeship は private で見れないので割愛させて頂きます。



さて、これで github に push すると自動で svn も更新できる環境ができました。
現在 iutest v1.6.0 リリースに向けて開発中ですが、こちらの開発から git での開発に移行をしました。
バグとか typo とかあると思うので、是非是非プルリクして頂ければと思います。

では。


2016年9月2日金曜日

[雑記] ブログが紹介された

8月某日、私のブログ記事を紹介したいとの連絡が来た。
6年もブログ書いているとこんなこともあるもんなんだなーと、ちょっと嬉しくなりましたね。
で、紹介記事が公開されたのでご紹介。

紹介している記事はこちらで、

紹介された記事はこっち、

それかーって思いました。(Jenkins とか Cppcheck とか Visual Studio とか紹介してくれてもいいのよw)
なんか適当に書いた記事なので、こんなん紹介してもらっていいのかな?って気がしますが…
まぁいっかー


では、また来週。

2016年8月30日火曜日

このブログのアドセンス収益が最小支払額に到達しました

このブログを始めて約6年で、アドセンスの最小支払額に到達しました。
お小遣い稼ぎ程度に設定をしておりましたが、ようやくリターンが得られました。長かったですね。
こういったので生活している人は大変だなぁと思った。


さて、せっかくなのでここに至るまでのレポートを載せておこうと思います。



赤色がページビューで、青色が収益です。
ページビューは右肩上がり、収益は(先月が異常に高かったですが)、年を追うごとに少しずつですが上がってる感じでした。

さらに、直近一年間の月平均
ページビュー表示回数クリック数収益
9,31817,9804¥309

月平均約300円の収益なので、1年で3600円。3年くらいしたら、また最小支払額に到達する感じですね。
収益を上げることがこのブログの目的ではありませんが、モチベーションの1つとして今後もやっていきたいと思います。どうぞ今後ともよろしくお願いします。

2016年8月22日月曜日

[Jenkins] Warnings Plugin の新規警告の計算について

Warnings Plugin には警告の総数もしくは新規警告数に応じて、ステータスを変更する機能があります。

この機能を使って、警告が残っていたら不安定(黄)にすることが多いのですが、
最近になって、警告が増えたら(新規警告があったら)不安定にするような使い方を始めました。
そうしたらものの見事にハマったので備忘録として書き残しておきます。

新規警告がないにも関わらず不安定になってしまう!!
そんなことが起こってました。
再現ジョブを作ったのでそちらで確認していきます。

まず、ビルドするソースコードはこちら
int main(int argc, char** argv)
{
    return 0;
}
なんのへんてつもないコードです。
これを g++ -Wall -Wextra でビルドするジョブを作成します。

これを1回成功させておきます。
このときの警告は2件です。


続いて、新規警告が1件でもあったら不安定するように設定を変更します。
そして、ソースコードも以下のように書き換えます。
int main(int argc, char** argv)
{
    int x;
    return 0;
}

これを実行すると、結果は新規警告1件により不安定になります。
このとき警告の総数は3件です。



ここまでは、問題ありません。
次が問題です。

もう一度ジョブを実行します。
今度はソースコードを変えてませんので、警告数は3件のままで新規警告も 0件 のはずなので、成功になるはずです。ところが、実際には不安定になってしまうのです。なぜ?!



なぜなのか
ログを見てみましょう。

なぜか新規警告が1件と出力されています。
ビルド結果ページを見ると 0件 なのに?

どうやら、Warnings Plugin で見る新規警告は、最後の成功ビルドから見ての新規警告だったようです。
(ソースコード変更後の警告数は3件なので、成功時の警告2件からみると1件増えたように見える)
ログにもちゃんと
[WARNINGS] Computing warning deltas based on reference build #9
と書いてありました。

前回のビルドから見て欲しい
簡単でした。
「Use previous build as reference」にチェックを入れるだけです。


この状態でもう一度ジョブを実行すると、意図通り成功になりました!


ログもこの通り、ちゃんと1つ前のビルドを参照しているようです。

最後に
「Use previous build as reference」とか、「Only use stable builds as reference」とか、
説明が英語だったのでスルーしてましたが使いどころが分かりました。
また、どういう挙動をしているのか少し分かったことで、通知の仕方の幅が広がりました。
(成功時の警告数を下回るまで不安定するのもアリだと思った)

今回は以上。
では。