public CompileResult Build(CompileOptions options) { var settings = new GenerationSettings( partialsFolder: Path.Combine(SharedData.GeneratedFolder, assemblyNameNoExtension), macrosFolder: Path.Combine(SharedData.GeneratedFolder, "_macros"), txtForPartials: null, baseDirectory: "."); if (_cache == null || _cache._options.WorkDirectory != options.WorkDirectory || _cache._options.AssemblyName != options.AssemblyName || _cache._options.Output != options.Output || _cache._options.NoWarnings.SequenceEqual(options.NoWarnings) == false || _cache._options.Defines.SequenceEqual(options.Defines) == false || _cache._options.DebugSymbolFile != options.DebugSymbolFile || _cache._options.IsUnityPackage != options.IsUnityPackage) { (previousResult, _cache) = BuildFull(options, settings); return(previousResult); } else { _cache._options = options; return(BuildIncremental(options, settings, _cache, previousResult !)); } }
public CompileResult Build(string projectPath, CompileOptions options) { _logger.Info("Build(projectPath={0}, output={1})", projectPath, options.Output); if (string.IsNullOrEmpty(_projectPath) || _projectPath != projectPath) { // create new one _compilerMap = new Dictionary <string, Compiler>(); if (string.IsNullOrEmpty(_projectPath) == false) { _logger.Info("Flush old project. (Project={0})", _projectPath); } } _projectPath = projectPath; Compiler compiler; if (_compilerMap.TryGetValue(options.Output, out compiler) == false) { compiler = new Compiler(); _compilerMap.Add(options.Output, compiler); _logger.Info("Add new project. (Project={0})", _projectPath); } try { return(compiler.Build(options)); } catch (Exception e) { _logger.Error(e, "Error in build."); throw; } }
public CompileResult Build(string projectPath, CompileOptions options) { _logger.Info("Build(projectPath={0}, output={1})", projectPath, options.Output); if (string.IsNullOrEmpty(_projectPath) || _projectPath != projectPath) { // create new one _compilerMap = new Dictionary<string, Compiler>(); if (string.IsNullOrEmpty(_projectPath) == false) _logger.Info("Flush old project. (Project={0})", _projectPath); } _projectPath = projectPath; Compiler compiler; if (_compilerMap.TryGetValue(options.Output, out compiler) == false) { compiler = new Compiler(); _compilerMap.Add(options.Output, compiler); _logger.Info("Add new project. (Project={0})", _projectPath); } try { return compiler.Build(options); } catch (Exception e) { _logger.Error(e, "Error in build."); throw; } }
private CompileResult BuildFull(CompileOptions options) { var result = new CompileResult(); _logger.Info("BuildFull"); _options = options; _referenceFileList = new FileTimeList(); _referenceFileList.Update(options.References); _sourceFileList = new FileTimeList(); _sourceFileList.Update(options.Files); _referenceMap = options.References.ToDictionary( file => file, file => CreateReference(file)); var parseOption = new CSharpParseOptions(LanguageVersion.CSharp6, DocumentationMode.Parse, SourceCodeKind.Regular, options.Defines); _sourceMap = options.Files.ToDictionary( file => file, file => ParseSource(file, parseOption)); _compilation = CSharpCompilation.Create( options.AssemblyName, _sourceMap.Values, _referenceMap.Values, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); Emit(result); return result; }
public Compiler(CompileOptions options) { assemblyNameNoExtension = Path.GetFileNameWithoutExtension(options.AssemblyName); parseOptions = new CSharpParseOptions( LanguageVersion.CSharp8, DocumentationMode.Parse, SourceCodeKind.Regular, options.Defines ).WithFeatures(new [] { new KeyValuePair <string, string>("IOperation", ""), }); }
public static CompileResult Request(int parentProcessId, string currentPath, CompileOptions options, bool useCompilationServer) { if (!useCompilationServer) { return(new CompilerService().Build(currentPath, options)); } var address = CompilerServiceHelper.BaseAddress + parentProcessId; // var client = new IpcServiceClientBuilder<ICompilerService>() // .UseNamedPipe(address) // // or .UseTcp(IPAddress.Loopback, 45684) to invoke using TCP // .Build(); var client = new NamedPipeIpcServiceClient <ICompilerService>(new DefaultIpcMessageSerializer(), new DefaultValueConverter(), address); try { var result = client.InvokeAsync(cs => cs.Build(currentPath, options)).Result; return(result); } catch (AggregateException e) { if (e.InnerException != null && e.InnerException is TimeoutException) { throw e.InnerException; } else { throw; } } }
public CompileResult Build(string projectPath, CompileOptions options) { _logger.Info("Build(projectPath={0}, output={1})", projectPath, options.Output); Compiler compiler; if (options.IsUnityPackage) { // do not cache packages in ram, because they do not change compiler = new Compiler(options); } else { lock (_lockObj) { if (string.IsNullOrEmpty(_projectPath) || _projectPath != projectPath) { // create new one _projectPath = projectPath; _compilerMap = new Dictionary <string, Compiler>(); if (string.IsNullOrEmpty(_projectPath) == false) { _logger.Info("Flush old project. (Project={0})", _projectPath); } } if (_compilerMap.TryGetValue(options.Output, out var cachedCompiler)) { compiler = cachedCompiler; } else { compiler = new Compiler(options); _compilerMap.Add(options.Output, compiler); _logger.Info("Add new project. (Project={0})", _projectPath); } } } try { lock (compiler) { var result = compiler.Build(options); if (options.IsUnityPackage) { compiler.Dispose(); } return(result); } } catch (Exception e) { _logger.Error(e, "Error in build."); throw; } }
public static CompileResult Request(int parentProcessId, string currentPath, CompileOptions options) { var address = CompilerServiceHelper.BaseAddress + parentProcessId; var binding = CompilerServiceHelper.GetBinding(); var ep = new EndpointAddress(address); var channel = ChannelFactory <ICompilerService> .CreateChannel(binding, ep); return(channel.Build(currentPath, options)); }
ImmutableArray <DiagnosticAnalyzer> Analyzers(CompileOptions options, List <Diagnostic> diagnostics) { lock (_lockAnalyzers) { if (_loadedAnalyzers.HasValue) { return(_loadedAnalyzers.Value); } _loadedAnalyzers = AnalyzersInner(options, diagnostics); return(_loadedAnalyzers.Value); } }
public static CompileResult Request(int parentProcessId, string currentPath, CompileOptions options) { var address = "net.pipe://localhost/Unity3D.IncrementalCompiler/" + parentProcessId; var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { MaxBufferSize = 1048576, MaxReceivedMessageSize = 1048576 }; var ep = new EndpointAddress(address); var channel = ChannelFactory<ICompilerService>.CreateChannel(binding, ep); return channel.Build(currentPath, options); }
public static CompileResult Request(int parentProcessId, string currentPath, CompileOptions options) { var address = "net.pipe://localhost/Unity3D.IncrementalCompiler/" + parentProcessId; var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue }; var ep = new EndpointAddress(address); var channel = ChannelFactory <ICompilerService> .CreateChannel(binding, ep); return(channel.Build(currentPath, options)); }
public CompileResult Build(CompileOptions options) { if (_compilation == null || _options.WorkDirectory != options.WorkDirectory || _options.AssemblyName != options.AssemblyName || _options.Output != options.Output || _options.Defines.SequenceEqual(options.Defines) == false) { return BuildFull(options); } else { return BuildIncremental(options); } }
void CompileAnalyzer(CompileOptions options, string fullPath, string assembliesPath) { _logger.Info($"Compiling analyzer: {fullPath}"); var name = Path.GetFileNameWithoutExtension(Path.GetFileName(fullPath)); var parsed = ParseSource(options, fullPath, parseOptions); var assemblyRefs = AppDomain.CurrentDomain.GetAssemblies() .Select(a => MetadataReference.CreateFromFile(a.Location)) .ToArray(); var c = CSharpCompilation.Create( name, new[] { parsed }, assemblyRefs, new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default, sourceReferenceResolver: new SourceFileResolver(ImmutableArray <string> .Empty, options.WorkDirectory) ) ); using (var stream = new FileStream(Path.Combine(assembliesPath, name + ".dll"), FileMode.OpenOrCreate)) { var res = c.Emit(stream); foreach (var diagnostic in res.Diagnostics) { switch (diagnostic.Severity) { case DiagnosticSeverity.Error: _logger.Error(diagnostic.ToString()); break; case DiagnosticSeverity.Warning: _logger.Warn(diagnostic.ToString()); break; default: _logger.Info(diagnostic.ToString()); break; } } if (!res.Success) { throw new Exception($"Could not compile `{fullPath}`"); } } }
public CompilationCache( CSharpCompilation compilation, CompileOptions options, FileTimeList referenceFileList, FileTimeList sourceFileList, Dictionary <string, MetadataReference> referenceMap, Dictionary <string, SyntaxTree> sourceMap, CodeGeneration.GeneratedFilesMapping filesMapping) { _referenceFileList = referenceFileList; _sourceFileList = sourceFileList; _referenceMap = referenceMap; _sourceMap = sourceMap; _filesMapping = filesMapping; _compilation = compilation; _options = options; }
public CompileResult Build(CompileOptions options) { if (_compilation == null || _options.WorkDirectory != options.WorkDirectory || _options.AssemblyName != options.AssemblyName || _options.Output != options.Output || _options.NoWarnings.SequenceEqual(options.NoWarnings) == false || _options.Defines.SequenceEqual(options.Defines) == false) { return(BuildFull(options)); } else { return(BuildIncremental(options)); } }
private CompileResult BuildFull(CompileOptions options) { var result = new CompileResult(); _logger.Info("BuildFull"); _options = options; _referenceFileList = new FileTimeList(); _referenceFileList.Update(options.References); _sourceFileList = new FileTimeList(); _sourceFileList.Update(options.Files); _referenceMap = options.References.ToDictionary( file => file, file => CreateReference(file)); var parseOption = new CSharpParseOptions(LanguageVersion.CSharp6, DocumentationMode.Parse, SourceCodeKind.Regular, options.Defines); _sourceMap = options.Files.ToDictionary( file => file, file => ParseSource(file, parseOption)); var specificDiagnosticOptions = options.NoWarnings.ToDictionary(x => x, _ => ReportDiagnostic.Suppress); _compilation = CSharpCompilation.Create( options.AssemblyName, _sourceMap.Values, _referenceMap.Values, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) .WithSpecificDiagnosticOptions(specificDiagnosticOptions) .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default) .WithAllowUnsafe(options.Options.Contains("-unsafe"))); Emit(result); return(result); }
string CompileAnalyzers(CompileOptions options) { var analyzers = "compiled-analyzers-" + assemblyNameNoExtension; var outputPath = Directory.Exists("Temp") ? Path.Combine("Temp", analyzers) : analyzers; if (Directory.Exists(outputPath)) { Directory.Delete(outputPath, true); } Directory.CreateDirectory(outputPath); var analyzerSources = Directory .GetFiles(analyzersPath) .Where(x => x.EndsWith(".cs", StringComparison.OrdinalIgnoreCase)) .ToArray(); foreach (var cs in analyzerSources) { CompileAnalyzer(options, cs, outputPath); } return(outputPath); }
private CompileResult BuildFull(CompileOptions options) { var result = new CompileResult(); _logger.Info("BuildFull"); _options = options; _referenceFileList = new FileTimeList(); _referenceFileList.Update(options.References); _sourceFileList = new FileTimeList(); _sourceFileList.Update(options.Files); _referenceMap = options.References.ToDictionary( file => file, file => CreateReference(file)); var parseOption = new CSharpParseOptions(LanguageVersion.CSharp6, DocumentationMode.Parse, SourceCodeKind.Regular, options.Defines); _sourceMap = options.Files.ToDictionary( file => file, file => ParseSource(file, parseOption)); var specificDiagnosticOptions = options.NoWarnings.ToDictionary(x => x, _ => ReportDiagnostic.Suppress); _compilation = CSharpCompilation.Create( options.AssemblyName, _sourceMap.Values, _referenceMap.Values, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) .WithSpecificDiagnosticOptions(specificDiagnosticOptions) .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default) .WithAllowUnsafe(options.Options.Contains("-unsafe"))); Emit(result); return result; }
/// <summary> /// analyzers can only use dependencies that are already in this project /// dependency versions must match those of project dependencies /// </summary> /// <param name="diagnostics"></param> ImmutableArray <DiagnosticAnalyzer> AnalyzersInner(CompileOptions options, List <Diagnostic> diagnostics) { // if Location.None is used instead, unity doesnt print the error to console. var defaultPos = Location.Create( "/Analyzers", TextSpan.FromBounds(0, 0), new LinePositionSpan() ); try { if (PlatformHelper.CurrentPlatform == Platform.Mac) { return(ImmutableArray <DiagnosticAnalyzer> .Empty); } if (!Directory.Exists(analyzersPath)) { Directory.CreateDirectory(analyzersPath); File.WriteAllText( analyzersPath + "/readme.txt", "Add Roslyn Analyzers here\r\nAdd analyzer dependencies in sub-folders" ); return(ImmutableArray <DiagnosticAnalyzer> .Empty); } var loader = new AL(); var additionalPath = CompileAnalyzers(options); var analyzerNames = Directory.GetFiles(analyzersPath).Concat(Directory.GetFiles(additionalPath)) .Where(x => x.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) .ToArray(); var analyzerDependencies = Directory.GetDirectories(analyzersPath).SelectMany(Directory.GetFiles).ToArray(); foreach (var analyzerDependency in analyzerDependencies) { _logger.Info("Analyzer dependency: " + analyzerDependency); loader.LoadFromPath(analyzerDependency); } _logger.Info("Analyzers:"); var analyzers = analyzerNames .Select(dll => { _logger.Info("Analyzer dll: " + dll); var _ref = new AnalyzerFileReference(dll, loader); _ref.AnalyzerLoadFailed += (_, e) => { _logger.Error("failed to load analyzer: " + e.TypeName + "; " + e.Message); diagnostics.Add(Diagnostic.Create(new DiagnosticDescriptor( "A01", "Error", "Compiler couldn't load provided code analyzer: " + e.TypeName + ". Please fix or remove from /Analyzers directory. More info in compiler log.", "Error", DiagnosticSeverity.Error, true ), defaultPos)); }; return(_ref.GetAnalyzers(LanguageNames.CSharp)); }) .Aggregate(new List <DiagnosticAnalyzer>(), (list, a) => { a.ForEach(_logger.Info); list.AddRange(a); return(list); }) .ToImmutableArray(); return(analyzers); } catch (Exception e) { _logger.Error(e); diagnostics.Add(Diagnostic.Create(new DiagnosticDescriptor( "A02", "Warning", "Exception was thrown when loading analyzers: " + e.Message, "Warning", DiagnosticSeverity.Warning, true ), defaultPos)); return(ImmutableArray <DiagnosticAnalyzer> .Empty); } }
static int RunAsClient(string[] args) { SetupLogger("IncrementalCompiler.log", false); var logger = LogManager.GetLogger("Client"); logger.Info("Started"); Settings settings; try { settings = Settings.Load() ?? Settings.Default; } catch (Exception e) { logger.Error(e, "Failed in loading settings."); return 1; } var currentPath = Directory.GetCurrentDirectory(); var options = new CompileOptions(); options.ParseArgument(args); options.WorkDirectory = currentPath; options.References = options.References.Distinct().ToList(); options.Files = options.Files.Distinct().ToList(); options.DebugSymbolFile = settings.DebugSymbolFile; options.PrebuiltOutputReuse = settings.PrebuiltOutputReuse; logger.Info("CurrentDir: {0}", Directory.GetCurrentDirectory()); logger.Info("Output: {0}", options.Output); if (string.IsNullOrEmpty(options.Output)) { logger.Error("No output"); return 1; } // Get unity process ID var parentProcessId = 0; var pd = options.Defines.FirstOrDefault(d => d.StartsWith("__UNITY_PROCESSID__")); if (pd != null) { int.TryParse(pd.Substring(19), out parentProcessId); } else { var parentProcess = Process.GetProcessesByName("Unity").FirstOrDefault(); if (parentProcess != null) parentProcessId = parentProcess.Id; } if (parentProcessId == 0) { logger.Error("No parent process"); return 1; } logger.Info("Parent process ID: {0}", parentProcessId); // Run Process serverProcess = null; while (true) { try { var w = new Stopwatch(); w.Start(); logger.Info("Request to server"); var result = CompilerServiceClient.Request(parentProcessId, currentPath, options); w.Stop(); logger.Info("Done: Succeeded={0}. Duration={1}sec.", result.Succeeded, w.Elapsed.TotalSeconds); Console.WriteLine("Compile {0}. (Duration={1}sec)", result.Succeeded ? "succeeded" : "failed", w.Elapsed.TotalSeconds); foreach (var warning in result.Warnings) { logger.Info(warning); Console.Error.WriteLine(warning); } foreach (var error in result.Errors) { logger.Info(error); Console.Error.WriteLine(error); } return result.Succeeded ? 0 : 1; } catch (EndpointNotFoundException) { if (serverProcess == null) { logger.Info("Spawn server"); serverProcess = Process.Start( new ProcessStartInfo { FileName = Assembly.GetEntryAssembly().Location, Arguments = "-server " + parentProcessId, WindowStyle = ProcessWindowStyle.Hidden }); Thread.Sleep(100); } else { if (serverProcess.HasExited == false) Thread.Sleep(100); else return 1; } } catch (Exception e) { logger.Error(e, "Error in request"); Console.Error.WriteLine("Internal error: " + e); return 1; } } }
private static int RunAsDev(string[] args) { SetupLogger("IncrementalCompiler.log", true); var workDirectory = args[1]; var reponseFile = args[2]; var settings = Settings.Load() ?? Settings.Default; var logger = LogManager.GetLogger("Dev"); logger.Info("Started"); Directory.SetCurrentDirectory(workDirectory); var curPath = Directory.GetCurrentDirectory(); var options = new CompileOptions(); options.ParseArgument(new string[] { "-nostdlib+", "-noconfig", // Unity5 // "-r:" + @"C:/Software/Unity-2018/Editor/Data/Mono/lib/mono/2.0/mscorlib.dll", // "-r:" + @"C:/Software/Unity-2018/Editor/Data/Mono/lib/mono/2.0/System.dll", // "-r:" + @"C:/Software/Unity-2018/Editor/Data/Mono/lib/mono/2.0/System.Core.dll", // "-r:" + @"C:/Software/Unity-2018/Editor/Data/Mono/lib/mono/2.0/System.Xml.dll", "@Temp/" + reponseFile, }); options.WorkDirectory = curPath; options.References = options.References.Distinct().ToList(); options.Files = options.Files.Distinct().ToList(); options.PrebuiltOutputReuse = settings.PrebuiltOutputReuse; var parentProcessId = Process.GetCurrentProcess().Id; Process?serverProcess = null; // new Thread(() => CompilerServiceServer.Run(logger, parentProcessId)).Start(); while (true) { try { var w = new Stopwatch(); w.Start(); Console.WriteLine("Run"); var result = CompilerServiceClient.Request(parentProcessId, curPath, options, false); w.Stop(); Console.WriteLine("Done: Succeeded={0}. Duration={1}sec. ", result.Succeeded, w.Elapsed.TotalSeconds); foreach (var warning in result.Warnings) { Console.WriteLine(warning); } foreach (var error in result.Errors) { Console.WriteLine(error); } Console.ReadLine(); } catch (TimeoutException) { if (serverProcess == null) { var a = new Thread(() => CompilerServiceServer.Run(logger, parentProcessId)); a.Start(); serverProcess = Process.GetCurrentProcess(); // serverProcess = Process.Start( // new ProcessStartInfo // { // FileName = Assembly.GetEntryAssembly().Location, // Arguments = "-server " + parentProcessId, // WindowStyle = ProcessWindowStyle.Hidden // }); // Thread.Sleep(100); } else { if (serverProcess.HasExited == false) { Thread.Sleep(100); } else { serverProcess = null; } } } } }
private CompileResult BuildIncremental(CompileOptions options) { var result = new CompileResult(); _logger.Info("BuildIncremental"); _options = options; // update reference files var referenceChanges = _referenceFileList.Update(options.References); foreach (var file in referenceChanges.Added) { _logger.Info("+ {0}", file); var reference = CreateReference(file); _compilation = _compilation.AddReferences(reference); _referenceMap.Add(file, reference); } foreach (var file in referenceChanges.Changed) { _logger.Info("* {0}", file); var reference = CreateReference(file); _compilation = _compilation.RemoveReferences(_referenceMap[file]) .AddReferences(reference); _referenceMap[file] = reference; } foreach (var file in referenceChanges.Removed) { _logger.Info("- {0}", file); _compilation = _compilation.RemoveReferences(_referenceMap[file]); _referenceMap.Remove(file); } // update source files var sourceChanges = _sourceFileList.Update(options.Files); var parseOption = new CSharpParseOptions(LanguageVersion.CSharp6, DocumentationMode.Parse, SourceCodeKind.Regular, options.Defines); foreach (var file in sourceChanges.Added) { _logger.Info("+ {0}", file); var syntaxTree = ParseSource(file, parseOption); _compilation = _compilation.AddSyntaxTrees(syntaxTree); _sourceMap.Add(file, syntaxTree); } foreach (var file in sourceChanges.Changed) { _logger.Info("* {0}", file); var syntaxTree = ParseSource(file, parseOption); _compilation = _compilation.RemoveSyntaxTrees(_sourceMap[file]) .AddSyntaxTrees(syntaxTree); _sourceMap[file] = syntaxTree; } foreach (var file in sourceChanges.Removed) { _logger.Info("- {0}", file); _compilation = _compilation.RemoveSyntaxTrees(_sourceMap[file]); _sourceMap.Remove(file); } // emit or reuse prebuilt output var reusePrebuilt = _outputDllStream != null && ( (_options.PrebuiltOutputReuse == PrebuiltOutputReuseType.WhenNoChange && sourceChanges.Empty && referenceChanges.Empty) || (_options.PrebuiltOutputReuse == PrebuiltOutputReuseType.WhenNoSourceChange && sourceChanges.Empty && referenceChanges.Added.Count == 0 && referenceChanges.Removed.Count == 0)); if (reusePrebuilt) { _logger.Info("Reuse prebuilt output"); // write dll var dllFile = Path.Combine(_options.WorkDirectory, _options.Output); using (var dllStream = new FileStream(dllFile, FileMode.Create)) { _outputDllStream.Seek(0L, SeekOrigin.Begin); _outputDllStream.CopyTo(dllStream); } // write pdb or mdb switch (_options.DebugSymbolFile) { case DebugSymbolFileType.Pdb: var pdbFile = Path.Combine(_options.WorkDirectory, Path.ChangeExtension(_options.Output, ".pdb")); using (var debugSymbolStream = new FileStream(pdbFile, FileMode.Create)) { _outputDebugSymbolStream.Seek(0L, SeekOrigin.Begin); _outputDebugSymbolStream.CopyTo(debugSymbolStream); } break; case DebugSymbolFileType.PdbToMdb: case DebugSymbolFileType.Mdb: var mdbFile = Path.Combine(_options.WorkDirectory, _options.Output + ".mdb"); using (var debugSymbolStream = new FileStream(mdbFile, FileMode.Create)) { _outputDebugSymbolStream.Seek(0L, SeekOrigin.Begin); _outputDebugSymbolStream.CopyTo(debugSymbolStream); } break; } result.Succeeded = true; } else { _logger.Info("Emit"); Emit(result); } return result; }
private CompileResult BuildIncremental(CompileOptions options) { var result = new CompileResult(); _logger.Info("BuildIncremental"); _options = options; // update reference files var referenceChanges = _referenceFileList.Update(options.References); foreach (var file in referenceChanges.Added) { _logger.Info("+ {0}", file); var reference = CreateReference(file); _compilation = _compilation.AddReferences(reference); _referenceMap.Add(file, reference); } foreach (var file in referenceChanges.Changed) { _logger.Info("* {0}", file); var reference = CreateReference(file); _compilation = _compilation.RemoveReferences(_referenceMap[file]) .AddReferences(reference); _referenceMap[file] = reference; } foreach (var file in referenceChanges.Removed) { _logger.Info("- {0}", file); _compilation = _compilation.RemoveReferences(_referenceMap[file]); _referenceMap.Remove(file); } // update source files var sourceChanges = _sourceFileList.Update(options.Files); var parseOption = new CSharpParseOptions(LanguageVersion.CSharp6, DocumentationMode.Parse, SourceCodeKind.Regular, options.Defines); foreach (var file in sourceChanges.Added) { _logger.Info("+ {0}", file); var syntaxTree = ParseSource(file, parseOption); _compilation = _compilation.AddSyntaxTrees(syntaxTree); _sourceMap.Add(file, syntaxTree); } foreach (var file in sourceChanges.Changed) { _logger.Info("* {0}", file); var syntaxTree = ParseSource(file, parseOption); _compilation = _compilation.RemoveSyntaxTrees(_sourceMap[file]) .AddSyntaxTrees(syntaxTree); _sourceMap[file] = syntaxTree; } foreach (var file in sourceChanges.Removed) { _logger.Info("- {0}", file); _compilation = _compilation.RemoveSyntaxTrees(_sourceMap[file]); _sourceMap.Remove(file); } // emit or reuse prebuilt output var reusePrebuilt = _outputDllStream != null && ( (_options.PrebuiltOutputReuse == PrebuiltOutputReuseType.WhenNoChange && sourceChanges.Empty && referenceChanges.Empty) || (_options.PrebuiltOutputReuse == PrebuiltOutputReuseType.WhenNoSourceChange && sourceChanges.Empty && referenceChanges.Added.Count == 0 && referenceChanges.Removed.Count == 0)); if (reusePrebuilt) { _logger.Info("Reuse prebuilt output"); // write dll var dllFile = Path.Combine(_options.WorkDirectory, _options.Output); using (var dllStream = new FileStream(dllFile, FileMode.Create)) { _outputDllStream.Seek(0L, SeekOrigin.Begin); _outputDllStream.CopyTo(dllStream); } // write pdb or mdb switch (_options.DebugSymbolFile) { case DebugSymbolFileType.Pdb: var pdbFile = Path.Combine(_options.WorkDirectory, Path.ChangeExtension(_options.Output, ".pdb")); using (var debugSymbolStream = new FileStream(pdbFile, FileMode.Create)) { _outputDebugSymbolStream.Seek(0L, SeekOrigin.Begin); _outputDebugSymbolStream.CopyTo(debugSymbolStream); } break; case DebugSymbolFileType.PdbToMdb: case DebugSymbolFileType.Mdb: var mdbFile = Path.Combine(_options.WorkDirectory, _options.Output + ".mdb"); using (var debugSymbolStream = new FileStream(mdbFile, FileMode.Create)) { _outputDebugSymbolStream.Seek(0L, SeekOrigin.Begin); _outputDebugSymbolStream.CopyTo(debugSymbolStream); } break; } result.Succeeded = true; } else { _logger.Info("Emit"); Emit(result); } return(result); }
private static int RunAsClient(string[] args) { SetupLogger("IncrementalCompiler.log", false); var logger = LogManager.GetLogger("Client"); logger.Info("Started"); Settings settings; try { settings = Settings.Load() ?? Settings.Default; } catch (Exception e) { logger.Error(e, "Failed in loading settings."); return(1); } var currentPath = Directory.GetCurrentDirectory(); var options = new CompileOptions(); options.ParseArgument(args); options.WorkDirectory = currentPath; options.References = options.References.Distinct().ToList(); options.Files = options.Files.Distinct().ToList(); options.PrebuiltOutputReuse = settings.PrebuiltOutputReuse; logger.Info("CurrentDir: {0}", Directory.GetCurrentDirectory()); logger.Info("Output: {0}", options.Output); if (string.IsNullOrEmpty(options.Output)) { logger.Error("No output"); return(1); } // Get unity process ID var parentProcessId = 0; var pd = options.Defines.FirstOrDefault(d => d.StartsWith("__UNITY_PROCESSID__")); if (pd != null) { int.TryParse(pd.Substring(19), out parentProcessId); } else { var parentProcess = Process.GetProcessesByName("Unity").FirstOrDefault(); if (parentProcess != null) { parentProcessId = parentProcess.Id; } } if (parentProcessId == 0) { logger.Error("No parent process"); return(1); } logger.Info("Parent process ID: {0}", parentProcessId); // Run var useCompilationServer = true; // it does not work on mac for some reason useCompilationServer &= PlatformHelper.CurrentPlatform == Platform.Windows; useCompilationServer = false; Process?serverProcess = null; while (true) { try { var w = new Stopwatch(); w.Start(); logger.Info("Request to server"); var result = CompilerServiceClient.Request(parentProcessId, currentPath, options, useCompilationServer); w.Stop(); logger.Info("Done: Succeeded={0}. Duration={1}sec.", result.Succeeded, w.Elapsed.TotalSeconds); Console.WriteLine("Compile {0}. (Duration={1}sec)", result.Succeeded ? "succeeded" : "failed", w.Elapsed.TotalSeconds); foreach (var warning in result.Warnings) { logger.Info(warning); Console.Error.WriteLine(warning.Replace("\r\n", " ~~ ").Replace("\n", " ~~ ")); } foreach (var error in result.Errors) { logger.Info(error); Console.Error.WriteLine(error.Replace("\r\n", " ~~ ").Replace("\n", " ~~ ")); } return(result.Succeeded ? 0 : 1); } catch (TimeoutException) { if (serverProcess == null) { logger.Info("Spawn server"); serverProcess = Process.Start( new ProcessStartInfo { FileName = (Assembly.GetEntryAssembly() ?? typeof(Program).Assembly).Location, Arguments = "-server " + parentProcessId, WindowStyle = ProcessWindowStyle.Hidden }); Thread.Sleep(100); } else { if (serverProcess.HasExited == false) { Thread.Sleep(100); } else { return(1); } } } catch (Exception e) { logger.Error(e, "Error in request"); Console.Error.WriteLine("Internal error: " + e); return(1); } } }
static int RunAsDev(string[] args) { SetupLogger("IncrementalCompiler.log", true); var workDirectory = args[1]; var reponseFile = args[2]; var settings = Settings.Load() ?? Settings.Default; var logger = LogManager.GetLogger("Dev"); logger.Info("Started"); Directory.SetCurrentDirectory(workDirectory); var curPath = Directory.GetCurrentDirectory(); var options = new CompileOptions(); options.ParseArgument(new string[] { "-nostdlib+", "-noconfig", "-r:" + @"C:/Program Files/Unity/Editor/Data\Mono/lib/mono/2.0/mscorlib.dll", "-r:" + @"C:/Program Files/Unity/Editor/Data\Mono/lib/mono/2.0/System.dll", "-r:" + @"C:/Program Files/Unity/Editor/Data\Mono/lib/mono/2.0/System.Core.dll", "-r:" + @"C:/Program Files/Unity/Editor/Data\Mono/lib/mono/2.0/System.Xml.dll", "@Temp/" + reponseFile, }); options.WorkDirectory = curPath; options.References = options.References.Distinct().ToList(); options.Files = options.Files.Distinct().ToList(); options.DebugSymbolFile = settings.DebugSymbolFile; options.PrebuiltOutputReuse = settings.PrebuiltOutputReuse; var parentProcessId = Process.GetCurrentProcess().Id; Process serverProcess = null; while (true) { try { var w = new Stopwatch(); w.Start(); Console.WriteLine("Run"); var result = CompilerServiceClient.Request(parentProcessId, curPath, options); w.Stop(); Console.WriteLine("Done: Succeeded={0}. Duration={1}sec. ", result.Succeeded, w.Elapsed.TotalSeconds); foreach (var warning in result.Warnings) Console.WriteLine(warning); foreach (var error in result.Errors) Console.WriteLine(error); Console.ReadLine(); } catch (EndpointNotFoundException) { if (serverProcess == null) { var a = new Thread(() => CompilerServiceServer.Run(logger, parentProcessId)); a.Start(); serverProcess = Process.GetCurrentProcess(); /* serverProcess = Process.Start( new ProcessStartInfo { FileName = Assembly.GetEntryAssembly().Location, Arguments = "-server " + parentProcessId, WindowStyle = ProcessWindowStyle.Hidden }); */ Thread.Sleep(100); } else { if (serverProcess.HasExited == false) Thread.Sleep(100); else serverProcess = null; } } catch (Exception e) { Console.WriteLine(e); return 1; } } }