示例#1
0
文件: Program.cs 项目: xllj/BSPTools
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                throw new Exception("Usage: risc-v.exe <freedom-e-sdk directory>");
            }

            var bspBuilder = new RISCVBSPBuilder(new BSPDirectories(args[0], @"..\..\Output", @"..\..\rules"));

            PathTools.CopyDirectoryRecursive(@"..\..\bsp-template", bspBuilder.Directories.OutputDir);

            var bsp = XmlTools.LoadObject <BoardSupportPackage>(Path.Combine(bspBuilder.BSPRoot, "bsp.xml"));

            var commonPseudofamily = new MCUFamilyBuilder(bspBuilder, XmlTools.LoadObject <FamilyDefinition>(bspBuilder.Directories.RulesDir + @"\CommonFiles.xml"));

            List <string> projectFiles = new List <string>();
            PropertyList  unused       = null;

            if (commonPseudofamily.Definition.CoreFramework != null)
            {
                foreach (var job in commonPseudofamily.Definition.CoreFramework.CopyJobs)
                {
                    job.CopyAndBuildFlags(bspBuilder, projectFiles, null, ref unused);
                }
            }

            List <EmbeddedFramework> frameworks = new List <EmbeddedFramework>(bsp.Frameworks);

            frameworks.AddRange(commonPseudofamily.GenerateFrameworkDefinitions());
            bsp.Frameworks = frameworks.ToArray();

            var samples = commonPseudofamily.CopySamples(frameworks).ToArray();

            bsp.Examples = samples.Select(s => s.RelativePath).ToArray();


            var mainFamily = bsp.MCUFamilies.First();

            if (mainFamily.AdditionalSourceFiles != null || mainFamily.AdditionalHeaderFiles != null || bsp.FileConditions != null)
            {
                throw new Exception("TODO: merge lists");
            }

            mainFamily.AdditionalSourceFiles = projectFiles.Where(f => !MCUFamilyBuilder.IsHeaderFile(f)).ToArray();
            mainFamily.AdditionalHeaderFiles = projectFiles.Where(f => MCUFamilyBuilder.IsHeaderFile(f)).ToArray();
            bsp.FileConditions = bspBuilder.MatchedFileConditions.ToArray();

            XmlTools.SaveObject(bsp, Path.Combine(bspBuilder.BSPRoot, "BSP.XML"));
        }
示例#2
0
        public void UpdateGitAndRescanTargets()
        {
            string gitExe    = (Registry.CurrentUser.OpenSubKey(@"Software\Sysprogs\BSPGenerators")?.GetValue("git") as string) ?? "git.exe";
            string pythonExe = (Registry.CurrentUser.OpenSubKey(@"Software\Sysprogs\BSPGenerators")?.GetValue("python") as string) ?? "python.exe";

            Process proc;

            if (Directory.Exists(mbedRoot))
            {
                proc = Process.Start(new ProcessStartInfo(gitExe, "reset --hard")
                {
                    WorkingDirectory = mbedRoot, UseShellExecute = false
                });
            }
            else
            {
                proc = Process.Start(new ProcessStartInfo(gitExe, $"clone https://github.com/ARMmbed/mbed-os.git mbed")
                {
                    WorkingDirectory = outputDir, UseShellExecute = false
                });
                proc.WaitForExit();

                if (proc.ExitCode != 0)
                {
                    throw new Exception("Git exited with code " + proc.ExitCode);
                }

                proc = Process.Start(new ProcessStartInfo(gitExe, $"checkout mbed-os-{Version}")
                {
                    WorkingDirectory = outputDir + "\\mbed", UseShellExecute = false
                });
            }
            proc.WaitForExit();

            if (proc.ExitCode != 0)
            {
                throw new Exception("Git exited with code " + proc.ExitCode);
            }

            foreach (var lds in Directory.GetFiles(mbedRoot, "*.ld", SearchOption.AllDirectories))
            {
                if (File.ReadAllText(lds).Contains("\n#if"))
                {
                    ProcessStartInfo preprocessInfo = new ProcessStartInfo($@"{toolchainDir}\bin\arm-eabi-cpp.exe", $"-P -C {lds} -o {lds}.preprocessed");
                    preprocessInfo.UseShellExecute = false;
                    preprocessInfo.EnvironmentVariables["PATH"] += $@";{toolchainDir}\bin";
                    proc = Process.Start(preprocessInfo);
                    proc.WaitForExit();

                    File.Copy(lds + ".preprocessed", lds, true);
                    File.Delete(lds + ".preprocessed");
                }
            }

            var patchedFile = Path.Combine(mbedRoot, @"tools\config\__init__.py");
            var lines       = File.ReadAllLines(patchedFile).ToList();
            var idx2        = Enumerable.Range(0, lines.Count).First(i => lines[i].Contains("self.value = int(value) if isinstance(value, bool) else value"));

            if (!lines[idx2 + 1].Contains("is_bool"))
            {
                lines.Insert(idx2 + 1, "        self.is_bool = isinstance(value, bool)  #Patch by Sysprogs");
                File.WriteAllLines(patchedFile, lines);
            }

            //7. Enable exporting LPC targets
            patchedFile = Path.Combine(mbedRoot, @"tools\export\exporters.py");
            lines       = File.ReadAllLines(patchedFile).ToList();
            string str = "target.post_binary_hook['function'] in whitelist:";

            idx2 = Enumerable.Range(0, lines.Count).FirstOrDefault(i => lines[i].Contains(str));
            if (idx2 > 0)
            {
                int subIdx = lines[idx2].IndexOf(str);
                lines[idx2] = lines[idx2].Substring(0, subIdx) + "True:";
                File.WriteAllLines(patchedFile, lines);
            }

            string sampleDir = Path.Combine(mbedRoot, "samples");

            if (Directory.Exists(sampleDir))
            {
                Directory.Delete(sampleDir, true);
            }
            PathTools.CopyDirectoryRecursive(Path.Combine(dataDir, "samples"), sampleDir);

            ProcessStartInfo bspGenInfo = new ProcessStartInfo(pythonExe, Path.Combine(dataDir, "BuildConfigExtractor.py"));

            bspGenInfo.UseShellExecute = false;
            bspGenInfo.EnvironmentVariables["PYTHONPATH"] = mbedRoot;
            bspGenInfo.EnvironmentVariables["PATH"]      += $@";{toolchainDir}\bin";
            proc = Process.Start(bspGenInfo);
            proc.WaitForExit();

            if (proc.ExitCode != 0)
            {
                throw new Exception("BSP generator exited with code " + proc.ExitCode);
            }
        }
