Skip to content

[Beam] Generate rebar3 project scaffold automatically#4387

Merged
dbrattli merged 5 commits intomainfrom
dbrattli/beam-rebar3
Mar 7, 2026
Merged

[Beam] Generate rebar3 project scaffold automatically#4387
dbrattli merged 5 commits intomainfrom
dbrattli/beam-rebar3

Conversation

@dbrattli
Copy link
Collaborator

@dbrattli dbrattli commented Mar 7, 2026

Summary

When Fable compiles F# to Erlang/BEAM, it now generates a complete, immediately buildable rebar3 project structure as a side effect of compilation — no extra steps required.

What's generated

  • .erl files are placed in src/ (project) and fable_modules/<dep>/src/ (libraries), following rebar3 conventions
  • rebar.config with {project_app_dirs, [".", "fable_modules/*"]} so rebar3 treats each NuGet dep as a sub-app
  • src/<project>.app.src for the root application
  • fable_modules/<dep>/src/<app>.app.src and rebar.config for each dependency

Design

  • Always-on for BEAM — no flags needed
  • Stateless — runs after every successful compilation; correct in watch mode
  • Idempotent — files with a %% Generated by Fable - safe to regenerate marker are always refreshed; user-written rebar.config without the marker is left alone (warning emitted)
  • OTP namingFable.Logging.0.10.0fable_logging, fable-library-beamfable_library_beam

Test runner

./build.sh test beam now uses rebar3 compile instead of manual erlc invocations, validating the scaffold end-to-end. All 2247 tests pass.

Test plan

  • dotnet build src/Fable.Cli/Fable.Cli.fsproj — builds cleanly
  • ./build.sh test beam — all 2247 tests pass via rebar3
  • Validated on a real Giraffe/Cowboy project (fable.giraffe repo)

🤖 Generated with Claude Code

dbrattli and others added 5 commits March 7, 2026 08:54
When compiling to Erlang/BEAM, Fable now generates a complete rebar3
project structure alongside the .erl files:

- .erl files are placed in src/ (project files) and
  fable_modules/<dep>/src/ (library files), following rebar3 conventions
- rebar.config is generated with project_app_dirs pointing to
  fable_modules/* so rebar3 treats each NuGet dep as a sub-app
- Each dep gets src/<app>.app.src and rebar.config (idempotent,
  regenerated if Fable-generated marker is present)
- The root project gets src/<project>.app.src

The scaffold is generated after every successful BEAM compilation,
making it stateless and watch-mode-safe. Existing rebar.config files
without the Fable marker are left untouched (warning emitted).

The test runner is updated to use `rebar3 compile` instead of manual
erlc invocations, validating the scaffold end-to-end.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…README

The beam test runner now uses rebar3 to compile the generated scaffold.
Add rebar3-version to the erlef/setup-beam action so it is available
on the CI runner, and document Erlang/OTP + rebar3 as requirements.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ctName, log rebar.config updates

- Extract `Pipeline.Beam.normalizeAppName` as single source of truth for OTP app name normalization; use it in both `deriveDepAppName` and `compilationCycle` (fixes missing `.Trim('_')` at call site)
- Compute `testProjectName` in `Test/Beam.fs` from the project filename instead of hardcoding `"fable_tests_beam"`
- Log `[BEAM] Updated rebar.config` when the generated file changes content (not just on first creation)
- Update CHANGELOG

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…language check first

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dbrattli dbrattli merged commit 7766c49 into main Mar 7, 2026
23 checks passed
@dbrattli dbrattli deleted the dbrattli/beam-rebar3 branch March 7, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant