internal ProjectFile TrackFile(ProjectFile pf, Boolean allowDuplicate = false) { solutionFiles.Add(pf); return(pf); }
public void AddInfoFromCommandLine(AbsoluteCrosspath workingDir, List <String> args) { // parse arguments to obtain all -I, -D, -U // start from 1 to skip compiler name for (Int32 i = 1; i < args.Count; i++) { // includes: // -I // -iquote // -isystem // -idirafter // ..., see https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html // TODO: also process -nostdinc to control whether system include dirs should be added or not. // TODO: preserve priority between -I, -iquote and other include dir types IncludeDirectoryType idt = IncludeDirectoryType.Null; String includeDirStr = String.Empty; foreach (IncludeDirectoryType idk in IncludeDirectory.IncludeParam.Keys) { if (TakeParamValue(args, ref i, IncludeDirectory.IncludeParam[idk], out includeDirStr)) { idt = idk; break; } } if (idt != IncludeDirectoryType.Null) { // DONE: determine more accurately which include is local and which is remote // this is done with the use of Solution.Rebase() so we customly point to local files AbsoluteCrosspath includeDirPath = AbsoluteCrosspath.FromString(includeDirStr, workingDir); IncludeDirectory includeDir = OwnerSolution.TrackIncludeDirectory(includeDirPath, idt); // relax if we're adding the same include directory twice // TODO: rewrite this using PriorityQueue to preserver order this.AddIncludeDir(includeDir); continue; } // defines: // -D if (TakeParamValue(args, ref i, "-D", out String defineString)) { this.SetCppDefine(defineString); Logger.WriteLine(LogLevel.Trace, $"[i] Added -D{defineString}"); continue; } // undefines: // -U if (TakeParamValue(args, ref i, "-U", out String undefineString)) { this.UnsetCppDefine(undefineString); Logger.WriteLine(LogLevel.Trace, $"[i] Added -U{undefineString}"); continue; } if (TakeParamValue(args, ref i, "-include", out String forceInclude)) { AbsoluteCrosspath forceIncludePath = AbsoluteCrosspath.FromString(forceInclude, workingDir); ProjectFile forceIncludeProjectFile = this.OwnerSolution.TrackFile(new ProjectFile(OwnerSolution, forceIncludePath, this.CompilerOfFile), true); this.ForceIncludes.Add(forceIncludeProjectFile.FilePath); // ReSharper disable once RedundantJumpStatement continue; } } }
public void ParseCompileDB(String filename) { // hope compiledb is not so large to eat all the memory String compiledbRaw = File.ReadAllText(filename); List <CompileDBEntry> entries = JsonConvert.DeserializeObject <List <CompileDBEntry> >(compiledbRaw); foreach (CompileDBEntry entry in entries) { // get full file path AbsoluteCrosspath workingDir = AbsoluteCrosspath.FromString(entry.directory); AbsoluteCrosspath xpath = AbsoluteCrosspath.FromString(entry.file, workingDir); // TODO: filter out entries by include and exclude lists // get compiler path // it can be absolute or relative Crosspath compilerPath = Crosspath.FromString(entry.arguments[0]); // TODO: filter out compilers by include and exclude lists Compiler compiler = null; foreach (Compiler solutionCompiler in solutionCompilers) { if (solutionCompiler.ExePath.ToString().Equals(compilerPath.ToString())) { // already registered compiler = solutionCompiler; break; } } if (compiler == null) { compiler = new Compiler(compilerPath); if (solutionCompilers.Add(compiler)) { Logger.WriteLine(LogLevel.Info, $"New compiler '{compiler.ExePath}'"); } } CompilerInstance compilerInstance = null; CompilerInstance compilerInstanceTmp = new CompilerInstance(compiler, entry.arguments); foreach (CompilerInstance compilerInstanceInUse in compiler.Instances) { if (compilerInstanceInUse.Equals(compilerInstanceTmp)) { compilerInstance = compilerInstanceInUse; break; } } if (compilerInstance == null) { compilerInstance = compilerInstanceTmp; compiler.Instances.Add(compilerInstanceTmp); Logger.WriteLine(LogLevel.Info, $"New compiler instance '{compilerInstanceTmp.BaseCompiler.ExePath} {compilerInstanceTmp}'"); } ProjectFile pf = new ProjectFile(this, xpath, compilerInstance); Logger.WriteLine(LogLevel.Trace, $"===== file {xpath} ====="); pf.AddInfoFromCommandLine(workingDir, entry.arguments); // put global override defines silently // TODO: write them to solution-wide props foreach (Define define in config.OverrideDefines) { pf.UnsetCppDefine(define.Name); pf.SetCppDefine(define.ToString()); } // add to project files now? //pf.DumpData(); Int64 projectHash = pf.HashProjectID(); if (!projects.ContainsKey(projectHash)) { projects.Add(projectHash, new Project(AllocateGuid(), projectHash, this, compilerInstance, pf.IncludeDirectories, pf.SetOfDefines, pf.ForceIncludes)); } // add file to project if (!projects[projectHash].TestWhetherProjectFileBelongs(pf)) { throw new ApplicationException( $"[x] Could not add '{pf.FilePath}' to project '{projectHash}' - hash function error"); } if (!projects[projectHash].AddProjectFile(pf)) { //throw new ApplicationException( // $"[x] Could not add '{pf.FilePath}' to project '{projectHash}' - already exists"); Logger.WriteLine(LogLevel.Error, $"[x] Could not add '{pf}' to project '{projectHash}' - already exists"); } TrackFile(pf); } Logger.WriteLine(LogLevel.Info, $"[i] Created a solution of {projects.Count} projects from {solutionFiles.Count} files"); if (Logger.Level == LogLevel.Trace) { foreach (var projectKvp in projects) { Logger.WriteLine(LogLevel.Trace, $"# Project ID {projectKvp.Key}"); foreach (var file in projectKvp.Value.ProjectFiles) { Logger.WriteLine(LogLevel.Trace, $"# > {file.FilePath}"); } using (var enumerator = projectKvp.Value.ProjectFiles.GetEnumerator()) { if (!enumerator.MoveNext()) { break; } if (enumerator.Current != null) { enumerator.Current.DumpData(); } } Logger.WriteLine(LogLevel.Trace, "============================================"); } } }