2018年10月25日木曜日

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

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

1.16 系は終わったと言ったな。。。あれはウソだ!

変更点は以下の通りです。
* Improved
  *  iuwandbox: コードサイズをさらに削減したヘッダーファイルに対応(--iutest-use-wandbox-min)

* Bug fixes
  * 古い google mock の互換性エラー修正
  * いくつかの不具合を修正

今回は主に、iuwandbox で利用する iutest.min.hpp のさらなる圧縮をした iutest.wandbox.min.hpp を使用するオプションを追加しました。
こちらの機能は試験的機能となっております。
問題なさそうであれば 1.17 系でデフォルトになる予定です。







もともと 600KB 近くあったのを、500KB 以下まで削減しました。
(↑は develop ブランチの計測なので、v1.16.7 だと少し違うかも。)

できあがった iutest.wandbox.min.hpp を見えもらえるとわかると思うのですが(Gist においておきました)、
iutest.min.hpp には、主に「構文の許す限りのインデントや改行削除」を行っていたのですが、iutest.wandbox.min.hpp では「内部マクロの名前省略」「Wandbox にない OS/Compiler 向け Config 削除」をしました。

iutest.min.hpp を作ったときの記事は以前書いているのでそちらも見ていただくとなにをしているかが、よりわかると思います。


今回の Wandbox 向けの圧縮はまた別途まとめて記事にしたいと思います。
(ローカル変数名とか、公開している部分でなければもっと名前の省略はできると思う)
(同一で連続したアクセス修飾子は消しても大丈夫なはずなので、そこも削れるはず)
(独自のリストクラスを使ってる部分をやめたらかなり減らせると思う。v1.17 でやる予定)

2018年10月24日水曜日

Travis CI に Windows がやってきた

The Travis CI Blog: Windows is Available (Early Release)
※1

Travis CI で Windows OS が使えるようになりました。
というわけで早速使ってみました。

ちょうど昨日、この記事に書いたことに対応した環境に更新されったっぽいので、状況変わってそうです。https://travis-ci.community/t/c-support-on-windows/282/10


iutest で試してみた
サクッと試したいので、既存のリポジトリを使って、Windows でのテストを追加したいと思います。
対象のリポジトリは iutest です。

概要
* https://github.com/srz-zumix/iutest
* C++
* CMake でビルド、テスト

差分
最初にできあがった .travis.yml の差分を見ていきましょう。
https://github.com/srz-zumix/iutest/pull/116/files
追加した変更が下記のあたりになります。



情報
Windows のビルド環境の情報は以下の公式ページにまとまっています。
https://docs.travis-ci.com/user/reference/windows

os: windows とすることで、Windows 上でのビルド・テストが実行できるようになるわけですが、
プリインストールされているツールやサポートされている言語など、こちらで確認しておくとよいでしょう。

基本的には公式ドキュメントを見れば、ジョブを組めると思いますが、 iutest で行ったことのうちポイントになりそうところを紹介していきます。

C++ はまだ対応言語に含まれていない
C++ はまだ対応言語に含まれてません。
現在(2018/10)、対応している言語は以下の4つです。
* Node.js (language: node_js)
* Rust (language: rust)
* Go (language: go)
* Bash variants (language: shell, language: sh)
https://docs.travis-ci.com/user/reference/windows#supported-languages

フォーラムに topic も上がってるので対応されるのを期待して待つとして、
Visual Studio がインストールされているので C++ のビルドができるでしょという期待のもと、 language: sh で一時しのぎしました。

pre-installed ツールにパスが通っていない?
Windows 環境のプリインストールツールは以下のようですが、cmake がいない(見えていない?)状態でした。
https://docs.travis-ci.com/user/reference/windows#pre-installed-packages

昔の記憶をたよりに、探してみると…
(Chocholatey をむかーし使ったときの記憶だと、インストールパスがツールによって異なったりして困ったことがあったので)
Program Files にいました!


というわけで、CMake 使う場合は下記のようにパスを通しましょう(今後の更新でデフォで見えてるようになることを願う)
export PATH=$PATH:${PROGRAMFILES}/CMake/bin
(ProgramFiles だった気がするんだが、PROGRAMFILES だった…??)

pre-install ツールが見えなかったら、デフォルトインストールパスを探してみましょう。

cmake --build でタイムアウト
cmake へのパスが通って、コマンドが無事叩けましたが、今度は cmake --build でタイムアウトしてしまいました。


