Skip to content

Add an opt-in to write the generated lexer and parser to obj - #255

Merged
nojaf merged 4 commits into
fsprojects:masterfrom
nojaf:fix-247
Sep 24, 2026
Merged

nojaf merged 4 commits into
fsprojects:masterfrom
nojaf:fix-247

Conversation

@nojaf

@nojaf nojaf commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

MSBuild only honours FileWrites under the output or intermediate folder, so the registration that was meant to let dotnet clean remove the generated .fs and .fsi never took effect: by default they land next to the grammar, outside both folders.

FsLexYaccOutputToIntermediate=true now defaults FsLexOutputFolder and FsYaccOutputFolder to IntermediateOutputPath, so clean removes the generated sources and they stay out of the source tree. Projects reference them as $(FsLexOutputFolder)Lexer.fs and $(FsYaccOutputFolder)Parser.fs(i). Because every existing project references Parser.fs next to Parser.fsy, this is opt-in for now and becomes the default in the next major version.

The defaults are resolved at evaluation time so the properties can be used in Compile items, which requires the targets to be imported after the SDK targets, as the NuGet package does. A project that imports the targets file from its body would otherwise get Compile items that silently point next to the grammar, so FsLexYaccCheckOutputFolders fails the build with an error that explains the cause and the fix.

JsonLexAndYaccExample opts in to cover the new mode, and imports the SDK explicitly so the targets evaluate the way a package consumer sees them. LexAndYaccMiniProject keeps the default so both modes stay covered.

Release as 12.2.0.

Closes #247

MSBuild only honours FileWrites under the output or intermediate folder, so
the registration that was meant to let `dotnet clean` remove the generated
.fs and .fsi never took effect: by default they land next to the grammar,
outside both folders.

FsLexYaccOutputToIntermediate=true now defaults FsLexOutputFolder and
FsYaccOutputFolder to IntermediateOutputPath, so clean removes the generated
sources and they stay out of the source tree. Projects reference them as
$(FsLexOutputFolder)Lexer.fs and $(FsYaccOutputFolder)Parser.fs(i). Because
every existing project references Parser.fs next to Parser.fsy, this is
opt-in for now and becomes the default in the next major version.

The defaults are resolved at evaluation time so the properties can be used
in Compile items, which requires the targets to be imported after the SDK
targets, as the NuGet package does. A project that imports the targets file
from its body would otherwise get Compile items that silently point next to
the grammar, so FsLexYaccCheckOutputFolders fails the build with an error
that explains the cause and the fix.

JsonLexAndYaccExample opts in to cover the new mode, and imports the SDK
explicitly so the targets evaluate the way a package consumer sees them.
LexAndYaccMiniProject keeps the default so both modes stay covered.

Release as 12.2.0.

Closes fsprojects#247
@nojaf
nojaf requested a review from baronfel September 16, 2026 13:13
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@baronfel baronfel left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, and as we discussed I would just go ahead and change defaults to emit the files to the Intermediate locations. MSBuild Targets are (by convention) expected to not pollute the source tree because it can lead to circularity and all kinds of fun, subtle issues during the build.

MSBuild targets are expected to stay out of the source tree, since writing
there invites circularity and subtle build issues. FsLexOutputFolder and
FsYaccOutputFolder now default to IntermediateOutputPath, so the generated
.fs and .fsi stay out of the source tree and `dotnet clean` removes them.
FsLexYaccOutputToIntermediate=false keeps the previous behaviour of writing
them next to the grammar.

A project written for the old default compiles Parser.fs next to
Parser.fsy. After the upgrade that copy is no longer regenerated, so the
build would silently keep compiling a stale file. FsLexYaccCheckOutputFolders
now fails the build in that case and explains how to reference the
generated files or opt out. Its existing error for importing the targets
before the SDK now also points at the opt-out.

JsonLexAndYaccExample covers the new default and LexAndYaccMiniProject
opts out, so both modes stay covered.

Release as 13.0.0.
@nojaf
nojaf merged commit 0598398 into fsprojects:master Sep 24, 2026
5 checks passed
@nojaf
nojaf deleted the fix-247 branch September 24, 2026 20:25
@nojaf
nojaf restored the fix-247 branch September 25, 2026 06:35
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.

Generate fslex/fsyacc output into the intermediate folder so dotnet clean removes it

3 participants