简体   繁体   中英

ProjectCracker with .netstandard 2.0 projects

My team has recently switched from using .net framework to use .net standard 2.0 for our F# libraries. We have some internal scripts that we run on our projects to automatically generate markdown documentation, and these scripts use the F# Compiler Services SDK to analyze the code and retrieve the type metadata, documentation comments, etc.

We are using the FSharp.Compiler.Service.ProjectCracker library to read our .fsproj files and generate the FSharpProjectOptions instance to use when running the FSharpChecker.ParseAndCheckFileInProject method. However, with the .net standard projects, we get the following error when calling ProjectCracker.GetProjectOptionsFromProjectFile :

System.Exception: Could not load project Example.fsproj in ProjectCollection. 
Available tools: 
["C:\Program Files (x86)\MSBuild\12.0\bin\amd64";
 "C:\Program Files (x86)\MSBuild\14.0\bin\amd64";
 "C:\Windows\Microsoft.NET\Framework64\v2.0.50727";
 "C:\Windows\Microsoft.NET\Framework64\v3.5";
 "C:\Windows\Microsoft.NET\Framework64\v4.0.30319"]. 

Message: The default XML namespace of the project must be the MSBuild XML namespace. 
If the project is authored in the MSBuild 2003 format, please add xmlns="http://schemas.microsoft.com/developer/msbuild/2003" to the <Project> element. 
If the project has been authored in the old 1.0 or 1.2 format, please convert it to MSBuild 2003 format.```

Is there any way to read .net standard project files using the Project Cracker library, or will we need to manually parse the file and create the FSharpProjectOptions by hand for our new libraries?

It appears that the standard ProjectCracker package cannot be used to read .netstandard project files. However, there is already a NuGet package available to provide this functionality, Dotnet.ProjInfo . This project allows you to read all the variations of .NET project files, including .NET Framework and .NET Core, as well as both project.json and .csproj/.fsproj files.

The project isn't extremely well documented as an API (the documentation is better for the command-line tool), but programmatic usage of the tool can be seen in the FsAutoComplete library .

For a .netstandard project, you can use the getProjectInfos function, like so:

let getProjectInfo additionalMSBuildProps file =
    let projDir = Path.GetDirectoryName file
    let additionalInfo = 
            [ "OutputType"
              "IsTestProject"
              "Configuration"
              "IsPackable"
              MSBuildKnownProperties.TargetFramework
              "TargetFrameworkIdentifier"
              "TargetFrameworkVersion"
              "MSBuildAllProjects"
              "ProjectAssetsFile"
              "RestoreSuccess"
              "Configurations"
              "TargetFrameworks"
              "RunArguments"
              "RunCommand"
              "IsPublishable"
            ]

    let loggedMessages = System.Collections.Concurrent.ConcurrentQueue<string>()
    let msBuildExec = Dotnet.ProjInfo.Inspect.msbuild (Dotnet.ProjInfo.Inspect.MSBuildExePath.DotnetMsbuild "dotnet") (fun exePath args -> Utils.runProcess loggedMessages.Enqueue projDir exePath (args |> String.concat " "))
    let gp () = Dotnet.ProjInfo.Inspect.getProperties (["TargetPath"; "IsCrossTargetingBuild"; "TargetFrameworks"] @ additionalInfo)

    let additionalArgs = additionalMSBuildProps |> List.map (Dotnet.ProjInfo.Inspect.MSBuild.MSbuildCli.Property)

    let cliList = [Dotnet.ProjInfo.Inspect.getFscArgs; Dotnet.ProjInfo.Inspect.getResolvedP2PRefs; gp]

    file |> Dotnet.ProjInfo.Inspect.getProjectInfos loggedMessages.Enqueue msBuildExec cliList additionalArgs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM