steel.org

Steel Manifest (documentation complete)

Ce document est la reference complete du projet. Il couvre la CLI, les formats, la syntaxe MUF, les regles de resolution, les logs et les conventions en usage dans le code.

1. Vision et modele mental

Steel est la couche de configuration declarative du build. Il:

Le pipeline est en deux phases: 1) Configuration (steel / build steelconf) -> produit steelconfig.mff. 2) Execution (run) -> interprete steelconf pour executer des outils.

Cette separation garantit la reproductibilite: la configuration figee peut etre relue, versionnee et comparee.

2. Concepts clefs

2.1 SteelLib (backends)

Steel expose des backends via la crate SteelLib. Exemple d import OCaml:

use SteelLib::ocaml::{OcamlArgs, OcamlDriver, OcamlSpec};

Backends disponibles (liste rapide):

3. Fichiers et artefacts

3.1 Entrees

3.2 Sorties

3.3 Dossiers conventionnels

4. CLI complete (contrat actuel)

Liste rapide (toutes les commandes):

Flags frequents (profil/target/emit/log)

Ces flags apparaissent dans plusieurs commandes; ils sont censes rester stables.

--profile <name>

Exemples:

steel run --profile debug --all

--log <path> (et --log-mode)

Exemples:

steel run --log target/run.mff --log-mode truncate --all

4.1 Aide et version

4.2 build steelconf (configuration)

Commande principale (alias steel build steelconf):

steel

Semantique:

Aliases:

4.3 run (execution)

steel run [--root <path>] [--file <path>] [--profile <name>]
           [--toolchain <path>] [--bake <name>] [--all]
           [--print] [--no-cache]
           [--log <path>] [--log-mode <append|truncate>] [-v]

Semantique:

4.4 doctor

steel doctor [--root <path>] [--json] [-v]

4.5 cache

steel cache <status|clear> [--root <path>] [--json] [-v]

4.6 graph (stub)

steel graph [--root <path>] [--text|--dot] [-v]

4.7 fmt (stub)

steel fmt [--file <path>] [--check] [-v]

4.8 Codes de sortie

5. Resolution et discovery (build steelconf)

5.1 Racine du workspace

5.2 Recherche de steelconf

Ordre: 1) steelconf dans la racine. 2) scan DFS deterministe sous la racine, avec tri lexicographique.

Regles de scan (fixes):

5.3 Profil et target

5.4 Toolchain et fingerprint

6. Format steelconfig.mff (mff v1)

6.1 Header

mff 1

6.2 Sections

project
  root "/path/to/root"
  steelfile "/path/to/steelconf"
.end

select
  profile "debug"
  target "x86_64-unknown-linux-gnu"
.end

paths
  build "/path/to/root/build"
  dist "/path/to/root/dist"
  cache "/path/to/root/.steel-cache"
.end

toolchain
  cc "gcc"
  cxx "g++"
  ar "ar"
  ld "ld"
  rustc "rustc"
  python "python3"
  ocaml "/opt/ocaml/lib"
  ghc "/opt/ghc/pkgdb"

  versions
    cc "gcc (GCC) 13.2.0"
  .end
.end

vars
  set "steel.profile" "debug"
  set "steel.target" "x86_64-unknown-linux-gnu"
  set "steel.offline" "false"
  set "steel.root" "/path/to/root"
  set "steel.file" "/path/to/steelconf"
.end

fingerprint
  value "fnv1a64:..."
.end

Notes:

6.3 Schemas machine-readables (IDE/CI)

7. Format MUF (v4.1)

7.1 Structure generale

7.2 Lexemes

7.3 EBNF minimal

Block     = WS0 , BlockHead , WS0 , NL , { BlockItem } , WS0 , BlockClose , WS0 , NL ;
BlockHead = "[" , WS0 , Tag , [ WS1 , Name ] , WS0 , "]" ;
BlockClose = ".." ;
Directive = WS0 , "." , Op , { WS1 , Atom } , WS0 , NL ;
Atom = Ref | String | Number | Name ;

8. Regles MUF interpretees par le runner

Le runner actuel supporte un sous-ensemble volontairement limite.

8.1 Bloc [workspace]

8.2 Bloc [profile ]

8.3 Bloc [tool ]

8.4 Bloc [bake ]

8.5 Bloc [run ]

Directives supportees:

8.6 Variables et interpolation

Exemple:

.set "-O${opt}" 1
.set "-g" "${debug}"

9. Regles de selection et execution

9.1 Selection des bakes

Priorite: 1) --all -> tous les bakes dans l ordre du fichier. 2) --bake <name> (repete). 3) bake app si present. 4) premier bake dans le fichier.

9.2 DAG et dependances

9.3 Incremental et cache

10. Logs d execution (runner)

10.1 Emplacement

10.2 Format

[log meta]
format "steel-runlog-1"
tool "steel"
version "steel <version>"
ts_iso "<RFC3339>"
..

[bake log "<name>"]
output "<path>"
sources_count <n>
source "<path>"   ;; repete
[run log]
ts <epoch>
ts_iso "<RFC3339>"
duration_ms <n>
cmd "gcc ..."
cwd "/path/to/root"
status <code>
ok true|false
stdout_bytes <n>
stderr_bytes <n>
stdout "..."   ;; optionnel
stderr "..."   ;; optionnel
..
runs <n>
duration_ms <n>
..
[run summary]
ts_iso "<RFC3339>"
..

11. Globs et determinisme

12. Exemples complets

12.1 Exemple minimal (C)

!muf 4

[workspace]
  .set name "steel-example-c"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[profile debug]
  .set opt 0
  .set debug 1
  .set ndebug 0
..

[tool gcc]
  .exec "gcc"
