LoginSignup
1
0

More than 3 years have passed since last update.

VSCodeでProjectのビルドっぽいことをしてみた

Last updated at Posted at 2021-05-02

はじめに

筆者は普段Androidアプリをkotlinで書いています(on AndroidStudio)
週末プログラミングで、普段使っていないVSCode上でkotlinを書こうかなという試みです。
この記事を書くにあたって、VSCodeの導入やKotlinのStand aloneなコンパイラの導入などをまとめ記事を見ながら一通りやったのですが、
大体の記事が Hello world! を出すところで紹介が終わっていることに(後から)気が付きました。

実装して・・・クラスを分割して・・・を楽しんだ後、さぁビルドしようと思ったときに、
はて、VSCode上でProject単位でまとめてビルドまでやってくれんのかなー・・・?と。
もちろんそこまでやってくれるはずもなく、それっぽいまとめ記事も出てこなかったので、
今回まとめてみようと思った次第です。

大前提

正直ガッツリ実装環境を作る!というなら統合開発環境でやるか、gradleとか入れたほうが早いような気がします。
なので参考程度に御覧ください・・・。

VSCodeの導入やKotlinのコンパイラの導入はすでに終わっているものとします。
今回の環境はラズパイ上にVSCodeやKotlinを入れています。
おおよそ他の方が既に書かれている記事の通りで導入できます。

Project & Sources

Project

今回ビルドしようとしたのは下記のようなファイルたち。
ディレクトリ構造はわりと適当です。

-- TestApp/
      ├-- src/com/nonameplayer/testapp
      |                           ├-- Main.kt
      |                           ├-- Factory.kt
      |                           └-- Person.kt
      └-- build/Main.jar                           <- ビルド結果

Sources

人のリストを出力するプログラムを複数ファイルに渡って書いてみました。
実際こんな感じでファイルを分けて書くよね・・・というイメージで見てもらえれば。
(中身については本質的ではないので触れないでください。。。)

Main.kt
package com.nonameplayer.testapp

import com.nonameplayer.testapp.Factory

fun main() {
    Factory.create().forEach {
        it.print()
    }
}

Factory.kt
package com.nonameplayer.testapp

import com.nonameplayer.testapp.Person

object Factory {
    fun create(): List<Person> {
        return mutableListOf<Person>().apply {
            add(
                Person("Sato", 28)
            )
            add(
                Person("Tanaka", 25)
            )
        }
    }
}
Person.kt
package com.nonameplayer.testapp

class Person(private val name: String, private val age: Int) {
    fun print() {
        println("Name: $name, Age: $age")
    }
}

Pre-defined command

VSCode には Code Runner というプラグインを導入することで、簡易的にプログラムを実行できるようになっています。
Ctrl+Alt+N がビルドコマンドとして設定されていて、下記のコマンドが走るようです。

cd "/home/pi/kotlin/Testapp/src/com/nonameplayer/testapp" && kotlinc Main.kt -include-runtime -d Main.jar && java -jar Main.jar

Main.kt の階層までcd、Main.ktをビルド、できたjarを実行という内容なのですが、、、
(当たり前ですが)Main.kt 単体を でビルドしても、Factory が参照できないので当然通りません。

Main.kt:3:31: error: unresolved reference: Factory

上記の Factory.kt, Person.kt も一緒にビルドしてあげれば Main.kt から Factory.kt を参照できてビルドが通るようになります。
コマンド的には次のようなものがほしいです。

expected
cd "/home/pi/kotlin/Testapp/src/com/nonameplayer/testapp" && kotlinc Main.kt Factory.kt Person.kt -include-runtime -d Main.jar && java -jar Main.jar

Ctrl+Alt+N を実行したときにカレントのディレクトリにあるファイルをビルドするようなコマンドに書き換えてしまうこともできるのですが、
汎用性が著しく落ちるので、tasks.json を変更してビルドコマンドを作ってみたいと思います。

tasks.json

VSCodeのメニューの Terminal > Configure tasks... から テンプレート > Other を選択して tasks.json を作ります。
defaultでは次のような中身になっていますが、これを変更していきます。

tasks.json(変更前)
{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "echo",
      "type": "shell",
      "command": "echo Hello"
    }
  ]
}
tasks.json(変更後)
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "kotlinc",
            "args": [
                "./src/com/nonameplayer/testapp/*.kt",
                "-include-runtime",
                "-d",
                "./build/Main.jar"
            ],
            "presentation": {
                "reveal": "always"
            },
            "group": "build"
        },
        {
            "label": "executeJar",
            "type": "shell",
            "command": "java",
            "args": [
                "-jar",
                "./build/Main.jar"
            ],
            "presentation": {
                "reveal": "always"
            },
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "dependsOn": [ "build" ]
        }
    ]
}

buildexecuteJar という2つのタスクを作っていて、executeJarbuild に依存する ( "dependsOn": [ "build" ] ) 設定にしています。
また executeJar の方をデフォルト( "isDefault": true )で実行されるタスクにしています。
こうすることで、タスク実行のコマンドで executeJar が実行され、依存している build も同時に走らせることができます。
そして肝心のビルドファイルの指定ですが、"./src/com/nonameplayer/testapp/*.kt"と指定していて、Main.kt と同じディレクトリにいれば同時にビルドしてくれるように設定しています。

いざ実行

タスクの実行は Ctrl+Shift+B で出来るようで、実行するとターミナルが起動し、タスクが実行されます。

result
> Executing task: kotlinc ./src/com/nonameplayer/testapp/*.kt -include-runtime -d ./build/Main.jar <

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.intellij.util.ReflectionUtil to method java.util.ResourceBundle.setParent(java.util.ResourceBundle)
WARNING: Please consider reporting this to the maintainers of com.intellij.util.ReflectionUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Terminal will be reused by tasks, press any key to close it.

> Executing task: java -jar ./build/Main.jar <

Name: Sato, Age: 28
Name: Tanaka, Age: 25

Terminal will be reused by tasks, press any key to close it.

おわりに

オブジェクト指向プログラミングをやると、どうしてもファイルが複数に渡ってしまい、一つのクラス(ファイル)のみのビルドだけでは実現できないことがしばしばあります。
単体ファイルのビルドだけで実行したいからと言って1つのファイルに全部まとめてしまうのはイケてないし、まとめてビルドするためにgradleなどの仕組みを勉強して導入するのは手間・・・
ということで、今回は複数のクラス(ファイル)からなるプログラムを簡易的にまとめてビルドして動かせるような環境( tasks.json )を作ってみました。
ただし、ディレクトリ構造がややこしくなればなるほど tasks.json で指定するプログラムのファイルが増えるため、あまりおすすめはできません。

Hello world! 程度では終わらないけど、統合開発環境や便利なgradleなどのコンパイラを導入してまではガッツリやらない!という中間的なレベルでは使えるのではと。

参考

https://qiita.com/ShortArrow/items/dc0c8cacd696154510f1
https://qiita.com/__cooper/items/9517addaaf1e77215848
https://code.visualstudio.com/docs/editor/tasks

1
0
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
0