From e872a6c0b8febd9f18854b9cc78c35f6324716d9 Mon Sep 17 00:00:00 2001
From: Martin521 <29605222+Martin521@users.noreply.github.com>
Date: Mon, 1 Sep 2025 17:22:19 +0200
Subject: [PATCH 1/3] avoid artifact left-overs on error
---
src/Runfs/Build.fs | 22 ++++++++++++----------
src/Runfs/Runfs.fsproj | 7 +++----
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/src/Runfs/Build.fs b/src/Runfs/Build.fs
index 98e9d18..70cbdcb 100644
--- a/src/Runfs/Build.fs
+++ b/src/Runfs/Build.fs
@@ -6,7 +6,6 @@ open Microsoft.Build.Evaluation
open Microsoft.Build.Execution
open Microsoft.Build.Framework
open Microsoft.Build.Logging
-open Microsoft.Build.Locator
open System
open System.IO
open System.Xml
@@ -21,7 +20,7 @@ type Project =
type MSBuildError = MSBuildError of target: string * result: string
-let initMSBuild() = MSBuildLocator.RegisterDefaults() |> ignore
+let initMSBuild() = Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults() |> ignore
let createProject verbose projectFilePath (projectFileText: string) : Project =
let verbosity = if verbose then "m" else "q"
@@ -46,14 +45,17 @@ let createProject verbose projectFilePath (projectFileText: string) : Project =
// let projectInstance = ProjectInstance.FromProjectRootElement(projectRoot, options)
File.WriteAllText(projectFilePath, projectFileText)
- let projectInstance = ProjectInstance.FromFile(projectFilePath, options)
-
- let parameters = BuildParameters projectCollection
- parameters.Loggers <- loggers
- parameters.LogTaskInputs <- false
- let buildManager = BuildManager.DefaultBuildManager
- buildManager.BeginBuild parameters
- {buildManager = buildManager; projectInstance = projectInstance}
+ try
+ let projectInstance = ProjectInstance.FromFile(projectFilePath, options)
+ let parameters = BuildParameters projectCollection
+ parameters.Loggers <- loggers
+ parameters.LogTaskInputs <- false
+ let buildManager = BuildManager.DefaultBuildManager
+ buildManager.BeginBuild parameters
+ {buildManager = buildManager; projectInstance = projectInstance}
+ with ex ->
+ File.Delete projectFilePath
+ reraise()
let build target project =
let flags =
diff --git a/src/Runfs/Runfs.fsproj b/src/Runfs/Runfs.fsproj
index 9b846e1..c30bf52 100644
--- a/src/Runfs/Runfs.fsproj
+++ b/src/Runfs/Runfs.fsproj
@@ -36,11 +36,10 @@
+
-
+
+
\ No newline at end of file
From de6a1eb12b0351637338b7bfeb8ceda379ddc67c Mon Sep 17 00:00:00 2001
From: Martin521 <29605222+Martin521@users.noreply.github.com>
Date: Mon, 1 Sep 2025 17:24:22 +0200
Subject: [PATCH 2/3] change log
---
CHANGELOG.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 98c0711..e6aab80 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# CHANGELOG
+## 1.0.4
+
+### changed
+
+* Avoid artifact left-over in certain error situations
+
## 1.0.3
### changed
From 602565075f8fa47c38a145e9d190688bf70a4602 Mon Sep 17 00:00:00 2001
From: Martin521 <29605222+Martin521@users.noreply.github.com>
Date: Tue, 2 Sep 2025 14:24:47 +0200
Subject: [PATCH 3/3] virtual project file
---
CHANGELOG.md | 6 +++++
README.md | 8 ++-----
src/Runfs/Build.fs | 33 ++++++++++------------------
src/Runfs/ProjectFile.fs | 26 ++++++++++++++++++++++
src/Runfs/Runfs.fs | 16 +++++++-------
src/Runfs/Runfs.fsproj | 4 ++--
tests/Runfs.Tests/TestFiles/test1.fs | 2 --
7 files changed, 56 insertions(+), 39 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6aab80..e15c922 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# CHANGELOG
+## 1.0.5
+
+### changed
+
+* "Virtual" (in-memory) project file
+
## 1.0.4
### changed
diff --git a/README.md b/README.md
index 6dc9979..0a1028b 100644
--- a/README.md
+++ b/README.md
@@ -58,15 +58,11 @@ Main learnings
- A small compiler change is needed to allow for the directive format.
- The most important missing piece is editor support.
-Open items
-- I did not succeed yet in replicating the "virtual project file" approach. If I use the msbuild API's `BuildManager`, it doesn't find the sdk, probably because I am missing the right global build properties that `dotnet run` has available internally. I am not sure if there is a workaround. For now, I settled for a less nice file-based approach. Less nice because the script location must be writable.
-- Not sure yet if the "compile only" shortcut can easily be replicated for F#.
-
## TODOs
Runfs
-- investigate the open items: virtual project file, optimize the build step (cache core compile input beyond restore)
-- add more tests, automate publishing, possibly Rid-package, fix case sensitivity issue in Directives.fs
+- investigate if the "compile only" shortcut can be replicated for F#
+- add more tests, possibly Rid-package, fix case sensitivity issue in Directives.fs
- implement the #project, #source and #dll directives and `--convert`
Elsewhere
diff --git a/src/Runfs/Build.fs b/src/Runfs/Build.fs
index 70cbdcb..dfe50b9 100644
--- a/src/Runfs/Build.fs
+++ b/src/Runfs/Build.fs
@@ -27,9 +27,7 @@ let createProject verbose projectFilePath (projectFileText: string) : Project =
let loggerArgs = [|$"-verbosity:{verbosity}"; "-tl:off"; "NoSummary"|]
let consoleLogger = TerminalLogger.CreateTerminalOrConsoleLogger loggerArgs
let loggers = [|consoleLogger|]
- let globalProperties =
- dict [
- ]
+ let globalProperties = dict []
let projectCollection = new ProjectCollection(
globalProperties,
loggers,
@@ -38,24 +36,17 @@ let createProject verbose projectFilePath (projectFileText: string) : Project =
options.ProjectCollection <- projectCollection
options.GlobalProperties <- globalProperties
- // let reader = new StringReader(projectFileText)
- // let xmlReader = XmlReader.Create reader
- // let projectRoot = ProjectRootElement.Create(xmlReader, projectCollection)
- // projectRoot.FullPath <- projectFilePath
- // let projectInstance = ProjectInstance.FromProjectRootElement(projectRoot, options)
-
- File.WriteAllText(projectFilePath, projectFileText)
- try
- let projectInstance = ProjectInstance.FromFile(projectFilePath, options)
- let parameters = BuildParameters projectCollection
- parameters.Loggers <- loggers
- parameters.LogTaskInputs <- false
- let buildManager = BuildManager.DefaultBuildManager
- buildManager.BeginBuild parameters
- {buildManager = buildManager; projectInstance = projectInstance}
- with ex ->
- File.Delete projectFilePath
- reraise()
+ let reader = new StringReader(projectFileText)
+ let xmlReader = XmlReader.Create reader
+ let projectRoot = ProjectRootElement.Create(xmlReader, projectCollection)
+ projectRoot.FullPath <- projectFilePath
+ let projectInstance = ProjectInstance.FromProjectRootElement(projectRoot, options)
+ let parameters = BuildParameters projectCollection
+ parameters.Loggers <- loggers
+ parameters.LogTaskInputs <- false
+ let buildManager = BuildManager.DefaultBuildManager
+ buildManager.BeginBuild parameters
+ {buildManager = buildManager; projectInstance = projectInstance}
let build target project =
let flags =
diff --git a/src/Runfs/ProjectFile.fs b/src/Runfs/ProjectFile.fs
index 8a9a415..eea9551 100644
--- a/src/Runfs/ProjectFile.fs
+++ b/src/Runfs/ProjectFile.fs
@@ -59,5 +59,31 @@ let createProjectFileLines directives entryPointSourceFullPath artifactsPath ass
$""" """
" "
yield! sdks |> List.map (sdkLine "Sdk.targets")
+
+ $""" """
+ $""" """
+
+ $""" """
+ $""" """
+ $""" """
+ $""" """
+ $""" """
+
+ $""" """
+ $""" """
+ $""" <_RestoreProjectPathItems Include="@(FilteredRestoreGraphProjectInputItems)" /> """
+ $""" """
+ $""" """
+
+ $""" """
+ $""" """
+ $""" """
+
""
]
\ No newline at end of file
diff --git a/src/Runfs/Runfs.fs b/src/Runfs/Runfs.fs
index dffb70e..7ae69b8 100644
--- a/src/Runfs/Runfs.fs
+++ b/src/Runfs/Runfs.fs
@@ -107,7 +107,7 @@ let run (options, sourcePath, args) =
return computeDependenciesHash (string fullSourceDir) directives
}
- let! dependenciesChanged, sourceChanged, noExecutable = guardAndTime "computing build level" <| fun () ->
+ let! needsRestore, needsBuild = guardAndTime "computing build level" <| fun () ->
let dependenciesChanged =
if noDependencyCheck then
false
@@ -118,34 +118,34 @@ let run (options, sourcePath, args) =
let readPreviousSourceHash() = File.ReadAllText sourceHashPath
not (File.Exists sourceHashPath && readPreviousSourceHash() = sourceHash)
let noDll = not (File.Exists dllPath)
- Ok (dependenciesChanged, sourceChanged, noDll)
+ Ok (dependenciesChanged || noDll, sourceChanged)
- if dependenciesChanged || noExecutable then
+ if needsRestore then
do! guardAndTime "creating and writing project file" <| fun () ->
let projectFileLines = createProjectFileLines directives fullSourcePath artifactsDir AssemblyName
File.WriteAllLines(savedProjectFilePath, projectFileLines) |> Ok
- if dependenciesChanged || sourceChanged || noExecutable then
+ if needsRestore || needsBuild then
use! project = guardAndTime "creating msbuild project instance" <| fun () ->
let projectFileText = File.ReadAllText savedProjectFilePath
createProject verbose virtualProjectFilePath projectFileText |> Ok
- if dependenciesChanged || noExecutable then
+ if needsRestore then
do! guardAndTime "running msbuild restore" <| fun () -> result {
File.Delete dependenciesHashPath
do! build "restore" project |> Result.mapError BuildError
}
-
+
do! guardAndTime "running dotnet build" <| fun () -> result {
File.Delete sourceHash
do! build "build" project |> Result.mapError BuildError
}
- if dependenciesChanged then
+ if needsRestore then
do! guardAndTime "saving dependencies hash" <| fun () ->
File.WriteAllText(dependenciesHashPath, dependenciesHash) |> Ok
- if sourceChanged then
+ if needsBuild then
do! guardAndTime "saving source hash" <| fun () ->
File.WriteAllText(sourceHashPath, sourceHash) |> Ok
diff --git a/src/Runfs/Runfs.fsproj b/src/Runfs/Runfs.fsproj
index c30bf52..f020813 100644
--- a/src/Runfs/Runfs.fsproj
+++ b/src/Runfs/Runfs.fsproj
@@ -2,7 +2,7 @@
Runfs
- 1.0.4
+ 1.0.5
"dotnet run app.cs" functionality for F#.
Copyright 2025 by Martin521
Martin521 and contributors
@@ -19,7 +19,7 @@
MIT
-
+ README.md
diff --git a/tests/Runfs.Tests/TestFiles/test1.fs b/tests/Runfs.Tests/TestFiles/test1.fs
index cac4644..fc3b416 100644
--- a/tests/Runfs.Tests/TestFiles/test1.fs
+++ b/tests/Runfs.Tests/TestFiles/test1.fs
@@ -13,5 +13,3 @@ printfn $"args: {args}"
// let RuntimeVersion = Environment.Version
// printfn $"Runtime version: {RuntimeVersion}"
-
-