← Spring コース
25. ビルドとは何か: 手作業なら何をするか
ビルドとは、ソースから動く形( や )を作るまでの手作業の列のことで、はその手作業を代わりにやる道具です。手作業は5段あります。 でコンパイルする、 などのリソースをコピーする、テストをコンパイルして実行する、 で JAR にまとめる、 をに並べる、の5つです。どの段も、あるファイル群を読んで別のファイル群を書く操作です。
Node で言うと、コンパイルは tsc、リソースのコピーはアセットのコピー、テストは jest、JAR 化は npm pack に近い作業です。違いは依存の扱いです。Java では依存の JAR をコンパイル時にも実行時にも に並べ、jar コマンドでまとめた JAR には依存は入りません(依存ごと入れる は後のレッスンで扱います)。(Java のテストの枠組み)もコマンドではなく JAR です。
段を1つ飛ばすと、違う形で失敗します。依存なしのコンパイルは ... does not exist、リソースのコピー忘れは実行時に app.properties not found、 だけの起動は 、テストが落ちれば終了コード 1 です。ビルドツールが持つのは、各段が何を読み何を書くか、順序、済んだかの判定で、 と は依存の取得も担います。
点線の付いた語はタップすると説明が出ます。用語集を開く →
src/ の .java 2個Main.java、Greeter.java(commons-lang3 を使う)
resources/app.propertiesgreeting=Hello の1行
lib/ と lib-test/ の JAR依存1本と JUnit の実行役。人がダウンロードして置いた
(a) javac -d build/classes -cp lib/commons-lang3-3.21.0.jar …
build/classes/com/example/…/*.class.class が2個。.properties は作られない
-cp に依存が無いと: package org.apache.commons.lang3 does not exist(exit 1)(b) cp -r resources/. build/classes/
build/classes/app.propertiesjavac は触らないので別の段が要る
忘れると実行時に: IllegalStateException: app.properties not found on the classpath(c) javac -d build/test-classes …(main の .class と JUnit の JAR も -cp に)/ java -jar junit-platform-console-standalone-6.1.3.jar execute …
build/test-classes/…/GreeterTest.class1 tests successful なら exit 0
テストが落ちると: 1 tests failed、exit 1(d) jar --create --file dist/app.jar --main-class com.example.app.Main -C build/classes .
dist/app.jar2,489 B。MANIFEST.MF、app.properties、.class 2個。依存は入らない
(e) java -cp dist/app.jar:lib/commons-lang3-3.21.0.jar com.example.app.Main
Hello, World!依存は JAR の外に置いたまま、クラスパスに並べて起動する
java -jar dist/app.jar だけだと: NoClassDefFoundError: org/apache/commons/lang3/StringUtils- ・レッスン「ツール無しで手でビルドする」で見た javac、jar、java の3コマンドに、リソースのコピーとテストを足した5段です。JDK 25(Temurin 25.0.4.1)のコマンドだけで行いました。commons-lang3 3.21.0 と junit-platform-console-standalone 6.1.3 は Maven Central から手で取り、隣の .sha1 と照合しました。コマンドと出力の全文はサンプル集にあります
- ・src、resources、test、lib、lib-test という置き場所は、この実験で自分で決めた名前です。ビルドツール無しの段階では、置き場所の規約はありません
- ・(a) と (b) はどちらが先でもかまいません。ただし、どちらも出力先の build/classes があることが前提です(この実験では (a) の javac -d が作りました)。(c) は (a) の出力を読むので順序が決まります。ビルドツールが覚えているのは、この「どの段がどの段の出力を読むか」です
- ・JUnit は Java のテストの枠組みで、ここで使った junit-platform-console-standalone 6.1.3 は、テストをコマンドラインから実行するための JAR です。公式文書はこの JAR を、依存をすべて含んだ実行可能な Fat JAR(executable Fat JAR)と説明しています
- ・Node 側との対応は、役割が近いという意味のたとえです。tsc の公式文書は「tsconfig.json のプロジェクトをコンパイルする」、npm pack は「パッケージから tarball を作る」と自己紹介しています。アセットのコピーに当たる Node 公式の説明は確かめていません
- ・下のコードは、ファイルシステムを Map に見立てて5段を実行する模型です。Ant、Maven、Gradle の実装ではありません
▶ サンプルコードを実行してみよう(自由に書き換えてOK)
Java
図やコードに出てくる用語(タップで説明)
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