예제 #1
0
        public void RelativizeTest1()
        {
            AbsoluteCrosspath xIncludeDirectory = AbsoluteCrosspath.FromString("/local/store/bin-src/qemu");
            AbsoluteCrosspath xFile             = AbsoluteCrosspath.FromString("/local/store/bin-src/qemu/hw/mips/serial.c");
            RelativeCrosspath relPath           = xFile.Relativized(xIncludeDirectory);

            Assert.AreEqual("hw/mips/serial.c", relPath.ToString());
        }
예제 #2
0
        public void AppendedTest()
        {
            AbsoluteCrosspath xLocalIncludeDirectory = AbsoluteCrosspath.GetCurrentDirectory();
            RelativeCrosspath xRelPath = RelativeCrosspath.FromString("lzcintrin.h");
            AbsoluteCrosspath xPath    = xLocalIncludeDirectory.Appended(xRelPath);

            Assert.AreEqual(xPath.ToString(), xLocalIncludeDirectory + @"\" + xRelPath);
        }
예제 #3
0
        public void RelativizeTestWin1()
        {
            AbsoluteCrosspath xIncludeDirectory = AbsoluteCrosspath.FromString(@"C:\Windows\system32\config");
            AbsoluteCrosspath xFile             = AbsoluteCrosspath.FromString(@"C:\Program Files (x86)\Common Files\Microsoft");
            RelativeCrosspath relPath           = xFile.Relativized(xIncludeDirectory);

            Assert.AreEqual(@"..\..\..\Program Files (x86)\Common Files\Microsoft", relPath.ToString());
        }
예제 #4
0
        public void RelativizeTest2()
        {
            AbsoluteCrosspath xIncludeDirectory = AbsoluteCrosspath.FromString("/local/store/bin-src/qemu");
            AbsoluteCrosspath xFile             = AbsoluteCrosspath.FromString("/local/store/fast/bin-src/ccache/ccache.c");
            RelativeCrosspath relPath           = xFile.Relativized(xIncludeDirectory);

            Assert.AreEqual("../../fast/bin-src/ccache/ccache.c", relPath.ToString());
        }
예제 #5
0
        public String GetLocalProjectPath(AbsoluteCrosspath solutionDir)
        {
            if (autoDownloaded)
            {
                return($@"$(SolutionDir)\{this.Relativized(solutionDir, true)}");
            }

            return(this.ToString());
        }
예제 #6
0
        public void RebaseFromUnixToWindowsTestFull()
        {
            Crosspath         xpath  = Crosspath.FromString("/local/store/bin-src/qemu");
            AbsoluteCrosspath before = Crosspath.FromString("/local/store/bin-src/qemu") as AbsoluteCrosspath;
            AbsoluteCrosspath after  = Crosspath.FromString(@"D:\Workspace\Source\qemu") as AbsoluteCrosspath;
            AbsoluteCrosspath apath  = ((AbsoluteCrosspath)xpath).Rebase(before, after);

            Assert.AreEqual(CrosspathFlavor.Windows, apath.Flavor);
            Assert.AreEqual('D', apath.WindowsRootDrive);
            Assert.AreEqual(@"D:\Workspace\Source\qemu", apath.ToString());
            Assert.AreEqual(@"D:\Workspace\Source\qemu", apath.ToAbsolutizedString());
        }
예제 #7
0
        public void RelativizeTest3()
        {
            AbsoluteCrosspath xIncludeDirectory = AbsoluteCrosspath.FromString("/local/store/bin-src/qemu");
            AbsoluteCrosspath xFile             = AbsoluteCrosspath.FromString("/local/store/fast/bin-src/ccache/ccache.c");

            try {
                RelativeCrosspath unused = xFile.Relativized(xIncludeDirectory, true);
                Assert.Fail("should fail");
            }
            catch (CrosspathLibException) {
            }
        }
예제 #8
0
        public void RelativizeTestWin2()
        {
            AbsoluteCrosspath xIncludeDirectory = AbsoluteCrosspath.FromString(@"C:\Windows\system32\config");
            AbsoluteCrosspath xFile             = AbsoluteCrosspath.FromString(@"D:\Games\Call of Duty 2");

            try {
                RelativeCrosspath unused = xFile.Relativized(xIncludeDirectory);
                Assert.Fail("should fail");
            }
            catch {
                // ignored
            }
        }
예제 #9
0
        public void TestMethod3()
        {
            Crosspath cpath = Crosspath.FromString(@"/local/store/qemu");

            Assert.IsInstanceOfType(cpath, typeof(AbsoluteCrosspath));
            Assert.AreEqual(CrosspathFlavor.Unix, cpath.Flavor);
            Assert.AreEqual(CrosspathOrigin.Absolute, cpath.Origin);
            Assert.AreEqual(@"/local/store/qemu", ((AbsoluteCrosspath)cpath).ToString());
            // DONE: substitute (rebase) absolute paths
            Assert.AreEqual(@"D:\Projects\local\store\qemu"
                            , ((AbsoluteCrosspath)cpath).Rebase(AbsoluteCrosspath.FromString("/")
                                                                , AbsoluteCrosspath.FromString(@"D:\Projects")).ToString());
        }
예제 #10
0
 public ProjectFile(Solution sln, AbsoluteCrosspath filePath, CompilerInstance compilerInstance)
 {
     CompilerOfFile     = compilerInstance;
     IncludeDirectories = new IncludeDirectoryList();
     DoNotUseStandardIncludeDirectories = false;
     Defines       = new Dictionary <String, Define>();
     SetOfDefines  = new HashSet <Define>(DefineExactComparer.Instance);
     ForceIncludes = new HashSet <AbsoluteCrosspath>();
     FilePath      = filePath;
     OwnerSolution = sln;
     if (sln.config.BaseDir != null)
     {
         ProjectFolder = RelativeCrosspath.CreateRelativePath(filePath, sln.config.BaseDir, true).ToContainingDirectory() as RelativeCrosspath;
     }
 }
예제 #11
0
        public void HashDiversedEquality()
        {
            HashSet <Crosspath> hs = new HashSet <Crosspath> {
                Crosspath.FromString("/tmp/VCXProjWriter")
                , AbsoluteCrosspath.FromString("/tmp/VCXProjWriter1")
                , RelativeCrosspath.FromString("tmp/VCXProjWriter")
            };
            RelativeCrosspath relativeCrosspath = RelativeCrosspath.FromString("VCXProjWriter");

            relativeCrosspath.SetWorkingDirectory(AbsoluteCrosspath.FromString("/tmp"));
            Boolean has_added = hs.Add(relativeCrosspath);

            Assert.AreEqual(false, has_added);
            Assert.AreEqual(3, hs.Count);
        }
예제 #12
0
        public void DownloadStandardIncludeDirectories(RemoteHost remote)
        {
            if (Skip)
            {
                return;
            }
            // use sftp, or, when not possible, ssh cat
            AbsoluteCrosspath xpwd         = AbsoluteCrosspath.GetCurrentDirectory();
            AbsoluteCrosspath xCompilerDir = xpwd.Appended(RelativeCrosspath.FromString($@"compilers\{ShortName}"));

            Directory.CreateDirectory(xCompilerDir.ToString());
            foreach (IncludeDirectory includeDirectory in IncludeDirectories)
            {
                includeDirectory.RebaseToLocal(remote, xCompilerDir);
            }
        }
예제 #13
0
        /// <summary>
        /// Writes compiler_${ShortName}.props and compiler_$(ShortName}_compat.h
        /// </summary>
        public void WriteToFile(AbsoluteCrosspath solutionDir)
        {
            if (Skip)
            {
                return;
            }

            AbsoluteCrosspath compilerDir = RelativeCrosspath.FromString(PropsFileName).Absolutized(AbsoluteCrosspath.GetCurrentDirectory()).ToContainingDirectory();

            Directory.CreateDirectory(compilerDir.ToString());

            foreach (CompilerInstance compilerInstance in Instances)
            {
                compilerInstance.WriteToFile(solutionDir);
            }

            XmlDocument doc = new XmlDocument();

            doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null));

            XmlElement projectNode = doc.CreateElement("Project");

            projectNode.SetAttribute("DefaultTargets", "Build");
            projectNode.SetAttribute("ToolsVersion", "Current");
            projectNode.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");

            XmlElement projectImportProps = doc.CreateElement("Import");

            projectImportProps.SetAttribute("Project", @"$(SolutionDir)\Solution.props");
            projectNode.AppendChild(projectImportProps);

            XmlElement projectPropertyGroupCompiler = doc.CreateElement("PropertyGroup");
            XmlElement projectCompilerExeName       = doc.CreateElement("RemoteCCompileToolExe");

            projectCompilerExeName.InnerText = ExePath.ToString();
            projectPropertyGroupCompiler.AppendChild(projectCompilerExeName);
            XmlElement projectCompilerCppExeName = doc.CreateElement("RemoteCppCompileToolExe");

            projectCompilerCppExeName.InnerText = ExePath.ToString();
            projectPropertyGroupCompiler.AppendChild(projectCompilerCppExeName);

            projectNode.AppendChild(projectPropertyGroupCompiler);

            doc.AppendChild(projectNode);
            doc.Save(PropsFileName);
        }