..

[bake app]
  .make c_src cglob "**/*.c"
  [run gcc]
    .takes c_src as "@args"
    .set "-std=c17" 1
    .set "-O${opt}" 1
    .set "-g" "${debug}"
    .set "-DNDEBUG" "${ndebug}"
    .set "-Wall" 1
    .set "-Wextra" 1
    .emits exe as "-o"
  ..
  .output exe "target/out/app"
..

12.2 CLI

# configuration
steel
steel print

# execution
steel run --root . --file steelconf --bake app
steel run --root . --all --print

12.3 Exemples steelconf (C/C++/OCaml)

C (binaire simple)

!muf 4

[workspace]
  .set name "demo-c"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[tool gcc]
  .exec "gcc"
..

[bake app_c]
  .make c_src cglob "src/**/*.c"
  [run gcc]
    .takes c_src as "@args"
    .set "-std=c17" 1
    .set "-O0" 1
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/app_c"
..
!muf 4

[workspace]
  .set name "demo-c-lib"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool gcc]
  .exec "gcc"
..

[tool ar]
  .exec "ar"
..

[bake lib_c]
  .make c_src cglob "lib/**/*.c"
  [run gcc]
    .takes c_src as "@args"
    .set "-std=c17" 1
    .set "-O2" 1
    .set "-c" 1
    .emits obj as "-o"
  ..
  .output obj "target/obj/lib_c.o"
..

[bake app_c]
  .make main file "src/main.c"
  [run gcc]
    .takes main as "@args"
    .takes "target/obj/lib_c.o" as "@args"
    .set "-O2" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/app_c"
..

C++ (binaire simple)

!muf 4

[workspace]
  .set name "demo-cpp"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[tool gpp]
  .exec "g++"
..

[bake app_cpp]
  .make cpp_src cglob "src/**/*.cpp"
  [run gpp]
    .takes cpp_src as "@args"
    .set "-std=c++20" 1
    .set "-O0" 1
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/app_cpp"
..

C++ (include + libs)

!muf 4

[workspace]
  .set name "demo-cpp-inc"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool gpp]
  .exec "g++"
..

[bake app_cpp]
  .make cpp_src cglob "src/**/*.cpp"
  [run gpp]
    .takes cpp_src as "@args"
    .set "-std=c++20" 1
    .set "-O2" 1
    .set "-Iinclude" 1
    .set "-lpthread" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/app_cpp"
..

OCaml (native ocamlopt)

!muf 4

[workspace]
  .set name "demo-ocaml"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool ocamlopt]
  .exec "ocamlopt"
..

[bake app_ml]
  .make ml_src cglob "src/**/*.ml"
  [run ocamlopt]
    .takes ml_src as "@args"
    .set "-O2" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/app_ml"
..

OCaml (bytecode ocamlc)

!muf 4

[workspace]
  .set name "demo-ocaml-byte"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[tool ocamlc]
  .exec "ocamlc"
..

[bake app_ml_byte]
  .make ml_src cglob "src/**/*.ml"
  [run ocamlc]
    .takes ml_src as "@args"
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/app_ml.byte"
..

12.4 Exemples avances (multi-bakes, tests, libs dynamiques)

Multi-bakes (lib + app C)

!muf 4

[workspace]
  .set name "demo-multi-bakes"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool gcc]
  .exec "gcc"
..

[bake lib_core]
  .make c_src cglob "lib/**/*.c"
  [run gcc]
    .takes c_src as "@args"
    .set "-std=c17" 1
    .set "-O2" 1
    .set "-c" 1
    .emits obj as "-o"
  ..
  .output obj "target/obj/lib_core.o"
..

[bake app]
  .make main file "src/main.c"
  [run gcc]
    .takes main as "@args"
    .takes "target/obj/lib_core.o" as "@args"
    .set "-O2" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/app"
..

Tests C (bake dedie)

!muf 4

[workspace]
  .set name "demo-tests-c"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[tool gcc]
  .exec "gcc"
..

[bake tests_c]
  .make test_src cglob "tests/**/*.c"
  [run gcc]
    .takes test_src as "@args"
    .set "-std=c17" 1
    .set "-g" 1
    .set "-O0" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/tests_c"
..

Lib dynamique C (shared)

!muf 4

[workspace]
  .set name "demo-shared-c"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool gcc]
  .exec "gcc"
..

[bake lib_shared]
  .make c_src cglob "src/**/*.c"
  [run gcc]
    .takes c_src as "@args"
    .set "-fPIC" 1
    .set "-shared" 1
    .set "-O2" 1
    .emits so as "-o"
  ..
  .output so "target/lib/libdemo.so"
..

Lib dynamique C (shared) — Windows

!muf 4

[workspace]
  .set name "demo-shared-c-win"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool gcc]
  .exec "gcc"
..

[bake lib_shared_win]
  .make c_src cglob "src/**/*.c"
  [run gcc]
    .takes c_src as "@args"
    .set "-shared" 1
    .set "-O2" 1
    .emits dll as "-o"
  ..
  .output dll "target\\lib\\demo.dll"
..

Lib dynamique C (shared) — macOS

!muf 4

[workspace]
  .set name "demo-shared-c-macos"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool clang]
  .exec "clang"
..

[bake lib_shared_macos]
  .make c_src cglob "src/**/*.c"
  [run clang]
    .takes c_src as "@args"
    .set "-shared" 1
    .set "-O2" 1
    .emits dylib as "-o"
  ..
  .output dylib "target/lib/libdemo.dylib"
..

Lib dynamique C++ (shared)

!muf 4

[workspace]
  .set name "demo-shared-cpp"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool gpp]
  .exec "g++"