示例#3
0
        public IEnumerable <CopiedSample> CopySamples(IEnumerable <EmbeddedFramework> allFrameworks = null, IEnumerable <SysVarEntry> extraVariablesToValidateSamples = null)
        {
            if (Definition.SmartSamples != null)
            {
                foreach (var sample in Definition.SmartSamples)
                {
                    string destFolder = Path.Combine(BSP.BSPRoot, sample.DestinationFolder);
                    string sourceDir  = sample.SourceFolder;
                    BSP.ExpandVariables(ref sourceDir);
                    PathTools.CopyDirectoryRecursive(sourceDir, destFolder);

                    var sampleObj = XmlTools.LoadObject <EmbeddedProjectSample>(Path.Combine(destFolder, "sample.xml"));
                    if (sample.AdditionalSources != null)
                    {
                        sampleObj.AdditionalSourcesToCopy = sample.AdditionalSources.Select(f =>
                        {
                            int idx = f.IndexOf("=>");
                            if (idx == -1)
                            {
                                return new AdditionalSourceFile {
                                    SourcePath = f
                                }
                            }
                            ;
                            else
                            {
                                return new AdditionalSourceFile {
                                    SourcePath = f.Substring(0, idx).Trim(), TargetFileName = f.Substring(idx + 2).Trim()
                                }
                            };
                        }).ToArray();

                        foreach (var f in sampleObj.AdditionalSourcesToCopy)
                        {
                            string path = f.SourcePath.Replace("$$SYS:BSP_ROOT$$", BSP.Directories.OutputDir);
                            if (!File.Exists(path))
                            {
                                if (extraVariablesToValidateSamples != null)
                                {
                                    foreach (var v in extraVariablesToValidateSamples)
                                    {
                                        path = path.Replace("$$" + v.Key + "$$", v.Value);
                                    }
                                }

                                if (!File.Exists(path))
                                {
                                    Console.WriteLine("Missing sample file: " + f.SourcePath);
                                }
                            }
                        }
                    }

                    if (sampleObj.MCUFilterRegex == null & allFrameworks != null && sampleObj.RequiredFrameworks != null)
                    {
                        string[] devices = null;

                        foreach (var fw in allFrameworks)
                        {
                            if (fw.MCUFilterRegex == null)
                            {
                                continue;
                            }

                            if (sampleObj.RequiredFrameworks.Contains(fw.ID) || sampleObj.RequiredFrameworks.Contains(fw.ClassID))
                            {
                                if (devices == null)
                                {
                                    devices = fw.MCUFilterRegex.Split('|');
                                }
                                else
                                {
                                    devices = devices.Intersect(fw.MCUFilterRegex.Split('|')).ToArray();
                                }
                            }
                        }

                        if (devices != null)
                        {
                            sampleObj.MCUFilterRegex = string.Join("|", devices);
                        }
                    }

                    if (sampleObj.MCUFilterRegex == null && sample.MCUFilterRegex != null)
                    {
                        sampleObj.MCUFilterRegex = sample.MCUFilterRegex;
                    }

                    XmlTools.SaveObject(sampleObj, Path.Combine(destFolder, "sample.xml"));
                    yield return(new CopiedSample {
                        RelativePath = sample.DestinationFolder, IsTestProjectSample = sample.IsTestProjectSample
                    });
                }
            }
        }
