示例#1
0
 internal ProjectFile TrackFile(ProjectFile pf, Boolean allowDuplicate = false)
 {
     solutionFiles.Add(pf);
     return(pf);
 }
示例#2
0
        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;
                }
            }
        }
示例#3
0
        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, "============================================");
                }
            }
        }