Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 7, 2026

Move Bootstrap Logic into MSBuild Targets - COMPLETE ✅

Successfully implemented automatic bootstrap execution via MSBuild targets, making dotnet build FSharp.sln work without scripts.

Changes Made:

  • Created eng/targets/Bootstrap.targets with automatic bootstrap detection and execution
  • Modified Directory.Build.targets to import Bootstrap.targets
  • Modified proto.proj to add telemetry property for AzDO error categorization
  • Simplified .github/workflows/copilot-setup-steps.yml to use direct dotnet commands
  • Simplified .github/copilot-instructions.md to remove bootstrap detection logic
  • Fixed: Skip bootstrap for projects under artifacts/ to prevent test conflicts

Latest Fix (commit 3f0a7c9):

Added condition to skip bootstrap for any project under the artifacts/ directory. This prevents temporary test projects (created in artifacts/Temp/) from triggering bootstrap builds, which was causing resource conflicts and build failures during test execution.

Skip conditions now include:

  • Configuration=Proto (we ARE the bootstrap)
  • BUILDING_USING_DOTNET=true (FCS solution uses SDK compiler)
  • DisableCompilerRedirection=true (user wants SDK compiler)
  • MSBuildProjectDirectory under artifacts/ (test/temp projects, build outputs)

Validation:

✅ Bootstrap auto-execution for source projects
✅ Bootstrap skip for subsequent builds
✅ FSharp.Compiler.Service.sln uses SDK (no bootstrap)
✅ Error handling with proper MSBuild errors
✅ Script compatibility maintained
Test projects skip bootstrap (no conflicts)

Original prompt

Summary

Move bootstrap logic into MSBuild targets so that dotnet build FSharp.sln works without scripts, bootstrap runs automatically when needed, bootstrap output is minimal on success, and bootstrap errors surface as proper MSBuild errors.


Goals

  • dotnet build FSharp.sln works without scripts
  • dotnet test <project> works without scripts
  • Bootstrap runs automatically on first build (if missing)
  • Bootstrap errors surface as proper MSBuild errors (fail-fast, CI-visible)
  • Bootstrap output is silent on success
  • Existing scripts remain unchanged and functional
  • Existing FSharp.Compiler.Service.sln behavior unchanged (uses SDK compiler, no bootstrap)

Changes Required

1. Create eng/targets/Bootstrap.targets (New File)

Create a new MSBuild targets file (~50-80 lines) with the following structure:

Properties to define:

  • BootstrapDir = $(ArtifactsDir)Bootstrap\
  • FsLexBootstrapPath = $(BootstrapDir)fslex\fslex.dll
  • FsYaccBootstrapPath = $(BootstrapDir)fsyacc\fsyacc.dll
  • FscBootstrapPath = $(BootstrapDir)fsc\fsc.dll
  • _SkipBootstrap = true when any of:
    • $(Configuration) == Proto
    • $(DisableCompilerRedirection) == true
    • $(BUILDING_USING_DOTNET) == true

Target: _CheckBootstrapNeeded

  • Runs BeforeTargets="Restore;Build"
  • Condition: '$(_SkipBootstrap)' != 'true'
  • Sets _BootstrapNeeded=true if any of FsLexBootstrapPath, FsYaccBootstrapPath, FscBootstrapPath do not exist
  • Calls _RunBootstrap if _BootstrapNeeded=true

Target: _RunBootstrap

  • Emits <Message Text="Building bootstrap compiler..." Importance="high" />
  • Executes: dotnet publish "$(RepoRoot)proto.proj" -c Proto -v:minimal /clp:NoSummary;ErrorsOnly
  • Captures exit code
  • On failure: <Error Text="Bootstrap build failed. Check output above." />
  • On success: <Message Text="Bootstrap complete." Importance="high" />

Target: RebuildBootstrap

  • Deletes $(BootstrapDir)
  • Calls _RunBootstrap

2. Modify Directory.Build.targets

Add one import line (before other imports):

<Import Project="eng/targets/Bootstrap.targets" Condition="'$(DISABLE_ARCADE)' != 'true'" />

3. Modify proto.proj

Add default verbosity and telemetry properties for proper AzDO error categorization:

<PropertyGroup>
  <NETCORE_ENGINEERING_TELEMETRY>Bootstrap</NETCORE_ENGINEERING_TELEMETRY>
</PropertyGroup>

4. Simplify .github/workflows/copilot-setup-steps.yml

Replace current setup steps with:

steps:
  - uses: actions/checkout@v4
  - uses: actions/setup-dotnet@v4
    with:
      global-json-file: global.json
  - name: Restore
    run: |
      dotnet restore FSharp.sln || true
      dotnet restore LSPSolutionSlim.sln || true
      dotnet tool restore || true

Note: || true is intentional—setup must succeed so the agent can start. Errors surface when the agent builds.

5. Simplify .github/copilot-instructions.md

Replace Section 1 (Core Command) and Section 2 (Bootstrap) with:

## 1. Build

dotnet build FSharp.sln -c Release


## 2. Test

dotnet test tests/FSharp.Compiler.ComponentTests -c Release
dotnet test tests/FSharp.Compiler.Service.Tests -c Release

Remove all bootstrap detection logic from Section 2 (the "Two-phase build" and "Error building tools" detection instructions).


Edge Cases to Handle

Case Expected Behavior
FSharp.Compiler.Service.sln BUILDING_USING_DOTNET=true auto-set by existing props → _SkipBootstrap=true → no bootstrap, uses SDK compiler. Unchanged behavior.
Configuration=Proto _SkipBootstrap=true → no bootstrap (we ARE the bootstrap). Unchanged behavior.
DisableCompilerRedirection=true _SkipBootstrap=true → no bootstrap, uses SDK compiler. Unchanged behavior.
Bootstrap already exists _CheckBootstrapNeeded sees fsc.dll exists → skips _RunBootstrap. Idempotent.
Scripts (build.sh) used Scripts build bootstrap first (existing logic), then MSBuild runs, Bootstrap.targets sees artifacts exist → skips. Both paths converge.
Bootstrap fails <Error> task fires → MSBuild stops → CI shows red error annotation. No cryptic downstream errors.
Force bootstrap rebuild User runs dotnet build /t:RebuildBootstrap or deletes artifacts/Bootstrap/.

Validation

  1. Delete artifacts/Bootstrap/ folder
  2. Run dotnet build FSharp.sln -c Release
  3. Verify: Bootstrap runs automatically with minimal output ("Building bootstrap compiler..." and "Bootstrap complete.")
  4. Run dotnet build FSharp.sln -c Release again
  5. Verify: Bootstrap is skipped (no bootstrap messages)
  6. Run dotnet build FSharp.Compiler.Service.sln
  7. Verify: No bootstrap runs (uses SDK compiler)
  8. Introduce an error in proto.proj (e.g., invalid syntax)
  9. Run dotnet build FSharp.sln -c Release
  10. Verify: Clear error message, build stops immediately

This pull request was created from Copilot chat.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits January 7, 2026 12:30
- Created eng/targets/Bootstrap.targets with automatic bootstrap detection
- Updated Directory.Build.targets to import Bootstrap.targets
- Updated proto.proj with NETCORE_ENGINEERING_TELEMETRY property
- Simplified .github/workflows/copilot-setup-steps.yml
- Updated .github/copilot-instructions.md with new build/test commands

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
- Removed invalid /clp parameter from dotnet publish command
- Tested bootstrap auto-detection and execution
- Verified bootstrap skip on subsequent builds
- Verified FSharp.Compiler.Service.sln doesn't trigger bootstrap
- Verified error handling with proper MSBuild error messages

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copilot AI changed the title [WIP] Move bootstrap logic into MSBuild targets for automatic handling Move bootstrap logic into MSBuild targets Jan 7, 2026
Copilot AI requested a review from T-Gro January 7, 2026 13:05
@T-Gro
Copy link
Member

T-Gro commented Jan 7, 2026

@copilot :

Tests, which are internally also triggering builds of test projects, now also launch bootstrap and it leads to conflicts and resource exhaustion.

[xUnit.net 00:10:16.41] Miscellaneous.FsharpSuiteMigrated_TypeCheckTests.type check neg29 [SKIP]
Skipped Miscellaneous.FsharpSuiteMigrated_TypeCheckTests.type check neg29 [1 ms]
Failed FSharp.Tests.Core+RegressionTests.OverloadResolution-bug-FSI [7 m 10 s]
Error Message:
Error running command 'dotnet.exe' with args 'build /t:RunFSharpScriptAndPrintOutput' in directory 'D:\a_work\1\s\artifacts\Temp\FSharp.Test.Utilities\8f223d4b\7b10edfd\regression\OverloadResolution-bug'. ERRORLEVEL 1
Stack Trace:
at TestFramework.checkResultPassed(CmdResult result) in D:\a_work\1\s\tests\FSharp.Test.Utilities\TestFramework.fs:line 427
at TestFramework.execBothToOutCheckPassed@587.Invoke(String x)
at SingleTest.executeFsi@277.Invoke(String testCompilerVersion, String targetFramework) in D:\a_work\1\s\tests\fsharp\single-test.fs:line 282
at SingleTest.executeSingleTestBuildAndRun@231.Invoke(OutputType outputType, String compilerType, String targetFramework, Boolean optimize, Boolean buildOnly) in D:\a_work\1\s\tests\fsharp\single-test.fs:line 283
at SingleTest.singleTestBuildAndRunCore(TestConfig cfg, String copyFiles, Permutation p, String languageVersion) in D:\a_work\1\s\tests\fsharp\single-test.fs:line 288
at SingleTest.singleTestBuildAndRunAux(TestConfig cfg, Permutation p) in D:\a_work\1\s\tests\fsharp\single-test.fs:line 318
at SingleTest.singleTestBuildAndRun(String dir, Permutation p) in D:\a_work\1\s\tests\fsharp\single-test.fs:line 326
at FSharp.Tests.Core.RegressionTests.OverloadResolution-bug-FSI() in D:\a_work\1\s\tests\fsharp\tests.fs:line 1637
at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Standard Output Messages:
dotnet.exe build /t:RunFSharpScriptAndPrintOutput 1>D:\a_work\1\s\artifacts\Temp\FSharp.Test.Utilities\8f223d4b\7b10edfd\regression\OverloadResolution-bug\buildoutput.txt 2>1
Determining projects to restore...
Building bootstrap compiler...
Determining projects to restore...
All projects are up-to-date for restore.
Determining projects to restore...
All projects are up-to-date for restore.
Determining projects to restore...
All projects are up-to-date for restore.
Determining projects to restore...
All projects are up-to-date for restore.
Determining projects to restore...
All projects are up-to-date for restore.
FSharp.Core -> D:\a_work\1\s\artifacts\bin\FSharp.Core\Proto\netstandard2.0\FSharp.Core.dll
D:\a_work\1\s\eng\restore\optimizationData.targets(17,5): warning MSB3026: Could not copy "D:\a_work\1\s.packages\optimization.windows_nt-arm64.mibc.runtime\1.0.0-prerelease.25502.1\data\DotNet_FSharp.mibc" to "D:\a_work\1\s\artifacts\mibc\optimization.linux-arm64.mibc.runtime\DotNet_FSharp.mibc". Beginning retry 1 in 1000ms. The process cannot access the file 'D:\a_work\1\s\artifacts\mibc\optimization.linux-arm64.mibc.runtime\DotNet_FSharp.mibc' because it is being used by another process. [D:\a_work\1\s\artifacts\Temp\FSharp.Test.Utilities\8f223d4b\7b10edfd\regression\OverloadResolution-bug\44e3c18e-37f5-445e-a25e-2edee3195861.tmp.fsproj]
fslex -> D:\a_work\1\s\artifacts\bin\fslex\Proto\net10.0\win-x64\fslex.dll
fslex -> D:\a_work\1\s\artifacts\Bootstrap\fslex
FSharp.Core -> D:\a_work\1\s\artifacts\bin\FSharp.Core\Proto\netstandard2.0\FSharp.Core.dll
fsyacc -> D:\a_work\1\s\artifacts\bin\fsyacc\Proto\net10.0\win-x64\fsyacc.dll
fsyacc -> D:\a_work\1\s\artifacts\Bootstrap\fsyacc
FSharp.Core -> D:\a_work\1\s\artifacts\bin\FSharp.Core\Proto\netstandard2.0\FSharp.Core.dll
AssemblyCheck -> D:\a_work\1\s\artifacts\bin\AssemblyCheck\Proto\net10.0\win-x64\AssemblyCheck.dll
AssemblyCheck -> D:\a_work\1\s\artifacts\Bootstrap\AssemblyCheck
FSharp.Core -> D:\a_work\1\s\artifacts\bin\FSharp.Core\Proto\netstandard2.0\FSharp.Core.dll
FSharp.DependencyManager.Nuget -> D:\a_work\1\s\artifacts\bin\FSharp.DependencyManager.Nuget\Proto\netstandard2.0\FSharp.DependencyManager.Nuget.dll
C:\Program Files\dotnet\sdk\10.0.100\FSharp\Microsoft.FSharp.Targets(354,9): error MSB6006: "dotnet.exe" exited with code -1. [D:\a_work\1\s\src\Compiler\FSharp.Compiler.Service.fsproj::TargetFramework=netstandard2.0] [D:\a_work\1\s\artifacts\Temp\FSharp.Test.Utilities\8f223d4b\7b10edfd\regression\OverloadResolution-bug\44e3c18e-37f5-445e-a25e-2edee3195861.tmp.fsproj]
D:\a_work\1\s\eng\targets\Bootstrap.targets(71,5): error : Bootstrap build failed. Check output above. [D:\a_work\1\s\artifacts\Temp\FSharp.Test.Utilities\8f223d4b\7b10edfd\regression\OverloadResolution-bug\44e3c18e-37f5-445e-a25e-2edee3195861.tmp.fsproj]

Fixes issue where test projects in artifacts/Temp trigger bootstrap build,
causing resource conflicts. Projects under artifacts/ now skip bootstrap
since they are build outputs/temporary projects, not source code.

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 7, 2026

@copilot :

Tests, which are internally also triggering builds of test projects, now also launch bootstrap and it leads to conflicts and resource exhaustion.
...

Fixed in commit 02fff16. Added skip condition for projects under artifacts/ directory to prevent test/temp projects from triggering bootstrap. Test projects in artifacts/Temp/ will now skip bootstrap automatically, avoiding resource conflicts.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2026

✅ No release notes required

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

2 participants