예제 #14
0
        public Boolean AddEntry(AbsoluteCrosspath path)
        {
            NTree <String> fs = (NTree <String>) this;

            foreach (String pathEntry in path)
            {
                if (fs.children[pathEntry] == null)
                {
                    fs.children[pathEntry] = new NTree <String>(fs, pathEntry);
                }
                else
                {
                    fs = fs.children[pathEntry];
                }
            }

            return(false);
        }
예제 #15
0
        /// <summary>
        /// Can be called multiple times.
        /// </summary>
        /// <param name="before">Old base (e.g. Unix path where compiled)</param>
        /// <param name="after">New base (e.g. Windows path where edited)</param>
        public void Rebase(AbsoluteCrosspath before, AbsoluteCrosspath after)
        {
            // move project files to another location
            foreach (ProjectFile projectFile in solutionFiles)
            {
                projectFile.FilePath.Rebase(before, after);
            }

            // move include directories to another location
            foreach (KeyValuePair <String, IncludeDirectory> includeDirPair in solutionIncludeDirectories)
            {
                includeDirPair.Value.Rebase(before, after);
            }

            if (this.config.BaseDir != null)
            {
                this.config.BaseDir.Rebase(before, after);
            }
        }
예제 #16
0
        internal IncludeDirectory TrackIncludeDirectory(AbsoluteCrosspath includeDirPath, IncludeDirectoryType idt)
        {
            String           includeDirStrReconstructed = includeDirPath.ToString();
            IncludeDirectory includeDir;

            if (!solutionIncludeDirectories.ContainsKey(includeDirStrReconstructed))
            {
                includeDir = new IncludeDirectory(includeDirPath, idt);
                solutionIncludeDirectories.Add(includeDirStrReconstructed, includeDir);
                Logger.WriteLine(LogLevel.Debug, $"New include directory '{includeDirStrReconstructed}'");
            }
            else
            {
                // if this include directory is already known, then drop current object and get old reference
                includeDir = solutionIncludeDirectories[includeDirStrReconstructed];
                Logger.WriteLine(LogLevel.Trace, $"Reusing include directory '{includeDirStrReconstructed}'");
            }

            return(includeDir);
        }
예제 #17
0
        public void IncludeDirsOrder()
        {
            IncludeDirectoryList includeDirs = new IncludeDirectoryList();

            IncludeDirectory[] expected =
            {
                new IncludeDirectory(AbsoluteCrosspath.FromString("/opt/qemu-5.3/inc/private"), IncludeDirectoryType.Quote)
                ,                                                                               new IncludeDirectory(AbsoluteCrosspath.FromString("/opt/qemu-5.3/hw/mips/include"), IncludeDirectoryType.Generic)
                ,                                                                               new IncludeDirectory(AbsoluteCrosspath.FromString("/opt/qemu-5.3/hw/mips"), IncludeDirectoryType.Generic)
                ,                                                                               new IncludeDirectory(AbsoluteCrosspath.FromString("/opt/qemu-5.3/inc"), IncludeDirectoryType.System)

                ,                                                                               new IncludeDirectory(AbsoluteCrosspath.FromString("/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include"), IncludeDirectoryType.System)
                ,                                                                               new IncludeDirectory(AbsoluteCrosspath.FromString("/usr/local/include"), IncludeDirectoryType.System)
                ,                                                                               new IncludeDirectory(AbsoluteCrosspath.FromString("/usr/include"), IncludeDirectoryType.System)

                ,                                                                               new IncludeDirectory(AbsoluteCrosspath.FromString("/opt/qemu-5.3-helper/if-a-compiler-didnt-handle/include"), IncludeDirectoryType.DirAfter)
            };

            // a tricky project
            includeDirs.AddIncludeDirectory(expected[3]);                                 /* /opt/qemu-5.3/inc */
            includeDirs.AddIncludeDirectory(expected[0]);                                 /* /opt/qemu-5.3/inc/private */
            includeDirs.AddIncludeDirectory(expected[0]); /* /opt/qemu-5.3/inc/private */ // intentional duplicate
            includeDirs.AddIncludeDirectory(expected[7]);                                 /* /opt/qemu-5.3-helper/if-a-compiler-didnt-handle/include */
            includeDirs.AddIncludeDirectory(expected[1]);                                 /* /opt/qemu-5.3/hw/mips/include */
            includeDirs.AddIncludeDirectory(expected[2]);                                 /* /opt/qemu-5.3/hw/mips */
            // compiler should go after the project
            includeDirs.AddIncludeDirectory(expected[4]);                                 /* /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include */
            includeDirs.AddIncludeDirectory(expected[5]);                                 /* /usr/local/include */
            includeDirs.AddIncludeDirectory(expected[6]);                                 /* /usr/include */


            int idx = 0;

            foreach (IncludeDirectory includeDirectory in includeDirs)
            {
                Assert.AreEqual(expected[idx], includeDirectory);
                ++idx;
            }
        }
예제 #18
0
        private static void ProcessArgs(String[] args)
        {
            for (int idx = 0; idx < args.Length; idx++)
            {
                switch (args[idx])
                {
                case "-s":
                case "--substitute-path":
                    String[] subst = TakeArg(args, ref idx).Split(new[] { '=' }, 2);
                    if (subst.Length != 2)
                    {
                        throw new ApplicationException("--substitute-path requires next arg to be like '/path/before=/path/after'");
                    }
                    AbsoluteCrosspath[] pair = new AbsoluteCrosspath[2];
                    for (int i = 0; i < 2; ++i)
                    {
                        try {
                            pair[i] = Crosspath.FromString(subst[i]) as AbsoluteCrosspath;
                        }
                        catch (Exception e) {
                            throw new PolymorphismException($"{e.GetType()}: '{subst[i]}' is not a valid absolute path");
                        }
                    }
                    config.Substitutions.Add(new Tuple <AbsoluteCrosspath, AbsoluteCrosspath>(pair[0], pair[1]));
                    break;

                case "-b":
                case "--base-dir":
                    config.BaseDir = AbsoluteCrosspath.FromString(TakeArg(args, ref idx));
                    break;

#if PATH_BASED_FILTERING
                case "--include":
                    config.IncludeFilesFrom.Add(Crosspath.FromString(TakeArg(args, ref idx)));
                    break;

                case "--exclude":
                    config.ExcludeFilesFrom.Add(Crosspath.FromString(TakeArg(args, ref idx)));
                    break;
#endif

                case "-o":
                case "--output-dir":
                    config.Outdir = TakeArg(args, ref idx);
                    break;

                case "-f":
                case "--file":
                    config.InputFile = TakeArg(args, ref idx);
                    break;

                case "-r":
                case "--remote":
                    RemoteHost remote = RemoteHost.Parse(TakeArg(args, ref idx));
                    config.AssignRemote(remote);
                    break;

                case "-D":
                case "--define":
                    config.OverrideDefines.Add(new Define(TakeArg(args, ref idx)));
                    break;

                case "--exclude-compiler":
                    config.ExcludeCompilers.Add(Crosspath.FromString(TakeArg(args, ref idx)));
                    break;

                case "--relax-include-dirs-order":
                    config.RelaxIncludeDirsOrder = true;
                    break;

                case "--randomize-outdir":
                    config.Outdir = Path.Combine(config.Outdir, new Random().Next().ToString("x8"));
                    break;

                case "--open-now":
                    config.OpenSolution = true;
                    break;

                case "--debug":
                    Logger.Level = LogLevel.Debug;
                    break;

                case "--help":
                    ShowHelp();
                    return;

                default:
                    throw new Exception($"Unknown command line parameter '{args[idx]}");
                }
            }
        }
예제 #19
0
        private static void Main(String[] args)
        {
#if !DEBUG
            try {
#endif
            ProcessArgs(args);
            if (config.InputFile == null)
            {
                ShowHelp();
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();
            Solution sln = new Solution(config);
            sln.ParseCompileDB(config.InputFile);
            sw.Stop();
            Int64 parseAndGroup = sw.ElapsedMilliseconds;

            sw.Reset();
            sw.Start();
            if (config.Remote != null)
            {
                sln.RetrieveExtraInfoFromRemote(config.Remote);
            }
            sw.Stop();
            Int64 remoteInfo = sw.ElapsedMilliseconds;

            sln.FilterOutEntries();

            sw.Reset();
            sw.Start();
            foreach (Tuple <AbsoluteCrosspath, AbsoluteCrosspath> substitution in config.Substitutions)
            {
                sln.Rebase(substitution.Item1, substitution.Item2);
            }
            sw.Stop();
            Int64 rebase = sw.ElapsedMilliseconds;

            // DONE: also check for:
            //   - project file accessibility
            //   - include dirs accessibility
            List <IncludeDirectory> remoteNotRebased = new List <IncludeDirectory>();
            sln.CheckForTotalRebase(ref remoteNotRebased);

            try {
                Directory.Delete(config.Outdir, true);
            }
            catch {
                // ignored
            }

            if (config.Remote != null)
            {
                sln.DownloadCompilerIncludeDirectoriesFromRemote(config.Remote, config.Outdir);
                foreach (IncludeDirectory includeDirectory in remoteNotRebased)
                {
                    Crosspath outdir = Crosspath.FromString(config.Outdir);
                    if (outdir is RelativeCrosspath relativeCrosspath)
                    {
                        outdir = relativeCrosspath.Absolutized(AbsoluteCrosspath.GetCurrentDirectory());
                    }

                    includeDirectory.RebaseToLocal(config.Remote
                                                   , ((AbsoluteCrosspath)outdir).Append(
                                                       RelativeCrosspath.FromString(String.Format(SolutionStructure.RemoteIncludePath
                                                                                                  , config.Remote.Host))));
                }
            }

            sw.Reset();
            sw.Start();
            sln.WriteToDirectory(config.Outdir);
            sw.Stop();
            Int64 write = sw.ElapsedMilliseconds;

            Console.WriteLine();
            Console.WriteLine($"Elapsed time: parseAndGroup = {parseAndGroup} ms, remoteInfo = {remoteInfo} ms"
                              + $", rebase = {rebase} ms, write = {write} ms.");

            if (config.OpenSolution)
            {
                Process.Start(new ProcessStartInfo(Path.Combine(config.Outdir, SolutionStructure.SolutionFilename))
                {
                    UseShellExecute = true
                });
            }
#if !DEBUG
        }

        catch (Exception e) {
            Console.WriteLine($"[x] {e.Message}");
            Console.WriteLine();
            Console.WriteLine("Stack trace for debugging purposes:");
            Console.WriteLine($"{e.StackTrace}");
            Console.WriteLine("Press Enter to continue...");
            Console.ReadLine();
        }
#endif
        }
예제 #20
0
        public void WriteToFile(AbsoluteCrosspath solutionDir)
        {
            String inheritFrom;

            if (Skip || CompilerInstance.BaseCompiler.Skip)
            {
                return;
            }

            // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
            if (CompilerInstance.HaveAdditionalInfo)
            {
                inheritFrom = $@"$(SolutionDir)\{CompilerInstance.PropsFileName}";
            }
            else
            {
                inheritFrom = @"$(SolutionDir)\Solution.props";
            }

            Directory.CreateDirectory(Path.GetDirectoryName(this.Filename) ?? Directory.GetCurrentDirectory());

            // compatibility files
            // DONE: add compatibility files directly to the project node
            String compatPrefix    = SolutionStructure.SeparateProjectsFromEachOther ? "" : $"{Name}.";
            String compatLocal     = String.Format(SolutionStructure.ForcedIncludes.LocalCompat, compatPrefix);
            String compatLocalPost = String.Format(SolutionStructure.ForcedIncludes.LocalPostCompat, compatPrefix);

            File.WriteAllText($@"{Path.GetDirectoryName(Filename)}\{compatLocal}", @"");
            File.WriteAllText($@"{Path.GetDirectoryName(Filename)}\{compatLocalPost}", @"");

            // create with XML API
            XmlDocument doc = new XmlDocument();

            doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null));

            XmlElement projectNode = doc.CreateElement("Project");

            projectNode.SetAttribute("DefaultTargets", "Build");
            projectNode.SetAttribute("ToolsVersion", "Current");
            projectNode.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");

            XmlElement projectImportProps = doc.CreateElement("Import");

            projectImportProps.SetAttribute("Project", inheritFrom);
            projectNode.AppendChild(projectImportProps);

            XmlElement projectPropertyGroupGlobals = doc.CreateElement("PropertyGroup");

            projectPropertyGroupGlobals.SetAttribute("Label", "Globals");
            XmlElement projectGuid = doc.CreateElement("ProjectGuid");

            projectGuid.InnerText = $"{{{Guid}}}";
            projectPropertyGroupGlobals.AppendChild(projectGuid);
            projectNode.AppendChild(projectPropertyGroupGlobals);

            XmlElement projectPropertyGroupIDU = doc.CreateElement("PropertyGroup");
            // maybe someday this will be helpful, but now it can be inherited from Solution.props
            XmlElement projectForcedIncludes = doc.CreateElement("NMakeForcedIncludes");

            // TODO: add compiler compat header to forced includes
            projectForcedIncludes.InnerText = $@"$(ProjectDir)\{compatLocal};$(SolutionPreCompilerCompat);$(CompilerCompat);$(SolutionPostCompilerCompat);$(ProjectDir)\{compatLocalPost}";
            projectPropertyGroupIDU.AppendChild(projectForcedIncludes);
            projectNode.AppendChild(projectPropertyGroupIDU);

            // source file list
            XmlElement projectItemGroupCompiles = doc.CreateElement("ItemGroup");

            projectItemGroupCompiles.SetAttribute("Label", "Source Files");
            foreach (ProjectFile projectFile in this.ProjectFiles)
            {
                // exclusion list comes here!
                // TODO: we need to access path before rebase occured...
                XmlElement projectFileXmlElement = doc.CreateElement("ClCompile");
                projectFileXmlElement.SetAttribute("Include", projectFile.FilePath.ToString());

                // IDU settings

                XmlElement pfIncludePaths = doc.CreateElement("AdditionalIncludeDirectories");
                // DONE?: intermix project include directories with compiler include directories
                // in the project file
                foreach (IncludeDirectory includePath in projectFile.IncludeDirectories)
                {
                    // append -idirafter to the very end, below compiler dirs
                    if (includePath.Type == IncludeDirectoryType.DirAfter)
                    {
                        continue;
                    }
                    pfIncludePaths.InnerText += includePath.GetLocalProjectPath(solutionDir) + ";";
                }
                pfIncludePaths.InnerText += "%(AdditionalIncludeDirectories)";
                foreach (IncludeDirectory includePath in projectFile.IncludeDirectories)
                {
                    // append -idirafter to the very end, below compiler dirs
                    if (includePath.Type == IncludeDirectoryType.DirAfter)
                    {
                        pfIncludePaths.InnerText += ";" + includePath.GetLocalProjectPath(solutionDir);
                    }
                }
                projectFileXmlElement.AppendChild(pfIncludePaths);

                // maybe someday this will be helpful, but now it can be inherited from Solution.props
                XmlElement pfForcedIncludes = doc.CreateElement("ForcedIncludeFiles");
                foreach (AbsoluteCrosspath projectForcedInclude in projectFile.ForceIncludes)
                {
                    pfForcedIncludes.InnerText += $"{projectForcedInclude};";
                }
                pfForcedIncludes.InnerText += $"%(ForcedIncludeFiles)";
                projectFileXmlElement.AppendChild(pfForcedIncludes);

                XmlElement pfDefines = doc.CreateElement("PreprocessorDefinitions");
                foreach (Define define in projectFile.Defines.Values)
                {
                    pfDefines.InnerText += define + ";";
                }
                pfDefines.InnerText += "$(PreprocessorDefinitions)";
                projectFileXmlElement.AppendChild(pfDefines);

                projectItemGroupCompiles.AppendChild(projectFileXmlElement);
            }

            // add local_compat.h and local_post_compiler_compat.h
            XmlElement projectFileLocalCompatXmlElement = doc.CreateElement("ClCompile");

            projectFileLocalCompatXmlElement.SetAttribute("Include", "local_compat.h");
            projectItemGroupCompiles.AppendChild(projectFileLocalCompatXmlElement);
            XmlElement projectFileLocalPostCompatXmlElement = doc.CreateElement("ClCompile");

            projectFileLocalPostCompatXmlElement.SetAttribute("Include", "local_post_compiler_compat.h");
            projectItemGroupCompiles.AppendChild(projectFileLocalPostCompatXmlElement);

            projectNode.AppendChild(projectItemGroupCompiles);

            // TODO: add headers somehow...
            XmlElement projectItemGroupIncludes = doc.CreateElement("ItemGroup");

            projectItemGroupIncludes.SetAttribute("Label", "Header Files");

            /*
             * foreach (ProjectFile projectFile in this.ProjectDepends.Values) {
             *  XmlElement projectFileXmlElement = doc.CreateElement("ClInclude");
             *  projectFileXmlElement.SetAttribute("Include", projectFile.FilePath);
             *  projectItemGroupIncludes.AppendChild(projectFileXmlElement);
             * }
             */
            projectNode.AppendChild(projectItemGroupIncludes);

            doc.AppendChild(projectNode);
            doc.Save(this.Filename);

            WriteStructureToFile();
        }
예제 #21
0
        /// <summary>
        /// Call RemoteHost.ExtractInfoFromCompiler() instead.
        /// Requires these utilities on the remote system: pwd, echo, which, touch, sort, pushd, popd, zip
        /// </summary>
        /// <param name="remote">Remote host where compiler installed</param>
        public void ExtractAdditionalInfo(RemoteHost remote)
        {
            String remoteTempFile = String.Format(Compiler.RemoteTempFile, BaseCompiler.ShortName, instanceGuid.ToString());

            if (remote.Execute("pwd || echo $PWD", out String pwd) != RemoteHost.Success)
            {
                throw new ApplicationException("could not get current directory name");
            }
            pwd = pwd.TrimEnd(RemoteHost.LineEndingChars);

            if (remote.Execute($"which {BaseCompiler.ExePath}", out String absExePath) != RemoteHost.Success)
            {
                throw new ApplicationException("could not get absolute compiler path");
            }
            absExePath = absExePath.TrimEnd(RemoteHost.LineEndingChars);

            if (remote.Execute($"{BaseCompiler.ExePath} -dumpversion", out String version) != RemoteHost.Success)
            {
                throw new ApplicationException("could not extract version from compiler");
            }
            Version = version.TrimEnd(RemoteHost.LineEndingChars);

            // create temporary .c file for auto-distinguishment between C and C++
            if (remote.Execute($"touch {remoteTempFile} || echo > {remoteTempFile}", out String _) != RemoteHost.Success)
            {
                throw new ApplicationException("could not create temporary file");
            }

            if (remote.Execute($"{BaseCompiler.ExePath} {this} -E -dM {remoteTempFile} | sort", out String defines) != RemoteHost.Success)
            {
                throw new ApplicationException("could not extract defines from compiler");
            }

            if (remote.Execute($"{BaseCompiler.ExePath} {this} -E -Wp,-v {remoteTempFile} 2>&1 1> /dev/null", out String includeDirs) != RemoteHost.Success)
            {
                throw new ApplicationException("could not extract include dirs from compiler");
            }

            AbsoluteCrosspath xpwd      = AbsoluteCrosspath.FromString(pwd);
            AbsoluteCrosspath xcompiler = AbsoluteCrosspath.FromString(absExePath);

            if (!xcompiler.ToString().Equals(BaseCompiler.ExePath.ToString()))
            {
                AbsoluteCrosspath compilerLocatedIn = new AbsoluteCrosspath(xcompiler);
                ((RelativeCrosspath)BaseCompiler.ExePath).SetWorkingDirectory(xcompiler.ToContainingDirectory());
                Logger.WriteLine(LogLevel.Info, $"compiler '{BaseCompiler.ExePath}' actually located at '{xcompiler}'");
            }

            Defines.Clear();
            Platform fallbackPlatform = Platform.x64;

            foreach (String macro in defines.Split(RemoteHost.LineEndings, StringSplitOptions.RemoveEmptyEntries))
            {
                // assuming standard format '#define MACRO some thing probably with spaces'
                String[] defArray = macro.Split(new[] { ' ' }, 3);
                // try to auto-detect the platform
                if (VSPlatform == Platform.Unknown)
                {
                    switch (defArray[1])
                    {
                    case "__x86_64__": VSPlatform = Platform.x64; break;

                    case "__i386__": VSPlatform = Platform.x86; break;

                    case "__arm__": VSPlatform = Platform.ARM; break;

                    case "__aarch64__": VSPlatform = Platform.ARM64; break;

                    case "__mips__": VSPlatform = Platform.MIPS; break;

                    case "__WORDSIZE__":     /* this seems to be standard */
                    case "__INTPTR_WIDTH__": /* this not, but use as fallback */
                        if (Int32.Parse(defArray[2]) == 32)
                        {
                            fallbackPlatform = Platform.x86;
                        }
                        break;
                    }
                }
                Defines.Add(new Define(defArray[1], defArray[2]));
            }
            if (VSPlatform == Platform.Unknown)
            {
                VSPlatform = fallbackPlatform;
            }

            IncludeDirectories.Clear();
            IncludeDirectoryType incDirType = IncludeDirectoryType.Null;

            foreach (String cppLine in includeDirs.Split(RemoteHost.LineEndings, StringSplitOptions.RemoveEmptyEntries))
            {
                // sample output:

/*
 * ignoring nonexistent directory "/opt/gcc-4.1.2-glibc-2.5-binutils-2.17-kernel-2.6.18/arm-v5te-linux-gnueabi/include"
 #include "..." search starts here:
 #include <...> search starts here:
 * /opt/gcc-4.1.2-glibc-2.5-binutils-2.17-kernel-2.6.18/bin/../lib/gcc/arm-v5te-linux-gnueabi/4.1.2/include
 * /opt/gcc-4.1.2-glibc-2.5-binutils-2.17-kernel-2.6.18/bin/../sysroot-arm-v5te-linux-gnueabi/usr/include
 * End of search list.
 */
                // regarding priority:
                // -iquote has the highest priority affecting #include "..." not only #include <...>
                // -I has lower priority than -iquote
                // -isystem has lower priority but yet higher priority than system-wide headers
                //   then follows the priority of system-wide-headers
                // -idirafter has the lowest priority possible
                // example (gcc 9):

/*
 * $ gcc -x c -c -Wp,-v -iquote /proc/1 -I /proc/10 -isystem /proc/12 -I /proc/14 -idirafter /proc/1204 - < /dev/null
 * ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
 * ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"
 * ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"
 #include "..." search starts here:
 * /proc/1
 #include <...> search starts here:
 * /proc/10
 * /proc/14
 * /proc/12
 * /usr/lib/gcc/x86_64-linux-gnu/9/include
 * /usr/local/include
 * /usr/include/x86_64-linux-gnu
 * /usr/include
 * /proc/1204
 * End of search list.
 */
                // usually gcc does not have any include directories in the #include "..." section.
                // so the reason for parsing this section is when using some compiler wrapper that puts some paths to -iquote.
                if (cppLine == "#include \"...\" search starts here:")
                {
                    incDirType = IncludeDirectoryType.Quote;
                    continue;
                }
                if (cppLine == "#include <...> search starts here:")
                {
                    incDirType = IncludeDirectoryType.System;
                    continue;
                }

                if (cppLine.Length > 0 && cppLine[0] == ' ')
                {
                    Crosspath xpath = Crosspath.FromString(cppLine.Substring(1));
                    if (xpath is RelativeCrosspath relPath)
                    {
                        relPath.SetWorkingDirectory(xpwd);
                        xpath = relPath.Absolutized();
                    }
                    IncludeDirectory incDir       = new IncludeDirectory(xpath as AbsoluteCrosspath, incDirType);
                    IncludeDirectory incDirCached = BaseCompiler.TrackIncludeDir(incDir);
                    if (incDirCached != null)
                    {
                        incDir = incDirCached;
                    }
                    IncludeDirectories.Add(incDir);

                    continue;
                }

                if (cppLine == "End of search list.")
                {
                    break;
                }
            }

            HaveAdditionalInfo = true;

            Logger.WriteLine(LogLevel.Info, $"{absExePath} {this} is {VSPlatform} compiler");
        }
예제 #22
0
        public void WriteToDirectory(String directory)
        {
            Directory.CreateDirectory(directory);
            String pwd = Directory.GetCurrentDirectory();

            Directory.SetCurrentDirectory(directory);

            AbsoluteCrosspath solutionDir = AbsoluteCrosspath.GetCurrentDirectory();

            foreach (Compiler compiler in solutionCompilers)
            {
                compiler.WriteToFile(solutionDir);
            }

            foreach (Project projectKvp in projects.Values)
            {
                // remember there will also be .vcxproj.filters
                projectKvp.WriteToFile(solutionDir);
            }

            // TODO: add them as "Solution Items"
            File.WriteAllText(SolutionStructure.ForcedIncludes.SolutionCompat, @"#pragma once");
            File.WriteAllText(SolutionStructure.ForcedIncludes.SolutionPostCompat, templates.SolutionCompat);

            // regarding compiler_compat.h:
            // generate one file per compiler and reference them from projects
            // see Compiler.WriteToFile() instead

            File.WriteAllBytes(SolutionStructure.SolutionPropsFilename, templates.SolutionProps);

            // write .sln itself
            // using simple text generator
            using (StreamWriter sw = new StreamWriter(SolutionStructure.SolutionFilename, false, Encoding.UTF8)) {
                sw.WriteLine("");
                sw.WriteLine("Microsoft Visual Studio Solution File, Format Version 12.00");
                sw.WriteLine("# Visual Studio Version 16");
                sw.WriteLine("VisualStudioVersion = 16.0.31613.86");
                sw.WriteLine("MinimumVisualStudioVersion = 10.0.40219.1");
                foreach (Project project in projects.Values)
                {
                    if (project.Skip || project.CompilerInstance.BaseCompiler.Skip)
                    {
                        continue;
                    }
                    // this magic GUID is "Windows (Visual C++)" project type
                    sw.WriteLine($"Project(\"{{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}}\") = \"{project.Name}\", \"{project.Filename}\", \"{{{project.Guid.ToString().ToUpper()}}}\"");
                    sw.WriteLine("EndProject");
                }

                // this magic GUID is "Solution Folder"
                sw.WriteLine($"Project(\"{{2150E333-8FDC-42A3-9474-1A3956D46DE8}}\") = \"Compat files\", \"Compat files\", \"{{{AllocateGuid()}}}\"");
                sw.WriteLine("\tProjectSection(SolutionItems) = preProject");
                sw.WriteLine("\t\tsolution_compat.h = solution_compat.h");
                sw.WriteLine("\t\tsolution_post_compiler_compat.h = solution_post_compiler_compat.h");
                sw.WriteLine("\tEndProjectSection");
                sw.WriteLine("EndProject");

                sw.WriteLine("Global");
                sw.WriteLine("GlobalSection(SolutionConfigurationPlatforms) = preSolution");
                foreach (String cfg in SolutionStructure.SolutionConfigurations)
                {
                    sw.WriteLine($"\t\t{cfg}|{SolutionStructure.SolutionPlatformName} = {cfg}|{SolutionStructure.SolutionPlatformName}");
                }

                sw.WriteLine("EndGlobalSection");
                sw.WriteLine("GlobalSection(ProjectConfigurationPlatforms) = postSolution");
                String[] cfgStages = { "ActiveCfg", "Build.0", "Deploy.0" };
                foreach (Project project in projects.Values)
                {
                    if (project.Skip || project.CompilerInstance.BaseCompiler.Skip)
                    {
                        continue;
                    }
                    foreach (String cfg in SolutionStructure.SolutionConfigurations)
                    {
                        foreach (String cfgStage in cfgStages)
                        {
                            sw.WriteLine($"\t\t{{{project.Guid.ToString().ToUpper()}}}.{cfg}|{SolutionStructure.SolutionPlatformName}.{cfgStage} = {cfg}|{project.CompilerInstance.VSPlatform}");
                        }
                    }
                }

                sw.WriteLine("\tEndGlobalSection");
                sw.WriteLine("\tGlobalSection(SolutionProperties) = preSolution");
                sw.WriteLine("\t\tHideSolutionNode = FALSE");
                sw.WriteLine("\tEndGlobalSection");
                sw.WriteLine("\tGlobalSection(ExtensibilityGlobals) = postSolution");
                sw.WriteLine($"\t\tSolutionGuid = {{{selfGuid}}}");
                sw.WriteLine("\tEndGlobalSection");
                sw.WriteLine("EndGlobal");
                sw.Close();
            }

            Directory.SetCurrentDirectory(pwd);
        }
예제 #23
0
        /// <summary>
        /// Writes compiler_${ShortName}.props and compiler_$(ShortName}_compat.h
        /// </summary>
        public void WriteToFile(AbsoluteCrosspath solutionDir)
        {
            if (BaseCompiler.Skip)
            {
                return;
            }

            AbsoluteCrosspath xpath = solutionDir.Appended(RelativeCrosspath.FromString(CompilerInstanceCompatHeaderPath)).ToContainingDirectory();

            Directory.CreateDirectory(xpath.ToString());
            using (StreamWriter sw = new StreamWriter(CompilerInstanceCompatHeaderPath, false, Encoding.UTF8)) {
                sw.WriteLine(@"#pragma once");
                sw.WriteLine($"/* This is generated from compiler instance {BaseCompiler} {this} */");
                foreach (Define compilerInternalDefine in Defines)
                {
                    sw.WriteLine($"#define {compilerInternalDefine.Name} {compilerInternalDefine.Value}");
                }
            }

            XmlDocument doc = new XmlDocument();

            doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null));

            XmlElement projectNode = doc.CreateElement("Project");

            projectNode.SetAttribute("DefaultTargets", "Build");
            projectNode.SetAttribute("ToolsVersion", "Current");
            projectNode.SetAttribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");

            XmlElement projectImportProps = doc.CreateElement("Import");

            projectImportProps.SetAttribute("Project", $@"$(SolutionDir)\{BaseCompiler.PropsFileName}");
            projectNode.AppendChild(projectImportProps);

            // Platform settings

            /*
             * <ItemGroup Label="ProjectConfigurations">
             * <ProjectConfiguration Include="Debug|x64">
             * <Configuration>Debug</Configuration>
             * <Platform>x64</Platform>
             * </ProjectConfiguration>
             * <ProjectConfiguration Include="Release|x64">
             * <Configuration>Release</Configuration>
             * <Platform>x64</Platform>
             * </ProjectConfiguration>
             * </ItemGroup>
             */
            XmlElement projectItemGroupPlatform = doc.CreateElement("ItemGroup");

            projectItemGroupPlatform.SetAttribute("Label", "ProjectConfigurations");

            foreach (String buildConfiguration in SolutionStructure.SolutionConfigurations)
            {
                XmlElement projectPlatformConfiguration = doc.CreateElement("ProjectConfiguration");
                projectPlatformConfiguration.SetAttribute("Include", $"{buildConfiguration}|{VSPlatform}");
                XmlElement projectPlatformConfiguration_Configuration = doc.CreateElement("Configuration");
                projectPlatformConfiguration_Configuration.InnerText = buildConfiguration;
                projectPlatformConfiguration.AppendChild(projectPlatformConfiguration_Configuration);
                XmlElement projectPlatformConfiguration_Platform = doc.CreateElement("Platform");
                projectPlatformConfiguration_Platform.InnerText = VSPlatform.ToString();
                projectPlatformConfiguration.AppendChild(projectPlatformConfiguration_Platform);
                projectItemGroupPlatform.AppendChild(projectPlatformConfiguration);
            }

            projectNode.AppendChild(projectItemGroupPlatform);

            // IDU settings
            XmlElement projectPropertyGroupIDU = doc.CreateElement("PropertyGroup");

            XmlElement projectIncludePaths = doc.CreateElement("NMakeIncludeSearchPath");

            // DONE: intermix project include directories with compiler include directories
            foreach (IncludeDirectory includePath in IncludeDirectories)
            {
                projectIncludePaths.InnerText += includePath.GetLocalProjectPath(solutionDir) + ";";
            }
            projectIncludePaths.InnerText += "$(CompilerIncludeDirAfter);$(NMakeIncludeSearchPath)";
            projectPropertyGroupIDU.AppendChild(projectIncludePaths);

            // maybe someday this will be helpful, but now it can be inherited from Solution.props
            XmlElement projectForcedIncludes = doc.CreateElement("NMakeForcedIncludes");

            // DONE: add compiler compat header to forced includes
            projectForcedIncludes.InnerText = $@"$(SolutionDir)\solution_compat.h;$(SolutionDir)\{CompilerInstanceCompatHeaderPath};$(SolutionDir)\solution_post_compiler_compat.h";
            projectPropertyGroupIDU.AppendChild(projectForcedIncludes);

            XmlElement compilerForcedIncludes = doc.CreateElement("CompilerCompat");

            // DONE: add compiler compat header to forced includes
            compilerForcedIncludes.InnerText = $@"$(SolutionDir)\{CompilerInstanceCompatHeaderPath}";
            projectPropertyGroupIDU.AppendChild(compilerForcedIncludes);

            projectNode.AppendChild(projectPropertyGroupIDU);

            doc.AppendChild(projectNode);
            doc.Save(PropsFileName);
        }
