是否可以使用.net core Roslyn编译器编译单个C#代码文件?

在旧的.net中,我们曾经能够运行csc编译器来编译单个cs文件或多个文件。 使用.net核心,我们有dotnet build ,坚持拥有一个合适的项目文件。 是否有一个独立的命令行编译器,它可以在没有项目的情况下编译源代码文件(并在同一命令行中列出引用的依赖项)?

在Linux上,当我安装了旧的csc和新的.net核心时,我得到了这些时间:

 [root@li1742-80 test]# time dotnet build Microsoft (R) Build Engine version 15.3.409.57025 for .NET Core Copyright (C) Microsoft Corporation. All rights reserved. test -> /root/test/bin/Debug/netcoreapp2.0/test.dll Build succeeded. 0 Warning(s) 0 Error(s) Time Elapsed 00:00:03.94 real 0m7.027s user 0m5.714s sys 0m0.838s [root@li1742-80 test]# time csc Program.cs Microsoft (R) Visual C# Compiler version 2.3.0.61801 (3722bb71) Copyright (C) Microsoft Corporation. All rights reserved. real 0m0.613s user 0m0.522s sys 0m0.071s [root@li1742-80 test]# 

使用.net核心注意7秒,使用相同Program.cs旧csc注意几百毫秒。

我希望能够使用.net核心快速编译,因为我曾经能够使用csc。

是的,可以使用.NET Core中的csc或vbc编译器编译单个文件。

; TL; DR; 要直接调用Roslyn编译器,必须使用命令行驱动程序csc。{exe | dll} ,因为与旧的csc.exe相比,Roslyn不会隐式引用mscorlib.dll,所以必须将引用传递给所需的依赖项,即System.RuntimeSystem.Private.CoreLib库以及任何其他必需的引用。 以下清单显示了如何编译以下HelloWorld程序。

 using System; namespace HelloWorld { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } } } 

使用安装了Ubuntu 16.04和dotnet-sdk-2.0.0的WSL:

 time dotnet /usr/share/dotnet/sdk/2.0.0/Roslyn/csc.exe -r:/usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.0/System.Private.CoreLib.dll -r:/usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.0/System.Console.dll -r:/usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.0/System.Runtime.dll HelloWorld.cs Microsoft (R) Visual C# Compiler version 2.3.2.61921 (ad0efbb6) Copyright (C) Microsoft Corporation. All rights reserved. real 0m0.890s user 0m0.641s sys 0m0.250s ls -li total 4 4785074604720852 -rw-rw-rw- 1 developer developer 178 Dec 7 15:07 HelloWorld.cs 11821949022487213 -rw-rw-rw- 1 developer developer 4096 Dec 7 15:13 HelloWorld.exe 

传递给编译器的必需依赖项在不同平台上是不同的,即在Windows上,它足以传递System.Runtime.dllSystem.Console.dll而在Ubuntu 16.04上则需要传递System.Private.CoreLib.dll 。 不同的SDK版本将具有位于不同位置的Roslyn和命令行驱动程序 – 版本之间的SDK布局更改 – 以及最新的2.2.2 SDK附带csc.dllvbc.dll而不是csc.exevbc.exe 。 因此,在使用此方法之前,有必要检查SDK布局。

详细解释

Roslyn编译器的设计方式与以前使用的csc.exevbc.exe编译器有点不同。 首先,Roslyn是用C#和VB编写的,是一个托管的.NET应用程序。 在Windows上,它主要用作在服务器进程VBCSCompiler.exe (.dll)中运行的公共服务。 但是,Roslyn附带托管命令行驱动程序csc.exevbc.exe (最新的dotnet SDK版本附带csc.dllvbc.dll ),可用于直接从命令行编译源文件。 无论如何,这正是dotnet中的构建系统通过命令行调用Roslyn的原因。 运行简单的dotnet csc.exe -help命令将打印使用信息,该信息将指导直接从命令行使用编译器(参见上一个清单)。

旧的本机编译器和Roslyn之间的主要区别在于后者是托管应用程序,这是启动时间。 Roslyn甚至在被编译为R2R本机程序集( Ready To Run )后,还需要从加载整个dotnet框架开始,初始化它,然后加载Roslyn程序集并开始编译过程。 然而,它总是比运行本机编译器慢一点,从上面的时间可以看出,并没有那么慢。

