Skip to content

build: run build.fsx with dotnet fsi instead of the FAKE runner - #4422

Merged
fpellet merged 2 commits into
masterfrom
build/run-build-with-fsi
Aug 31, 2026
Merged

build: run build.fsx with dotnet fsi instead of the FAKE runner#4422
fpellet merged 2 commits into
masterfrom
build/run-build-with-fsi

Conversation

@fpellet

@fpellet fpellet commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

First step towards #4348.

The build is started through mono packages/build/FAKE/tools/FAKE.exe, a .NET Framework
executable. That runner is what forces Mono on Linux, pulls in the legacy MSBuild discovery and
the obsolete RoslynTools.MSBuild path behind #4002, and has to stay in step with the .NET SDK.

The problem is the runner, not the library. So this PR only changes how the script is started:
build.fsx stays the same FAKE 4.64.17 script, but runs under dotnet fsi.

Upgrading to FAKE 6 is deliberately left for later: it would mean rewriting the ~730 lines of the
script (every API is renamed), replacing Octokit.fsx with Fake.Api.GitHub and moving the GitHub
release to a token. None of that is needed to drop the runner.

Changes

  • build.sh / build.cmd call dotnet fsi build.fsx. The Mono-specific certmgr / mozroots
    diagnostics block goes away, as does the RoslynTools.MSBuild line (that package is not even in
    paket.dependencies any more).
  • build.fsx gains ~10 lines: without the runner the script has to parse its own command line, so
    it translates <Target> key=value ... into the environment variables FAKE reads back through
    getBuildParam / hasBuildParam. It runs before any other binding, because top-level values such
    as testSuiteFilterFlakyTests read build parameters while the script loads.
  • build.fsx drops the ServicePointManager.SecurityProtocol assignment. It enabled TLS 1.2 on old
    runtimes and now throws NotSupportedException on .NET 10, since it also requests SSL3.
  • Documentation updated. CLAUDE.md's skip examples are corrected on the way: skip switches are
    build parameters, not targets, so they take a value and follow the target name — the documented
    build.cmd SkipTests was read as a target name and never worked.

No change to paket.dependencies / paket.lock, to the targets, to the produced artifacts, to the
target frameworks, or to ci.yml.

What this does not do

Mono is still installed and still required, for the targets that execute .NET Framework binaries:
MergePaketTool (which runs ILRepack.exe) and the net461 test passes. FAKE keeps prefixing those
with mono on its own, so they needed no change. Removing that is the next step.

Validation

Run on Linux, .NET SDK 10.0.400:

  • dotnet fsi build.fsx CleanDocs — target selection works, only that target runs.
  • dotnet fsi build.fsx Build — OK.
  • dotnet fsi build.fsx Publish — OK, produces bin/net461/paket.exe, bin/net10.0/paket.dll,
    bin_bootstrapper/net461/paket.bootstrapper.exe, bin_bootstrapper/net10.0/paket.bootstrapper.dll.
  • dotnet fsi build.fsx MergePaketTool — OK, including RunTests through the target graph.
    bin/merged/paket.exe is produced and runs: Paket version 11.0.0-alpha001.

Worth a look on Windows CI, since build.cmd under dotnet fsi could not be exercised locally.

Also checked while porting: FakeLib.dll (which targets .NETFramework,Version=v4.5) loads fine
under .NET 10, as do #load of Octokit.fsx and the #r of the GAC assemblies at the top of the
script; isMono still evaluates to true on Linux, so the not isMono guards keep the exact same
"not Windows" meaning as before.

Follow-ups for #4348

  1. Replace ILRepack.exe with the dotnet-ilrepack tool and restrict the net461 test passes to
    Windows — only then can Install Mono leave ci.yml.
  2. Move FAKE 4 to FAKE 6 as a library. Note for whoever does it: DotNet.test defaults to
    Configuration = Debug in FAKE 6 while build/publish/pack default to Release, so with
    --no-build the tests would look in bin/Debug.
  3. Documentation generation still runs on FAKE 4 and FSharp.Formatting 3 (the package only ships
    lib/net40), which is why FAKE < 5 stays in the Build group.

The build was started through `mono packages/build/FAKE/tools/FAKE.exe`, a
.NET Framework executable. That runner is what forced Mono on Linux, pulled in
the legacy MSBuild discovery, and had to stay in step with the .NET SDK.

Run the script with `dotnet fsi` instead. FAKE 4.64.17 is now used as a library
only: build.fsx itself, its targets and the produced artifacts are unchanged.

Without the runner the script has to parse its own command line, so translate
`<Target> key=value ...` into the environment variables FAKE reads back through
getBuildParam/hasBuildParam. This happens before any other binding, since
top-level values such as testSuiteFilterFlakyTests read build parameters while
the script loads.

Also drop the ServicePointManager.SecurityProtocol assignment: it enabled TLS
1.2 on old runtimes and now throws NotSupportedException on .NET 10, because it
also requests SSL3.

Mono is still required for the targets that execute .NET Framework binaries,
namely MergePaketTool (ILRepack) and the net461 test passes; FAKE keeps
prefixing those with mono on its own.

Refs #4348
State that build.cmd and build.sh run build.fsx with dotnet fsi and that FAKE
is used as a library, so no runner has to be installed and its version no
longer has to match the SDK. Keep saying that Mono is still needed on Linux,
but narrow it to what actually needs it: MergePaketTool and the net461 test
passes.

Fix the skip examples in CLAUDE.md along the way. Skip switches are build
parameters, not targets, so they take a value and follow the target name; the
documented `build.cmd SkipTests` was read as a target name and never worked.

Refs #4348
@fpellet
fpellet merged commit 957f67f into master Aug 31, 2026
10 checks passed
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