AppVeyor ではどうしていたかな?と確認すると、そちらでは cmake --build を使わずソリューションファイル指定をして、msbuild が叩かれていたので、同じように msbuild を使うように修正しました。

MSBuild もパスが通ってない
(デフォルトで通ってて欲しいなー)こちらもパスを通しましょう。
Windows ビルドを調べていたら、find で検索してパスをセットしている .travis.yml があったので、そちらの方法に切り替えました。
(これで環境変わってもある程度大丈夫になるはず)
https://github.com/chensoft/libfs/blob/339aa134aa94a34b5c5a27f5a30a4d37a6af66d5/.travis.yml

CMAKE=`dirname "$(find '/c/Program Files'* -name 'cmake.exe' 2>/dev/null | head -n1)"`
      MSBUILD=`dirname "$(find '/c/Program Files'* -name 'MSBuild.exe' 2>/dev/null | grep 'amd64' | head -n1)"`
      export PATH=$PATH:"$CMAKE":"$MSBUILD"

MSBuild もタイムアウト
MSBuild に切り替えましたが、症状変わらずタイムアウト…
そこで Widonws ビルドに関係のない設定をすべて取り払って見たところ、ログが出ました。。。(うーん、謎)
https://travis-ci.org/srz-zumix/iutest/jobs/444078696
before_install:
  - |
    if [ "$TRAVIS_OS_NAME" == "windows" ]; then
      CMAKE=`dirname "$(find '/c/Program Files'* -name 'cmake.exe' 2>/dev/null | head -n1)"`
      MSBUILD=`dirname "$(find '/c/Program Files'* -name 'MSBuild.exe' 2>/dev/null | grep 'amd64' | head -n1)"`
      export PATH=$PATH:"$CMAKE":"$MSBUILD"
      echo $PATH
    fi
  - python .ci/travisci/travis_blocking_stdout.py || true

script:
  - |
    if [ "${USE_CMAKE}" == '1' ]; then
      set -e
      mkdir ./cmake-build && cd ./cmake-build
      cmake ../projects/cmake
      if [ "$TRAVIS_OS_NAME" == "windows" ]; then
        echo msbuild
        MSBuild.exe iutest.sln /verbosity:minimal
      else
        cmake --build .
      fi
      ctest -C Debug -V
      cd ..
    fi

matrix:
  include:
    - os: windows
      language: sh
      env: WINDOWS=1 USE_CMAKE=1
      before_script:
        - cmake.exe --version
        - cmd.exe /C echo test
        - MSBuild.exe --version
    - os: windows
      language: go
      env: WINDOWS=1 USE_CMAKE=1
      before_script:
        - powershell /?
    - os: windows
      language: rust
      env: WINDOWS=1 USE_CMAKE=1
    - os: windows
      language: node_js
      env: WINDOWS=1 USE_CMAKE=1
 

dist: trusty とか sudo: false が悪さをしているのかと思って試してみましたが、ログは出ず。
上記のような(マトリックスしてるのはテストのため)最小構成だと、ちゃんとログが出る。
(ちなみに、before_script で MSBuild.exe --version してるのもログが出ないので、ますますよくわからん)

tee コマンドで回避
結局は tee コマンドを介して上げるとログ出力がちゃんと認識されたので、それで回避しました。

なんとか完成
tee コマンドでなんとか問題回避できたので、ようやくビルド・テストに成功しました!


cmake --build でも tee すれば回避できました
というわけで、最終的に最初に示した YAML となりました。


最後に
ログ出力がなぜか出ず、タイムアウトしてしまうのに手こずりましたがなんとか Windows でのビルド・テストが Travis-CI 上でできるようになりました。
まだベータ状態なのでこれから改善されていくとは思いますが、この記事が誰かの参考になれば幸いです。。。


※1 マイクロソフトの許諾を得て使用しています。

2018年10月15日月曜日

AppVeyor のジョブを1つのマトリックスにまとめました

AppVeyor は1つのリポジトリに対して、複数のプロジェクトを作成することができます。
GUI Config では複雑なマトリックスを構築できないですが、複数のプロジェクトを作成することによって、擬似的に複雑なマトリックスを組みことができてました。

これで十分ではあったのですが、 iutest で使用している CI サービスも増えてきて(現在 15 サービス超)、管理する場所をなるべく少なくしたいという点と、Webhook が足りなくなってきたという2点の理由から、なるべくまとめることとしました。
(1プロジェクトにつき、GitHub の Webhook を1つ消費する。GitHub の Webhook は1リポジトリにつき、20 まで)

