LoginSignup
1
1

More than 3 years have passed since last update.

[Android]gradle taskのビルド時間を抽出するスクリプト書いてみた

Posted at

はじめに

現在、Androidインターンでビルド時間の改善に向けて日々奮闘中です。

マルチモジュールへの分割であったり、app moduleとは別なapplication moduleを作成してデバッグ速度をあげようとしている中のですが、

ビルド時間の計測を手動でしていたため、効率も悪く、ビルドがいつ終わったかを常に意識して待つ必要がありした。

そこで、shellscriptを書くことにより、人力ビルドから開放されようという試みです。

shell scriptを書くのは初めてなのでもっと良い書き方等あれば教えてくださいmm

ざっくり流れ

  1. 何回ビルドを行うかを入力
  2. ビルドキャッシュを使うか否かを入力
  3. output先のファイルを生成
  4. 2の入力をもとにgradleのタスクを実行
  5. 正規表現でビルド時間のみを抽出し、ファイルに書き込む
  6. 4~5を1で入力した回数繰り返す

実際のコードはこちら


    #!/bin/bash
    # ./build/build-time-2020-01-29-17-50-00.txt のようなファイルにビルド時間を書き込むスクリプト


    read -p "How many tasks do you try ? [1~99] => " -r n
    if [[ ! $n =~ [0-9]{1,2} ]] || [ $n == 0 ]; then
      echo "input number range of [1~99]"
      exit
    fi
    read -p "use build cache? [y/n] => " -r yn
    case "$yn" in
      "y") echo "start tasks with using build cache.";;
      "n") echo "start tasks with full build.";;
        *) echo "input y or n. "
           exit;;
    esac

    dirPath=./buildtime
    if [[ ! -e $dirPath ]]; then
       mkdir "buildtime"
    fi

    filePath=$dirPath/build-time-`date '+%Y-%m-%d-%H-%M-%S'`.txt
    touch "$filePath"

    # taskの実行とcleanを行い、ビルド実行時間をtextファイルに書き出す
    for count in `seq 1 $n`
    do
      echo "now caliculating... $count"
      noBuildCache=""
      if [ "$yn" == "n" ]; then
        ./gradlew clean > /dev/null
        noBuildCache="--no-build-cache"
      fi
      ./gradlew app:assembleDebug $noBuildCache | while read -r line
      do
        if [[ $line =~ ^'BUILD SUCCESSFUL in '([0-5]{0,1}[0-9]{1}.)$ ]]
       then
        echo "${BASH_REMATCH[1]}, " >> $filePath
       elif [[ $line =~ ^'BUILD SUCCESSFUL in '([0-9]{*}.[0-5]{0,1}[0-9]{1}.)$ ]]
       then
        echo "${BASH_REMATCH[1]}" >> $filePath
       fi
      done
    done

    echo "gradle tasks completed"

最初はzshで書いていたのですが、マッチした正規表現の抽出方法がいまいちわからずbashに変更しました。

ざっくり解説

何回ビルドを行うか


    read -p "How many tasks do you try ? [1~99] => " -r n
    if [[ ! $n =~ [0-9]{1,2} ]] || [ $n == 0 ]; then
      echo "input number range of [1~99]"
      exit
    fi

read -p の後に、ユーザーに入力を促す文章を記述し、入力内容をnに入れています。

ここで、

  • 数字のみを入力
  • 2桁まで

というバリデーションを効かせる記述もしておきます。

bashの場合正規表現は、

[[ ]] で囲むこと、 =~ の左辺に対象,右辺に正規表現のパターンを書くことで実装できます。

上記では、

  • 数字のみ ⇒ [0-9]
  • 2桁まで ⇒ {1,2}

と表現しています。

ビルドキャッシュを使うか

    read -p "use build cache? [y/n] => " -r yn
    case "$yn" in
      "y") echo "start tasks with using build cache.";;
      "n") echo "start tasks with full build.";;
        *) echo "input y or n. "
           exit;;
    esac

上記と同じ要領で入力を受け取ります。

そしてここでは case 文を使って、yとn以外に入力された場合はスクリプトの実行を終わらせるようにしています。

shellの書き方の特徴として、case文の終わりやif文の終わりに、逆文字を記述するようになっています。

結果を出力するファイルの作成


    dirPath=./buildtime
    if [[ ! -e $dirPath ]]; then
       mkdir "buildtime"
    fi

    filePath=$dirPath/build-time-`date '+%Y-%m-%d-%H-%M-%S'`.txt
    touch "$filePath"

ここではディレクトリが存在しなければ作成し、

buildtime ディレクトリの子階層にファイルを作成しています。

`date '+%Y-%m-%d-%H-%M-%S'`

のように `` で囲んだ箇所はコマンドとして実行できるため、

dateコマンドで現在の標準時刻を取得し、 2020-01-28-23-11-15 のようにフォーマットしています。

ループを開始


    for count in `seq 1 $n`
    do
      echo "now caliculating... $count"
      noBuildCache=""
      if [ "$yn" == "n" ]; then
        ./gradlew clean > /dev/null
        noBuildCache="--no-build-cache"
      fi
    #略
    done

入力で受け取った回数だけループを回します。

キャッシュを使用しない場合には ./gradlew clean を実行すると同時に、変数に --no-build-cache を代入しておきます。(あとで使う)

このとき、ただgradleのタスクを実行するだけだと、内部的に exit が呼ばれるためタスク以降のスクリプトが実行されません。

そこで、タスクの出力を /dev/null に渡すことでこれを回避します。

/dev/null(nullデバイスとも呼ばれる)は、UNIXやUnix系オペレーティングシステム (OS) におけるスペシャルファイルの1つで、そこに書き込まれたデータを全て捨て(writeシステムコールは成功する)、読み出してもどんなプロセスに対してもデータを返さない(EOFを返す)。

wikipedia

gradleのタスクを実行してファイルに書き込む


    ./gradlew app:assembleDebug $noBuildCache | while read -r line
      do
        if [[ $line =~ ^'BUILD SUCCESSFUL in '([0-5]{0,1}[0-9]{1}.)$ ]]
       then
        echo "${BASH_REMATCH[1]}, " >> $filePath
       elif [[ $line =~ ^'BUILD SUCCESSFUL in '([0-9]{*}.[0-5]{0,1}[0-9]{1}.)$ ]]
       then
        echo "${BASH_REMATCH[1]}" >> $filePath
       fi
      done

gradleのタスク実行結果を、パイプ | を利用して一行ずつ読み込み、

BUILD SUCCESSFUL in **s or BUILD SUCCESSFUL in **m**s を抽出するような正規表現を書きました。

参考文献

正規表現サンプル集

シェルの入出力制御あれこれ - Qiita

初心者向けシェルスクリプトの基本コマンドの紹介 - Qiita

シェルスクリプトで [y/n] を入力させて処理を分岐する方法 | LFI

ファイルやディレクトリが存在するかシェルスクリプトで確認する

koalaman/shellcheck

EZ-NET: 標準出力や標準エラーの内容を捨てる - Linux シェルスクリプトプログラミング

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1