ラベル AdventCalendar の投稿を表示しています。 すべての投稿を表示
ラベル AdventCalendar の投稿を表示しています。 すべての投稿を表示

2022年12月15日木曜日

Git に Contribute してみた

この記事は「Gitのカレンダー | Advent Calendar 2022 - Qiita」の 15日目の記事です。

Git そのものの修正を出したい、手順ってどうすればいいんだろ?
と検索しても GitHub で OSS に貢献(Contribute)する方法みたいなのがヒットして役に立たず。
結局、公式の英語文とにらめっこして Contribute したので備忘録です。

はじめに

出した PR はこちら
https://github.com/gitgitgadget/git/pull/1406

そしてこの修正が含まれた Git 2.39 がリリースされました。

Highlights from Git 2.39 | The GitHub Blog
[ANNOUNCE] Git v2.39.0 - Junio C Hamano

Changes にアカウント名が載ってましたねぇ。嬉しい。

Contribute 方法

さて、まずはじめに Git はよくある OSS のように GitHub での Pull Request を出したらレビューされて Approve されたらマージされる。というフローではありません。
基本的にメーリングリストにパッチを送る形式のようです。

CONTRIBUTING.md

ただ、メーリングリストは自分もそう感じましたが非常にハードルが高いです。(英語だし)
そこで私は GitGitGadget に PR を出す方法で Contribute してみました。
やり方はドキュメントをたどっていけばわかりますが、日本語情報がなかったので、かなり慎重になりました。

ドキュメントはこちら MyFirstContribution

修正をする

修正するまでは他 OSS の場合とあまり変わらないですが、まず gitgitgadget/git に PR 出すのでこちらから fork しましょう。
修正したらビルドして動作確認、テストをすることになります。
この辺は README 読めばわかると思うので省略。
ちなみに今回の PR は1行修正であることと、テストってどうやる?どうやってる?って感じの内容だったのでやってません。
(実際にはやったけど自分の環境では修正と関係ないところがパスしなかった。PR 出すとテストされるのでそっちに任せました。ごめんなさい)

コミットをする

変更できたら、次は commit します。
ここは少し注意が必要です。コミットメッセージは当然英語ですが、そこは頑張ってください。

1つ目は git commit に --signoff (-s) をつける必要がある点です。このオプションを付けるとメッセージに「Signed-off-by: <user.email>」のメッセージが追加されます。
これが必須なので普段つけてない人は気をつけましょう。

2つ目は commit メッセージのフォーマットが決まっている点です。
.editorconfig で1行あたりの文字数が設定されているので、.editorconfig 対応してるエディタでコミットメッセージを編集するのをおすすめします。
コミットメッセージの1行目は変更対象のコンポーネント名を含む 50 文字以下で概要を書きます。
1行空行を空けたあとに、変更の詳細を書きます。
詳細には、コード差分からは読み取れない部分を書くことが重要です。

自分の場合、今回はとにかくメッセージの部分に時間を取られましたが、過去の commit のメッセージを参考にしてシンプルな日本語文章を書いてから、少しずつ翻訳ツールを使って英語のメッセージにしました。
(普段英語できないのにテキトーな英語使ってたが、今回はかなり気を使った。。)

プルリクエストを出す

commit したらプルリクエスト(PR)を出します。
PR を出す先は gitgitgadget/git なので気をつけてください。
やり方はこちらに記載されています。
https://git-scm.com/docs/MyFirstContribution#send-pr-ggg

PR の内容はメーリングリストに流れるカバーレターのタイトルと本文になるので、こちらもドキュメントを参考に書きましょう。

カバーレターについてはこちらに記載されているので、これを参考に PR のタイトルと本文を記載します。
https://git-scm.com/docs/MyFirstContribution#cover-letter

今回のように修正が 1 commit であれば、commit の概要をタイトルにしても良いと思います。
説明文のほうは、commit や commit メッセージでは読み取れない補足情報を書きます。
今回は簡単な内容説明と再現条件を記載しました。

これも過去の PR を参考にすると良いかもしれません。

PR 後の対応

PR を作成すると bot からのメッセージが投稿されます。
こちらにも Contribute 方法について書かれてます。
それに記載されてますが、初めて Contribute する場合は許可された GitHub ユーザー名にないため、すでに許可されたユーザーから /allow のコメントをもらう必要があります。

自分の場合は幸運なことに特になにもせずとも /allow されました。
もし /allow されない場合は issues から /allow コメントを出してる人を探すといいそうです。

(すでに /allow されたユーザーなら誰でも /allow できるっぽいので今度は自分が /allow できるってことか。つまり私に /allow してーと頼むことも可能ってことか。)

次に /submit コメントを書くと、PR の内容がメーリングリストに投稿されます。
が、その前に /preview で投稿されるメールを確認できるので、しておきましょう。
GitHub に登録してるメールにプレビューメールが届きます。
内容に問題がなければ /submit コメントを送ります。

メーリングリストの返信や patch のステータスなどがボットにより自動で PR に送られてきます。
メーリングリストで修正依頼や質問などが来たら返信する必要がありますが、今回は特に眺めてるだけで取り込まれました。(軽微な修正でしたので)
ドキュメントにそのようなケースの対応方法も書いてあったので、たぶんそれを見ながら対応すれば大丈夫だと思います。(経験しなかったので省略)

あとは勝手に進んだのであまり知見として得るものはなかったのですが、待っていたら master に取り込まれて PR は close になります。
(PR は merge されず close になります。取り込まれたかどうかは label でわかりそうです)

最後に

最後の方は待ってるだけで、これなにもしなくていいのかな?認識間違ってるかな?と不安にもなったのですが、結果的に取り込まれてそれがリリースされたのでとっても嬉しいです。
なんか、Git そのものに Contribute するというのはちょっと特別感がある気がします。

Git 自体の修正って大変そう。難しそうというイメージがありましたが、今回の PR 内容は調べてみたらそんなに難しい修正じゃなかったです。みなさんも普段 Git を使っていてなんか変だな?バグかな?と思ったら Contribute にチャレンジしてみてはいかがでしょうか?

とりあえずあまり有益な記事じゃないかもしれませんが、怖くないよってことが伝われば幸いです。ではでは。



2021年12月16日木曜日

Visual Studio でライブラリなど外部コードの警告を出さないようにする方法

これは「C++のカレンダー | Advent Calendar 2021 - Qiita」の16日目の記事です。

はじめに

警告はときにプログラムの問題を教えてくれます。
警告は基本的にないのが望ましいです。なぜなら、野原から四葉のクローバーを探し出すのは大変だからです。(見つけた四葉は幸運をもたらすか、不幸をもたらすか。。見つけるなら早いほうがいいですよ)

CI/CD 担当をやっていると警告を直してもらうための対応とかしたりします。
警告出てたらステータスを変えて通知とか、ちょっとずつ警告をエラーにしていくとか。
ここで問題になるのは、自分たちが改変することができない SDK やライブラリの警告です。
通知で頑張ってる場合はフィルターでなんとかなるかもしれません。
as Error にしている場合は困ります。

そんな場合は自分たちのコード以外をシステムインクルード(#include <...>)し別途警告レベルを制御することで解決できます。

Visual Studio で外部コードの警告を制御する

Visual Studio では 2017 (15.6) からシステムインクルードの警告レベルを別途設定できるようになりました。「/external (外部ヘッダー診断) | Microsoft Docs」こちらの公式ドキュメントにもありますが 2017 では試験機能となっています。/external オプションに加えて /experimental:external オプションも必要になるので注意してください。2019 からは正式機能となっており、設定も専用のページができました。

さて、これを利用すれば外部コードはシステムインクルードとすることで警告がでないようにできます。試しに以下のコードで試してみました。


/external の設定

プロジェクトプロパティの「C/C++」→「外部インクルード」を開き、 /external:W0 を設定します。コード分析も外部インクルードに対して別途制御可能なので、有効にしている場合は設定しましょう。

外部インクルードディレクトリにパスを追加している場合は、システムインクルードすれば外部インクルードとして認識されます。もしただのインクルードディレクトリにパスを追加している場合は、/external:anglebracket オプションを有効にすることで外部インクルードとみなされます。(システムインクルードすれば警告でなくなると逃げ口として意図しない対応をされる可能性があるので、インクルードディレクトリの設定を変更するのをオススメします)

システムインクルードではない場合

C4390 と C4456 が出ます。

システムインクルードの場合

システムインクルードにすると警告が消えました!

消えない警告もある?

たまたま見つけたのですが、システムインクルードしたファイルの警告でも /external:W0 が効かずに警告されるケースがありました。(こういう書き方をすることはない気もしますが)
コードはこちらです。gcc/clang では警告されませんでした。(https://wandbox.org/permlink/kPn2z1MLCAvbOBny

↑は C4390/C4702 の2つ。↓は C4390 は消えるが、C4702 は消えない。

Visual Studio でシステムインクルードヘッダーの警告を厳しくする

逆にシステムインクルードの警告レベルを上げるとどうなるのでしょうか?
標準ライブラリはシステムインクルードしていると思いますが、それらのコードに警告はあるのか・・? /external:W4 にして試してみました。


結果としては警告は出ない、が警告があるのかないのかはわからない。でした。
というのも VS2017 より前から標準ライブラリの警告って見た記憶がないため(たぶん)、別途制御されているのでは?と思ったからです。
ちなみに後述してますが gcc/clang では(とあるコンパイルオプションをつけると)標準ライブラリからも警告が出ていたこともあります。
MSVC の STL は公開されているので、暇なときにビルドしてみて確認してみようかと思います。
https://github.com/microsoft/STL

gcc/clang の場合

gcc/clang の場合は古くからシステムインクルードの警告は除外されていました。
(Visual Studio が今までできてなくて 2017 でようやくという感じでした)
Wandbox で試してみたのでリンクを貼っておきます。
コードは Gist にも置いてあります。

システムインクルードではない場合

警告でます。
gcc: https://wandbox.org/permlink/MLrLASaM5o5A3UWm
clang: https://wandbox.org/permlink/x6TT2NFROSmyLhV4


システムインクルードの場合

警告でません。
gcc: https://wandbox.org/permlink/XVHXnWIMyOfDMjl3
clang: https://wandbox.org/permlink/strTYwduT4ZLH5NK

gcc/clang でシステムインクルードヘッダーの警告を有効にする

gcc/clang でもシステムインクルードの警告を有効にできます。-Wsystem-headers オプションを使います。
試しにしてみると・・

新しいコンパイラーと標準ライブラリの組み合わせだと警告でませんでした。
古いとそこそこ出ます。

gcc 9.1.0: https://wandbox.org/permlink/lhXWuNvWEJdKwJNh
gcc 8.3.0: https://wandbox.org/permlink/4dHKZKtdqmDGmXNU 
clang 6.0.0: https://wandbox.org/permlink/MaVYzrGDeT79eMZa
clang 5.0.0: https://wandbox.org/permlink/qjbmV9U2c8MxHe6A

まとめ

システムインクルードを使って外部コードの警告を除外、自身のコードの警告を取り除く/取り除いてもらうように自動化/自働化しましょう。

2021年12月9日木曜日

Facebook 改め Meta 社の静的解析ツール Infer を GitHub Actions でかける

この記事は「C++のカレンダー | Advent Calendar 2021 - Qiita」の9日目です。

Infer とは

Infer は Facebook 社改め Meta 社が作った静的解析ツールです。
今回は C++ Advent Calendar ということで C++ の静的解析ツールとして紹介しますが、Infer 自体は OCaml で書かれています。
また、C++ の他に Java/C/Objective-C の解析も可能です。

C++ の静的解析ツールというと Cppcheck や Coverity 、コンパイラ付属のものがあったりします。筆者はこれまでこれらのツールを使ってきました。
Infer は 2015 年にOSS化して公開されたのですが、ずっと使ってみたいと思いつつ機会がありませんでした。

今回こうして記事にしているのは、仕事で必要になったからとか趣味でやる気になったからではなく、社名が変わったからネタとして触ることにしました。
理由はともあれ、以下で紹介していきます!

ローカル環境で使う場合

本記事は表題どおり「GitHub Actions」で Infer を使う手順を紹介しますが、ローカル環境で実行する場合も軽く触れておきます。
まず大事なこととして、Windows 非対応です!
Mac の場合は brew install infer でインストールできます。Linux の場合はビルド済みバイナリをダウンロードするか、ソースコードビルドで使うことができます。Docker という手もあります。
詳しいことは公式の「Getting Started with Infer」を見てください。

セットアップできたら「infer run -- ビルドコマンド」のようにコマンド実行すると以下のように結果が出ます。

ビルドコマンドは対象によって変わると思いますが、コンパイラー以外にも cmake や make 、mvn などのビルドツールにも対応しています。

ビルドコマンドが bash script になっているような場合はキャプチャーするコマンドを認識できないので、--force-integration オプションで教えてあげてください。
対応している integration は --force-integration オプションのヘルプで確認できます。
e.g. infer run --force-integration clang -- build.sh

GitHub Actions で使う

では、ここから本題です。
GitHub Actions で Infer を使うために、Setup Infer action (srz-zumix/setup-infer) と Infer reviewdog action (srz-zumix/reviewdog-action-infer) を作成しました。

setup-infer

Infer を現在の環境にセットアップするアクションです。
当然ですが Windows は非対応です。また Mac の場合はバージョン指定はできず、 brew install で取得できるバージョンがインストールされます。
(要望あれば対応しようかと思いますので、issues へどうぞ)

reviewdog-action-infer

Infer の結果を reviewdog を使って PR にコメントするアクションです。
Infer の実行結果が入っている infer-out から result.txt を参照し、reviewdog を使って PR に問題をコメントします。


なぜ action を分けたのか

最初は Infer インストールや解析込みの action を書こうと思ったのですが、ビルドツールや環境はユーザーによってバラバラで、action 側ですべてに対応するのは難しいと考えてこのようになりました。

Infer の実行

上記2つの action は infer での解析処理をしませんので、ワークフローで適宜呼び出してください。
個人開発してるテストフレームワーク(iutest)の例を記載しておきます。

  infer:
    runs-on: ubuntu-latest
    needs: prepare
    steps:
      - uses: actions/checkout@v2
      - uses: srz-zumix/setup-infer@v1
      - name: infer
        run: |
          infer -- make -C test IUTEST_USE_PYTHON=0
      - name: Check Infer report
        uses: srz-zumix/reviewdog-action-infer@v1
        with:
          reporter: github-pr-review
   
結果

iutest のワークフローの結果はこちらです。
静的解析なしだと 10 分くらいのテストが、Infer ありだと 25 分弱と少し時間がかかってますが、まぁ趣味開発なので許容範囲です。

速度向上

Recommended flow for CI | Infer」こちらで CI 向けのおすすめ実行方法が書いてあります。うまくキャッシュできるのであれば --reactive オプションでキャプチャーした情報を再利用すれば早くなると思います。
reportdiff は reviewdog で同等のことができるのでどちらでも。

また --changed-files-index オプションで差分ファイルのリストを指定すれば、そのファイルの解析だけが行われるため、速度向上可能です。
ただし、C++ の場合はヘッダーファイルを指定しても解析されません。.cpp ファイルを指定しないとダメです。(※ --changed-files-index は analyze 時に有効なので capture 時間の短縮にはならない)

Infer capture/analyze TIPS
capture/analyze 中にクラッシュする場合

--skip-analysis-in-path で除外指定できるのでそれをおすすめします。
-g オプションでデバッグモードになるので原因調査ができるかもしれませんが、ストレージを圧迫するかもしれません。
(3,000 弱のソースコードファイル数からなるプロジェクトでやったら 600GB 越えたあたりでディスクフルになって PC 自体が落ちました。。)

解析途中でエラーが出る場合

--keep-going オプションを付けると続行可能です。

compile_commands.json の場合 --clang-blacklisted-flags/--clang-blacklisted-flags-with-arg は効かない

そのまんまです。特に xcodebuild の場合 infer が使う clang が知らないオプションを使ってることがあり、「error: unknown argument: '-index-store-path'」のように失敗していまいます。 infer はデフォルトで  --clang-blacklisted-flags-with-arg に -index-store-path が入ってますが、 compile_commands.json から capture をする場合は --clang-blacklisted-flags(-with-arg) オプションは考慮されないので、json ファイルの command から削除してください。

--continue-analyz

仕事のプロジェクトに Infer 掛けてみたら analyze でクラッシュするわ、エラー起こるわ、なんか応答なくなるわ、そもそも解析時間がクソ長いわ、で辛かったんですが、--continue-analyz オプションつけると続きから解析してくれるので作業が無駄になりません。
(最初に知りたかった)

.inferconfig にオプションを書ける

infer のコマンドラインオプションは .inferconfig ファイルに書いておくことができます。
ファイルの中身は JSON 形式でオプションから -- を除いた名前をキーに設定をします。

例えば、上記で紹介した --skip-analysis-in-path や、 infer の clang にインクルードパスを追加する場合は以下のように書けます。

{
    "skip-analysis-in-path": [
        "path/to/lib/xxx/src",
    ],
    "Xclang": [
        "-I /path/to/dir/include",
    ]
}
まとめ

静的解析ツールは1つかければ十分というものではないので、ぜひ試してみてください。

以上。

2021年12月6日月曜日

CircleCI の Concurrency と Parallelism

この記事は「CircleCI Advent Calendar 2021のカレンダー | Advent Calendar 2021 - Qiita」の6日目です。

CircleCI が無料プランで 30 同時実行可能になったので、Parallelism との関係を調べてみました。

Parallelism とは?

CircleCI ではワークフローのジョブとジョブはそれぞれ並行実行されます。
参考:ワークフローを使用したジョブのスケジュール - CircleCI#ワークフローの構成例 

一方、Parallelism はジョブの中の処理を並列実行する仕組みです。
参考:テストの並列実行 - CircleCI

Parallelism はジョブの steps をそれぞれのワーカーで同じように実行されますが、各ワーカーに付与される CIRCLE_NODE_INDEX 環境変数の値(0,1,2...)でテストを分割したり条件分岐できます。
この Parallelism はプランによって使用できる上限が決まっています。
筆者の場合は今月頭の時点で 16 でした。

さて、ここで少し疑問がわきました。
16 parallelism のジョブを 2 つ使ったら 30 同時実行されるのでしょうか?

Parallelism を含むジョブを 30 以上実行したらどうなるか?

筆者が CI サービスのまとめをしてるリポジトリで検証してみました。

まとめルートリポジトリ:https://github.com/srz-zumix/ci-specs
同時実行の関連まとめ:https://github.com/srz-zumix/ci-parallel

ジョブの開始・終了時刻を記録、その情報から json を生成して chrome://tracing で可視化しています。
この方法は以前「ブログズミ: chrome://tracing で並列処理の可視化をしてみたらすごく便利だった話」で詳細に書いてますので、そちらを参照してください。
ジョブ設定はこちらを参照してください。
https://github.com/srz-zumix/ci-parallel/blob/master/.circleci/config.yml

16 parallelism x 2 job

16 -> 16 という感じでジョブは同時実行されませんでした。
続いて Parallelism を減らし、ジョブ数を増やしてみます。

4 parallelism x 8 job

今度は 28 -> 4 という感じで実行されました。
組み合わせたらダメとうわけではないようです。

(1 parallelism x ) 31 job

最後に Parallelism なし(1)を 31 job です。

当然ですが、30 -> 1 のように実行されました。

まとめ

Parallelism の数分だけ空きがないとそのジョブはキュー待ちする
同時実行数に収まるように Parallelism 数を決めると良さそうですね。
※この挙動に関しては 2021/12/05 時点での結果であり将来的に変わる可能性はあります。

以上。

2020年12月22日火曜日

[C++] Clang ではオーバーロードされた private 関数に明示的な実体化時のアクセスができない?

※この記事は C++ Advent Calendar 2020 22日目の記事です。

はじめに

過去に本ブログでも紹介した template の明示的実体化時に private メンバーアクセス可能な仕様を利用した private メンバー変数・関数へのアクセスですが、最近それを使っていて clang だけとある条件でアクセスできないことに気づきました。

この挙動が仕様として正しいのか正しくないのかは筆者ではわからないので、実挙動ベースの話になってしまいますことをご了承ください。

過去の記事

ブログズミ: [C++] Private な関数のテスト
ブログズミ: [C++] 本当に private なところ

サンプルコード

こちらは iutest の private メンバーのテストのための機能を使ったサンプルです。
Wandbox 用に圧縮したソースコードを使ってますので、実装を確認したい場合はこちらを御覧ください。
https://github.com/srz-zumix/iutest/blob/master/include/iutest_prod.hpp#L62

#define IUTEST_USE_MAIN
#include "iutest.hpp"

class A
{
public:
    int GetX(void) { return m_x; }
private:
    int m_x;
};

IUTEST_MAKE_PEEP(int A::*, A, m_x);

IUTEST(Peep, Test1)
{
    A a;
    IUTEST_PEEP_GET(a, A, m_x) = 42;
    IUTEST_EXPECT_EQ(42, a.GetX());
    IUTEST_EXPECT_EQ(42, IUTEST_PEEP_GET(a, A, m_x));
}

IUTEST(Peep, Test2)
{
    A a;
    IUTEST_PEEP(A, m_x) x(&a);
    x = 54;
    IUTEST_EXPECT_EQ(54, a.GetX());
    x += x;
    IUTEST_EXPECT_EQ(108, a.GetX());
    IUTEST_EXPECT_EQ(108, x);
}

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ
https://wandbox.org/permlink/2ZPvpUz1zDe1KHHs

ポイントは IUTEST_MAKE_PEEP と IUTEST_PEEP_GET です。
IUTEST_MAKE_PEEP で private メンバーアクセスするための情報をセットアップし、IUTEST_PEEP_GET で実インスタンスの private メンバーへの R/W を実現しています。

問題のコード
class Hoge
{
    int x;
public:
    Hoge() : x(42) {}
private:
    int GetX() { return x; }
    
private:
    int gX() { return x; }
    int gX() const { return x; }
    int gX(int) { return x; }
};


IUTEST_MAKE_PEEP(int (Hoge::*)(), Hoge, GetX);
IUTEST_MAKE_PEEP(int (Hoge::*)(), Hoge, gX);

int main()
{
    Hoge hoge;
    std::cout << IUTEST_PEEP_GET(hoge, Hoge, GetX)() << std::endl;
    std::cout << IUTEST_PEEP_GET(hoge, Hoge, gX)() << std::endl;
}

Clang の場合はエラー
https://wandbox.org/permlink/roGkNKKwsnaLX7og 
GCC の場合は OK
https://wandbox.org/permlink/AWd5A19WWDznccfq

エラーとなるのは gX 関数の PEEP で、オーバーロードされた関数があるとダメなようです。
Visual Studio はバージョンによって static メンバー関数がダメだったりするのは認識してましたが、 clang でもうまくいかないケースがあることがわかりました。

この挙動に関してなにか進展があったら、追記したいと思います。

では。


2020年12月8日火曜日

Zapcc を使った複数プログラムの並列ビルドでハマった話

※この記事は C++ Advent Calendar 2020 8日目の記事です。

Zapcc とは

zapcc は clang ベースのキャッシュを利用した高速な C++ コンパイラーです。
zapcc はサーバープロセスのメモリ上にキャッシュを構築して高速化します。
ヘッダーファイルの解析結果や template のインスタンス化などがキャッシュされます。

プリコンパイルヘッダーを使うよりも生成されたコードもキャッシュされるので高速です。
類似のツールで ccache というキャッシュツールがありますが、こちらは翻訳単位ごとにキャッシュする仕組みなのでフルビルドのときはキャッシュ生成するだけでキャッシュの恩恵を受けられませんが、 zapcc の場合は同じヘッダーファイルを include してるファイルで、template インスタンス化などのキャッシュが利用されるためフルビルドでも高速になります。

また、zapcc サーバープロセスがいる間は別のプログラムのコンパイル時でもキャッシュ利用可能なので複数のプログラムをビルドする際も高速になります。

導入は簡単でビルド・インストール後、 CXX=zapcc++ とするだけで使えます。
自作の C++ テスティングフレームワーク iutest のテスト環境として zapcc インストール済みの Docker を用意してるので、よろしければそちらからでも試せます。
https://hub.docker.com/r/srzzumix/zapcc

ハマったこと

zapcc はビルドを高速に行うためにキャッシュをサーバーに蓄えます。
キャッシュはサーバープロセスが生きてるうちは有効です。
つまり、1つの実行ファイルをビルドするときだけでなく、その後に別プログラムをビルドする場合にもキャッシュが有効になります。
ライブラリの大量にあるテストプログラムをビルドするときには、このキャッシュがとても有効に働くと思います。

筆者が開発している iutest でも、複数のテストプログラムがあるのでビルド時間が短縮されるのを期待しましたが、結果は「テストの失敗」でした。

何が起きたか。

ビルドは特に問題なくできているように見えました、しかしながらテストは失敗している。
どうやらテストが失敗するのは、デフォルト設定ではなくテスト用に機能の有効化・無効化をしているテストでした。
iutest はコンフィグマクロを定義することで任意の機能を有効にしたり、無効にしたりするのですが、これが zapcc と相性最悪でした。。

どうやら、以下のようにとあるテストでコンフィグを変えても、キャッシュされたヘッダーファイルを利用してしまうため、#define が伝わっていないことがわかりました。

#define IUTEST_HAS_VARIADIC_TEMPLATES   0
#include "iutest.hpp"
  
対策

並列ビルドしているとキャッシュされたヘッダーを利用してしまうため、直列にしました。 -j4 とかせず -j1 を指定。
はい。もこの時点で Zapcc の恩恵を捨てています。いやむしろビルド時間的には悪化する場合も考えられます。。。

次に、キャッシュサーバーのプロセスが生きたままになっているので、1プログラム作る度に kill するようにしました。。。

Makefile はこんな感じになりました。

ifeq ($(CXX_NAME),zapcc++)
BUILD4ZAPCC=pkill zapcc++; sleep 1
endif

$(TARGETS1) : $(OUTDIR)/% : %.cpp $(IUTEST_HEADERS) $(MAKEFILE)
	$(BUILD4ZAPCC)
	$(CXX) $(IUTEST_INCLUDE) $(CXXFLAGS) -o $@ $< $(LDFLAGS)

なんか無理くりですが、 iutest はビルド速度改善を目的に zapcc を使っているわけじゃなく、zapcc コンパイラで不具合がないか検証するために使っているので、これでもまぁいいのです。。

最後に

zapcc はすごいけど万能ではなかった。



2020年12月1日火曜日

[C++] Concepts で外部ライブラリの template よりも優先されるオーバーロード関数を書く

※この記事は C++ Advent Calendar 2020 一日目の記事です。

はじめに

 C++20 で Concepts が導入されました。
コンセプト - cpprefjp C++日本語リファレンス

コンセプトはテンプレートパラメータを制約する機能で、「コンセプトによって関数オーバーロードやテンプレート特殊化」ができます。
今までテンプレート関数のオーバーロードを書く場合は SFINAE などのテクニックを使って書いていたと思いますが、コンセプトで書きやすくなりました。
これも大きな変化の1つですが、コンセプト関数が通常の関数よりも優先して lookup されるのも便利になった点の1つです。
コンセプトによるオーバーロードの場合、コンセプト関数が通常の関数よりも優先して lookup され、要件を満たすコンセプト関数がなかったら他の候補を探しに行きます。SFINAE では優先順位がつけられないケースでもコンセプトなら可能になりました。

どういうこと?
SFINAE では解決できなかった優先順位問題とコンセプトを使った実装の例

↑こちらは、std::cout << できない型の場合は "unknown" を出力するようにしようとしている様子です。

donot-change.h には std::cout するだけの template 関数 print があります。
こちらは変更ができない想定です。(外部ライブラリとか)

SFINAE.cpp では頑張って、 std::cout ができない場合で特殊化しオーバーロードしようとしてます。他の書き方を書いたりもしましたが、どうしても ambiguous になってしまって条件を満たすことができませんでした。

一方 Concepts.cpp は printable ではないコンセプト制約でオーバーロードするだけで実現できています。
すごく簡単ですね。

ちなみに
ちなみに donot-change.h を変更可能とした場合は、以下のように書くことができます。
namespace printer_internal
{
template<typename Elem, typename Traits, typename T>
::std::basic_ostream<Elem, Traits>& operator << (::std::basic_ostream<Elem, Traits>& os, const T&)
{
    return os << "unknown";
}
}

// 解決順序
// foo::operator <<
// ::operator <<
// ::printer_internal::operator <<
template<typename T>
void print(const T& val)
{
    using namespace ::printer_internal;
    ::std::cout << val << ::std::endl;
}
これは ADL の解決順序を利用して実現しています。
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ https://wandbox.org/permlink/rlQoH37cvYTI23qo 
使い所は?
例でも示したとおり、オーバーロードしたい対象の関数を変更できるのであれば、そちらで解決する方法を模索するのが良いと思います。
ただ、外部ライブラリなど変更することができない場合、非侵入的に解決する方法として覚えておくと役に立つ日が来るかもしれません。

実例
そもそも私がなんで外部ライブラリの挙動をオーバーロードで変更したいと思ったのかというと、以下の理由でした。

* Google Test はアサーションが失敗すると、そのときの値を出力します
* std::cout できない場合はバイト列を出力します
* できない場合の対応は「ちなみに」の ADL を利用した方法で実現されています
* 古い Google Test ではこの機能がない
* 自作テスティングフレームワーク iutest は Google Test と互換性がある
* iutest は Google Test の拡張機能としての一面もある
* 古い Google Test と iutest の組み合わせでも不明な型を printable にしたい
* Google Test 側のコードは書き換えられない
* どうしよう

実際にコンセプトで対応してる部分はこちらになります。
最後に
教えていただいた いなむのみたま(@mitama_rs) 先生ありがとうございました。
ちなみにそのツイートにもぶら下がってますが、C++20 未満のコンパイラでこの問題を解決する方法も募集しておりますmm


2019年12月17日火曜日

ゆく CI くる CI

はじめに
この記事は「CI/CD Advent Calendar 2019 - Qiita」17日目の投稿です。
はじめに

Rocro のサービス終了が発表されました。
コードレビュー系のサービスは GitHub Actions の登場もあり厳しいのかもしれないなぁーと思った今日このごろ。。

個人的には、GitHub Actions + reviewdog でもうええやんってなってる。
(reviewdog のことは別途記事にしたい)

と、まぁ GitHub Actions が目立った年だったなと思いますが、
各サービスの一年を軽く振り返ってみたいと思います。
(いろんなサービス使ってるけど、常にニュースを追っかけてるわけじゃないのでいい機会ですね)


AppVeyor
Build macOS projects with AppVeyor | AppVeyor
AppVeyor でも Mac が使えるようになりました。
ブログでは E-mail で連絡してねと書いてありますが、現在はすべてのユーザーが使用可能になっているようです。

かつては、Windows の CI は AppVeyor 一択だったころもありましたが、
もはや、OS のバリエーションは CI サービスの優位性にならなくなってしまいましたね。
今後 AppVeyor がどうなっていくのか気になるところです。

Azure Pipelines
What’s new with Azure Pipelines | Azure DevOps Blog
Multi-stage YAML pipelines というのが使えるようになっていたみたいです。
まだ使ったことないので、そのうち使ってみたいですね。

Bitrise
Bitrise Ship just released to Open Beta | Bitrise Blog (日本語)
Ship はストアへのデプロイを Bitrise 上で行えるようになる機能のようですね。
個人開発ではモバイル開発をしてないので、あまりお世話になることはないものですが、
Bitrise はモバイル開発の強みが加速しているように見えますね。

Buddy
New feature: Multiple YAML-file support for pipeline definitions | Buddy: The DevOps Automation Platform
パイプラインを分けてかけるようになったみたいですね。
.buddy ディレクトリ配下に、.yml をおけばよいみたいです。(ルートの buddy.yml は必須)

buddy は制限きつくてあんまり使ってないのですが、いっぱい使えるようになったら分割してみたいですね。

Circle CI
Windows CI - Windows support | CircleCI
AppVeyor とは逆ですね。Circle CI でも Windows 環境が使えるようになりました。

Cirrus CI
Cirrus CI は FreeBSD に対応しましたね。と言いたいところでしたが、去年の話でした。


なんか普段から使ってると昔からこうだった気がしちゃいますが、GitHub との連携周りが強化されていたようです。



と、思ったらマニュアルタスク対応してたのか!
ちょうど欲しかったんだよね。


Codefresh
Use parallel steps in your Codefresh pipelines - Codefresh
並列ステップができるようになりました。
これは、本ブログでも紹介しましたね。「ブログズミ: [Codefresh] Parallel 実行してみた

Pause your pipelines and resume after manual approval - Codefresh
もう一個。
Codefresh もマニュアル対応してたんですね。

Codeship
New CloudBees CodeShip Beta - a Faster, Simpler, Unified Build Page - via @codeship | via @codeship

新しい UI が出てたみたいですね。
「Personal Settings」の「New build details page」を Turn On すればよさそうです。
今度試してみます。

Drone Cloud
Announcing Support for Starlark Scripting
GitHub Actions が HCL(HashiCorp Configuration Language)から YAML に変わったのは記憶に新しいですが、
Drone は YAML じゃなくて Starlark で書けるようになったみたいです。
Bazel な人にとっては嬉しいのかな?

GitHub Actions
New from Universe 2019: GitHub for mobile, GitHub Archive Program, and more - The GitHub Blog
はい。正式リリースおめでとうございます。
今後ともよろしくお願いします。

Pekaflow
前回の記事を参考にしてください。
ブログズミ: [CI] Peakflow 始めました

Rocro
Rocro will not be available after Jaunary 31, 2020 – Rocro News Releases
冒頭で書いたとおり、2020年1月31日にクローズとなります。
いままでお世話になりましたmm

Scrutinizer
2018年の4月以降ブログが更新されてない。大丈夫かな?

Semaphore CI
Semaphore 2.0 Welcomes Open Source Developers with Free Continuous Integration
OSS のビルド時間制限がなくなったみたいですね。
これはちょー嬉しい!あとでちゃんと確認しよ。

Shippable
こちらもブログの更新が滞ってますね。
ただ、Shippable は2月に JFrog に買収されたので、JFrog Pipeline の方に注力してるのかもしれないですね。
We’ve Acquired Shippable to Complete DevOps Pipeline Automation From Code to Production | JFrog

Shippable も継続してくれると嬉しい限りですが・・

Sider (旧SideCI)
Siderの運営会社が2019年10月末日より株式会社スリークに変わります - Sider Blog
Sleeek の機能の一端として取り込まれるみたいですね。

Shppable といい、統合が進んでますね。

Travis CI
CPU アーキテクチャが選べるようになりました。
OS の次は CPU アーキテクチャなのだろうか。
The Travis CI Blog: Multi-CPU architecture support for your builds
The Travis CI Blog: Build your open source projects on IBM Power and IBM Z CPU architecture

Wercker
こちらも特に news はなし。。

最後に
見切り発車でアドカレに登録してしまったのだが、使ってるサービスが増えるほど情報追っかけるのが辛いので、こういう機会に見直してみるのはありかも。と思いました。

年明けにこの記事を見返してみて、試せることはやってみたいと思います。
では。

2019年12月10日火曜日

[CI] Peakflow 始めました

はじめに
この記事は「CI/CD Advent Calendar 2019 - Qiita」10日目の投稿です。

おそらく、GitHub Actions など有名・話題なサービスの話が多くなるのではないか、
と予測して、とてもマイナーな CI サービスの話にしました。
そして、全くもって得るものがない内容となりましたことを報告致します。
(この時点で興味がない方はバックキー推奨)

私は趣味で CI のバッジを集めており、今回は新しい CI サービスを使ってみた。という内容です。
iutest

GitLab CI が失敗してる・・タイミング悪し)

Peakflow 始めました


というわけで、本題。
Peakflow を始めてみました。

Pricing がわかりにくいけど、同時ビルド1本なら public/private 関わらずフリーでつかえるようです。


Sign up and Settings
Sign in しようとすると権限が求められるので許可します。


つづいて、最初のプロジェクト選択画面が出てくるので、選択します。
ここではいつもどおり iutest を選択。
(iutest は自作の C++ テスティングフレームワークです)


つぎに、peak_flow.yml を追加してと出てきます。
サンプルが ruby な感じですが、before_script と script があるのがわかったので、以下のようにしました。(ドキュメントどこでしょう・・)
before_script:
  - gcc --version || true
  - clang --version || true
script:
  - make -C test -j$((`nproc`))
  - make -C test test




追加するとビルドされます。簡単ですね。



ビルド時間が早い、が・・・
GitHub Actions や Travis CI と比べると圧倒的に早いけど。
Circle CI には負けてる。。




Peakflow では -j$((`nproc`)) でビルドしてたので、nproc 比較してみました。
CInproc
Circle CI36
Cirrus CI32
GitHub Actions2
Peakflow16
Travis CI2

・・比較してみたのはいいのですが、Circle CI は -j4 にしてたので、この比較は意味ないなと気づきました。
あと、おそらくビルドする中の1つがとても時間かかってる気がするので -j オプションの数を増やしてもあんまり意味ないことに気づきました。
(これは別途課題として解決しようと思います)


じゃあもう少し深追いしようということで、これを機に↓で各 CI サービスのスペックを調べ始めました。
https://github.com/srz-zumix/ci-specs
(まだ作業中です。)

バッジ
最後はお決まりのバッジですが・・なんか no build になっちゃうんですよね。。
URL はプロジェクトの「Badges」から取れます。





最後に
うーん。。。という感じ。
なんかドキュメントもほとんど見当たらないし、(肝心の)バッジもちゃんと表示されないので、微妙ですね。。
Circle CI の代替サービスの位置づけのようですが、Circle CI 使ったほうが良さげ・・(有償プランの場合はお値段が関係してくるとは思いますが・・)

ここまでお付き合い頂きましてありがとうございました。
また、CI サービスを使ってみたらブログに書きます。ではでは。

2019年12月6日金曜日

[C++] 本当に private なところ

※ この記事は「C++ Advent Calendar 2019」6日目の投稿です。


private メンバー変数の R/W テスト
まずはこちらをご覧ください。
#include "iutest.hpp"
//origin>> #include "../../include/iutest.hpp"
#include <iostream>

int main(int argc, char** argv)
{
    IUTEST_INIT(&argc, argv);
    return IUTEST_RUN_ALL_TESTS();
}

class Test
{
private:
    int A:12;
    int B:4;
    int C:4;
    int D:12;
    int E;
public:
    Test()
        : A(0x777)
        , B(0x3)
        , C(0x4)
        , D(0x400)
        , E(1)
    {}
};

IUTEST_MAKE_PEEP(int Test::*, Test, E);

IUTEST(PeepTest, MemberVariable)
{
    ::Test test;
    IUTEST_EXPECT_EQ(1, IUTEST_PEEP_GET(test, ::Test, E));
    IUTEST_PEEP_GET(test, ::Test, E) = 4;
    IUTEST_EXPECT_EQ(4, IUTEST_PEEP_GET(test, ::Test, E));
}
https://wandbox.org/permlink/GqDQ4zeCrzv1HABq

private メンバーである Test::E への書き込み・読み込みができていることがわかると思います。

private メンバー変数(ビットフィールド)の R/W テスト
続いて、上でアクセスしている private 変数を E から A に変えてみます。

IUTEST_MAKE_PEEP(int Test::*, Test, A);

IUTEST(PeepTest, MemberVariable)
{
    ::Test test;
    IUTEST_EXPECT_EQ(1, IUTEST_PEEP_GET(test, ::Test, A));
    IUTEST_PEEP_GET(test, ::Test, A) = 4;
    IUTEST_EXPECT_EQ(4, IUTEST_PEEP_GET(test, ::Test, A));
}
https://wandbox.org/permlink/NRPvHweGaDp6HAdy

今度はコンパイルエラーです。

解説
プライベートにアクセスした方法
上のコードで利用したテスティングフレームワークは iutest です。
private メンバーへのアクセスはこのフレームワークの PEEP 機能を利用しています。
PEEP は template explicit instantiation で private にアクセス可能なことを利用して、private メンバーのアドレスを取得して実現しております。
詳しくは昔書いたこちらの記事を参考にしてください。(「ブログズミ: [C++] Private な関数のテスト」)

ビットフィールドにアクセスできなかった理由
error: address of bit-field requested
上記 PEEP の方法ではアドレスを取得できる必要があるため、
アドレスが取れないビットフィールドではアクセスできないわけです。
(言語法律家によるアクセスが可能な場合はビットフィールドでもアクセスできますが・・ : https://wandbox.org/permlink/zYC1hAYuqqixaEUn

まとめ
C++ にプライベートはあった

2018年12月20日木曜日

[Azure Pipelines] ビルドをスキップするコミットメッセージコマンド

この記事は Azure DevOps Advent Calendar 2018 20日目の記事です。

今回の内容は非常に短いのですが、Azure Pipelines でビルドをスキップするコミットメッセージコマンドを紹介したいと思います。
前回、前々回の記事はこちら

コミットメッセージコマンド
多くの CI サービスで使われている機能で、コミットメッセージに特定の文字列を入れておくと、CI 上の機能を呼び出せるものになります。
その定番がビルドのスキップです。

ドキュメントの更新だけのときなど、CI が実行されなくても問題ないようなケースで役に立ちます。
筆者が使用している CI サービスの各スキップコマンドを以下のリポジトリでまとめていますので、Azure Pipelines 以外のサービスで気になるものがあれば見ていただければと思います。
https://github.com/srz-zumix/ci-skip/tree/master

Azure Pipelines でビルドスキップするコミットメッセージコマンド
さて、肝心の Azure Pipelines のスキップメッセージですが、
***NO_CI***
になります。

多くの CI サービスで使われている [ci skip] や [skip ci] は対応していないようです。
ちょっと残念ですが、 issue もあるようなので対応されることを期待して待ってます。
https://github.com/Microsoft/azure-pipelines-agent/issues/858


実際にスキップメッセージを入れたときの挙動は先に紹介した ci-skip リポジトリで見ることができます。
exsample commit: add Azure Pipelines ***NO_CI***

今回は以上です。
では。

2018年12月11日火曜日

Azure Pipelines でマトリックスを組んでみた

この記事はAzure DevOps Advent Calendar 2018 11日目の記事です。
4日目に投稿した「ブログズミ: Azure Pipelines 始めました」の続きになります。


早速ですが、上のスクリーンショットは 31 個のジョブを実行している様子です。
いやホント10 並列は素晴らしいですね!

では、今回はマトリックスを組んでみた流れを紹介したいと思います。
テンプレートを作る
まずは、パラメータで処理パターンを増やすためのベースとなるテンプレート部分を作ります。
ドキュメントを見た感じですと、ジョブ、もしくはステップをテンプレートにできるようです。
Job and step templates - Azure Pipelines & TFS | Microsoft Docs

テンプレートの記述と利用
テンプレートは azure-pipelines.yml とは 別の yaml ファイルに記述します。
そして、azure-pipelines.yml もしくは別のテンプレートから下記のように参照します。
steps:
  - template: templates/sample.yml  # Template reference
jobs:
  - template: templates/jobs.yml  # Template reference

サンプルがドキュメントに載ってますので、そちらを見ていただくとわかりやすいと思います。
テンプレートは別のリポジトリのファイルを参照することもできるようですが、今回は使わないので省略します。 > Using other repositories

テンプレートにパラメータを渡す
テンプレートにパラメータとして任意の要素を渡し、パラメータに応じて処理内容を変えたいと思います。
Passing parameters
(ドキュメントを見ていると、単純の値や配列だけでなく、ジョブをパラメータとして扱うこともできるようですが、まだ実践してないので今回は省略)

まずは、パラメータのやり方から。

template 側の yaml
parameters:
  name: ''
  options: ''
  vmImage: 'ubuntu 16.04' # デフォルト値

jobs:
  - job: ${{ parameters.name }}
    pool:
      vmImage: ${{ parameters.vmImage }}
parameters にパラメータを定義します。ここでセットした値はデフォルト値になります。
パラメータの値を使用する場合は、${{ parameters.hogehoge }} のようにします。

azure-pipelines.yml 側
jobs:
  - template: .ci/azure_pipelines/template-make-test.yml
    parameters:
      name: default
 
パラメータを渡す場合も、parameters に記述します。
これでパラメータの受け渡しができるようになりました。

パラメータに応じて処理を変える
さて、中核に迫ってまいりました。
パラメータの内容によって、処理を変える方法はいろいろ考えられます。
ドキュメントを見ていると、高度なことができそうな感じがしているのですが・・・
まだ使いこなせてないので、省略。
* Template expression functions
   Expressions
* Insertion
* Conditional insertion
* Iterative insertion

今回はとてもシンプルにパラメータをスクリプトの引数として使いました。
(Azure Pipelines 側の書き方や制約に縛られず、自分の好きな書き方をできるので、まずはこの方法で良いと思います。)

iutest では以下のようにしました。
parameters:
  options: ''
  package_name: 'default'

steps:
- script: make -C test -j4 OUTPUTXML=junit ${{ parameters.options }}
  displayName: 'make'
- script: make -C test -j4 OUTPUTXML=junit ${{ parameters.options }} ${run_option} test
  displayName: 'test'
  env:
    run_option: RUN_OPTION="--iutest_default_package_name=${{ parameters.package_name }}"

make にオプションを渡せるようにしたのと、テスト実行時のオプションを指定するようにしました。

azure-pipelines.ym > job template > step template
さて、ここまででほぼほぼテンプレートを作ることができるようになっていると思いますが、最後にテンプレートを2段構成にしてみました。
テンプレートをテンプレートで使うことも問題なくできるのです!

iutest では、make test とテスト結果を集計するステップテンプレート、
そして、それをある程度の粒度でパラメタライズドしたジョブテンプレートにしました。



azrue-pipelines.yml は以下のように、ジョブテンプレートを利用するだけの非常にシンプルな内容になりました。
jobs:
  - template: .ci/azure_pipelines/template-make-test.yml
    parameters:
      name: default
  - template: .ci/azure_pipelines/template-make-disabled-test.yml
    parameters:
      name: disabled

テンプレート側の yaml は長いので、GitHub を見てくださいmm
iutest/azure-pipelines.yml at master · srz-zumix/iutest
iutest/.ci/azure_pipelines at master · srz-zumix/iutest

マトリックスを書く

これが、ちょっと長いのですが・・・こんな感じになりました。


ステップテンプレートに make のオプションを生成して流しているジョブテンプレートになるのですが、
やっていることは1つのマクロを定義して config を変えて、ビルド・テストをさせています。
そのマクロ部分をマトリックスにしたのですが、いちいち名前をつけないといけないのが面倒・・・
DISABLED_CONFIG 配列に定義できると楽なんですが・・・

たぶん、もっとキレイに書けるんだろうなーという感触はありますが、今後の課題としたいと思いますmm

10並列の効果はどんなもんよ?
iutest の現時点で、1 pipeline で 57 ジョブが実行しています。
各ジョブでやっていることは、ほぼほぼ同等でマクロ定義が1つ異なるだけのビルド・テストです。
1ジョブの実行時間が約5分。

直列に行った場合は、5 x 57 分で約5時間です・・・

が、これが、


なんと!


およそ 35分 !!
10並列のパワー素晴らしい

テスト失敗してますよ?
はい。
今まで config 変更のテストは、ローカルの Jenkins もしくは今はなき SnapCI でやっていたのですが(それかローカル実行)、とにかく時間がかかって辛かった!のでやってませんでした。すみませんmm
今回、Azure Pipelines の力によってメンテナンスできてなかった部分が炙り出された感じです。
本当、ありがとうございます!!って感じです。
(FAIL はちゃんと直します。ごめんなさい)

今後やりたいこと
さて、今回はこれで以上となりますが、
まだまだ Azure Pipelines でやりたいこと・できることは多そうです。
また進展あったらまとめたいと思います。ではでは。

* [ci skip]
* auto cancel
* 簡易テスト後に、マトリックスが走るようにする(dependsOn の挿入?)
* 条件分岐(xml 出力がされないことを期待する場合に、集計をしない)
* yaml に書く量を減らしたい
* 本当のマトリックス( N x M )で爆発させたい

2018年12月4日火曜日

Azure Pipelines 始めました

この記事は(ちょうど公開するタイミングで空きがあったので)
Azure DevOps Advent Calendar 2018 4日目の記事になりました。


Azure Pipelines が9月にリリースされたようですが、最近知りました。
なんと! OSS なら 10 並列・時間制限なし!!
これは組み合わせ爆発させざるをえない!!!(マテ



Sign Up
脊髄反射で SignUp しましょう。

MS アカウントでサインインして、名前決めたら完了です。


あれ?すでに Organization がありますね?


どうやら、昔作った Visual Studio Online のが残ってたみたいです。
新規作成した Organization は削除。
Overview で「組織のURL」を更新し、プロジェクトもすべて削除しました。


ともあれ、これでサインナップ完了です。

パイプラインを作る
では、パイプライン作っていきましょう。
Azure Dev Ops のダッシュボードからプロジェクト作成しても良かったのですが、 GitHub からやったほうが楽かなーと思ったのでそっちにしました。

GitHub から登録
GitHub Marketplace に Azrue Pipeline があるので、インストールします。


フリープランで Order


リポジトリを選択(全部もしくは任意のリポジトリを選べます)


Organization を選択(SignUp 時に作成したもの)
プロジェクト名は任意で(すでにあれば選択)


認証したら・・・


プロジェクトの出来上がり!


ここまでで、プロジェクト作成が完了してパイプライン作成の第一ステップのロケーション(GitHub)の選択が終わっている状態になっています。
ここから、パイプラインを設定していきます。

リポジトリの選択
つづいて、リポジトリの選択をします。今回の場合は iutest を選択します。

テンプレートの選択
Choose a template でパイプラインのテンプレートを選びます。
c++ のテンプレートがあったので、「C/C++ with GCC」を選択しました。(リポジトリの内容によってオススメが出てくるみたいですね)


YAML
テンプレートから azure-pipelines.yml が生成されます。
ルートディレクトリで make するだけですが、iutest はそれではビルドされないので、ビルドとテストの実行をするように少し書き換えました。


Save and Run2
最後に保存して、最初のビルドを実行してみましょう!
生成した azure-pipelines.yml を commit/push するので、master に入れるかブランチ切るかを選択し、(必要であればコメントも)「Save and run」ボタンを押します。


今回はブランチを作成しました。
https://github.com/srz-zumix/iutest/pull/120

はじめてのビルド
「Save and run」を押すとビルドがキューに積まれて、処理が始まります。






しばらく待つと・・・無事成功!
ここまでは簡単でしたね!


テストの集計タスクを追加してみる
まだまだ、Azure Pipelines のことで把握していないことばかりではありますが、この流れのままテストの集計までしてしまいましょう。

テストができるようになったので、テストの集計をします。
テストの集計は「タスク」になっているようなので、タスクを追加します。

Publish Test Results task - Azure Pipelines & TFS | Microsoft Docs
先程作成した azure-pipelines.yml に以下を追加します。
- task: PublishTestResults@2
  inputs:
    testResultsFiles: 'test/*.xml'
変更を最初に作ったブランチに push しましょう。


集計できました!簡単!!
さて、これで GitHub に push するとテストが実行され、結果が集計されるところまで確認できました。
(失敗すべきテストまで集計されてしまっているのは make のオプションミスです・・・)
CI をするにあたっての基本的なことができるようになったので、ここからやりたいことを組み込んでいこうと思いますが、そのへんはまた次回で・・・

バッジを付ける
次回に行く前に・・・やっぱりバッジはつけておきましょう!
バッジはパイプラインのダッシュボードページの右上メニューの中にあります。

バッジのブランチは「?branchName=develop」をつけると指定できます。
※ ビルドページの URL のブランチ指定がうまくできなかったので、方法があれば知りたいですmm

最後に
OSS プロジェクトなら 10 並列が無料で使えるのは、個人的にすごくありがたいです。
まだ、10 並列を使い切ってはないのですが、これから使っていこうと思ってます。

また、導入してしばらく経っているのですが、GitHub に push してからビルドが走るまでの時間も早いので、そこも嬉しい。
YAML の書き方は・・・ちょっと四苦八苦しながらも書いてるので、もう少しドキュメントがわかりやすいと嬉しいな、とも思いました。(圧倒的英語力不足ともいう・・・)

OS も Windows だけでなく、macOS/Linux も使えるようなです。
(最近は、この辺での優位性がなくなりつつありますが・・・)

Azure Pipelines は非常に強力なサービスなのは間違いなさそうなので、これからもお世話になると思います。よろしくお願いしますmm

今回は以上です。