Skip to content

samedit66/fer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

19 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

> fer_

Predictable workflows for Eiffel projects.

A small, explicit project workflow layer for Gobo Eiffel.

License: MIT Rust 1.97+ Eiffel Status

fer removes the repetitive setup around Gobo Eiffel projects while keeping the project itself transparent and native to the Eiffel ecosystem.

ECF stays the source of truth. There is no private build format and no hidden compiler configuration.

Note

fer is currently an early MVP. The CLI and managed project format may evolve.

Install

The installer downloads a prebuilt binary from the latest stable GitHub Release. Rust, Cargo and Git are not required.

macOS and Linux:

curl -LsSf https://raw.githubusercontent.com/samedit66/fer/main/install.sh | sh

Windows (PowerShell):

powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/samedit66/fer/main/install.ps1 | iex"

The default installation directory is ~/.fer/bin on macOS and Linux and %LOCALAPPDATA%\fer\bin on Windows. Set FER_HOME to select another installation root.

Update an installation created by the official installer to the latest stable release:

fer self update

Check without changing the installation, or select an exact release:

fer self update --check
fer self update --version 0.2.0

To remove the installation:

fer self uninstall

self update and self uninstall deliberately do not modify installations managed by Cargo or another package manager. Update or remove those installations through their original manager.

Prebuilt binaries and SHA256SUMS are also available on the Releases page.

πŸš€ Quick start

Create and run an application:

fer new my-app
cd my_app
fer run

Create a library:

fer new my-library --library
cd my_library
fer build

Use a custom root class and creation procedure:

fer new my-app --root SERVER --create start

✨ What fer gives you

πŸ—‚οΈ Predictable project layout Conventional locations for source code, tests, documentation, and fer metadata.
🧩 Native ECF projects fer generates and updates standard ECF files instead of replacing them.
πŸ”’ Reproducible Git dependencies Direct dependencies are pinned to exact commits with content hashes.
⚑ Focused CLI Create, adopt, migrate, diagnose, build, run, test, and manage dependencies without a large build system.

fer also finds the project root when commands are run from nested directories and can work with unmanaged Eiffel projects when the ECF file is unambiguous or supplied explicitly.

πŸ“ Project layout

Creating an application with:

fer new my-app

creates a project named my_app:

my_app/
β”œβ”€β”€ system.ecf
β”œβ”€β”€ fer.toml
β”œβ”€β”€ AGENTS.md
β”œβ”€β”€ src/
β”œβ”€β”€ test/
β”œβ”€β”€ doc/
β”œβ”€β”€ .fer/
β”‚   β”œβ”€β”€ metadata.toml
β”‚   β”œβ”€β”€ lock.toml
β”‚   β”œβ”€β”€ deps/
β”‚   β”œβ”€β”€ cache/
β”‚   └── tmp/
β”œβ”€β”€ README.md
└── .gitignore

The rules are intentionally simple:

  • Eiffel source code lives in src/.
  • Tests live in test/.
  • Documentation lives in doc/.
  • Direct dependency requirements live in fer.toml.
  • fer's internal data lives in .fer/.
  • The primary ECF file lives at the project root.
  • AGENTS.md gives coding agents concise Eiffel project guidance.
  • README.md includes requirements, development commands, the project structure, and a made with fer badge.

Library projects use library.ecf and also include an examples/ directory.

πŸ”„ Adopt and migrate projects

Adopt an existing Eiffel project that already follows the managed layout:

cd existing_project
fer init

The restricted adoption mode requires an application to use system.ecf, or a library to use library.ecf. The ECF system name, primary target name, project type, and root declaration must already satisfy the same rules as a project created by fer new. fer init never edits the ECF or Eiffel source. When a project is not compatible, it reports the manual ECF change required before the command can be run again.

Use explicit selection when the project has more than one ECF or target:

fer init --ecf system.ecf --target my_app
fer init --name my_app --application

Bring a project created by an older fer release up to the current layout:

fer migrate

Migration can recreate a missing fer.toml, .fer/lock.toml, and runtime directories when their contents can be derived without ambiguity. It never changes the primary ECF. Inspect the plan without changing files with:

fer migrate --check
fer migrate --dry-run

Diagnose either a current or legacy managed project:

fer doctor

fer doctor is read-only. It exits unsuccessfully and recommends fer migrate when the layout is incomplete.

πŸ”¨ Build and run

For a managed application:

fer build
fer run

For a managed library:

fer build

A library is not runnable because it has no application root. Building it acts as a compilation check for its Eiffel classes.

fer can also work with an existing, unmanaged Eiffel project. If exactly one ECF file is found, it is used automatically. Otherwise, specify it explicitly:

fer build --ecf path/to/system.ecf
fer run --ecf path/to/system.ecf

πŸ“¦ Reproducible dependencies

Adding a library should not mean losing track of the exact revision that made the project work.

Add a direct Git dependency:

fer add https://github.com/example/json.git

Choose a branch or tag explicitly:

fer add https://github.com/example/json.git --branch main
fer add https://github.com/example/json.git --tag v1.4.0

fer selects the dependency's library ECF and recursively resolves dependencies declared by that repository's fer.toml. Original checkouts are materialized under .fer/deps/; a derived, path-rewritten graph is built under .fer/cache/graph/. Only direct dependencies are added to the primary ECF.