示例#4
0
        public IEnumerable <CopiedSample> CopySamples(IEnumerable <EmbeddedFramework> allFrameworks = null, IEnumerable <SysVarEntry> extraVariablesToValidateSamples = null)
        {
            if (Definition.SmartSamples != null)
            {
                foreach (var sample in Definition.SmartSamples)
                {
                    string destFolder = Path.Combine(BSP.BSPRoot, sample.DestinationFolder);
                    string sourceDir  = sample.SourceFolder;
                    BSP.ExpandVariables(ref sourceDir);

                    if (sample.CopyFilters == null)
                    {
                        PathTools.CopyDirectoryRecursive(sourceDir, destFolder);
                    }
                    else
                    {
                        var filters = new CopyFilters(sample.CopyFilters);
                        foreach (var fn in Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories))
                        {
                            string relPath = fn.Substring(sourceDir.Length).TrimStart('\\');
                            if (filters.IsMatch(relPath))
                            {
                                string targetPath = Path.Combine(destFolder, relPath);
                                Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
                                File.Copy(fn, targetPath);
                            }
                        }
                    }

                    if (sample.AdditionalBuildTimeSources != null)
                    {
                        foreach (var src in sample.AdditionalBuildTimeSources)
                        {
                            string source = src;
                            BSP.ExpandVariables(ref source);
                            string targetPath = Path.Combine(destFolder, Path.GetFileName(source));
                            File.Copy(source, targetPath);
                        }
                    }

                    if (sample.Patches != null)
                    {
                        foreach (var p in sample.Patches)
                        {
                            foreach (var fn in p.FilePath.Split(';'))
                            {
                                List <string> allLines = File.ReadAllLines(Path.Combine(destFolder, fn)).ToList();
                                p.Apply(allLines);
                                File.WriteAllLines(Path.Combine(destFolder, fn), allLines);
                            }
                        }
                    }

                    var sampleObj = sample.EmbeddedSample ?? XmlTools.LoadObject <EmbeddedProjectSample>(Path.Combine(destFolder, "sample.xml"));
                    if (sampleObj.RequiredFrameworks == null && allFrameworks != null)
                    {
                        sampleObj.RequiredFrameworks = allFrameworks.Where(fw => fw.DefaultEnabled).Select(fw => fw.ClassID ?? fw.ID)?.ToArray();
                    }

                    if (sample.AdditionalSources != null)
                    {
                        sampleObj.AdditionalSourcesToCopy = sample.AdditionalSources.Select(f =>
                        {
                            int idx = f.IndexOf("=>");
                            if (idx == -1)
                            {
                                return new AdditionalSourceFile {
                                    SourcePath = f
                                }
                            }
                            ;
                            else
                            {
                                return new AdditionalSourceFile {
                                    SourcePath = f.Substring(0, idx).Trim(), TargetFileName = f.Substring(idx + 2).Trim()
                                }
                            };
                        }).ToArray();


                        for (int i = 0; i < sampleObj.AdditionalSourcesToCopy.Length; i++)
                        {
                            string path = sampleObj.AdditionalSourcesToCopy[i].SourcePath.Replace("$$SYS:BSP_ROOT$$", BSP.Directories.OutputDir);
                            if (!File.Exists(path))
                            {
                                if (extraVariablesToValidateSamples != null)
                                {
                                    foreach (var v in extraVariablesToValidateSamples)
                                    {
                                        path = path.Replace("$$" + v.Key + "$$", v.Value);
                                    }
                                }

                                if (!File.Exists(path))
                                {
                                    var args = new MissingSampleFileArgs {
                                        UnexpandedPath = sampleObj.AdditionalSourcesToCopy[i].SourcePath, ExpandedPath = path
                                    };

                                    OnMissingSampleFile(args);
                                    if (args.SubstitutePath != null)
                                    {
                                        if (args.SubstitutePath.StartsWith(BSP.BSPRoot))
                                        {
                                            args.SubstitutePath = "$$SYS:BSP_ROOT$$" + args.SubstitutePath.Substring(BSP.BSPRoot.Length).Replace('\\', '/');
                                        }
                                        else if (args.SubstitutePath.StartsWith("$$"))
                                        {
                                            //Already encoded
                                        }
                                        else
                                        {
                                            throw new Exception("Invalid substitute path: " + args.SubstitutePath);
                                        }

                                        sampleObj.AdditionalSourcesToCopy[i].SourcePath = args.SubstitutePath;
                                    }
                                }
                            }
                        }
                    }

                    if (sampleObj.MCUFilterRegex == null & allFrameworks != null && sampleObj.RequiredFrameworks != null)
                    {
                        string[] devices = null;

                        foreach (var fw in allFrameworks)
                        {
                            if (fw.MCUFilterRegex == null)
                            {
                                continue;
                            }

                            if (sampleObj.RequiredFrameworks.Contains(fw.ID) || sampleObj.RequiredFrameworks.Contains(fw.ClassID))
                            {
                                if (devices == null)
                                {
                                    devices = fw.MCUFilterRegex.Split('|');
                                }
                                else
                                {
                                    devices = devices.Intersect(fw.MCUFilterRegex.Split('|')).ToArray();
                                }
                            }
                        }

                        if (devices != null)
                        {
                            sampleObj.MCUFilterRegex = string.Join("|", devices);
                        }
                    }

                    if (sampleObj.MCUFilterRegex == null && sample.MCUFilterRegex != null)
                    {
                        sampleObj.MCUFilterRegex = sample.MCUFilterRegex;
                    }

                    XmlTools.SaveObject(sampleObj, Path.Combine(destFolder, "sample.xml"));
                    yield return(new CopiedSample {
                        RelativePath = sample.DestinationFolder, IsTestProjectSample = sample.IsTestProjectSample
                    });
                }
            }
        }
