Bitbucket Pipelines を使って c++(g++) をビルドする手順について記載します。
リポジトリを作成します。詳細割愛。
リポジトリをローカルPCへクローンします。
ソースコードを作成します。下記は例です。
プログラム例(”hello.cpp”)
#include <iostream> int main() { std::cout << "Hello world." << std::endl; return EXIT_SUCCESS; }
作成したソースコードをコミット&プッシュします。
クラウド側に登録を完了
以下の手順で Pipelines を有効化します。
NOTE
リポジトリの管理者権限を持つ人のみが以下を実施可能です。
(1) ”Repository settings” をクリックします。
(2) “PIPELINES“ の中の "Settings“ をクリックします。
(3) “Enable Pipelines“ をチェック状態にします。
これで Pipelines が有効になりました。
(4) ”bitbucket-pipelines.yml” の雛形を準備します。ここでは下記手順で雛形を準備してみました。
「パイプライン」⇨「Build C++ Application」
内容を確認後[Commit file]ボタンをクリックします。
すると・・・初めての Pipelines が実行されました。
当然ながら Failed となりました。
こんなメールが私へ届きました。これは良いですね。
複数メンバーがいるときなど、このメールは誰に対して送信されるのかが気になりましたが、ここでは一旦忘れて進めます。
”パイプライン” メニューをクリックすると Status が ”Failed” のものがあります。
クリックして内容を確認してみると・・・ make に check の記載がされていない ・・・ということらしいです。そもそも makefile を準備していないので、エラーになって当然の状況です。
「ソース」を確認すると、とりあえず ”bitbucket-pipelines.yml” ファイルが追加されています。
現時点の yml ファイル内容を以下に記載します。今後このファイルを編集していくことで Pipelines を実際に動くようにしていきます。
["bitbucket-pipelines.yml"]
# Template C++ Application # This template allows you to validate your C++ application. # The workflow allows running tests and code linting on the default branch. image: gcc:10.2 pipelines: default: - parallel: - step: name: Test script: - make check - step: name: Lint script: # apt update && apt -y install cppcheck && cppcheck . - make lint - step: name: Build and Run script: - make compile # Execute your C++ application after compilation to check success - make distcheck
以上で 事前準備 を完了とします。
“bitbucket-pipelines.yml” を編集することで、基本的なビルド&デプロイを実装していきます。
ここでは例として実行環境(Docker Image)を ubuntu:18.04 に設定します。
(新)image: ubuntu:18.04
(旧)image: gcc:10.2
ちゃんと “Ubuntu 18.04” になったか確認のため、"cat /etc/lsb-release" の一文も追加します。
下記2行を追加します。
- apt-get update - apt-get -y install build-essential
下記1行を追加します。
- g++ hello.cpp -o hello
Pipelines の実施をシンプルにすることを目的に、”Test” の step のみを残して他の step を削除して簡略化します。詳細説明を割愛。修正後の内容は後述の ”bitbucket-pipelines.yml” を参照。
(parallel は高速な実行を実現できるとても魅力的な機能ですが、この機能を使用するのは Pipelines をある程度使用できるようになってから検討しましょう。)
以上の修正を行った結果の ”bitbucket-pipelines.yml” を以下に示します。
["bitbucket-pipelines.yml"]
image: ubuntu:18.04 pipelines: default: - step: name: Build script: - cat /etc/lsb-release - apt-get update - apt-get -y install build-essential - g++ hello.cpp -o hello
上記修正で Pipelines 実行を正常に完了できるようになりました。OS も “Ubuntu 18.04.6 LTS“ を意図通りにロードできていることを確認できました。
本書記載時点、正常終了した Pipelines に対するメールは届きませんでした。
機能拡張「Jira and Bitbucket (Atlassian Labs)」をインストールした “VS code” から正常終了した Pipelines を下図のように確認することができました。
以上で正常動作する “bitbucket-pipelines.yml” を構築できました。
この後は少しずつ機能を加えていく感じで修正を行っていきたいと思います。
アーティファクトは、ステップによって作成されるファイルです。パイプライン設定で定義したら、以降のステップで共有したり、エクスポートしてステップの完了後にアーティファクトを保持したりすることができます。たとえば、ビルド ステップで生成された JAR ファイルまたはレポートを、後のデプロイメント ステップで使用できます。ステップで生成されたアーティファクトをダウンロードしたり、外部ストレージにアップロードすることもできます。
次の点に留意する必要があります。
ここまで作成した “bitbucket-pipelines.yml“ にアーティファクト指定を加えてみます。
["bitbucket-pipelines.yml"] ファイルをアーティファクトへ登録した例
image: ubuntu:18.04 pipelines: default: - step: name: Build script: - cat /etc/lsb-release - apt-get update - apt-get -y install build-essential - g++ hello.cpp -o hello artifacts: - hello
["bitbucket-pipelines.yml"] フォルダーをアーティファクトへ登録した例
image: ubuntu:18.04 pipelines: default: - step: name: Build script: - cat /etc/lsb-release - apt-get update - apt-get -y install build-essential zip - mkdir out - g++ hello.cpp -o out/hello artifacts: - out/**
パイプラインを実行後の画面です。”Artifacs” の画面から “hello“ をダウンロードすることができます。
参考:
アーティファクトは保存期間14日以内という制約がありました。
アーティファクトを14日以上保存する必要がある場合は他の場所へデプロイする必要があります。
AWS へ保存する、ftp で保存する、など様々な方法を Bitbucket
は提供していますが、ここでは「ダウンロード」メニューからビルド結果を取得できるようにする方法を紹介します。
言い換えると、Pipelines
にダウンロードサイトへ デプロイ する処理を追加します。
アプリパスワードを作成します。
(1) Bitbucket にログイン後、①設定アイコン 、②[Personal Bitbucket settings]を順にクリックします。
(2) メニューから [アクセス管理] のグループ中にある[アプリパスワード]を選択します。
(3) [アプリパスワードの作成] ボタンをクリックします。
(4) 下図中の ①、② を記入後、③をクリックします。
①の Label はユーザーの識別用に使用されるため「Pipelines」などの任意の名前を設定できます。
ここでは評価に使用しているリポジトリ名をそのまま使用します。
(5) 「新しいアプリ パスワード」を表示するので記録します。
Bitbucket Downloads にファイルをアップロードするには、以下の変数を設定する必要があります。
パラメータ名 | 値 |
---|---|
BITBUCKET_USERNAME | リポジトリを所有、かつアーティファクトをアップロードするユーザーの Bitbucket ユーザー名 |
BITBUCKET_APP_PASSWORD | Bitbucket が生成したアプリパスワード |
(1) リポジトリの設定で、特定のデプロイメント環境に対してこれらの変数を定義します。
[Repository settings] > “PIPELINES“ の[Repository variables] をクリックします。
(2) 下記内容を "Repository variables" へ登録します。
Name | Value |
---|---|
BITBUCKET_USERNAME | リポジトリを所有、かつアーティファクトをアップロードするユーザーの Bitbucket ユーザー名 |
BITBUCKET_APP_PASSWORD | Bitbucket が生成したアプリパスワード |
重要
BITBUCKET_USERNAME として設定するのは、下図赤枠に表示の "ユーザー名" です。その上の "名前" ではありません。
設定後の様子(例)です。
アーティファクトを Bitbucket Downloads にアップロードするには、bitbucket-upload-file パイプを使用します。必要な作業は、アップロードするファイルをビルドのアウトプットから参照するだけです。
ここまでに作成した “bitbucket-pipelines.yml“ へ “bitbucket-upload-file“ パイプの処理を追加します。ここでは “step” を加える形で追加してみます。 “name: Deploy“ としました。
下記例で FILENAME をフルパス表記で記載していますが、説明資料を見る限り ${BITBUCKET_CLONE_DIR} からの相対パスの表記で大丈夫そうです。ただし私は未確認ですのでご自身で試してみてください。
["bitbucket-pipelines.yml"]
image: ubuntu:18.04 pipelines: default: - step: name: Build script: - cat /etc/lsb-release - apt-get update - apt-get -y install build-essential - g++ hello.cpp -o hello artifacts: - hello - step: name: Deploy script: - echo $BITBUCKET_CLONE_DIR - pipe: atlassian/bitbucket-upload-file:0.3.3 variables: BITBUCKET_USERNAME: $BITBUCKET_USERNAME BITBUCKET_APP_PASSWORD: $BITBUCKET_APP_PASSWORD FILENAME: "${BITBUCKET_CLONE_DIR}/hello"
NOTE
“BITBUCKET_CLONE_DIR“ はカレントパスを示す変数です。これを使用することでフルパス表記で FILENAME を記載しています。詳細は資料 “Variables in pipelines | Bitbucket Cloud | Atlassian Documentation” を参照してください。パイプラインで使用できる他の変数も確認することができます。
注意
2022/10/14 時点、スクリプト最新バージョンは 0.3.3 です。時々バージョンアップを行うようなので、注意しつつ原則最新版の使用をご検討ください。
- pipe: atlassian/bitbucket-upload-file:0.3.3
この “bitbucket-pipelines.yml“ によりパイプラインを実行した結果を以下に記載します。
こちらは パイプライン実行を成功 (Successful) した例です。
[ダウンロード]をクリックすると、”hello” をダウンロードできるようになっていることを確認できます。
NOTE
複数のファイルを登録する場合、事前に zip コマンドで圧縮したファイルを登録することを推奨します。
前述「ステップ3a」の pipe 処理部分を curl コマンドにより実行する方法を紹介します。
詳細は こちら 資料の「ステップ3b」を参照ください。
["bitbucket-pipelines.yml"]
image: ubuntu:18.04
pipelines:
default:
- step:
name: Build
script:
- cat /etc/lsb-release
- apt-get update
- apt-get -y install build-essential
- g++ hello.cpp -o hello
artifacts:
- hello
- step:
name: Deploy
script:
- echo $BITBUCKET_CLONE_DIR
- curl -X POST "https://${BITBUCKET_USERNAME}:${BITBUCKET_APP_PASSWORD}@api.bitbucket.org/2.0/repositories/${BITBUCKET_REPO_OWNER}/${BITBUCKET_REPO_SLUG}/downloads" --form files=@"hello"
NOTE
Atlassian ドキュメント中に変数 BITBUCKET_REPO_OWNER の説明を見つけられませんでしたが、上記 YAML コードでちゃんと動作することを確認できました。
NOTE
REST API 詳細については The Bitbucket Cloud REST API (atlassian.com) を参照ください。
ダウンロードへ登録したファイルを下記 curl コマンドによりダウンロードすることができます。任意の端末からダウンロードする、各種自動化などで活用する、Pipelines 実行時にビルド済み最新ライブラリを別リポジトリからダウンロードしてくる、など活用の可能性がいろいろありそうです。
■一般書式1
curl --user $USER_ID:$APP_PASSWORD -s -L https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/downloads/{filename} -o {filename}
■一般書式2
curl --user $USER_ID:$APP_PASSWORD -s -L https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/downloads/{filename} > {filename}
■具体例
項目 | 説明 |
---|---|
$USER_ID | ログインユーザのIDを記載します。ここでは私のID Hidetoshi_Kinoshita を例示します。 |
$APP_PASSWORD | $USER_ID で取得済みのアプリパスワードです。例示では **** としていますが実際に使用時は取得したパスワードを入力します。 アプリパスワードの権限はリポジトリへ "書き込み" でテストしましたが、ファイル取得だけなら "読み取り" 権限だけでも良いかもしれません。 basic 認証では正常に動作しませんでした。アプリパスワードを使う必要があります。 |
{workspace} | ワークスペース名を記載します。下記例では "Hidetoshi_Kinoshita" を指定しています。 |
{repo_slug} | リポジトリ名を記載します。下記例では "test_repository" を指定しています。 |
{filename} | 取得するファイル名です。 下記では "hello" を指定しています。 |
curl --user Hidetoshi_Kinoshita:************************************ -s -L https://api.bitbucket.org/2.0/repositories/Hidetoshi_Kinoshita/test_repository/downloads/hello -o hello
※ 上記コマンドによる動作確認は、Ubuntu 22.04 にて行いました。
参考:
Pipelines のビルド構成は bitbucket-pipelines.yml ファイルで定義できます。Pipelines を初めて利用される場合は、Bitbucket Pipelines を使い始める のドキュメントをご確認ください。
ブラウザ画面で Bitbucket のリポジトリを表示して、この画面から希望するブランチやコミットを対象にパイプライン実行することができます。
パイプラインを手動でのみ実行したい場合、カスタム パイプラインを使用します。カスタム パイプラインは、ブランチへのコミットでは自動的に実行されません。カスタム パイプラインを定義するには、bitbucket-pipelines.yml ファイルの custom セクションにパイプライン構成を追加します。カスタム パイプラインとして定義されていないパイプラインは、ブランチへのプッシュが発生したときに自動的に実行されます。
カスタム パイプラインのもう 1 つのメリットは、変数の値を一時的に追加または更新できる点です。バージョン番号を追加したり、1 回のみ使用する値を提供したりするために使用できます。詳細は パイプライン トリガー | Bitbucket Cloud | アトラシアン サポート (atlassian.com) を参照してください。
パイプラインを手動で実行し、Bitbucket Cloud UI からトリガーするには、リポジトリへの書き込み権限が必要です。
["bitbucket-pipelines.yml" 例]
image: ubuntu:18.04
pipelines:
custom: # Pipelines that can only be triggered manually
- step:
name: Build
script:
- echo "This script can only be triggerd manually (custom)."
- cat /etc/lsb-release
- apt-get update
- apt-get -y install build-essential
- g++ hello.cpp -o hello
artifacts:
- hello
ブラウザ画面から、ブランチとパイプランを選んで手動でパイプラインを実行する、手順を記載します。
下記のような bitbucket-pipelines.yml ファイルを登録している場合を例に説明します。
["bitbucket-pipelines.yml" 例]
image: ubuntu:18.04
pipelines:
default:
- step:
name: Build
script:
- cat /etc/lsb-release
- apt-get update
- apt-get -y install build-essential zip
- g++ hello.cpp -o hello
artifacts:
- hello
- step:
name: Deploy
script:
- pwd && ls -al
- echo $BITBUCKET_CLONE_DIR
- pipe: atlassian/bitbucket-upload-file:0.3.2
variables:
BITBUCKET_USERNAME: $BITBUCKET_USERNAME
BITBUCKET_APP_PASSWORD: $BITBUCKET_APP_PASSWORD
FILENAME: "${BITBUCKET_CLONE_DIR}/hello"
custom: # Pipelines that can only be triggered manually
custom-build:
- step:
script:
- echo "This script can only be triggerd manually (custom)."
- cat /etc/lsb-release
- apt-get update
- apt-get -y install build-essential
- g++ hello.cpp -o hello
artifacts:
- hello
(1) [パイプライン]メニューを選択します。
(2) [Run pipeline] をクリックします。
(3) ”Branch” と ”Pipeline” を選択後、[Run]ボタンをクリックします。
以上の操作により、選択したブランチのコミット HEAD に対してパイプラインを実行します。
(1) [ブランチ]メニューを選択します。
(2) パイプランを実行するブランチの [・・・] > [Run pipelines for a branch] をクリックします。
(3) ”Pipeline” を選択後、[Run]ボタンをクリックします。
以上の操作により、選択したブランチのコミット HEAD に対してパイプラインを実行します。
以下の手順で行います。
(1) [コミット]メニューを選択します。
(2) パイプラインを実行するコミットを選択します。
(3) 「Run pipeline」をクリックします。
(4) "Pipeline" を選択後、[Run]ボタンをクリックします。
以上の操作により、コミットに対してパイプラインを実行します。
NOTE
当然のことですが、コミット時点の bitbucket-pipelines.yml ファイルに設定されている Pipelines 構成からのみ選択可能です。
プッシュ先のブランチに応じてパイプラインの動作を変えることができます。これを行うには、bitbucket-pipelines.yml ファイル内にブランチ固有の設定を含める必要があります。
「bitbucket-pipelines.yml を設定する」も参照してください。
["bitbucket-pipelines.yml" 例]
image: ubuntu:18.04
pipelines:
default:
- step:
script:
- echo "This script runs on all branches that don't have any specific pipeline assigned in 'branches'."
branches:
main:
- step:
name: Build
script:
- echo "This script runs only on commit to the main branch."
- cat /etc/lsb-release
- apt-get update
- apt-get -y install build-essential
- g++ hello.cpp -o hello
artifacts:
- hello
feature/*:
- step:
script:
- echo "This script runs only on commit to branches with names that match the feature/* pattern."
以上の設定により、条件を満たすブランチへのコミットに対してパイプラインを実行します。
NOTE
プルリクエストからのマージもコミットとして使われます。
具体例として、例えば feature/add_function1 ブランチを develop ブランチへマージした場合は devekop ブランチへのコミットとして扱われて該当するパイプラインがあれば実行されます。
NOTE
複数のブランチ条件で同一の steps を実行する方法について下記で紹介されていました。
git - Bitbucket Pipelines - multiple branches with same steps - Stack Overflow
こんな感じで複数条件を記載すれば良いようです。
注意事項として '{rev,staging}' 内にスペースを加えてはいけないと記載されていました。
pipelines:
branches:
'{release/**,hotfix/**}':
- step:
script:
- echo 'step'
"Pull Request" をトリガーにパイプラインを実行する例について記載します。
["bitbucket-pipelines.yml" 例]
image: ubuntu:18.04
pipelines:
pull-requests:
'**':
- step:
script:
- echo "This script runs on pull-requests to any branch not elsewhere defined."
feature/*:
- step:
name: Build
script:
- echo "This script runs only on pull-requests to the main branch."
- cat /etc/lsb-release
- apt-get update
- apt-get -y install build-essential
- g++ hello.cpp -o hello
artifacts:
- hello
以上の操作により、条件を満足するブランチのプルリクエストおよびプルリクエスト中のコミットに対してパイプラインを実行します。
スケジュールされたパイプラインを使用すると、パイプラインを時間、日、または週単位で実行できます。パイプラインを例えば毎晩0時に実行する、というスケジュールによるパイプライン実行はよく使用されるパイプライン運用方法の一つです。
以下の手順でパイプラインのスケジュールを作成します。
(1) Bitbucket のリポジトリに移動します。
(2) [パイプライン] > [Schedules] (右上) をクリックします。
(3) [New schedule] をクリックします。
(4) スケジュールを登録したいブランチとパイプラインを選択します。
(5) スケジュールを設定します。
[パイプライン] > [スケジュール] (画面右上の) に移動して、リポジトリのすべてのスケジュールを確認します。
参考:
public リポジトリを “git clone“ する例として “google test“ のリポジトリを対象に git clone してみます。
下記にサンプルを記載します。
["bitbucket-pipelines.yml" 例]
image: ubuntu:18.04 pipelines: default: - step: name: git clone script: - apt-get update && apt-get -y install tzdata - export TZ="Asia/Tokyo" && date - apt-get -y install git - git clone https://github.com/google/googletest.git - ls - cd googletest - ls
説明をかなり割愛しますが、public リポジトリはこんな感じで簡単に git clone できます。
下図の通り、このパイプラインを全て正常に実行することができました。
重要
上記例では、下記2行を入れることが正しく動作させるためのコツです。
これら無しだと git インストール中に入力待ちとなって無限に Pipelines を終わらなくなるので注意してください。
またこの状態になってしまったら 手動で中止 する必要があることも注意してください。
- apt-get update && apt-get -y install tzdata
- export TZ="Asia/Tokyo" && date
パイプラインの中で他の Bitbucket private リポジトリを git clone する手順について説明します。
下記のようなことをすることを想定します。Hidetoshi_Kinoshita/pipelines_test1.git はこの評価のために私が準備した実験用の private リポジトリです。
["bitbucket-pipelines.yml" 例]
image: ubuntu:18.04
pipelines:
default:
- step:
name: git clone
script:
- apt-get update && apt-get -y install tzdata
- export TZ="Asia/Tokyo" && date
- apt-get -y install git
- git clone git@bitbucket.org:Hidetoshi_Kinoshita/pipelines_test1.git
- ls
- cd pp_pipelines_test1
- ls
まずはこのままパイプラインを実行して結果を確認してみます。
予想通りですが、「Permission denied (publickey) .」となって "git clone" を失敗しました。パイプラインに対して SSH 鍵を登録してリポジトリへアクセスできるようにする必要がある、ということです。
以下、パイプラインに対して SSH 鍵を登録する手順の説明です。
(1) パイプラインを実行する側のリポジトリ設定から「SSH keys」メニューをクリックします。
(2) [Generate keys] または [Use my own keys] ボタンをクリックします。
ここでは [Generate keys] ボタンをクリックして進みます。
(3) "Private key" と "Public key" を生成して下図のような画面へ表示します。
(4) [Copy public key] ボタンをクリックして ”public key” をコピーします。
(5) ターゲットリポジトリへ “public key“ を登録します。リポジトリ("pipelines_test1")へ移動して、[Repository settings] > [一般] > [アクセスキー] をクリックします。
(6) [Add key] ボタンをクリックします。
(7) 下図のような画面を表示するので、必要事項を記入後に [Add SSH key] ボタンをクリックします。
ここでは下図のように入力してみました。[Add SSH key] ボタンをクリックします。
するとこんな感じの画面表示となりました。
以上で SSH 鍵の設定を完了です。
(8) 先程失敗(Failed)となったパイプラインを再度実行してみます。
[Run pipelines] ボタンをクリックします。
下図画面を表示するので[Run]ボタンをクリックします。
パイプライン実行を成功です。
以上の手順により、他の Bitbucket private リポジトリから git clone できることを確認できました。
参考:
変数 BITBUCKET_BUILD_NUMBER によりパイプライン中でビルド番号を使うことができます。これを使うことでパイプラインを実行する度にファイル名やフォルダ名を変えることが可能になります。
["bitbucket-pipelines.yml" 例]
image: ubuntu:18.04 pipelines: default: - step: name: Build script: - cat /etc/lsb-release - apt-get update - apt-get -y install build-essential - mkdir out - g++ hello.cpp -o out/hello_$BITBUCKET_BUILD_NUMBER - ls out artifacts: - out/**
これを実行することで hello_6 というファイルを出力することができました。6 という値はビルド番号 #6 からくるものです。
NOTE
'artifacts' で $BITBUCKET_BUILD_NUMBER を使うことはできないように見えます。
下記のようなサンプルで実験しましたが、 out_$BITBUCKET_BUILD_NUMBER/** を artifacts へ登録できませんでした。'script' を全て正常に動作できていることから、 artifacts 固有の問題と推測しています。
["bitbucket-pipelines.yml" 例]
image: ubuntu:18.04
pipelines:
default:
- step:
name: Build
script:
- cat /etc/lsb-release
- apt-get update
- apt-get -y install build-essential zip
- mkdir out
- mkdir out_$BITBUCKET_BUILD_NUMBER
- g++ hello.cpp -o out/hello_$BITBUCKET_BUILD_NUMBER
- cp out/hello_$BITBUCKET_BUILD_NUMBER out_$BITBUCKET_BUILD_NUMBER/hello_$BITBUCKET_BUILD_NUMBER
- ls out
- ls out_$BITBUCKET_BUILD_NUMBER
artifacts:
- out/**
- out_$BITBUCKET_BUILD_NUMBER/**
参考:
Pipelines 上でユニットテストを実施します。
cmake でユニットテストを構成済みであることを前提として以下を記載します。
["bitbucket-pipelines.yml" 例]
image: ubuntu:22.04 pipelines: default: - parallel: - step: name: build and unit-test script: - apt-get update && apt-get -y install tzdata - export TZ="Asia/Tokyo" && date - apt-get -y install build-essential cmake - gcc --version && cmake --version && lcov --version && cppcheck --version # build and install googletest. - tar zxvf release-1.12.0.tar.gz # googletest - cd googletest-release-1.12.0 - mkdir build - cd build - cmake .. - make - make install - cd .. - cd .. # build and tests. - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_TESTING=ON .. - make # do unit-tests. - ctest --output-on-failure
以下、CMakeLists.txt の部分の身参考記載します。
[(参考) "CMakeLists.txt" 例]
# このバージョン以上のCMAKEを使うよう宣言 cmake_minimum_required(VERSION 3.10) # プロジェクト名.c/c++言語であることを宣言 #project(sample CXX) project(sample C) # バージョン番号 set(serial "1.0.0") # c++17 が必要 set(CMAKE_CXX_STANDARD 17) # デバッグ出力 message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}") message(STATUS "PROJECT_BINARY_DIR = ${PROJECT_BINARY_DIR}") message(STATUS "CMAKE_CXX_STANDARD = ${CMAKE_CXX_STANDARD}") # 共通オプション set(CMAKE_CXX_FLAGS "--coverage") set(CMAKE_C_FLAGS "--coverage") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") # ビルドの種類によってオプションを変える set(CMAKE_CXX_FLAGS_DEBUG "-Wall -O0 -g") set(CMAKE_CXX_FLAGS_RELEASE "-Wall -O3 -DNDEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Wall -Os -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-Wall -O2 -g -DNDEBUG") set(CMAKE_C_FLAGS_DEBUG "-Wall -O0 -g") set(CMAKE_C_FLAGS_RELEASE "-Wall -O3 -DNDEBUG") set(CMAKE_C_FLAGS_MINSIZEREL "-Wall -Os -DNDEBUG") set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Wall -O2 -g -DNDEBUG") include_directories(include) add_subdirectory(PfLogPrintf) # ライブラリの作成を指示.SHARED で共有ライブラリ # sample.c を元に、libsample.so という名前で作成 add_library(sample SHARED sample.c) # sample.so をビルドする際に PfLogPrintf をリンクする target_link_libraries(sample PfLogPrintf) if(BUILD_TESTING) # ctest を valgrind ありで実行するために下記が必要 include(CTest) # テストを有効化 enable_testing() # サブディレクトリを指定.指定したディレクトリ内のCMakeLists.txt が実行される add_subdirectory(test) endif() # capability ライブラリのインクルードディレクトリを教えてあげる # PROJECT_SOURCE_DIRはこのプロジェクトのルートディレクトリの絶対パス target_include_directories( sample PUBLIC ${PROJECT_SOURCE_DIR}/include )
[(参考) test フォルダ内の "CMakeLists.txt" 例]
# このバージョン以上のCMAKEを使うよう宣言 cmake_minimum_required(VERSION 3.10) # プロジェクト名.c/c++言語であることを宣言 project(test_sample CXX) #project(test_sample C) # To use the googletest find_package(GTest REQUIRED) # デバッグ出力 message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}") message(STATUS "PROJECT_BINARY_DIR = ${PROJECT_BINARY_DIR}") message(STATUS "CMAKE_CXX_STANDARD = ${CMAKE_CXX_STANDARD}") # 共通オプション set(CMAKE_CXX_FLAGS "--coverage") set(CMAKE_C_FLAGS "--coverage") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") # ビルドの種類によってオプションを変える set(CMAKE_CXX_FLAGS_DEBUG "-Wall -O0 -g") set(CMAKE_CXX_FLAGS_RELEASE "-Wall -O3 -DNDEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Wall -Os -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-Wall -O2 -g -DNDEBUG") # リンクディレクトリの指定 #link_directories(PfLogPrintf) # 今回作成する実行ファイル test_sample, ソースファイル3つ add_executable( test_sample function1_test.cpp function2_test.cpp function3_test.cpp ) # gtest, pthread をリンクします target_link_libraries( test_sample ${GTEST_BOTH_LIBRARIES} pthread sample) #target_link_libraries(test_sample GTest::GTest GTest::Main) target_include_directories(test_sample PUBLIC ${GTEST_INCLUDE_DIRS}) include(GoogleTest) gtest_add_tests(TARGET test_sample)
Valgrind(ヴァルグリンド)は、メモリデバッグや、メモリリークの検出、スレッドエラーの検出、プロファイリングなどを行うための仮想機械を利用したソフトウェア開発ツールです。
ユニットテストと Valgrind を併用するのはとても有益で良い方法の1つです。
Valgrind で最もよく利用されている標準のツールは Memcheck です。 Memcheck はほぼすべての命令に特別な計測用のコードを挿入し、「正当性」があり、「アドレス可能」であるかという情報が、それぞれVビットおよびAビットに格納されているかを追跡します。データは移動したり加工されたりするが、計測用のコードは1ビットレベルで正確であるようにA、Vビットを追跡します。
さらに、Memcheck は標準のCメモリアロケータを独自の実装に置き換え、割り当て済みブロックの前後にメモリガードを挿入します。この機能により、Memcheck はプログラムが割り当てられたブロックよりわずかに外側の領域を読み書きする off-by-one エラーを検出できます。
Memcheck が検出や警告可能な問題には、下記のものがあります。
こうした機能への代償として処理性能が低下します。Memcheckの元で動作するプログラムはValgrindなしで動作する場合と比べて5倍から20倍遅く、また多くのメモリを使用します。(メモリ確保ごとにかなりのメモリを追加で消費します)。したがって、ほとんどの開発者は常にMemcheck(あるいは他のValgrindツール)の元でコードを走らせることはしません。特定のバグを解析したり、(Memcheckが検出可能な種類の)潜在的なバグがないことを検証するために使用するのが最も典型的な方法です。
ユニットテストの実行を Valgrind で実施する手順を以下に記載します。ここでは ctest のオプション指定を変更することで実施する例を示します。(ctest は標準で Valgrind をサポートしています。)
["bitbucket-pipelines.yml" 例]
image: ubuntu:22.04 pipelines: default: - parallel: - step: name: build and unit-test, coverage script: - apt-get update && apt-get -y install tzdata - export TZ="Asia/Tokyo" && date - apt-get -y install build-essential cmake valgrind lcov cppcheck zip - gcc --version && cmake --version && lcov --version && cppcheck --version # build and install googletest. - tar zxvf release-1.12.0.tar.gz # googletest - cd googletest-release-1.12.0 - mkdir build - cd build - cmake .. - make - make install - cd .. - cd .. # build IoGeneral and tests. - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_TESTING=ON .. - make # do unit-tests. - ctest --output-on-failure -T MemCheck --overwrite MemoryCheckCommandOptions="--leak-check=full --error-exitcode=1"
ソースコードカバレッジ処理を追加する例を以下に記載します。
["bitbucket-pipelines.yml" 例]
image: ubuntu:22.04 pipelines: default: - parallel: - step: name: build and unit-test, coverage script: - apt-get update && apt-get -y install tzdata - export TZ="Asia/Tokyo" && date - apt-get -y install build-essential cmake valgrind lcov cppcheck zip - gcc --version && cmake --version && lcov --version && cppcheck --version # build and install googletest. - tar zxvf release-1.12.0.tar.gz # googletest - cd googletest-release-1.12.0 - mkdir build - cd build - cmake .. - make - make install - cd .. - cd .. # build sample and tests. - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_TESTING=ON .. - make # do unit-tests. - ctest --output-on-failure after-script: # source code coverage <- - pwd && ls - pushd build/CMakeFiles/sample.dir - lcov -d . -c -o sample.info --rc lcov_branch_coverage=1 - lcov -r sample.info */googletest/* test/* */c++/* -o sampleFiltered.info --rc lcov_branch_coverage=1 - genhtml -o lcovHtml --num-spaces 4 -s --legend sampleFiltered.info --branch-coverage - popd # -> # deploy results of source code coverage. - echo $BITBUCKET_CLONE_DIR - zip -r lcovHtml_IoGeneral.zip build/CMakeFiles/sample.dir/lcovHtml - pipe: atlassian/bitbucket-upload-file:0.3.2 variables: BITBUCKET_USERNAME: $BITBUCKET_USERNAME BITBUCKET_APP_PASSWORD: $BITBUCKET_APP_PASSWORD FILENAME: "${BITBUCKET_CLONE_DIR}/lcovHtml_sample.zip" # -> artifacts: - build/CMakeFiles/sample.dir/lcovHtml/**
ソースコードカバレッジ測定の主たる実行部分は下記3行です。
- lcov -d . -c -o sample.info --rc lcov_branch_coverage=1 - lcov -r sample.info */googletest/* test/* */c++/* -o sampleFiltered.info --rc lcov_branch_coverage=1 - genhtml -o lcovHtml --num-spaces 4 -s --legend sampleFiltered.info --branch-coverage
- lcov -r sample.info */googletest/* test/* */c++/* -o sample.info --rc lcov_branch_coverage=1
以上の処理により下図のような結果を取得することができます。
オープンソースの静的解析ツール(cppcheck)を pipelines 中で適用する例を紹介します。
["bitbucket-pipelines.yml" 例]
image: ubuntu:22.04 pipelines: default: - parallel: - step: name: cppcheck script: - apt-get update && apt-get -y install tzdata - export TZ="Asia/Tokyo" && date - apt-get -y install build-essential cmake valgrind lcov cppcheck - cppcheck --version # build and install googletest. - tar zxvf release-1.12.0.tar.gz # googletest - cd googletest-release-1.12.0 - mkdir build - cd build - cmake .. - make - make install - cd .. - cd .. # build sample - mkdir build - cd build - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_TESTING=ON .. # cppcheck - cppcheck --project=compile_commands.json --enable=all --error-exitcode=1 --inline-suppr --force --suppressions-list=../suppressions_list.txt -i$BITBUCKET_CLONE_DIR/test/
Pipelines は Linux 上でbash / shellコマンドを実行しているだけです。スクリプトランナーは、各コマンドの戻り状況コードを探して成功したか失敗したかを確認します。したがって、さまざまな手法を使用してこのステータスコードを制御できます。
あなたのコマンドの末尾に " || true" を加える、という方法があります。
(例) ./gradlew -DBASE_URL=qa2 clean BSchrome_win || true
必ず実行したいステップを after-script へ記載すると、前のステップの成功/失敗ステータスに関係なく常に実行することができます。
- step: name: Hoge script: - 何か処理する - 何か処理する after-script: - cd config/geb # You may need this, if the current working directory is reset. Check with 'pwd' - cd build/reports - zip -r testresult.zip BSchrome_winTest
Pipelines は step 1つに対して最長 120分 を実行することができます。max-time を設定することでこの値を変更することができ、(1-120) の範囲でこの値を変更可能です。
options: max-time: 60
本ページの情報は、特記無い限り下記 MIT ライセンスで提供されます。
2021-04-10 | - | 新規作成 |