예제 #24
0
 public IncludeDirectory(AbsoluteCrosspath path, IncludeDirectoryType type) : base(path)
 {
     Type      = type;
     ShortName = $"{serial:D4}";
     ++serial;
 }
예제 #25
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;
                }
            }
        }
예제 #26
0
 public void Rebase(AbsoluteCrosspath before, AbsoluteCrosspath after)
 {
     xpath.Rebase(before, after);
 }
예제 #27
0
 public void Polymorphism()
 {
     Crosspath         cpath   = Crosspath.FromString(@"/");
     AbsoluteCrosspath unused  = cpath as AbsoluteCrosspath;
     RelativeCrosspath unused1 = cpath as RelativeCrosspath;
 }
예제 #28
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="remote">Remote host to download from</param>
        /// <param name="localXpath">Local directory for remote include directories, e.g. D:\Project1\remote\192.168.0.1.</param>
        public void RebaseToLocal(RemoteHost remote, AbsoluteCrosspath localXpath)
        {
            if (this.Flavor == CrosspathFlavor.Windows)
            {
                return;
            }

            int xtractBufSize = 65536;

            Byte[] zipExtractBuf = new Byte[xtractBufSize];

            String remoteFilename        = $"/tmp/{ShortName}.zip";
            String localDirectoryPattern = $@"include\{ShortName}";
            String localFilenamePattern  = $"{ShortName}.zip";

            AbsoluteCrosspath xLocalIncludeDirectory = localXpath.Appended(RelativeCrosspath.FromString(localDirectoryPattern));
            String            localIncludeDirectory  = xLocalIncludeDirectory.ToString();
            String            localFilename          = localXpath.Appended(RelativeCrosspath.FromString(localFilenamePattern)).ToString();

            Logger.WriteLine(LogLevel.Info, $"Rolling {this} into {localFilenamePattern}...");
            Directory.CreateDirectory(localIncludeDirectory);
            if (remote.Execute($"pushd {this} && zip -1 -r -q {remoteFilename} . && popd", out String result) != RemoteHost.Success)
            {
                Logger.WriteLine(LogLevel.Error, result);
                // FIXME, hack
                this.Rebase(this, xLocalIncludeDirectory);
                autoDownloaded = true;
                return;
            }

            remote.DownloadFile(remoteFilename, localFilename);
            File.WriteAllText(xLocalIncludeDirectory.Appended(RelativeCrosspath.FromString($@"..\{ShortName}_origin.txt")).ToString(), this.ToString());

            // not working bcz of NTFS case & special names restrictions. extract manually.
            //ZipFile.ExtractToDirectory(localFilename, localDirectory, Encoding.UTF8);

            using (FileStream fs = new FileStream(localFilename, FileMode.Open)) {
                ZipArchive za = new ZipArchive(fs, ZipArchiveMode.Read);
                foreach (ZipArchiveEntry zaEntry in za.Entries)
                {
                    RelativeCrosspath xRelPath = RelativeCrosspath.FromString(zaEntry.FullName);
                    AbsoluteCrosspath xPath    = xLocalIncludeDirectory.Appended(xRelPath);
                    if (zaEntry.FullName.EndsWith("/"))
                    {
                        // packed directory
                        continue;
                    }

                    String path = xPath.ToString();
                    if (File.Exists(path))
                    {
                        Logger.WriteLine(LogLevel.Warning, $"file '{zaEntry.FullName}' already exists as '{path}' - case problems?");
                        continue;
                    }

                    // hax, remove leading / from path
                    if (xRelPath.ToString() == Compiler.RemoteTempFile.Substring(1))
                    {
                        continue;
                    }

                    String dirname = new AbsoluteCrosspath(xPath).ToContainingDirectory().ToString();
                    try {
                        Directory.CreateDirectory(dirname);
                        // packed file
                        using (FileStream xfs = new FileStream(path, FileMode.CreateNew)) {
                            using (Stream zas = zaEntry.Open()) {
                                while (true)
                                {
                                    int len = zas.Read(zipExtractBuf, 0, xtractBufSize);
                                    if (len == 0)
                                    {
                                        // EOF
                                        break;
                                    }

                                    xfs.Write(zipExtractBuf, 0, len);
                                }
                                zas.Close();
                            }
                        }
                    }
                    catch (Exception e) {
                        Logger.WriteLine(LogLevel.Error, $"Could not extract '${zaEntry.FullName}': ${e.Message}");
                    }
                }
            }

            // if extraction went ok, we can remove files
            remote.Execute($"rm {remoteFilename}", out String _);
            File.Delete(localFilename);

            // since we definitely have a local copy of include directory, rebase on it
            this.Rebase(this, xLocalIncludeDirectory);
            autoDownloaded = true;
        }
예제 #29
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, "============================================");
                }
            }
        }