Example #1
0
        public bool Compile(ITaskItem source, out string objectFile)
        {
            //Console.WriteLine($"  {source.ItemSpec}");
            Logger.Instance.LogMessage($"  {source.ItemSpec}");
            if (!String.IsNullOrEmpty(source.GetMetadata("ObjectFileName")))
            { //ObjectFileName is actually a folder name which is usaully $(IntDir) or $(IntDir)/%(RelativeDir)/
                if (IsPathDirectory(source.GetMetadata("ObjectFileName")))
                {
                    objectFile = Path.Combine(source.GetMetadata("ObjectFileName"), Path.GetFileNameWithoutExtension(source.ItemSpec) + ".o");
                }
                else
                {
                    objectFile = source.GetMetadata("ObjectFileName");
                }
            }
            else
            {
                objectFile = Path.GetFileNameWithoutExtension(source.ItemSpec) + ".o";
            }

            string sourceFile       = source.ItemSpec;
            string projectfile_name = ProjectFile;

            string objectFile_converted       = objectFile;
            string sourceFile_converted       = sourceFile;
            string projectfile_name_converted = projectfile_name;

            if (shellApp.convertpath)
            {
                objectFile_converted       = shellApp.ConvertWinPathToWSL(objectFile);
                sourceFile_converted       = shellApp.ConvertWinPathToWSL(sourceFile);
                projectfile_name_converted = shellApp.ConvertWinPathToWSL(projectfile_name);
            }
            else
            {
                //here just shotens path it will help with huge projects
                objectFile_converted = Utilities.MakeRelative(Path.GetFullPath(objectFile), Environment.CurrentDirectory + Path.DirectorySeparatorChar);
            }

            Dictionary <string, string> Flag_overrides = new Dictionary <string, string>();

            Flag_overrides.Add("SourceFile", sourceFile_converted);
            Flag_overrides.Add("OutputFile", objectFile_converted);

            var flags     = GetConvertedFlags(GCCToolCompiler_Flags, GCCToolCompiler_AllFlags, source, Flag_overrides, shellApp);
            var flags_dep = GetConvertedFlags(GCCToolCompiler_Flags, GCCToolCompiler_AllFlagsDependency, source, Flag_overrides, shellApp);

            // let's get all dependencies
            string gccOutput;

            if (Path.GetDirectoryName(objectFile) != "")
            {
                Directory.CreateDirectory(Path.GetDirectoryName(objectFile));
            }

            // This part is to get all dependencies and so know what files to recompile!
            bool needRecompile = true;

            if (!String.IsNullOrEmpty(flags_dep))
            {
                try
                {
                    FileInfo             sourceInfo = fileinfoDict.GetOrAdd(sourceFile, (x) => new FileInfo(x));
                    IEnumerable <string> dependencies;

                    if (dependencyDict.ContainsKey(objectFile) && File.Exists(objectFile) && sourceInfo.LastWriteTime < fileinfoDict.GetOrAdd(objectFile, (x) => new FileInfo(x)).LastWriteTime)
                    {
                        // You dont need to run dependency extraction!
                        // you still need to go through all dependency chains and check files!
                        dependencies = dependencyDict[objectFile];
                    }
                    else
                    {
                        using (var runWrapper = new RunWrapper(GCCToolCompilerPathCombined, flags_dep, shellApp, GCCToolSupportsResponsefile))
                            // run dependency extraction if there is an object file there....if not obviously you have to recompile!
                            if (!runWrapper.RunCompilerAndGetOutput(out gccOutput,
                                                                    String.IsNullOrEmpty(source.GetMetadata("SuppressStartupBanner")) || source.GetMetadata("SuppressStartupBanner").Equals("true") ? false : true
                                                                    ))
                            {
                                if (gccOutput == "FATAL")
                                {
                                    return(false);
                                }
                                //Logger.Instance.LogDecide(gccOutput, shellApp);
                                ///return false;
                            }
                        dependencies = ParseGccMmOutput(gccOutput).Union(new[] { sourceFile, ProjectFile });
                        dependencyDict.AddOrUpdate(objectFile, dependencies.ToList(), (x, y) => dependencies.ToList());
                    }

                    //if there is no object file then offcourse you need to recompile! no need to get into dependency checking
                    if (File.Exists(objectFile))
                    {
                        needRecompile = false;
                        FileInfo objInfo = fileinfoDict.GetOrAdd(objectFile, (x) => new FileInfo(x));

                        foreach (var dep in dependencies)
                        {
                            string depfile = dep;

                            if (shellApp.convertpath)
                            {
                                depfile = shellApp.ConvertWSLPathToWin(dep);//here use original! convert back to windows
                            }
                            FileInfo fi = fileinfoDict.GetOrAdd(depfile, (x) => new FileInfo(x));
                            if (fi.Exists == false || fi.Attributes == FileAttributes.Directory || fi.Attributes == FileAttributes.Device)
                            {
                                continue;
                            }
                            if (fi.LastWriteTime > objInfo.LastWriteTime)
                            {
                                needRecompile = true;
                                break;
                            }
                        }
                    }
                }
                catch
                {
                    needRecompile = true;
                    Logger.Instance.LogError("Internal error while trying to get dependencies from gcc", null);
                }
            }

            bool runCompileResult = false;

            if (needRecompile)
            {
                using (var runWrapper = new RunWrapper(GCCToolCompilerPathCombined, flags, shellApp, GCCToolSupportsResponsefile))
                    runCompileResult = runWrapper.RunCompiler(String.IsNullOrEmpty(source.GetMetadata("SuppressStartupBanner")) || source.GetMetadata("SuppressStartupBanner").Equals("true") ? false : true);
                if (runCompileResult)
                {
                    Logger.Instance.LogMessage($"  {source.ItemSpec} => {objectFile_converted}");
                }
            }
            else
            {
                Logger.Instance.LogMessage($"  {source.ItemSpec} => {objectFile_converted} (not compiled - already up to date)");
                runCompileResult = true;
            }

            return(runCompileResult);
        }