できない.dev

Maven「No goals have been specified for this build」の原因と直し方

No goals have been specified for this build は、フェーズを付けて実行すれば直る。
mvn だけで動かしたいなら、pom.xml の defaultGoal に既定のフェーズを書いておく。

公開:

要約

mvn とだけ打つと、ビルドが始まる前に止まる。
Maven 3.10.0 では次の行が出る(後半のフェーズの一覧は途中を省いた)。

[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: pre-clean, clean, post-clean, validate, initialize, ... deploy, pre-site, site, post-site, site-deploy. -> [Help 1]

No goals have been specified for this build は、何を実行するかが 1 つも指定されていないという意味だ。
Maven は mvn というコマンド名だけでは動かない。compile・package・install のようなライフサイクルのフェーズか、compiler:compile のようなプラグインのゴールを受け取って、初めてビルドを始める。

Maven 3.10.0 では、pom.xml の無いディレクトリで mvn とだけ打っても、there is no POM in this directory ではなくこのエラーが先に出た。
何を実行するかの確認が、POM を探すより前に行われるためだ。

解決策

1. フェーズを付けて実行する

やりたいことに合わせてフェーズを付ける。
フェーズを指定すると、そこまでの前段も順に実行される。
たとえば package なら、compile と test を済ませてから JAR を作る(Introduction to the Build Lifecycle(新しいタブで開く))。

mvn compile          # コンパイルまで
mvn test             # テストまで
mvn package          # JAR などの成果物を作るまで
mvn clean install    # 前回の成果物を消し、ローカルリポジトリに入れるまで

オプションは、フェーズと一緒に書く。

mvn -DskipTests package

プラグインのゴールを直接呼ぶときは、プレフィックス:ゴール の形で書く。NoGoalSpecifiedException(新しいタブで開く) の例では mvn compiler:compile である。

2. スクリプトでは変数が空のときに備える

ゴールを変数で渡すなら、空のときの既定値を決めておく。

GOALS="${GOALS:-package}"   # 空なら package
mvn $GOALS

CI の設定でジョブごとに値を変えている場合は、そのジョブで値が渡っているかをログで確かめる。

3. 引数なしの mvn で動かしたいなら defaultGoal を書く

毎回同じフェーズを打つなら、pom.xml の <build> に <defaultGoal> を書いておく。POM Reference(新しいタブで開く) では、引数で何も指定されなかったときに実行するフェーズかゴールとされている。

<build>
  <defaultGoal>package</defaultGoal>
</build>

Maven 3.10.0 で <defaultGoal>validate</defaultGoal> を書いた pom.xml を置いたところ、mvn だけで BUILD SUCCESS になった。

ただし、チームの他の人や CI が mvn とだけ打ったときにも同じフェーズが走る。
ログを読んだときに何を実行したかが分かるよう、スクリプトや CI では mvn package のように明示しておく方がよい。

よくある原因

  1. mvn だけを打っている。
    コマンド名だけで既定のビルドが走ると思って実行している。
  2. オプションだけを付けている。-DskipTests や -q は実行の仕方を変えるだけで、何を実行するかは決めない。
    Maven 3.10.0 で mvn -DskipTests を実行しても、同じエラーになった。
  3. ゴールを入れた変数が空になっている。
    シェルスクリプトや CI で mvn $GOALS のように組み立てていて、変数に何も入っていない。
    展開した後は mvn だけと同じになる。