aspnet / RoslynCodeDomProvider

Roslyn CodeDOM provider
MIT License
84 stars 42 forks source link

CSharpCodeProvider doesn't support other then Web projects #38

Closed evil-shrike closed 6 years ago

evil-shrike commented 6 years ago

I understand that RoslynCodeDomProvider is part of ASP.NET ecosystem. But it's presented as a provider for CodeDom. Even package name has nothing to do with asp.net - Microsoft.CodeDom.Providers.DotNetCompilerPlatform. So it seems totally legit to expect that CSharpCodeProvider will work in non ASP.NET projects, right? But it doesn't.

Rebuilding a solution where Microsoft.CodeDom.Providers.DotNetCompilerPlatform package is installed in one of projects results in error MSB4044: The "KillProcess" task was not given a value for the required parameter "ImagePath".
Double click on the error leads to Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props:

  <Target Name = "KillVBCSCompilerAndRetryCopy" AfterTargets="CopyRoslynCompilerFilesToOutputDirectory" Condition="'$(MSBuildLastTaskResult)' == 'False'" >
    <KillProcess ProcessName="VBCSCompiler" ImagePath="$(WebProjectOutputDir)" />
    <Copy SourceFiles="@(RoslyCompilerFiles)" DestinationFolder="$(WebProjectOutputDir)\bin\roslyn" ContinueOnError="true" SkipUnchangedFiles="true" />
    <ItemGroup>
      <FileWrites Include="$(WebProjectOutputDir)\bin\roslyn\*" />
    </ItemGroup>
  </Target>

It seems that the issue can be fixed by addint Condition to KillProcess task:

    <KillProcess ProcessName="VBCSCompiler" ImagePath="$(WebProjectOutputDir)" Condition="'$(WebProjectOutputDir)' != ''" />
evil-shrike commented 6 years ago

Another issue (though I'm not sure that it depends on a project type) is that csc.exe isn't copied into output folder so runtime compilation doesn't work - it fails with error System.IO.DirectoryNotFoundException: Could not find a part of the path 'my-unittest-project\bin\Debug\net461\bin\roslyn\csc.exe'.

I do see that Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props is included in obj\MyProject.csproj.nuget.g.props file:

  <ImportGroup Condition=" '$(TargetFramework)' == 'net461' AND '$(ExcludeRestorePackageImports)' != 'true' ">
    <Import Project="$(NuGetPackageRoot)\teamcity.vstest.testadapter\1.0.7\build\net35\TeamCity.VSTest.TestAdapter.props" Condition="Exists('$(NuGetPackageRoot)\teamcity.vstest.testadapter\1.0.7\build\net35\TeamCity.VSTest.TestAdapter.props')" />
    <Import Project="$(NuGetPackageRoot)\microsoft.net.test.sdk\15.5.0\build\net45\Microsoft.Net.Test.Sdk.props" Condition="Exists('$(NuGetPackageRoot)\microsoft.net.test.sdk\15.5.0\build\net45\Microsoft.Net.Test.Sdk.props')" />
    <Import Project="$(NuGetPackageRoot)\microsoft.net.compilers\2.4.0\build\Microsoft.Net.Compilers.props" Condition="Exists('$(NuGetPackageRoot)\microsoft.net.compilers\2.4.0\build\Microsoft.Net.Compilers.props')" />
    <Import Project="$(NuGetPackageRoot)\microsoft.codedom.providers.dotnetcompilerplatform\1.0.8\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('$(NuGetPackageRoot)\microsoft.codedom.providers.dotnetcompilerplatform\1.0.8\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
  </ImportGroup>

but there's no roslyn\csc.exe in the output.

It seems that the same problem that in #13. But it's closed (as solved). But I have 1.0.8 where csc.exe still isn't copied to output.

Jinhuafei commented 6 years ago

@evil-shrike thanks for the feedback. We recently made some change to make the provider work on non-web project. Would you like to give it a try? You can get the package from the feed below.

Install-Package Microsoft.CodeDom.Providers.DotNetCompilerPlatform -Version 1.0.9 -Source https://www.myget.org/F/roslyncodedomprovider/api/v3/index.json

WeihanLi commented 6 years ago

I met the same problem with 1.0.8, and I use with 1.0.9 but met with the error as follows:

未能找到路径“D:\Document\projects\ProjectsSource\DbTool\src\DbTool\bin\Debug\net462\bin\roslyn\csc.exe”的一部分。

actually, the roslyn csc path should be net462\roslyn\csc.exe, by the way my project is new project file format, you can view my project here

I solve it with code as follows:

            //Set hardcoded environment variable to set the path to the library
            Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", System.IO.Directory.GetCurrentDirectory() + "\\roslyn", EnvironmentVariableTarget.Process);
            var provider = new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();
            //Clean up
            Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", null, EnvironmentVariableTarget.Process);
Jinhuafei commented 6 years ago

@WeihanLi We will introduce aspnet:RoslynCompilerLocation appsetting in new release through which you can specify the Rolsyn compiler location. You can find more details on the readme.

KirillOsenkov commented 6 years ago

While I'm here, check the typo: RoslyCompilerFiles. It should be replaced with RoslynCompilerFiles everywhere.

KirillOsenkov commented 6 years ago

Also, is this supported on a Mac? Current logic suggests Windows only and we've been getting a ton of complaints from users of VSMac that try building projects that use the https://www.nuget.org/packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform NuGet package.

Jinhuafei commented 6 years ago

@KirillOsenkov good catch. Will fix that typo. For now, the package only supports windows. If we get enough user requests, we may add that support. What's your use case on Mac?

KirillOsenkov commented 6 years ago

VSMac is getting a lot of reports that projects using this package fail to build on a mac :) I’m not sure what those projects are or what the usage is.

Jinhuafei commented 6 years ago

@WeihanLi Looked into you project and the issue you saw is caused by the fact that PackageReference mode ignores install.xdt in the nupkg. To workaround the issue, you can add the following appSetting into your app.config file(no need to use environment variable).

  <appSettings>
    <add key="aspnet:RoslynCompilerLocation" value="roslyn" />
  </appSettings>
WeihanLi commented 6 years ago

@Jinhuafei Thank you so much.

I've a few questions.

Jinhuafei commented 6 years ago

1 yes, it supports windows relative path. You can use something like below. And it is interpreted as relative to the current working directory. BTW, ~ is not windows relative.

    <appSettings>
        <add key="aspnet:RoslynCompilerLocation" value="..\\..\\..\\roslyn"/>
    </appSettings>

2 The default value is [working directory]\bin\roslyn

3 No, this package is not for .net core.

WeihanLi commented 6 years ago

Thank you @Jinhuafei

Jinhuafei commented 6 years ago

2.0.0-preview is released. After upgrading Microsoft.CodeDom.Providers.DotNetCompilerPlatform nupkg, please remember to uninstall Microsoft.Net.Compilers nupkg in your project.

MgSam commented 6 years ago

Can you add a method to CSharpCodeProvider that lets you specify the compiler path programmatically?

Jinhuafei commented 6 years ago

@MgSam CSharpCodeProvider is public now in 2.0.1 version. You can pass an ICompilerSettings to the constructor to specify the compiler location. See this PR.

MgSam commented 6 years ago

@Jinhuafei Thanks. That's very helpful. Two related questions:

  1. Is there a public implementation of ICompilerSetings? It seems weird that it is public but CompilerSettings is not.
  2. What is the default value for compilerServerTimeToLive?
Jinhuafei commented 6 years ago
  1. default is 10 sec on the server and 10 min on dev box(VS environment).
  2. yea, we missed that. Will be addressed in this PR.