示例#5
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                throw new Exception("Usage: esp32.exe <esp-idf directory>");
            }

            var bspBuilder = new ESP32BSPBuilder(new BSPDirectories(args[0], @"..\..\Output", @"..\..\rules"));

            PathTools.CopyDirectoryRecursive(@"..\..\bsp-template", bspBuilder.Directories.OutputDir);

            string registerSetFile = Path.Combine(bspBuilder.Directories.OutputDir, "registers.xml");
            var    registers       = PeripheralRegisterParser.ParsePeripheralRegisters(Path.Combine(bspBuilder.Directories.InputDir, "esp-idf"));

            XmlTools.SaveObject(new MCUDefinition {
                MCUName = "ESP32", RegisterSets = registers
            }, registerSetFile);

            var bsp = XmlTools.LoadObject <BoardSupportPackage>(Path.Combine(bspBuilder.BSPRoot, "bsp.xml"));

            var commonPseudofamily = new MCUFamilyBuilder(bspBuilder, XmlTools.LoadObject <FamilyDefinition>(bspBuilder.Directories.RulesDir + @"\CommonFiles.xml"));
            List <EmbeddedFramework> frameworks = new List <EmbeddedFramework>(bsp.Frameworks);

            frameworks.AddRange(commonPseudofamily.GenerateFrameworkDefinitions());
            bsp.Frameworks = frameworks.ToArray();

            List <string> projectFiles = new List <string>();

            if (commonPseudofamily.Definition.CoreFramework != null)
            {
                foreach (var job in commonPseudofamily.Definition.CoreFramework.CopyJobs)
                {
                    job.CopyAndBuildFlags(bspBuilder, projectFiles, null);
                }
            }

            var mainFamily = bsp.MCUFamilies.First();

            if (mainFamily.AdditionalSourceFiles != null || mainFamily.AdditionalHeaderFiles != null || bsp.FileConditions != null)
            {
                throw new Exception("TODO: merge lists");
            }

            mainFamily.AdditionalSourceFiles = projectFiles.Where(f => !MCUFamilyBuilder.IsHeaderFile(f)).ToArray();
            mainFamily.AdditionalHeaderFiles = projectFiles.Where(f => MCUFamilyBuilder.IsHeaderFile(f)).ToArray();
            bsp.FileConditions = bspBuilder.MatchedFileConditions.ToArray();

            foreach (var fn in Directory.GetFiles(Path.Combine(bspBuilder.Directories.OutputDir, @"esp-idf\components\nghttp"), "*.?", SearchOption.AllDirectories))
            {
                string ext = Path.GetExtension(fn).ToLower();
                if (ext != ".c" && ext != ".h")
                {
                    continue;
                }

                var  lines   = File.ReadAllLines(fn);
                bool changed = false;
                for (int i = 0; i < lines.Length; i++)
                {
                    if (lines[i].Contains("<config.h>"))
                    {
                        lines[i] = lines[i].Replace("<config.h>", "<nghttp-config.h>");
                        changed  = true;
                    }
                }
                if (changed)
                {
                    File.WriteAllLines(fn, lines);
                }
            }

            foreach (var mcu in bsp.SupportedMCUs)
            {
                mcu.MCUDefinitionFile = Path.GetFileName(registerSetFile);
            }

            File.WriteAllText(Path.Combine(bspBuilder.Directories.OutputDir, @"esp-idf\components\nghttp\port\include\nghttp-config.h"), "#include \"config.h\"\n");

            string linkerScript    = Path.Combine(bspBuilder.Directories.OutputDir, @"esp-idf\components\esp32\ld\esp32.common.ld");
            var    lines2          = File.ReadAllLines(linkerScript).ToList();
            Regex  rgLibrary       = new Regex(@"(.*)\*lib([0-9a-zA-Z_]+).a:\(([^()]+)\)");
            Regex  rgFileInLibrary = new Regex(@"(.*)\*lib([0-9a-zA-Z_]+).a:([0-9a-zA-Z]+\.o)\(([^()]+)\)");

            for (int i = 0; i < lines2.Count; i++)
            {
                var m = rgLibrary.Match(lines2[i]);
                if (m.Success)
                {
                    string dir = Path.Combine(bspBuilder.Directories.OutputDir, @"esp-idf\components\" + m.Groups[2].Value);
                    if (Directory.Exists(dir))
                    {
                        string[] fns = Directory.GetFiles(dir)
                                       .Select(f => Path.GetFileName(f))
                                       .Where(f => f.EndsWith(".S", StringComparison.InvariantCultureIgnoreCase) || f.EndsWith(".c", StringComparison.InvariantCultureIgnoreCase))
                                       .Select(f => Path.ChangeExtension(f, ".o"))
                                       .OrderBy(f => f)
                                       .ToArray();

                        int j = 0;

                        foreach (var fn in fns)
                        {
                            lines2.Insert(i + ++j, $"{m.Groups[1].Value}*{fn}({m.Groups[3].Value})");
                        }
                        lines2.RemoveAt(i--);
                        continue;
                    }
                }
                m = rgFileInLibrary.Match(lines2[i]);
                if (m.Success)
                {
                    lines2[i] = $"{m.Groups[1].Value}*{m.Groups[3].Value}({m.Groups[4].Value})";
                }
            }
            File.WriteAllLines(linkerScript, lines2);

            XmlTools.SaveObject(bsp, Path.Combine(bspBuilder.BSPRoot, "BSP.XML"));
        }
示例#6
0
        static void Main(string[] args)
        {
            string outputDir = Path.GetFullPath(@"..\..\Output");
            string dataDir   = Path.GetFullPath(@"..\..\data");

            Directory.CreateDirectory(outputDir);
            string mbedRoot = Path.Combine(outputDir, "mbed");

            List <KeyValuePair <Regex, string> > nameRules = new List <KeyValuePair <Regex, string> >();

            foreach (var line in File.ReadAllLines(Path.Combine(dataDir, "DeviceNameRules.txt")))
            {
                int idx = line.IndexOf('=');
                nameRules.Add(new KeyValuePair <Regex, string>(new Regex(line.Substring(0, idx).Trim()), line.Substring(idx + 1).Trim()));
            }

            bool regenerate = true;

            if (regenerate)
            {
                string gitExe    = (Registry.CurrentUser.OpenSubKey(@"Software\Sysprogs\BSPGenerators")?.GetValue("git") as string) ?? "git.exe";
                string pythonExe = (Registry.CurrentUser.OpenSubKey(@"Software\Sysprogs\BSPGenerators")?.GetValue("python") as string) ?? "python.exe";

                Process proc;
                if (Directory.Exists(mbedRoot))
                {
                    // Prevent pull fail due to modified files
                    proc = Process.Start(new ProcessStartInfo(gitExe, "reset --hard")
                    {
                        WorkingDirectory = mbedRoot, UseShellExecute = false
                    });
                    proc.WaitForExit();
                    if (proc.ExitCode != 0)
                    {
                        throw new Exception("Git reset command exited with code " + proc.ExitCode);
                    }
                    proc = Process.Start(new ProcessStartInfo(gitExe, "pull origin fix_5.2")
                    {
                        WorkingDirectory = mbedRoot, UseShellExecute = false
                    });
                }
                else
                {
                    proc = Process.Start(new ProcessStartInfo(gitExe, "clone https://github.com/oter/mbed-os.git -b fix_5.2 mbed")
                    {
                        WorkingDirectory = outputDir, UseShellExecute = false
                    });
                }
                proc.WaitForExit();
                if (proc.ExitCode != 0)
                {
                    throw new Exception("Git exited with code " + proc.ExitCode);
                }

                string sampleDir = Path.Combine(mbedRoot, "samples");
                if (Directory.Exists(sampleDir))
                {
                    Directory.Delete(sampleDir, true);
                }
                PathTools.CopyDirectoryRecursive(Path.Combine(dataDir, "samples"), sampleDir);

                ProcessStartInfo bspGenInfo = new ProcessStartInfo(pythonExe, Path.Combine(dataDir, "visualgdb_bsp.py") + " --alltargets");
                bspGenInfo.UseShellExecute = false;
                bspGenInfo.EnvironmentVariables["PYTHONPATH"] = mbedRoot;
                proc = Process.Start(bspGenInfo);
                proc.WaitForExit();

                if (proc.ExitCode != 0)
                {
                    throw new Exception("BSP generator exited with code " + proc.ExitCode);
                }
            }

            File.Copy(Path.Combine(dataDir, "stubs.cpp"), Path.Combine(mbedRoot, "stubs.cpp"), true);
            Dictionary <string, string> mcuDefs = new Dictionary <string, string>();
            var linkedBSPs = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\VisualGDB\EmbeddedBSPs\arm-eabi", "*.bsplink").Select(f => File.ReadAllText(f));

            foreach (var dir in Directory.GetDirectories(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\VisualGDB\EmbeddedBSPs\arm-eabi").Concat(linkedBSPs))
            {
                var anotherBSP = XmlTools.LoadObject <BoardSupportPackage>(Path.Combine(dir, "bsp.xml"));
                foreach (var mcu in anotherBSP.SupportedMCUs)
                {
                    if (mcu.MCUDefinitionFile != null)
                    {
                        mcuDefs[mcu.ID] = Path.Combine(dir, mcu.MCUDefinitionFile);
                    }
                }
            }

            string bspFile = Path.Combine(mbedRoot, "BSP.xml");
            var    bsp     = XmlTools.LoadObject <BoardSupportPackage>(bspFile);
            var    defDir  = Directory.CreateDirectory(Path.Combine(mbedRoot, "DeviceDefinitions"));

            foreach (var mcu in bsp.SupportedMCUs)
            {
                foreach (var rule in nameRules)
                {
                    var m = rule.Key.Match(mcu.ID);
                    if (m.Success)
                    {
                        string devRegex = rule.Value;
                        for (int i = 1; i < m.Groups.Count; i++)
                        {
                            devRegex = devRegex.Replace(@"\" + i, m.Groups[i].Value);
                        }

                        Regex  devRegexObj = new Regex(devRegex);
                        string definition  = null;
                        foreach (var dev in mcuDefs)
                        {
                            if (devRegexObj.IsMatch(dev.Key))
                            {
                                definition = dev.Value;
                            }
                        }

                        if (definition == null)
                        {
                            Console.WriteLine("Warning: cannot find device register definition for " + devRegex);
                        }
                        else
                        {
                            mcu.MCUDefinitionFile = "DeviceDefinitions/" + Path.GetFileName(definition);
                            File.Copy(definition + ".gz", Path.Combine(mbedRoot, mcu.MCUDefinitionFile + ".gz"), true);
                        }
                        break;
                    }
                }
            }
            ProduceBSPArchive(mbedRoot, bsp);

            var  testfFiles   = new TestInfo[] { new TestInfo("test_usbcd.xml", 0, 0), new TestInfo("test_ledblink_rtos.xml", 0, 0), new TestInfo("test_ledblink.xml", 0, 0), };
            bool performTests = true;

            if (performTests)
            {
                foreach (var test in testfFiles)
                {
                    Console.WriteLine("Testing BSP...");
                    var job = XmlTools.LoadObject <TestJob>(Path.Combine(dataDir, test.Filename));
                    if (job.ToolchainPath.StartsWith("["))
                    {
                        job.ToolchainPath = (string)Registry.CurrentUser.OpenSubKey(@"Software\Sysprogs\GNUToolchains").GetValue(job.ToolchainPath.Trim('[', ']'));
                        if (job.ToolchainPath == null)
                        {
                            throw new Exception("Cannot locate toolchain path from registry");
                        }
                    }
                    var toolchain = LoadedToolchain.Load(Environment.ExpandEnvironmentVariables(job.ToolchainPath), new ToolchainRelocationManager());
                    var lbsp      = LoadedBSP.Load(new BSPManager.BSPSummary(Environment.ExpandEnvironmentVariables(Path.Combine(outputDir, "mbed"))), toolchain);
                    var r         = StandaloneBSPValidator.Program.TestBSP(job, lbsp, Path.Combine(outputDir, "TestResults"));
                    test.Passed = r.Passed;
                    test.Failed = r.Failed;
                }

                foreach (var test in testfFiles)
                {
                    Console.WriteLine("Results for the test: " + test.Filename);
                    Console.WriteLine("Passed: " + test.Passed.ToString());
                    Console.WriteLine("Failed: " + test.Failed.ToString());
                    Console.WriteLine();
                }
            }
        }