..

[bake lib_shared_cpp]
  .make cpp_src cglob "src/**/*.cpp"
  [run gpp]
    .takes cpp_src as "@args"
    .set "-fPIC" 1
    .set "-shared" 1
    .set "-std=c++20" 1
    .set "-O2" 1
    .emits so as "-o"
  ..
  .output so "target/lib/libdemo_cpp.so"
..

Lib dynamique C++ (shared) — Windows

!muf 4

[workspace]
  .set name "demo-shared-cpp-win"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool gpp]
  .exec "g++"
..

[bake lib_shared_cpp_win]
  .make cpp_src cglob "src/**/*.cpp"
  [run gpp]
    .takes cpp_src as "@args"
    .set "-shared" 1
    .set "-std=c++20" 1
    .set "-O2" 1
    .emits dll as "-o"
  ..
  .output dll "target\\lib\\demo_cpp.dll"
..

Lib dynamique C++ (shared) — macOS

!muf 4

[workspace]
  .set name "demo-shared-cpp-macos"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool clangpp]
  .exec "clang++"
..

[bake lib_shared_cpp_macos]
  .make cpp_src cglob "src/**/*.cpp"
  [run clangpp]
    .takes cpp_src as "@args"
    .set "-shared" 1
    .set "-std=c++20" 1
    .set "-O2" 1
    .emits dylib as "-o"
  ..
  .output dylib "target/lib/libdemo_cpp.dylib"
..

OCaml (lib + app)

!muf 4

[workspace]
  .set name "demo-ocaml-lib"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[tool ocamlopt]
  .exec "ocamlopt"
..

[bake lib_ml]
  .make ml_src cglob "lib/**/*.ml"
  [run ocamlopt]
    .takes ml_src as "@args"
    .set "-a" 1
    .emits lib as "-o"
  ..
  .output lib "target/lib/libml.cmxa"
..

[bake app_ml]
  .make ml_src cglob "src/**/*.ml"
  [run ocamlopt]
    .takes ml_src as "@args"
    .takes "target/lib/libml.cmxa" as "@args"
    .set "-O2" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/app_ml"
..

C++ (tests + runner simple)

!muf 4

[workspace]
  .set name "demo-cpp-tests"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[tool gpp]
  .exec "g++"
..

[tool sh]
  .exec "sh"
..

[bake tests_cpp]
  .make test_src cglob "tests/**/*.cpp"
  [run gpp]
    .takes test_src as "@args"
    .set "-std=c++20" 1
    .set "-O0" 1
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/tests_cpp"
..

[bake run_tests]
  [run sh]
    .set "-c" 1
    .set "./target/bin/tests_cpp" 1
  ..
..

C++ (tests + runner PowerShell, Windows)

!muf 4

[workspace]
  .set name "demo-cpp-tests-win"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[tool gpp]
  .exec "g++"
..

[tool pwsh]
  .exec "pwsh"
..

[bake tests_cpp]
  .make test_src cglob "tests/**/*.cpp"
  [run gpp]
    .takes test_src as "@args"
    .set "-std=c++20" 1
    .set "-O0" 1
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target\\bin\\tests_cpp.exe"
..

[bake run_tests]
  [run pwsh]
    .set "-NoProfile" 1
    .set "-ExecutionPolicy" 1
    .set "Bypass" 1
    .set "-Command" 1
    .set ".\\target\\bin\\tests_cpp.exe" 1
  ..
..

C++ (tests conditionnes + PowerShell, Windows)

!muf 4

[workspace]
  .set name "demo-cpp-tests-win-profile"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[profile debug]
  .set run_tests 1
..

[profile release]
  .set run_tests 0
..

[tool gpp]
  .exec "g++"
..

[tool pwsh]
  .exec "pwsh"
..

[bake tests_cpp]
  .make test_src cglob "tests/**/*.cpp"
  [run gpp]
    .takes test_src as "@args"
    .set "-std=c++20" 1
    .set "-O0" 1
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target\\bin\\tests_cpp.exe"
..

[bake run_tests]
  [run pwsh]
    .set "-NoProfile" 1
    .set "-ExecutionPolicy" 1
    .set "Bypass" 1
    .set "-Command" 1
    .set "if (${run_tests} -eq 1) { .\\target\\bin\\tests_cpp.exe }" 1
  ..
..

C++ (tests conditionnes + PowerShell, Windows, skip)

!muf 4

[workspace]
  .set name "demo-cpp-tests-win-profile-skip"
  .set root "."
  .set target_dir "target"
  .set profile "release"
..

[profile debug]
  .set run_tests 1
..

[profile release]
  .set run_tests 0
..

[tool gpp]
  .exec "g++"
..

[tool pwsh]
  .exec "pwsh"
..

[bake tests_cpp]
  .make test_src cglob "tests/**/*.cpp"
  [run gpp]
    .takes test_src as "@args"
    .set "-std=c++20" 1
    .set "-O0" 1
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target\\bin\\tests_cpp.exe"
..

[bake run_tests]
  [run pwsh]
    .set "-NoProfile" 1
    .set "-ExecutionPolicy" 1
    .set "Bypass" 1
    .set "-Command" 1
    .set "if (${run_tests} -eq 1) { .\\target\\bin\\tests_cpp.exe } else { Write-Host \"skip tests (run_tests=0)\"; exit 5 }" 1
  ..
..

C++ (tests conditionnes par profile)

!muf 4

[workspace]
  .set name "demo-cpp-tests-profile"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[profile debug]
  .set run_tests 1
..

[profile release]
  .set run_tests 0
..

[tool gpp]
  .exec "g++"
..

[tool sh]
  .exec "sh"
..

[bake tests_cpp]
  .make test_src cglob "tests/**/*.cpp"
  [run gpp]
    .takes test_src as "@args"
    .set "-std=c++20" 1
    .set "-O0" 1
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/tests_cpp"
..

[bake run_tests]
  [run sh]
    .set "-c" 1
    .set "test ${run_tests} -eq 1 && ./target/bin/tests_cpp" 1
  ..
..

C (tests conditionnes par profile)

!muf 4

[workspace]
  .set name "demo-c-tests-profile"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[profile debug]
  .set run_tests 1
..

[profile release]
  .set run_tests 0
..

[tool gcc]
  .exec "gcc"
..

[tool sh]
  .exec "sh"
..

[bake tests_c]
  .make test_src cglob "tests/**/*.c"
  [run gcc]
    .takes test_src as "@args"
    .set "-std=c17" 1
    .set "-O0" 1
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target/bin/tests_c"
..

[bake run_tests]
  [run sh]
    .set "-c" 1
    .set "test ${run_tests} -eq 1 && ./target/bin/tests_c" 1
  ..
..

Petit exemple de test C minimal (pour tests/**/*.c):

#include <stdio.h>
#include <assert.h>

int main(void) {
    assert(1 + 1 == 2);
    puts("ok");
    return 0;
}

Petit exemple de test C++ minimal (pour tests/**/*.cpp):

#include <iostream>
#include <cassert>

int main() {
    assert(1 + 1 == 2);
    std::cout << "ok\n";
    return 0;
}

C (tests conditionnes + PowerShell, Windows)

!muf 4

[workspace]
  .set name "demo-c-tests-win-profile"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[profile debug]
  .set run_tests 1
..

[profile release]
  .set run_tests 0
..

[tool gcc]
  .exec "gcc"
..

[tool pwsh]
  .exec "pwsh"
..

[bake tests_c]
  .make test_src cglob "tests/**/*.c"
  [run gcc]
    .takes test_src as "@args"
    .set "-std=c17" 1
    .set "-O0" 1
    .set "-g" 1
    .emits exe as "-o"
  ..
  .output exe "target\\bin\\tests_c.exe"
..

[bake run_tests]
  [run pwsh]
    .set "-NoProfile" 1
    .set "-ExecutionPolicy" 1
    .set "Bypass" 1
    .set "-Command" 1
    .set "if (${run_tests} -eq 1) { .\\target\\bin\\tests_c.exe }" 1
  ..
..

12.5 Table recap (exemple -> objectif -> toolchain)

Exemple Objectif Toolchain
12.1 C minimal, binaire simple gcc
12.3 C (binaire) Binaire C avec sources multiples gcc
12.3 C (lib + link) Compilation en deux etapes gcc, ar
12.3 C++ (binaire) Binaire C++ standard g++
12.3 C++ (include + libs) Include + lien lib g++
12.3 OCaml (native) Binaire natif OCaml ocamlopt
12.3 OCaml (bytecode) Binaire bytecode OCaml ocamlc
12.4 Multi-bakes Lib + app, bakes separes gcc
12.4 Tests C Bake de tests gcc
12.4 Lib dynamique C .so partagee gcc
12.4 Lib dynamique C++ .so partagee g++
12.4 OCaml (lib + app) Lib OCaml + binaire ocamlopt
12.4 Lib dynamique C (Windows) .dll Windows gcc
12.4 Lib dynamique C (macOS) .dylib macOS clang
12.4 Lib dynamique C++ (Windows) .dll Windows g++
12.4 Lib dynamique C++ (macOS) .dylib macOS clang++
12.4 C++ tests + runner Binaire tests + run g++, sh
12.4 C++ tests + runner (Windows) Binaire tests + run g++, pwsh
12.4 C++ tests par profile Tests conditionnes g++, sh
12.4 C tests par profile Tests conditionnes gcc, sh
12.4 C++ tests (Windows, conditionnel) Tests conditionnes g++, pwsh
12.4 C tests (Windows, conditionnel) Tests conditionnes gcc, pwsh
12.4 C++ tests (Windows, conditionnel, skip) Tests conditionnes + skip g++, pwsh

13. Diagnostics et erreurs courantes

Conseils:

14. Roadmap (cibles plausibles)

Milestones (proposition)

M1 - CLI et outputs:

M2 - Configuration complete:

M3 - Runner et outillage:

15. Limitations et etat actuel

16. Glossaire rapide

17. Tutoriel complet (pas a pas)

Cette section est un guide long format qui suit un projet fictif de A a Z. Elle reutilise les concepts de la reference et les illustre avec un chemin concret: ecrire un steelconf, generer un MFF, puis executer.

17.1 Objectif et plan du tuto

Nous allons construire un petit projet C avec une lib statique et un binaire:

Plan: 1) creer un workspace minimal 2) declarer les tools 3) declarer les bakes 4) declarer les profiles 5) executer avec steel run 6) utiliser la configuration resolue .mff

17.2 Arborescence initiale

myproj/
  steelconf
  src/
    lib/
      lib.c
      lib.h
    app/
      main.c

Contenu minimal pour lib.c:

int add(int a, int b) { return a + b; }

Contenu minimal pour main.c:

#include "../lib/lib.h"
int main(void) { return add(1, 2); }

17.3 Base MUF

On commence par le header et un workspace:

!muf 4

[workspace]
  .set name "myproj"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

Ce bloc fixe des variables globales utilisables dans les autres blocs.

17.4 Declarer un tool

[tool cc]
  .exec "gcc"
..

Le nom cc est logique, il n est pas lie a la commande systeme.

17.5 Premier bake