几天前,在corefx repo中添加了一篇新的文档文章,描述了高级场景 – 使用csc / vbc和CoreRun构建和运行应用程序代码 。 任何有兴趣的人都可以将它作为指导如何在低级.NET Core中工作。

  Microsoft (R) Visual C# Compiler version 2.3.2.61921 (ad0efbb6) Copyright (C) Microsoft Corporation. All rights reserved. Visual C# Compiler Options - OUTPUT FILES - /out: Specify output file name (default: base name of file with main class or first file) /target:exe Build a console executable (default) (Short form: /t:exe) /target:winexe Build a Windows executable (Short form: /t:winexe) /target:library Build a library (Short form: /t:library) /target:module Build a module that can be added to another assembly (Short form: /t:module) /target:appcontainerexe Build an Appcontainer executable (Short form: /t:appcontainerexe) /target:winmdobj Build a Windows Runtime intermediate file that is consumed by WinMDExp (Short form: /t:winmdobj) /doc: XML Documentation file to generate /refout: Reference assembly output to generate /platform: Limit which platforms this code can run on: x86, Itanium, x64, arm, anycpu32bitpreferred, or anycpu. The default is anycpu. - INPUT FILES - /recurse: Include all files in the current directory and subdirectories according to the wildcard specifications /reference:= Reference metadata from the specified assembly file using the given alias (Short form: /r) /reference: Reference metadata from the specified assembly files (Short form: /r) /addmodule: Link the specified modules into this assembly /link: Embed metadata from the specified interop assembly files (Short form: /l) /analyzer: Run the analyzers from this assembly (Short form: /a) /additionalfile: Additional files that don't directly affect code generation but may be used by analyzers for producing errors or warnings. /embed Embed all source files in the PDB. /embed: Embed specific files in the PDB - RESOURCES - /win32res: Specify a Win32 resource file (.res) /win32icon: Use this icon for the output /win32manifest: Specify a Win32 manifest file (.xml) /nowin32manifest Do not include the default Win32 manifest /resource: Embed the specified resource (Short form: /res) /linkresource: Link the specified resource to this assembly (Short form: /linkres) Where the resinfo format is [,[,public|private]] - CODE GENERATION - /debug[+|-] Emit debugging information /debug:{full|pdbonly|portable|embedded} Specify debugging type ('full' is default, 'portable' is a cross-platform format, 'embedded' is a cross-platform format embedded into the target .dll or .exe) /optimize[+|-] Enable optimizations (Short form: /o) /deterministic Produce a deterministic assembly (including module version GUID and timestamp) /refonly Produce a reference assembly in place of the main output /instrument:TestCoverage Produce an assembly instrumented to collect coverage information /sourcelink: Source link info to embed into PDB. - ERRORS AND WARNINGS - /warnaserror[+|-] Report all warnings as errors /warnaserror[+|-]: Report specific warnings as errors /warn: Set warning level (0-4) (Short form: /w) /nowarn: Disable specific warning messages /ruleset: Specify a ruleset file that disables specific diagnostics. /errorlog: Specify a file to log all compiler and analyzer diagnostics. /reportanalyzer Report additional analyzer information, such as execution time. - LANGUAGE - /checked[+|-] Generate overflow checks /unsafe[+|-] Allow 'unsafe' code /define: Define conditional compilation symbol(s) (Short form: /d) /langversion: Specify language version mode: ISO-1, ISO-2, 3, 4, 5, 6, 7, 7.1, Default, or Latest - SECURITY - /delaysign[+|-] Delay-sign the assembly using only the public portion of the strong name key /publicsign[+|-] Public-sign the assembly using only the public portion of the strong name key /keyfile: Specify a strong name key file /keycontainer: Specify a strong name key container /highentropyva[+|-] Enable high-entropy ASLR - MISCELLANEOUS - @ Read response file for more options /help Display this usage message (Short form: /?) /nologo Suppress compiler copyright message /noconfig Do not auto include CSC.RSP file /parallel[+|-] Concurrent build. /version Display the compiler version number and exit. - ADVANCED - /baseaddress:
Base address for the library to be built /checksumalgorithm: Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 (default) or SHA256. /codepage: Specify the codepage to use when opening source files /utf8output Output compiler messages in UTF-8 encoding /main: Specify the type that contains the entry point (ignore all other possible entry points) (Short form: /m) /fullpaths Compiler generates fully qualified paths /filealign: Specify the alignment used for output file sections /pathmap:=,=,... Specify a mapping for source path names output by the compiler. /pdb: Specify debug information file name (default: output file name with .pdb extension) /errorendlocation Output line and column of the end location of each error /preferreduilang Specify the preferred output language name. /nostdlib[+|-] Do not reference standard library (mscorlib.dll) /subsystemversion: Specify subsystem version of this assembly /lib: Specify additional directories to search in for references /errorreport: Specify how to handle internal compiler errors: prompt, send, queue, or none. The default is queue. /appconfig: Specify an application configuration file containing assembly binding settings /moduleassemblyname: Name of the assembly which this module will be a part of /modulename: Specify the name of the source module

可以使用直接调用编译器

 $ /usr/local/share/dotnet/sdk/2.0.0/Roslyn/RunCsc.sh 

但是,如果没有支持的项目基础结构,此特定命令可能无效,因为您需要手动传入所有.NET Core或.NET Standard引用程序集,这通常由SDK和NuGet处理。 你会得到这样的错误:

 $ /usr/local/share/dotnet/sdk/2.0.0/Roslyn/RunCsc.sh Program.cs Microsoft (R) Visual C# Compiler version 2.3.2.61921 (ad0efbb6) Copyright (C) Microsoft Corporation. All rights reserved. Program.cs(1,7): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?) Program.cs(5,11): error CS0518: Predefined type 'System.Object' is not defined or imported Program.cs(7,26): error CS0518: Predefined type 'System.String' is not defined or imported Program.cs(7,16): error CS0518: Predefined type 'System.Void' is not defined or imported 

简而言之,没有预定义的项目就不支持它。

但是@ Andrew的评论显示,如果您准备好列出每个单独的依赖项,包括命令行选项中的隐式系统依赖项,它仍然是可能的。

从错误CS0518:未定义或导入预定义类型“System.Object”#12393 :

目前,我们还没有计划以这种方式轻松使用csc.exe。 该指南暂时使用dotnet CLI工具。 即使在这里做了一些修改,也会在框架上为编译器提供统一和/或简化的引用程序集。 编译器永远不会有比现在更复杂的类型或程序集分辨率(按设计)。

另请参见closed 可以直接调用编译器#7689 。