# Native Maven

> Run Apache Maven 4 builds with `elide mvn` without a separate Maven or JDK install: flavors for plain and Spring Boot projects, modes and output.

`elide mvn` runs Apache Maven 4 builds without a separate Maven or JDK install.

## Run a build

```bash
elide mvn -- package
elide mvn -- -f app/pom.xml clean install
elide mvn -- --version
```

Everything after `--` goes to Maven, except `--flavor`, `--mode`, `--yes` and `--porcelain`, which `elide mvn`
handles. The project root is the nearest `.mvn` directory above `-f`/`--file` or the working directory.

## First run

Each flavor is a one-time download, prompted on first use:

```terminaloutput
Native Maven component 'generic' is not installed. Download it now? [Y/n]
```

Images install to `lib/maven/bin/` in the Elide home. Non-interactive sessions download without asking; in a
terminal, `--yes` skips the prompt:

```bash
elide mvn -- --yes package
```

| Platform | Architecture |
| --- | --- |
| Linux | x86_64, aarch64 |
| macOS | aarch64 |
| Windows | x86_64 |

## Flavors

A flavor is the set of Maven plugins that run natively.

| Flavor | Plugins | For |
| --- | --- | --- |
| `generic` | Default lifecycle: clean, resources, compiler, surefire, jar, install, deploy | Plain Java or Kotlin projects |
| `spring@4.1.0` | Everything a [Spring Initializr](https://start.spring.io/) Boot 4.1 project uses | Spring Boot 4.1.x |
| `spring@4.0.7` | Same, for Boot 4.0 | Spring Boot 4.0.x |

Elide picks the `spring` flavor that matches the `major.minor` of the `spring-boot-starter-parent` parent or
`spring-boot-maven-plugin` version in `pom.xml` (Boot `4.1.3` → `spring@4.1.0`). Otherwise, including for `${…}`
placeholders, it uses `generic`. To override:

```bash
elide mvn -- --flavor spring@4.1.0 package
elide mvn -- --flavor=spring@4.0.7 -f app/pom.xml install
```

## Modes

`--mode=<value>` (or `-Dnmvn.mode=<value>`; the flag takes precedence) sets what runs plugins outside the flavor:

```bash
elide mvn -- --mode=mixed package
```

| Mode | Behavior |
| --- | --- |
| `native` (default) | Only flavor plugins run. A missing plugin fails early, naming the flavor that has it and suggesting `--mode=mixed`. |
| `mixed` | Flavor plugins run natively; other goals run one at a time on a JVM in the same process. |
| `legacy` | The whole build runs as plain Apache Maven on the in-process JVM, as a baseline. |

`mixed` and `legacy` download a Maven distribution into `lib/maven/` on first use. No separate JDK is needed.

### Mixed mode limits

- Each delegated goal adds about 0.2 s after a one-time startup. If most goals are delegated, pick a flavor with more
  of their plugins.
- A delegated goal's artifacts are not attached to the session. If the jar plugin is not in the flavor, run
  `package`, not `install` or `deploy`.
- Command-line plugin configuration is passed to delegated goals only as `-D` properties.

## Output

A terminal shows a status line (plugin, goal, version, module), then a phase summary and build time; failures print
the full Maven log. `--porcelain` streams Maven's own output, as do verbose, debug and non-interactive runs:

```bash
elide mvn -- --porcelain package
```

## Inspect an installed image

```bash
<elide-home>/lib/maven/bin/nmvn-generic --info
<elide-home>/lib/maven/bin/nmvn-spring-4.1.0 --info=plugins
```

`--info` prints the flavor, variant and plugins; `--info=plugins`, `--info=flavor` or `--info=variant` prints one.

## Compatibility

Native Maven reads the same `pom.xml` and follows the same lifecycle as Apache Maven 4. Plugin coverage is limited to
the published flavors. Compilation runs in-process; plugins that fork the compiler use Elide's `javac`.