[bake lib]
  .make c_src cglob "src/lib/*.c"
  [run cc]
    .takes c_src as "@args"
    .set "-std=c17" 1
    .set "-O0" 1
    .emits obj as "-o"
  ..
  .output obj "target/out/lib.o"
..

17.6 Bake app qui depend de lib

[bake app]
  .make c_src cglob "src/app/*.c"
  .needs lib
  [run cc]
    .takes c_src as "@args"
    .include "src/lib"
    .set "-std=c17" 1
    .set "-O0" 1
    .emits exe as "-o"
  ..
  .output exe "target/out/app"
..

17.7 Execution

steel run --root . --file steelconf --bake app

Le runner va:

17.8 Premiere configuration resolue

steel

Cela produit steelconfig.mff. C est une photo stable de votre config.

18. Tutoriel: profiles et variantes

18.1 Ajouter un profile release

[profile release]
  .set opt 2
  .set debug 0
  .set ndebug 1
..

Et adapter le run:

.set "-O${opt}" 1
.set "-g" "${debug}"
.set "-DNDEBUG" "${ndebug}"

18.2 Selection du profile

steel run --profile release --bake app

La selection --profile surcharge workspace.profile.

18.3 Profiles multiples

On peut declarer autant de profiles que necessaire:

[profile sanitize]
  .set opt 1
  .set debug 1
  .set asan 1
..

Dans le run:

.set "-fsanitize=address" "${asan}"

19. Tutoriel: targets et portabilite

19.1 Variables de target

[workspace]
  .set target "x86_64-unknown-linux-gnu"
..

Vous pouvez utiliser ${target} dans les chemins ou flags.

19.2 Separer output par target

.set target_dir "target/${target}"

Cela evite les collisions entre builds.

19.3 Exemple Windows

[profile windows]
  .set exe_ext ".exe"
..

Puis:

.output exe "target/out/app${exe_ext}"

20. Tutoriel: outils, toolchain et versions

20.1 Plusieurs tools

[tool cc]
  .exec "gcc"
..
[tool ar]
  .exec "ar"
..

20.2 Toolchain parametrable

Dans la vraie vie, on veut choisir clang ou gcc. Une strategie simple:

[workspace]
  .set cc "gcc"
..
[tool cc]
  .exec "${cc}"
..

20.3 Version et fingerprint

Le build steel calcule un fingerprint stable:

Le fingerprint peut etre injecte dans vos sorties ou logs.

21. Tutoriel: bakes avances

21.1 Plusieurs outputs

Un bake peut emettre plusieurs ports:

[bake compile]
  .make c_src cglob "src/**/*.c"
  [run cc]
    .takes c_src as "@args"
    .emits obj as "-o"
  ..
  .output obj "target/out/app.o"
  .output dep "target/out/app.d"
..

21.2 Plusieurs runs

Un bake peut avoir plusieurs runs, mais ici le runner supporte un seul bloc run. Dans ce cas, on decoupe en deux bakes:

21.3 Parametrer les patterns

On peut utiliser des variables dans les glob:

.make c_src cglob "src/${module}/*.c"

22. Tutoriel: wiring et ports

22.1 Passer un output comme input

Dans une version complete, on relierait un port obj vers link. Le runner actuel ne resolv pas un wiring complet, mais la logique est:

.needs compile

22.2 Convention de ports

Conventions conseillees:

22.3 Ports nommes

Les ports doivent etre stables et predictibles, car ils sont referencables.

23. Tutoriel: execution et logs

23.1 Logs par defaut

Le run produit un fichier .mff de log dans target/. Ce log sert a diagnostiquer les commandes et la duree.

23.2 Forcer un log fixe

steel run --log target/runlog.mff --log-mode truncate

23.3 Lecture rapide du log

Reperer:

24. Tutoriel: cache et incremental

24.1 Principe

Le runner compare:

Si output est plus recent, il skip.

24.2 Desactiver le cache

steel run --no-cache

24.3 Regles pour un build fiable

25. Tutoriel: graph et introspection

25.1 Graph text

steel graph --text

Dans le futur, cette commande montrera les bakes et dependances.

25.2 Graph dot

steel graph --dot > graph.dot

25.3 JSON de graphe

Le schema cible est schemas/steel.graph.json.schema.json. Utiliser ce format pour IDE/CI.

26. Tutoriel: diagnostics et qualite

26.1 Types de diagnostics

26.2 Exemple d erreur de syntaxe

error[P001]: invalid token
  at steelconf:12:3

26.3 Conseils pour debug

27. Tutoriel: integration CI/IDE

27.1 CI

Dans un pipeline: 1) steel print > steelconfig.mff 2) archiver steelconfig.mff 3) executer steel run

27.2 IDE

L IDE peut:

27.3 JSON schemas

Utiliser les schemas pour valider la sortie machine-readable.

28. Tutoriel: structure d un projet moyen

Exemple typique:

root/
  steelconf
  src/
    lib/
    app/
  include/
  tests/
  target/
  dist/

Conseils:

29. FAQ rapide

29.1 Pourquoi separer MUF et MFF

MUF est la source editable. MFF est un artefact stable et deterministe.

29.2 Comment changer de tool

Modifier la valeur de .exec ou utiliser une variable de workspace.

29.3 Comment deboguer un tool

Utiliser --log et inspecter la commande.

30. Annexes

30.1 Variables d environnement supportees

30.2 Rappel des chemins par defaut

30.3 Exemple de steelconf complet

!muf 4

[workspace]
  .set name "myproj"
  .set root "."
  .set target_dir "target"
  .set profile "debug"
..

[profile debug]
  .set opt 0
  .set debug 1
  .set ndebug 0
..

[profile release]
  .set opt 3
  .set debug 0
  .set ndebug 1
..

[tool cc]
  .exec "gcc"
..

[bake lib]
  .make c_src cglob "src/lib/*.c"
  [run cc]
    .takes c_src as "@args"
    .set "-std=c17" 1
    .set "-O${opt}" 1
    .set "-g" "${debug}"
    .set "-DNDEBUG" "${ndebug}"
    .emits obj as "-o"
  ..
  .output obj "target/out/lib.o"
..

[bake app]
  .make c_src cglob "src/app/*.c"
  .needs lib
  [run cc]
    .takes c_src as "@args"
    .include "src/lib"
    .set "-std=c17" 1
    .set "-O${opt}" 1
    .set "-g" "${debug}"
    .set "-DNDEBUG" "${ndebug}"
    .emits exe as "-o"
  ..
  .output exe "target/out/app"
..

30.4 Checklist de release

31. Tutoriel: structure multi-modules

Objectif: organiser un projet avec plusieurs libs et un binaire final.

31.1 Arborescence type

root/
  steelconf
  src/
    core/
      core.c
      core.h
    util/
      util.c
      util.h
    app/
      main.c

31.2 Bakes de compilation

[bake core]
  .make c_src cglob "src/core/*.c"
  [run cc]
    .takes c_src as "@args"
    .include "src/core"
    .emits obj as "-o"
  ..
  .output obj "target/out/core.o"
..

[bake util]
  .make c_src cglob "src/util/*.c"
  [run cc]
    .takes c_src as "@args"
    .include "src/util"
    .emits obj as "-o"
  ..
  .output obj "target/out/util.o"
..

31.3 Bake final

[bake app]
  .make c_src cglob "src/app/*.c"
  .needs core
  .needs util
  [run cc]
    .takes c_src as "@args"
    .include "src/core"
    .include "src/util"
    .emits exe as "-o"
  ..
  .output exe "target/out/app"
..

32. Tutoriel: artefacts et conventions de sortie

32.1 Convention target/out

Utiliser target/out pour les sorties immediates, puis dist/ pour publier.

32.2 Copier vers dist

Steel ne fait pas la copie automatiquement. On peut ajouter un bake:

[bake dist]
  .needs app
  [run sh]
    .set "cmd" "cp target/out/app dist/app"
  ..
  .output exe "dist/app"
..

Ce pattern est symbolique: il depend du runner et des tools autorises.

32.3 Nommage deterministe

Choisir des noms stables pour:

33. Tutoriel: schemas et JSON

33.1 Pourquoi un export JSON

Le JSON est pratique pour:

33.2 Graph JSON

Le schema cible est steel.graph.json/1. Le fichier est stable et deterministe.

33.3 Validation

Valider un JSON via un validateur standard et le schema fourni.

34. Tutoriel: MFF comme contrat

34.1 MFF versionne

Le header mff 1 fixe la version du format.

34.2 Utiliser MFF en CI

steel print > steelconfig.mff

Puis archiver l artefact. Cela permet:

34.3 Diff MFF

Comme c est deterministe, un diff git est lisible et utile.

35. Tutoriel: erreurs et recuperation

35.1 Erreurs de parse

Si MUF est invalide, la phase build steelconf renvoie des diagnostics.

35.2 Erreurs de run

Si une commande echoue, le code retour est non zero.

35.3 Strategie de debug

36. Tutoriel: performance et scalabilite

36.1 Limiter les globs

Eviter les patterns trop larges:

src/**/*

Preferer:

src/**/*.c

36.2 Decouper en bakes

Plusieurs bakes permettent d isoler les recompilations.

36.3 Cache

Le cache est simple mais efficace pour des projets moyens.

37. Tutoriel: tests et verifications

37.1 Bake de tests

[bake test]
  .needs app
  [run sh]
    .set "cmd" "target/out/app --selftest"
  ..
  .output exe "target/out/test.ok"
..

37.2 Tests par profile

steel run --profile debug --bake test
steel run --profile release --bake test

37.3 Tests en CI

Automatiser la sequence:

38. Tutoriel: conventions d equipe

38.1 Style steelconf

Recommandations:

38.2 Lint humain

Avant steel fmt, etablir une convention d equipe.

38.3 Revisions

Valider les changements MUF comme du code:

39. Tutoriel: extensions et limites

39.1 Runner minimal

Le runner actuel ne supporte pas toutes les directives MUF possibles.

39.2 Extensibilite

Les blocs et directives ont ete concus pour etre etendus sans casser la compatibilite.

39.3 Cas non couverts

40. Annexes supplementaires

40.1 Checklists par phase

Configuration:

Execution:

40.2 Memo MUF

40.3 Contacts et contribution

Voir CONTRIBUTING.md pour les regles de contribution.

Objectif: montrer un pipeline en deux etapes avec outputs intermediaires.

[bake compile]
  .make c_src cglob "src/**/*.c"
  [run cc]
    .takes c_src as "@args"
    .set "-std=c17" 1
    .emits obj as "-o"
  ..
  .output obj "target/out/app.o"
..

[bake link]
  .needs compile
  [run cc]
    .set "cmd" "gcc target/out/app.o -o target/out/app"
  ..
  .output exe "target/out/app"
..

41.2 Utiliser ar pour une lib statique

[bake ar]
  .needs compile
  [run ar]
    .set "cmd" "ar rcs target/out/lib.a target/out/app.o"
  ..
  .output lib "target/out/lib.a"
..

41.3 Conseils

42. Tutoriel: interoperabilite avec d autres langages

42.1 C + OCaml (conceptuel)

Steel peut orchestrer plusieurs tools:

42.2 Exemple de bakes paralleles