複雑なマトリックスの鍵: for
通常マトリックスは matrix: で環境変数やワーカーを複数用意して、"同じ"ビルド処理を行います。
environment:
  matrix:
    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
      PROJECT_DIR: msvc12
      CMAKE_GENERATOR_NAME: Visual Studio 12 2013
    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
      PROJECT_DIR: msvc14
      CMAKE_GENERATOR_NAME: Visual Studio 14 2015
    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
      PROJECT_DIR: msvc15
      CMAKE_GENERATOR_NAME: Visual Studio 15 2017
    - BUILD_NUGET: yes

ただ、これでは同じリポジトリで、ビルド・テスト以外のリリース(デプロイ)ビルドや、全く別環境(Windows vs Ubuntu)でビルドフローが異なるような場合には対応できず、
iutest でももともとやっていたような複数プロジェクト化による対応が必要でした。
(設定をパラメタライズドにして状態の異なるビルド・テストはできる。処理が単一で設定でいろいろ複雑に処理を変えるのは面倒だった)

しかし、今回紹介する for を利用することで、任意のマトリックスに対して通常とは異なるビルドやテスト・デプロイを記述することができるようになります。
for の使い方はこちらです。 Build configuration | AppVeyor

上記のマトリックスは iutest で実際に利用している yml の抜粋になりますが、NuGet ビルドの特殊化の部分を例として以下に載せます。
for:
# NuGet
-
  matrix:
    only:
      - configuration: Release
        BUILD_NUGET: yes
  before_build:
    cmd: echo.
  build_script:
    ps: |
      $nuspecPath = "projects\nuget\iutest.nuspec"
      Write-Output "Building NuGet package"
      nuget pack $nuspecPath -OutputDirectory ".\"
  test: off
for の要素として、特殊化するマトリックスの条件を matrix に記述し、任意のステップを上書き設定します。

注意したいこと
for を使った特殊化は、通常フローの上書きになります。
特殊化するケースで使用しないステップ(未記載)でも、通常フローでそのステップを使用している場合はそちらが呼ばれてしまいます
そのため、何もしない場合でも、空の状態に上書きする必要があります。
上記例では、before_build と test のステップを空にしています。

YAML の構文チェック
さて、YAML Config は記述を間違うと、YAML 解析時に失敗してジョブが即失敗してしまいます。
なので、 push するまえに YAML の構文チェックをしておきましょう。

AppVeyor では以下のページで構文チェックができます。
構文がエラーがあると以下のように、エラーの箇所を教えてくれるので便利です。
https://ci.appveyor.com/tools/validate-yaml


特に問題がなければ、グリーン表示になります。


最後に
for でまとめた結果、複数に分かれていたプロジェクトの統一ができました。(全部じゃないけど)

for を使った高度なマトリックスは本家ブログでも紹介されています。
Advanced build matrix configuration in AppVeyor | AppVeyor
詳細は、公式ドキュメントや上記を参考にすると良いと思います。

では。

2018年10月9日火曜日

技術書展5に行ってきた

技術書展5に行ってきました。
実のところ、こういったイベントに今まで一度も行ったことがなかったのですが、技術書を書くことに興味湧いてきているので重い腰を上げて行ってきました。



開場したら事前に気になったサークルを見て、あとはぐるっと一周して帰ろうと考えてたのですが、考えが甘々でした。
11:00 くらいについたときには、すでに長蛇の列で会場の1つ上の階まで並んでました。。。
それでも、思ってたより早く入場できたのでよかったです。(30分ちょっと待ちましたかね)

入場後:
目的の場所に行こうにも人がいっぱいでなかなか前に進めず・・・とにかく人がいっぱいでしたね。
途中気になる本があったりしたのですが、もっと見本誌を読んで回ってもよかったな、とあとから思いました。(移動が大変なので、移動しながら見てくのがいいんだろうな)
ぷらぷらと物色して全体的に回ろうと思ってたのですが、大変そうだったのでやめました。
(ハードウェア系とか全然見てなかった)

戦利品:
今回の戦利品はこちらです。

初技術書展でしたが、いつになるかはわかりませんがいつかサークル側で参加できたら嬉しいなと思いました。
あらためて・・・というか、これから始めるんですが、執筆頑張ろうと思いました。
(表紙大事だなーとか、高い位置に目印必須だなーとか、参考にもなりました)

以上。