Direct requirements are stored in the source-controlled fer.toml. Exact commits, content hashes, and graph edges are stored in .fer/lock.toml.

After cloning a managed project, restore its pinned dependencies with:

fer restore

Tip

Commit both fer.toml and .fer/lock.toml. Together they record dependency intent and the exact resolved graph.

Inspect the locked graph with:

fer tree

If two paths require different revisions of the same canonical dependency name, fer reports a version conflict. It never chooses one revision heuristically.

Update a branch-based dependency:

fer update json

Remove a dependency:

fer remove json

EiffelStudio ECF compatibility

Dependencies whose ECF files reference $ISE_LIBRARY work normally when that environment is available. For portable Eiffel source shipped with an EiffelStudio-specific ECF, fer add automatically recognizes the supported EiffelStudio Base reference and derives a Gobo-compatible configuration:

fer add https://github.com/schoelle/algae.git

The original locked checkout remains unchanged in .fer/deps/. In the disposable .fer/cache/graph/ copy, fer replaces the EiffelStudio base library with Gobo FreeELKS, and removes the incompatible concurrency capability from the copied ECF. The adapter and its version are recorded in fer.toml and .fer/lock.toml.

Automatic detection applies only to the direct dependency added by the current fer add command. Transitive dependencies use only adapters explicitly declared in their own fer.toml.

Disable automatic adaptation when the original EiffelStudio configuration is required:

fer add https://github.com/schoelle/algae.git --no-adapter

The explicit adapter option remains available:

fer add https://github.com/schoelle/algae.git \
  --adapter eiffelstudio-gobo-v1

--adapter and --no-adapter cannot be used together.

fer build, fer run, and fer restore recreate the derived graph cache when needed. Once restored, the generated primary ECF can also be used directly with gec. See the ALGAE matrix example and the eJSON parser example.

πŸ§ͺ Tests

fer does not invent its own testing framework or generate test classes.

When a project provides a Gobo getest configuration at test/getest.cfg, run:

fer test

🧭 ECF stays yours

fer reduces routine ECF editing; it does not replace ECF.

The primary ECF remains a normal Gobo Eiffel configuration file that you can inspect, edit, understand, and build without fer:

gec system.ecf
gec --run system.ecf

For a library:

gec library.ecf

Once dependencies have been restored, the project can be built directly with gec.

Important

There is no private build format. fer is a workflow layer around standard Eiffel tooling, not a replacement for it.

πŸ’‘ Why fer exists

Starting an Eiffel project often involves the same manual work:

  • creating directories for source code, tests, examples, and documentation;
  • writing or copying an ECF file;
  • deciding where dependencies should live;
  • editing ECF XML when a library is added or removed;
  • remembering which exact Git revision was used;
  • documenting how another developer restores the project after cloning it.

None of these tasks is especially difficult, but together they create repetitive project maintenance.

fer fills the gap between maintaining every detail manually and adopting a large, opinionated build system. It intentionally provides a small set of explicit conventions around Gobo Eiffel.

βœ… What fer is

fer is a lightweight workflow layer for Eiffel projects:

  • a conventional project layout;
  • explicit project metadata;
  • reproducible recursive Git dependency graphs;
  • focused commands around Gobo Eiffel;
  • predictable behavior when configuration is ambiguous.

It prefers clear rules over clever guesses. When a project or dependency configuration is ambiguous, fer asks for an explicit argument instead of silently choosing one.

🚫 What fer is not

fer is deliberately small. It is not trying to become a complete package ecosystem or replace existing Eiffel tooling.

It is not:

  • a replacement for ECF or the Gobo Eiffel compiler;
  • a package registry or semantic-version solver;
  • a solution for local/path dependencies, Git submodules, Git LFS, or credential storage;
  • a converter for arbitrary existing projects β€” fer init only adopts projects that already satisfy the managed ECF conventions;
  • a custom-layout generator or automatic project-repair tool;
  • a test generator or full test-management framework;
  • a manager for secondary ECF files, secondary targets, or library publishing.

The goal is smaller: make the common Eiffel project workflow less repetitive while keeping the project transparent and native to the tools it already uses.

πŸ› οΈ Build fer locally

fer is written in Rust and uses the standard Cargo workflow.

Requirements

  • Rust 1.97 or newer, including Cargo.
  • Git, used when creating projects and managing dependencies.

Gobo Eiffel is not required to compile fer itself. It is required when using fer build, fer run, or fer test with Eiffel projects.

Development build

From the repository root:

cargo build

The binary is available at:

target/debug/fer

Run it directly:

target/debug/fer --help

Or through Cargo:

cargo run -- --help
Release build
cargo build --release

The optimized binary is available at:

target/release/fer
Run the test suite
cargo test
Install from a local checkout
cargo install --path . --locked

Verify the installation:

fer --help

If Cargo's binary directory is not already on your PATH, add it before using the installed command.

Publish a release

Set the release version in Cargo.toml, update Cargo.lock, commit the change, and push a matching SemVer tag:

git tag v0.2.0
git push origin v0.2.0

The release workflow verifies that the tag and package version match, runs the full check suite, builds every supported target, generates SHA256SUMS and publishes the GitHub Release with build provenance attestations. A failure on any required target prevents publication.


fer β€” less project ceremony, more Eiffel.

Releases

Packages

Contributors

Languages