Kotlin Toolchain

repository·main·Indexed 43 days ago

https://github.com/jetbrains/kotlin-toolchain

A unified entry point for Kotlin development providing a declarative way to build applications across JVM, Android, iOS, multiplatform, and server-side platforms. It includes a CLI for build and execution tasks, integration with IntelliJ IDEA via the Kotlin Toolchain plugin, and the Amper CLI for project management and Maven-to-Amper conversion.

Tokens
92.5K
Snippets
370
Records
489
Agent score
58%

What's inside Kotlin Toolchain

  1. Overview of the Kotlin Toolchain

    main
    The Kotlin Toolchain provides a unified entry point for developing Kotlin applications. It allows developers to build JVM, Android, iOS, multiplatform, and server-side applications using a simple declarative configuration, abstracting away the complexities of managing different target environments.
  2. Supported Kotlin/Native application product types

    main

    The Kotlin Toolchain supports several product types for building native applications that run directly on the host operating system. The available types are:

    • linux/app: A native Linux application.
    • macos/app: A native macOS application.
    • windows/app: A native Windows application.

    If you are using IntelliJ IDEA, it is recommended to install the Kotlin Multiplatform plugin to ensure proper support for Kotlin/Native development.

  3. Convert Maven projects to Amper

    main

    The Maven converter is a tool designed to migrate projects from Maven to Amper. It processes the Maven model by building a plexus container and follows these conversion rules:

    • Subproject Aggregators: Maven subprojects with packaging = pom are treated as aggregators. They are used to populate the project.yaml file with Amper submodules.
    • Amper Modules: Only Maven subprojects with packaging = jar are converted into actual Amper modules (module.yaml).

    The conversion process involves multiple passes where the Maven model is traversed to build an Amper forest using a merging and refining process based on the TreeNode data structure.

  4. How task dependencies and execution avoidance work

    main

    The Kotlin Toolchain manages task execution based on @Input and @Output annotations:

    • Execution Avoidance: If a task's @Input paths have not changed relative to their previous @Output paths, the task is skipped.
    • Automatic Task Dependencies: If Task B has an @Input path that matches an @Output path from Task A, the toolchain automatically infers that Task B depends on Task A.
    • Side-effect Tasks: Tasks with no declared @Output will always run because they are typically used for diagnostics or deployment and do not contribute to the build graph's state.
  5. Configure Task Execution Avoidance

    main

    The Kotlin Toolchain uses execution avoidance to skip tasks that don't need to run. By default, a task is considered up-to-date if:

    1. The action execution classpath hasn't changed.
    2. The effective values of non-path arguments (including configurable interface properties) are the same.
    3. The state of all @Input and @Output file trees (based on file attributes and modification time) is unchanged.

    Note: File content is not currently checked; only attributes and modification times are used.

    Control this behavior using the executionAvoidance parameter in the @TaskAction annotation:

    • ExecutionAvoidance.Automatic (default): Computes up-to-dateness. If no outputs are declared, the task always re-runs.
    • ExecutionAvoidance.Disabled: The task always re-runs. Use this for tasks with complex side effects or manual up-to-date logic.
    @TaskAction(executionAvoidance = ExecutionAvoidance.Disabled)
    fun alwaysRunTask(input: @Input Path) {
        // ...
    }
  6. Modularize a project with project.yaml

    main

    To manage multiple modules, create a project.yaml file at the project root. This file defines the project structure by listing the paths to all modules under the modules key.

    Example structure:

    • project.yaml (root)
    • jvm-app/module.yaml (application module)
    • shared/module.yaml (library module)
    # project.yaml
    modules:
      - ./jvm-app
      - ./shared
  7. Understand how Maven plugin compatibility is handled

    main

    When converting Maven projects, plugin support is split into two categories:

    1. Fully Supported: A whitelist of plugins is directly mapped to native Amper features.
    2. Compatibility Layer: Other plugins are delegated to the Maven compatibility layer (implemented in amper-maven-plugins-compatibility).

    Handling Unsupported Configurations: If a plugin configuration cannot be fully supported (for example, if a goal is configured across several different executions), the converter will notify the user via YAML comments in the generated files. These comments are mapped to the corresponding YAML keys during the rendering phase to ensure users are explicitly informed of potential issues.

  8. How project-local version detection works

    main

    The Kotlin wrapper script acts as the source of truth for the toolchain version.

    If you use a globally installed Kotlin CLI (e.g., via SDKMAN), it will not blindly use its own version. Instead, it searches the current directory and its parent directories for a project containing a project.yaml or module.yaml file and a kotlin wrapper script. If found, the global CLI will use the Kotlin Toolchain version and distribution checksum specified by that wrapper, ensuring the project is built with its declared version.

  9. Configure a Root Module in a Multi-module Project

    main

    It is possible to have a module located at the project root even in a multi-module project, though this is generally discouraged. If a root module exists, it is included implicitly in the project.yaml file, and you only need to list the other modules in the modules section.

    # Root module layout
    ├─ lib/
    │  ├─ src/
    │  │  ╰─ util.kt
    │  ╰─ module.yaml
    ├─ src/  # src of the root module
    │  ├─ main.kt
    │  ╰─ ...
    ├─ module.yaml  # the module file of the root module
    ╰─ project.yaml
    # project.yaml
    modules:  # The root module is included implicitly
      - lib