[bake ocaml]
  .make ml_src cglob "src/ocaml/*.ml"
  [run ocamlc]
    .takes ml_src as "@args"
    .emits obj as "-o"
  ..
  .output obj "target/out/ocaml.o"
..

[bake c]
  .make c_src cglob "src/c/*.c"
  [run cc]
    .takes c_src as "@args"
    .emits obj as "-o"
  ..
  .output obj "target/out/c.o"
..

42.3 Binaire final

[bake link]
  .needs ocaml
  .needs c
  [run cc]
    .set "cmd" "gcc target/out/ocaml.o target/out/c.o -o target/out/app"
  ..
  .output exe "target/out/app"
..

43. Tutoriel: conventions de nommage

43.1 Noms de bakes

Regles conseillees:

Exemples:

43.2 Noms de ports

Ports usuels:

43.3 Noms de tools

Preferer cc, cxx, ar, ld pour l intention.

44. Tutoriel: variables et templates

44.1 Variables globales

[workspace]
  .set cc "gcc"
  .set cflags "-Wall -Wextra"
..

44.2 Utilisation

  .set "${cflags}" 1

44.3 Garder la lisibilite

Eviter les chaines trop longues. Preferer plusieurs .set simples.

45. Tutoriel: macros d equipe (pattern)

45.1 Facteur commun

Exemple: un bake standard C.

[bake c_compile]
  .make c_src cglob "src/**/*.c"
  [run cc]
    .takes c_src as "@args"
    .set "-std=c17" 1
    .set "-O${opt}" 1
    .set "-g" "${debug}"
    .emits obj as "-o"
  ..
  .output obj "target/out/app.o"
..

45.2 Copier le pattern

Le but est de garder une structure stable et reconnaissable.

46. Tutoriel: fichiers generes

46.1 Outputs temporaires

Les outputs intermediaires doivent etre dans target/out.

46.2 Nettoyage

steel cache clear supprime les caches, pas les outputs. Utiliser un script externe pour nettoyer target/.

46.3 Regle d or

Ne pas melanger sources et outputs.

47. Tutoriel: CLI approfondie

47.1 Steel build

steel

47.2 Steel print

steel print

47.3 Steel check

steel check

48. Tutoriel: audit de config

48.1 Verifier la coherence

48.2 Comparer deux MFF

diff steelconfig.mff other/steelconfig.mff

48.3 Metriques simples

Nombre de bakes, nombre de sources, taille du log.

49. Tutoriel: migration d un build legacy

49.1 Etapes

1) lister les commandes actuelles 2) en faire des bakes 3) stabiliser les paths

49.2 Exemple Makefile -> Steel

gcc -c src/main.c -o target/out/main.o
gcc target/out/main.o -o target/out/app

Devient:

[bake compile]
  .make c_src cglob "src/main.c"
  [run cc]
    .takes c_src as "@args"
    .emits obj as "-o"
  ..
  .output obj "target/out/main.o"
..

[bake link]
  .needs compile
  [run cc]
    .set "cmd" "gcc target/out/main.o -o target/out/app"
  ..
  .output exe "target/out/app"
..

50. Conclusion du guide

Steel vise:

Ce guide peut etre etendu en fonction de l evolution du runner et des schemas.

51. Tutoriel: documentation projet interne

51.1 Documenter le build

Ajouter un court README:

51.2 Exemples reproduisibles

Fournir un exemple minimal qui compile sans configuration externe.

51.3 Mettre a jour

Synchroniser la doc avec les changements du steelconf.

52. Tutoriel: projets multi-binaries

52.1 Deux binaires

[bake app_one]
  .make c_src cglob "src/app1/*.c"
  [run cc]
    .takes c_src as "@args"
    .emits exe as "-o"
  ..
  .output exe "target/out/app_one"
..

[bake app_two]
  .make c_src cglob "src/app2/*.c"
  [run cc]
    .takes c_src as "@args"
    .emits exe as "-o"
  ..
  .output exe "target/out/app_two"
..

52.2 Execution ciblee

steel run --bake app_one
steel run --bake app_two

52.3 Execution globale

steel run --all

53. Tutoriel: organisation par dossiers

53.1 Convention de root

Le root doit contenir:

53.2 Sous-projets

Si plusieurs projets cohabitent, preferer un steelconf par projet.

53.3 Eviter les chemins absolus

Les chemins absolus cassent la portabilite.

54. Tutoriel: traitement des assets

54.1 Copier des fichiers

[bake assets]
  .make data cglob "assets/**/*"
  [run sh]
    .set "cmd" "cp -R assets target/out/assets"
  ..
  .output dir "target/out/assets"
..

54.2 Assets par profile

Utiliser une variable:

.set assets_dir "assets/${profile}"

54.3 Conseils

55. Tutoriel: gestion des includes

55.1 Include unique

.include "include"

55.2 Plusieurs includes

.include "src/lib"
.include "src/util"

55.3 Convention

Preferer un dossier include/ commun.

56. Tutoriel: debug et traces

56.1 Activer plus de verbosite

Utiliser -v sur la CLI.

56.2 Tracer une commande

Inspecter le log:

56.3 Reproduire hors Steel

Copier la commande et l executer manuellement pour isoler l erreur.

57. Tutoriel: compatibilite OS

57.1 Windows

Penser au suffixe .exe et aux paths.

57.2 macOS

Attention aux differences de toolchain.

57.3 Linux

Le comportement par defaut est teste sur Linux.

58. Tutoriel: conventions de logs

58.1 Stockage

Utiliser target/logs/ si besoin de plusieurs logs.

58.2 Nommage

target/logs/run_debug.mff
target/logs/run_release.mff

58.3 Archivage

Archiver les logs avec les artefacts en CI.

59. Tutoriel: verifications pre-release

