Run a file. Build a project. Reproduce its dependencies and toolchains.
EVM brings source files, projects, dependencies, ECF, ISE Eiffel, and Gobo Eiffel into one workflow without replacing the native Eiffel ecosystem.
Important
EVM is a very young project under active development. Some interfaces may still evolve. Testing on real Eiffel projects is especially valuable at this stage; bug reports, use cases, and any other feedback are very welcome.
EVM requires Python 3.11 or newer. Install the command directly from the GitHub
repository with
uv:
uv tool install "git+https://github.com/samedit66/evm.git"
evm --versionFor a reproducible installation, append a commit SHA or release tag to the Git URL. See Installation for pinned and checkout-based installation.
For development from a checkout:
uv sync --all-groups
uv run evm --helpSee Installation for other environment details.
Create hello.e:
class
HELLO
create
make
feature {NONE} -- Initialization
make
do
print ("Hello, World!%N")
end
endRun it directly:
evm run hello.eNo project manifest or handwritten ECF is required. EVM selects a compatible installed toolchain, stages an internal ECF, builds the file, and runs it in an isolated cache.
Choose a provider or exact version when needed:
evm run --toolchain gobo hello.e
evm run --toolchain gobo@26.06 hello.eEVM can use an existing ISE Eiffel or Gobo Eiffel installation. It can also install a verified distribution in its shared user store:
evm toolchain list --available
evm toolchain install gobo
evm toolchain verify goboUse an exact selector such as gobo@26.06 when the version matters. See
Toolchains for linked installations, project matrices,
locked installation, offline use, and environment setup.
The same project can be checked with both Gobo Eiffel and ISE Eiffel without changing its ECF or shell environment. Try one compiler, name several, or run the project's complete compiler matrix:
evm test --toolchain gobo
evm test --toolchain gobo@26.06 --toolchain ise@25.12
evm test --toolchain allFor a reproducible team and CI setup, pin the exact toolchains with
evm toolchain use gobo@26.06 ise@25.12. EVM records the first as the default
and writes the policy to Eiffel.toml (with exact artifacts in Eiffel.lock):
[toolchain]
default = "gobo@26.06"
matrix = ["gobo@26.06", "ise@25.12"]Now plain evm build uses the pinned default, while evm check --toolchain all
or evm test --toolchain all catches portability differences across the whole
matrix before they reach another developer or CI.
Turn the same workflow into a reproducible application project:
evm new hello
cd hello
evm runThe generated project includes a human-readable Eiffel.toml, an exact
Eiffel.lock, a standard ECF, production sources, and a conventional test
directory. Common operations stay short:
evm check
evm build --release
evm test
evm lint
evm docevm lint uses Gobo gelint or EiffelStudio Code Analyzer according to the
selected toolchain. evm doc generates HTML through Gobo gedoc or the native
EiffelStudio documentation filter. Both commands accept an explicit --backend
when a project needs to pin the implementation.
The following project uses the real
Eiffel JSON library. Create it and add the
library from its v0.11 Git tag:
evm new json_demo
cd json_demo
evm add ejson \
--git https://github.com/eiffelhub/json.git \
--tag v0.11 \
--ecf library/json.ecfReplace src/application.e with this single file:
class
APPLICATION
create
make
feature {NONE} -- Initialization
make
local
document: JSON_OBJECT
do
create document.make
document.put_string ("evm", "project")
document.put_string ("works", "status")
print (document.representation)
print ("%N")
end
endRun the application:
evm runIt prints:
{"project":"evm","status":"works"}evm add records the declared source in Eiffel.toml, resolves the tag to
immutable Git identities in Eiffel.lock, materializes the dependency below
.evm/, and synchronizes the managed ECF. A fresh checkout can restore the
same state with:
evm install --lockedSee Package management for IRON, Git, local-path, ISE, and Gobo dependencies, updates, offline operation, and graph inspection.
ECF is an expressive native description of an Eiffel system, but it is mainly a compiler configuration format. By itself, it does not record where every dependency comes from, which exact revisions produced a build, or how the full project state can be restored on another machine.
EVM adds that project-management layer:
Eiffel.toml human-readable project intent
+
Eiffel.lock exact dependencies and locked toolchain artifacts
↓
standard ECF EiffelStudio, ISE Eiffel, and Gobo Eiffel
The result is one CLI for everyday project operations, reproducible package state, deterministic ECF generation, optional managed toolchains, and safe adoption of existing Eiffel projects.
EVM does not implement an Eiffel compiler or require users to stop using
EiffelStudio, Gobo, ECF, ec, or gec. Native tools and formats remain
accessible and first-class.
hello/
├── Eiffel.toml # project intent and direct dependencies
├── Eiffel.lock # exact resolved state
├── hello.ecf # native Eiffel configuration
├── src/ # production Eiffel sources
├── tests/ # test Eiffel sources
├── .evm/ # local dependencies and derived state
└── build/ # compiler output
Commit Eiffel.toml, Eiffel.lock, and the managed ECF. Ignore .evm/ and
build/; EVM reconstructs them from committed state.
Already have an ECF project? Adopt EVM without rewriting it:
evm import project.ecfSee Migrating existing projects for the safe legacy workflow.
- ISE Eiffel and Gobo Eiffel adapters with deterministic selection;
- managed, linked, exact, and project-matrix toolchains;
- AutoTest,
getest, conventional test targets, filters, and CI output; - portable project tasks with explicit opt-in for shell steps;
- multi-package workspaces with dependency-order execution;
- offline dependency and toolchain restoration;
- deterministic
package.ironimport and export; - stable JSON output for automation.
hello_timeuses a Gobo distribution library with both Gobo Eiffel and ISE EiffelStudio.jsonresolves the Eiffel JSON library from Git and calls it from a real application.calculator_autotestruns anEQA_TEST_SETsuite through EVM's generated AutoTest console runner.
| Guide | Contents |
|---|---|
| Installation | Installation and environment diagnosis |
| Projects and manifests | Project layout, targets, build modes, and daily workflow |
| Manifest reference | Eiffel.toml sections, fields, and inferred defaults |
| Compatibility contract | Stability guarantees for CLI and project files |
| Package management | Sources, locking, updates, offline use, and graph inspection |
| Toolchains | Discovery, installation, selection, matrices, and capabilities |
| Migrating existing projects | Adopt EVM without replacing an existing ECF |
| Testing and tasks | Test runners, filters, diagnostics, and workflows |
| Workspaces and CI | Multi-package repositories and reproducible automation |
| CLI reference | Every public command and option |
Every command also includes built-in help:
evm --help
evm add --help
evm toolchain --helpThe current implementation covers managed and legacy ECF projects, ISE and Gobo adapters, dependency resolution and locking, managed and linked toolchains, project compilation matrices, testing, tasks, IRON interoperability, and multi-package workspaces.
This is still a very young project. Testing against existing Eiffel codebases is useful even when a workflow is not yet fully supported. I am glad to receive bug reports, compatibility findings, workflow descriptions, and any other feedback through the GitHub repository.
EVM is licensed under the Apache License 2.0.
EVM — modern project ergonomics for the native Eiffel ecosystem.