59.1 Checklist

59.2 Nettoyage

Supprimer target/ avant une release propre.

59.3 Archive finale

Archiver dist/ et steelconfig.mff.

60. Annexes additionnelles

60.1 Exemple de structure finalisee

root/
  steelconf
  src/
  include/
  assets/
  target/
  dist/

60.2 Commandes essentielles

60.3 Rappel

Le format MUF reste la source, MFF est l artefact resolu.

61. Tutoriel: patterns de refactor

61.1 Extraire un bake commun

Quand plusieurs bakes se ressemblent, creer un bake modele et le copier.

61.2 Renommer sans casser

Renommer les bakes avec prudence:

61.3 Simplifier les ports

Garder des ports courts et explicites.

62. Tutoriel: gestion des sources

62.1 Sources par dossier

Decouper les globs par dossier pour garder un controle fin.

62.2 Exclure des fichiers

Eviter les fichiers generes dans les globs sources.

62.3 Stabilite

Les listes de fichiers doivent rester stables entre runs.

63. Tutoriel: conventions de paths

63.1 Paths relatifs

Toujours utiliser des paths relatifs au root.

63.2 Normalisation

Steel normalise les chemins avec /.

63.3 Depots multiples

Si un sous-projet est un submodule, preferer un steelconf separé.

64. Tutoriel: edition collaborative

64.1 Revue de steelconf

Considerer le steelconf comme du code critique.

64.2 Historique

Les diffs sur MUF sont lisibles et utiles.

64.3 Validation CI

Executer steel check en CI.

65. Tutoriel: logs et audit long terme

65.1 Logs persistants

Archiver les logs dans un dossier dedie.

65.2 Comparaison

Comparer les logs pour detecter des regressions de commandes.

65.3 Traçabilite

Associer un log a une version de steelconf.

66. Tutoriel: build reproductible

66.1 Sources propres

Nettoyer target/ avant un build de reference.

66.2 Versions fixes

Utiliser des toolchains versionnees.

66.3 MFF comme preuve

Archiver steelconfig.mff avec l artefact final.

67. Tutoriel: integrer des scripts

67.1 Utiliser un tool sh

[tool sh]
  .exec "sh"
..

67.2 Bake script

[bake script]
  [run sh]
    .set "cmd" "echo hello > target/out/hello.txt"
  ..
  .output file "target/out/hello.txt"
..

67.3 Prudence

Limiter les scripts pour conserver la reproductibilite.

68. Tutoriel: build multi-arch

68.1 Deux targets

steel
steel

68.2 Outputs separes

Utiliser target/${target} pour separer les artefacts.

68.3 Verifier les diffs

Comparer les steelconfig.mff par target.

69. Tutoriel: maintenir le guide

69.1 Version du format

Mettre a jour les sections MUF/MFF si le format evolue.

69.2 Roadmap

Ajouter des sections quand de nouvelles commandes arrivent.

69.3 Exemples

Garder des exemples courts et valides.

70. Annexes finales

70.1 Recap complet

70.2 Repertoire docs

Consulter:

70.3 Fin

Fin du guide et de la reference.

71. Tutoriel: discipline de versioning

71.1 Versionner le steelconf

Toujours committer le steelconf avec le code source.

71.2 Versionner le MFF

Archiver steelconfig.mff pour les builds importants.

71.3 Tagger les releases

Associer un tag git a un MFF archivé.

72. Tutoriel: bonnes pratiques de maintenance

72.1 Nettoyage periodique

Supprimer les anciens logs et outputs.

72.2 Audit des globs

Revoir les patterns pour eviter les inclusions accidentelles.

72.3 Revue des profiles

Supprimer les profiles obsoletes.

73. Tutoriel: ergonomie pour les nouveaux arrivants

73.1 README minimal

Documenter:

73.2 Scripts helper

Ajouter un script ./build.sh si besoin de simplifier.

73.3 Exemples

Fournir un exemple MUF minimal dans le repo.

74. Tutoriel: verification croisee

74.1 Comparer config et run

Verifier que le run correspond a la configuration resolue.

74.2 Verifier les chemins

Eviter les divergences entre target/ et dist/.

74.3 Consistance des tools

Utiliser les memes versions de tools en local et CI.

75. Tutoriel: build offline

75.1 Mode offline

Utiliser --offline pour eviter les acces reseau.

75.2 Tools locaux

Verifier que tout est present localement.

75.3 Logs

Archiver les logs pour audit.

76. Tutoriel: path mapping

76.1 Root stable

Garder un root stable facilite les diffs.

76.2 Paths relatifs

Toujours preferer des paths relatifs au root.

76.3 Normalisation

Eviter les separateurs OS dans les fichiers MUF.

77. Tutoriel: gestion des flags

77.1 Flags par profile

Conserver les flags dans les profiles:

[profile debug]
  .set cflags "-O0 -g"
..

77.2 Utilisation

.set "${cflags}" 1

77.3 Lisibilite

Eviter des lignes de flags trop longues.

78. Tutoriel: modularite

78.1 Decoupage logique

Un bake par responsabilite.

78.2 Reutilisation

Copier les patterns pour garder une structure uniforme.

78.3 Evolution

Ajouter des bakes sans casser les existants.

79. Tutoriel: compatibilite future

79.1 Garder le header

Toujours !muf 4 en tete.

79.2 Anticiper les changements

Lire la roadmap et adapter les exemples.

79.3 Compatibilite backward

Eviter les changements cassants dans les conventions internes.

80. Annexes supplementaires (fin)

80.1 Commandes resumees

80.2 Artefacts

80.3 Dernier rappel

Steel privilegie la stabilite et la lisibilite des configurations.