public GeneratedProject(LoadedBSP.ConfiguredMCU mcu, VendorSample vs, string projectDir, Dictionary <string, string> bspDict, string[] frameworks) : this(projectDir, mcu, frameworks) { _ProjectDir = projectDir; _LinkerScript = vs.LinkerScript; _SourceFiles.AddRange(vs.SourceFiles.Select(s => VariableHelper.ExpandVariables(s, bspDict))); var cf = vs.ExtraFiles?.Select(s1 => { var s2 = VariableHelper.ExpandVariables(s1.SourcePath, bspDict); var targetFile = projectDir + "\\" + s1.TargetPath.Replace("/", "\\"); var pth = Path.GetDirectoryName(targetFile); if (!Directory.Exists(pth)) { Directory.CreateDirectory(pth); } if (!File.Exists(targetFile)) { File.Copy(s2.Replace("/", "\\"), targetFile); } return(s1.TargetPath); }); if (cf != null) { _SourceFiles.AddRange(cf); } }
public GeneratedProject(LoadedBSP.ConfiguredMCU mcu, VendorSample vs, string projectDir, Dictionary <string, string> bspDict, string[] frameworks) : this(projectDir, mcu, frameworks) { _ProjectDir = projectDir; _SourceFiles.AddRange(vs.SourceFiles.Select(s => VariableHelper.ExpandVariables(s, bspDict))); }
public GeneratedProject(LoadedBSP.ConfiguredMCU mcu, VendorSample vs, string projectDir, Dictionary<string, string> bspDict, string[] frameworks) : this(projectDir, mcu, frameworks) { _ProjectDir = projectDir; _SourceFiles.AddRange(vs.SourceFiles.Select(s=>VariableHelper.ExpandVariables(s, bspDict))); }
protected virtual void AdjustVendorSampleProperties(VendorSample vs) { if (vs.SourceFiles.FirstOrDefault(f => ShouldFileTriggerHardFloat(f)) != null) { if (vs.Configuration.MCUConfiguration != null) { var dict = PropertyDictionary2.ReadPropertyDictionary(vs.Configuration.MCUConfiguration); dict["com.sysprogs.bspoptions.arm.floatmode"] = "-mfloat-abi=hard"; vs.Configuration.MCUConfiguration = new PropertyDictionary2 { Entries = dict.Select(kv => new PropertyDictionary2.KeyValue { Key = kv.Key, Value = kv.Value }).ToArray() }; } else { vs.Configuration.MCUConfiguration = new PropertyDictionary2 { Entries = new PropertyDictionary2.KeyValue[] { new PropertyDictionary2.KeyValue { Key = "com.sysprogs.bspoptions.arm.floatmode", Value = "-mfloat-abi=hard" } } }; } } }
static bool IsNonGCCFile(VendorSample vs, string fn) { if (fn.StartsWith(vs.Path + @"\MDK-ARM", StringComparison.InvariantCultureIgnoreCase)) { return(true); } return(false); }
protected override void AdjustVendorSampleProperties(VendorSample vs) { base.AdjustVendorSampleProperties(vs); vs.SourceFiles = vs.SourceFiles.Where(s => !IsNonGCCFile(vs, s)).ToArray(); if (vs.SourceFiles.FirstOrDefault(f => f.Contains("libBle_Mesh_CM4_GCC")) != null) { var dict = PropertyDictionary2.ReadPropertyDictionary(vs.Configuration.MCUConfiguration); dict["com.sysprogs.bspoptions.arm.floatmode"] = "-mfloat-abi=soft"; vs.Configuration.MCUConfiguration = new PropertyDictionary2(dict); } }
private static TestResult BuildAndRunValidationJob(LoadedBSP.LoadedMCU mcu, string mcuDir, bool validateRegisters, LoadedRenamingRule[] renameRules, GeneratedProject prj, ToolFlags flags, Dictionary <string, bool> sourceExtensions, string[] nonValidateReg, string[] UndefinedMacros, VendorSample vendorSample = null, bool keepDirectoryAfterSuccessfulBuild = false) { BuildJob job = new BuildJob(); string prefix = string.Format("{0}\\{1}\\{2}-", mcu.BSP.Toolchain.Directory, mcu.BSP.Toolchain.Toolchain.BinaryDirectory, mcu.BSP.Toolchain.Toolchain.GNUTargetID); job.OtherTasks.Add(new BuildTask { Executable = prefix + "g++", Arguments = $"{flags.StartGroup} {flags.EffectiveLDFLAGS} $^ {flags.EndGroup} -o $@", AllInputs = prj.SourceFiles.Where(f => sourceExtensions.ContainsKey(Path.GetExtension(f).TrimStart('.'))) .Select(f => Path.ChangeExtension(Path.GetFileName(f), ".o")) .Concat(prj.SourceFiles.Where(f => f.EndsWith(".a", StringComparison.InvariantCultureIgnoreCase))) .ToArray(), PrimaryOutput = "test.elf", }); job.OtherTasks.Add(new BuildTask { Executable = prefix + "objcopy", Arguments = "-O binary $< $@", AllInputs = new[] { "test.elf" }, PrimaryOutput = "test.bin", }); foreach (var sf in prj.SourceFiles) { var sfE = sf.Replace('\\', '/'); string ext = Path.GetExtension(sf); if (!sourceExtensions.ContainsKey(ext.TrimStart('.'))) { if (ext != ".txt" && ext != ".a" && ext != ".h") { Console.WriteLine($"#{sf} is not a recognized source file"); } } else { bool isCpp = ext.ToLower() != ".c"; string obj = Path.ChangeExtension(Path.GetFileName(sfE), ".o"); job.CompileTasks.Add(new BuildTask { PrimaryOutput = Path.ChangeExtension(Path.GetFileName(sfE), ".o"), AllInputs = new[] { sfE }, Executable = prefix + (isCpp ? "g++" : "gcc"), Arguments = $"-c $< { (isCpp ? "-std=gnu++11 " : " ")} {flags.GetEffectiveCFLAGS(isCpp, ToolFlags.FlagEscapingMode.ForMakefile)} -o {obj}".Replace('\\', '/').Replace("/\"", "\\\""), }); } } bool errorsFound = false; foreach (var g in job.CompileTasks.GroupBy(t => t.PrimaryOutput.ToLower())) { if (g.Count() > 1) { Console.WriteLine($"ERROR: {g.Key} corresponds to the following files:"); foreach (var f in g) { Console.WriteLine("\t" + f.AllInputs.FirstOrDefault()); } errorsFound = true; } } if (errorsFound) { throw new Exception("Multiple source files with the same name found"); } List <string> comments = new List <string>(); comments.Add("Tool flags:"); comments.Add("\tInclude directories:"); foreach (var dir in flags.IncludeDirectories ?? new string[0]) { comments.Add("\t\t" + dir); } comments.Add("\tPreprocessor macros:"); foreach (var dir in flags.PreprocessorMacros ?? new string[0]) { comments.Add("\t\t" + dir); } comments.Add("\tLibrary directories:"); foreach (var dir in flags.AdditionalLibraryDirectories ?? new string[0]) { comments.Add("\t\t" + dir); } comments.Add("\tLibrary names:"); foreach (var dir in flags.AdditionalLibraries ?? new string[0]) { comments.Add("\t\t" + dir); } comments.Add("\tExtra linker inputs:"); foreach (var dir in flags.AdditionalLinkerInputs ?? new string[0]) { comments.Add("\t\t" + dir); } comments.Add("\tCFLAGS:" + flags.CFLAGS); comments.Add("\tCXXFLAGS:" + flags.CXXFLAGS); comments.Add("\tLDFLAGS:" + flags.LDFLAGS); comments.Add("\tCOMMONFLAGS:" + flags.COMMONFLAGS); job.GenerateMakeFile(Path.Combine(mcuDir, "Makefile"), "test.bin", comments); if (!string.IsNullOrEmpty(mcu.MCUDefinitionFile) && validateRegisters) { string firstSrcFileInPrjDir = prj.SourceFiles.First(fn => Path.GetDirectoryName(fn) == mcuDir); InsertRegisterValidationCode(firstSrcFileInPrjDir, XmlTools.LoadObject <MCUDefinition>(mcu.MCUDefinitionFile), renameRules, nonValidateReg, UndefinedMacros); } bool buildSucceeded; if (true) { var proc = Process.Start(new ProcessStartInfo("cmd.exe", "/c " + Path.Combine(mcu.BSP.Toolchain.Directory, mcu.BSP.Toolchain.Toolchain.BinaryDirectory, "make.exe") + " -j" + Environment.ProcessorCount + " > build.log 2>&1") { UseShellExecute = false, CreateNoWindow = true, WorkingDirectory = mcuDir }); proc.WaitForExit(); buildSucceeded = proc.ExitCode == 0; } else { buildSucceeded = job.BuildFast(mcuDir, Environment.ProcessorCount); } bool success = false; string mapFile = Path.Combine(mcuDir, GeneratedProject.MapFileName); if (buildSucceeded && File.Exists(mapFile)) { success = File.ReadAllLines(Path.Combine(mcuDir, mapFile)).Where(l => RgMainMap.IsMatch(l)).Count() > 0; if (success) { string binFile = Path.Combine(mcuDir, "test.bin"); using (var fs = File.Open(binFile, FileMode.Open)) if (fs.Length < 512) { success = false; } } } if (!success) { if (vendorSample != null) { vendorSample.AllDependencies = null; } return(new TestResult(TestBuildResult.Failed, Path.Combine(mcuDir, "build.log"))); } if (vendorSample != null) { vendorSample.AllDependencies = Directory.GetFiles(mcuDir, "*.d") .SelectMany(f => SplitDependencyFile(f).Where(t => !t.EndsWith(":"))) .Distinct() .ToArray(); } if (!keepDirectoryAfterSuccessfulBuild) { Directory.Delete(mcuDir, true); } return(new TestResult(TestBuildResult.Succeeded, Path.Combine(mcuDir, "build.log"))); }
public static ParsedSDK ParseKSDKManifest(string sdkDirectory, IWarningSink sink) { string[] manifestFiles = Directory.GetFiles(sdkDirectory, "*manifest.xml"); if (manifestFiles.Length < 1) { throw new Exception($"No manifest files in {sdkDirectory}"); } string manifestFile = Directory.GetFiles(sdkDirectory, "*manifest.xml")[0]; List <VendorSample> vsl = new List <VendorSample>(); XmlDocument doc = new XmlDocument(); doc.Load(manifestFile); List <MCU> mcus = new List <MCU>(); List <MCUFamily> families = new List <MCUFamily>(); List <ParsedComponent> allFrameworks = new List <ParsedComponent>(); bool linkerScriptHandled = false; List <string> allFiles = new List <string>(); Dictionary <string, ParsedDevice> deviceDict = new Dictionary <string, ParsedDevice>(); Dictionary <string, EmbeddedFramework> frameworkDict = new Dictionary <string, EmbeddedFramework>(); List <FileCondition> allConditions = new List <FileCondition>(); string fwPrefix = "com.sysprogs.ksdk2x_imported."; HashSet <string> alwaysIncludedFrameworks = new HashSet <string>(); foreach (XmlElement devNode in doc.SelectNodes("//devices/device")) { ParsedDevice dev = new ParsedDevice(devNode, sdkDirectory); var mcuFamily = dev.ToMCUFamily(); int FLASHSize, RAMSize; int.TryParse((devNode.SelectSingleNode("memory/@flash_size_kb")?.Value ?? ""), out FLASHSize); int.TryParse((devNode.SelectSingleNode("memory/@ram_size_kb")?.Value ?? ""), out RAMSize); FLASHSize *= 1024; RAMSize *= 1024; families.Add(mcuFamily); string svdFile = null; //Map each component to an instance of EmbeddedFramework foreach (XmlNode componentNode in doc.SelectNodes($"//components/component")) { string componentName = componentNode.SelectSingleNode("@name")?.Value ?? ""; string componentType = componentNode.SelectSingleNode("@type")?.Value ?? ""; string device = componentNode.SelectSingleNode("@device")?.Value ?? ""; switch (componentType) { case "documentation": case "SCR": case "EULA": continue; case "debugger": case "linker": { List <string> relPaths = new List <string>(); bool isDebug = componentType == "debugger"; string sourceType = isDebug ? "debug" : "linker"; foreach (var src in componentNode.SelectNodes($"source[@type='{sourceType}']").OfType <XmlElement>().Select(e => new ParsedSource(e, dev))) { foreach (var fn in src.AllFiles) { relPaths.Add(fn.RelativePath); } } if (relPaths.Count > 0) { if (isDebug) { svdFile = relPaths[0]; } else if (!linkerScriptHandled) { linkerScriptHandled = true; if (relPaths.Count == 1) { mcuFamily.CompilationFlags.LinkerScript = "$$SYS:BSP_ROOT$$/" + relPaths[0]; } else { const string optionID = "com.sysprogs.imported.ksdk2x.linker_script"; mcuFamily.CompilationFlags.LinkerScript = $"$$SYS:BSP_ROOT$$/$${optionID}$$"; mcuFamily.ConfigurableProperties.PropertyGroups[0].Properties.Add(new PropertyEntry.Enumerated { UniqueID = optionID, Name = "Linker script", AllowFreeEntry = false, SuggestionList = relPaths.Select(p => new PropertyEntry.Enumerated.Suggestion { InternalValue = p, UserFriendlyName = Path.GetFileName(p) }).ToArray() }); } } } } continue; case "CMSIS": //KSDK 2.x defines a Include_xxx framework for each possible CMSIS core. Those frameworks are redundant (normal 'Include' framework references the same include path) and should be removed to avoid confusion. if (componentName.StartsWith("Include_")) { continue; } if (componentName == "Include") { alwaysIncludedFrameworks.Add(fwPrefix + componentName); } break; default: break; } List <string> headerFiles = new List <string>(); List <string> includeDirectories = new List <string>(); List <string> sourceFiles = new List <string>(); foreach (ParsedSource src in componentNode.SelectNodes("source").OfType <XmlElement>().Select(e => new ParsedSource(e, dev))) { if (src.Type == "c_include") { includeDirectories.Add(src.BSPPath); } foreach (var file in src.AllFiles) { if (src.Type == "src" || src.Type == "asm_include") { sourceFiles.Add(file.BSPPath); } else if (src.Type == "c_include") { headerFiles.Add(file.BSPPath); } } } if (componentName == "clock" && componentType == "driver") { alwaysIncludedFrameworks.Add(fwPrefix + componentName); } string[] dependencyList = componentNode.Attributes?.GetNamedItem("dependency")?.Value?.Split(' ') ?.Select(id => fwPrefix + id) ?.ToArray() ?? new string[0]; EmbeddedFramework fw = new EmbeddedFramework { ID = $"{fwPrefix}{componentName}", UserFriendlyName = $"{componentName} ({componentType})", ProjectFolderName = componentName, AdditionalSourceFiles = sourceFiles.Distinct().ToArray(), AdditionalHeaderFiles = headerFiles.Distinct().ToArray(), RequiredFrameworks = dependencyList, AdditionalIncludeDirs = includeDirectories.Distinct().ToArray(), AdditionalPreprocessorMacros = componentNode.SelectNodes("defines/define").OfType <XmlElement>().Select(el => new ParsedDefine(el).Definition).ToArray(), }; if (componentName == "freertos" && componentType == "OS") { fw.AdditionalPreprocessorMacros = LoadedBSP.Combine(fw.AdditionalPreprocessorMacros, "USE_RTOS=1;USE_FREERTOS".Split(';')); fw.ConfigurableProperties = new PropertyList { PropertyGroups = new List <PropertyGroup>() { new PropertyGroup { Properties = new List <PropertyEntry>() { new PropertyEntry.Enumerated { Name = "FreeRTOS Heap Implementation", UniqueID = "com.sysprogs.bspoptions.stm32.freertos.heap", DefaultEntryIndex = 3, SuggestionList = new PropertyEntry.Enumerated.Suggestion[] { new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_1", UserFriendlyName = "Heap1 - no support for freeing" }, new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_2", UserFriendlyName = "Heap2 - no block consolidation" }, new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_3", UserFriendlyName = "Heap3 - use newlib malloc()/free()" }, new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_4", UserFriendlyName = "Heap4 - contiguous heap area" }, new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_5", UserFriendlyName = "Heap5 - scattered heap area" }, } } } } } }; foreach (var fn in fw.AdditionalSourceFiles) { string name = Path.GetFileName(fn); if (name.StartsWith("heap_")) { allConditions.Add(new FileCondition { FilePath = fn, ConditionToInclude = new Condition.Equals { Expression = "$$com.sysprogs.bspoptions.stm32.freertos.heap$$", ExpectedValue = Path.GetFileNameWithoutExtension(fn) } }); } } } if (frameworkDict.ContainsKey(fw.ID)) { sink.LogWarning("Duplicate framework for " + fw.ID); continue; } frameworkDict[fw.ID] = fw; if (string.IsNullOrEmpty(fw.ID)) { sink.LogWarning($"Found a framework with empty ID. Skipping..."); continue; } if (string.IsNullOrEmpty(fw.UserFriendlyName)) { fw.UserFriendlyName = fw.ID; } allFrameworks.Add(new ParsedComponent { Framework = fw, OriginalType = componentType, OriginalName = componentName }); allFiles.AddRange(sourceFiles); allFiles.AddRange(headerFiles); } string deviceDefinitionFile = null; if (svdFile != null) { try { var mcuDef = SVDParser.ParseSVDFile(Path.Combine(sdkDirectory, svdFile), dev.DeviceName); deviceDefinitionFile = Path.ChangeExtension(svdFile, ".vgdbdevice"); XmlSerializer ser = new XmlSerializer(typeof(MCUDefinition)); using (var fs = File.Create(Path.Combine(sdkDirectory, Path.ChangeExtension(svdFile, ".vgdbdevice.gz")))) using (var gs = new GZipStream(fs, CompressionMode.Compress, true)) ser.Serialize(gs, new MCUDefinition(mcuDef)); } catch (Exception ex) { sink.LogWarning($"Failed to parse {svdFile}: {ex.Message}"); } } foreach (XmlNode packageNode in devNode.SelectNodes($"package/@name")) { string pkgName = packageNode?.Value; if (string.IsNullOrEmpty(pkgName)) { continue; } deviceDict[pkgName] = dev; mcus.Add(new MCU { ID = pkgName, UserFriendlyName = $"{pkgName} (KSDK 2.x)", FamilyID = mcuFamily.ID, FLASHSize = FLASHSize, RAMSize = RAMSize, CompilationFlags = new ToolFlags { PreprocessorMacros = new string[] { "CPU_" + pkgName } }, MCUDefinitionFile = deviceDefinitionFile }); } } if (families.Count == 0) { throw new Exception("The selected KSDK contains no families"); } List <VendorSample> samples = new List <VendorSample>(); foreach (XmlElement boardNode in doc.SelectNodes("//boards/board")) { string boardName = boardNode.GetAttribute("name"); string deviceID = boardNode.GetAttribute("package"); ParsedDevice dev; if (!deviceDict.TryGetValue(deviceID, out dev)) { continue; } foreach (XmlElement exampleNode in boardNode.SelectNodes("examples/example")) { List <string> dependencyList = new List <string>(exampleNode.Attributes?.GetNamedItem("dependency")?.Value?.Split(' ') ?.Select(id => fwPrefix + id) ?? new string[0]); dependencyList.AddRange(alwaysIncludedFrameworks); for (int i = 0; i < dependencyList.Count; i++) { EmbeddedFramework fw; if (frameworkDict.TryGetValue(dependencyList[i], out fw) && fw?.RequiredFrameworks != null) { dependencyList.AddRange(fw.RequiredFrameworks.Except(dependencyList)); } } VendorSample sample = new VendorSample { DeviceID = deviceID, UserFriendlyName = exampleNode.GetAttribute("name") ?? "???", BoardName = boardName, Configuration = new VendorSampleConfiguration { Frameworks = dependencyList.ToArray() }, VirtualPath = exampleNode.GetAttribute("category"), NoImplicitCopy = true }; List <string> headerFiles = new List <string>(); List <string> includeDirectories = new List <string>(); List <string> sourceFiles = new List <string>(); foreach (var src in exampleNode.SelectNodes("source").OfType <XmlElement>().Select(e => new ParsedSource(e, dev))) { foreach (var file in src.AllFiles) { if (src.Type == "src" || src.Type == "asm_include") { sourceFiles.Add(file.BSPPath); } else if (src.Type == "c_include") { headerFiles.Add(file.BSPPath); } } } sample.SourceFiles = sourceFiles.ToArray(); sample.HeaderFiles = headerFiles.ToArray(); if (sourceFiles.Count == 0 && headerFiles.Count == 0) { continue; } string[] matchingComponents = null; foreach (var fn in sourceFiles.Concat(headerFiles)) { string[] components = fn.Split('/', '\\'); if (matchingComponents == null) { matchingComponents = components; } else { int matches = CountMatches(matchingComponents, components); if (matches < matchingComponents.Length) { Array.Resize(ref matchingComponents, matches); } } } if (matchingComponents != null) { sample.Path = string.Join("/", matchingComponents); } samples.Add(sample); } } return(new ParsedSDK { BSP = new BoardSupportPackage { PackageID = "com.sysprogs.imported.ksdk2x." + families[0].ID, PackageDescription = "Imported KSDK 2.x for " + families[0].ID, PackageVersion = doc.SelectSingleNode("//ksdk/@version")?.Value ?? "unknown", GNUTargetID = "arm-eabi", Frameworks = allFrameworks.Where(f => f.OriginalType != "project_template").Select(f => f.Framework).ToArray(), MCUFamilies = families.ToArray(), SupportedMCUs = mcus.ToArray(), FileConditions = allFiles .Where(f => f.IndexOf("freertos", StringComparison.InvariantCultureIgnoreCase) != -1) .Select(f => new FileCondition { FilePath = f, ConditionToInclude = new Condition.ReferencesFramework { FrameworkID = fwPrefix + "freertos" } }) .Concat(allConditions) .ToArray(), VendorSampleCatalogName = "KSDK Samples", EmbeddedSamples = allFrameworks.Where(f => f.OriginalType == "project_template").Select(f => f.ToProjectSample(alwaysIncludedFrameworks)).ToArray(), }, VendorSampleDirectory = new VendorSampleDirectory { Samples = samples.ToArray() } }); }
protected override void OnVendorSampleParsed(VendorSample sample, CommonConfigurationOptions options) { base.OnVendorSampleParsed(sample, options); OptionDictionary[sample] = options; //Remember advanced sample data that didn't make it into the VendorSample object. }
VendorSample ParseMakFile(string nameFile, string relativePath, string SDKdir) { VendorSample vs = new VendorSample(); List <string> lstFileC = new List <string>(); List <string> lstFileInc = new List <string>(); List <string> splitArgs = new List <string>(); List <string> lstDef = new List <string>(); Dictionary <string, string> lstConstDir = new Dictionary <string, string>(); HashSet <string> referencedFrameworks = new HashSet <string>(); string aCurDir = Path.GetDirectoryName(nameFile); Boolean flFlags = false; lstFileInc.Add(aCurDir); foreach (var ln in File.ReadAllLines(nameFile)) { if (ln.StartsWith("CFLAGS =") || ln.StartsWith("CPPFLAGS =")) { flFlags = true; } if (flFlags) { if (ln.Contains(" -I") || ln.Contains(" \"-I")) { if (ln.Contains("$(GCC_ARMCOMPILER)")) { continue; //Toolchain-provided header directories should be handled automatically by toolchain itself. } lstFileInc.Add(GetUpDir(ToAbsolutePath(ln.Replace("CFLAGS =", "").Replace("\"", "").Replace("-I", "").Trim(' ', '\\'), SDKdir, lstConstDir), aCurDir)); } if (ln.Contains(" -D")) { lstDef.Add(ln.Replace("-D", "").Replace("\"", "").Trim(' ', '\\')); } } if (ln.StartsWith("LFLAGS =") || ln.StartsWith(".PRECIOUS:")) { flFlags = false; } if (ln.Contains("-std")) { if (ln.Contains("c99")) { vs.CLanguageStandard = "c99"; } else { vs.CPPLanguageStandard = ln.Replace("-std=", "").Trim('\\', ' ', '\t'); } } if (ln.Contains(".obj:")) { string files = ln.Remove(0, ln.IndexOf(":") + 1).Split('$')[0].Trim(' '); foreach (var file in files.Split(' ')) { var fullPath = Path.GetFullPath(Path.Combine(aCurDir, file)); if (!File.Exists(fullPath)) { throw new Exception("Missing " + fullPath); } lstFileC.Add(fullPath); } } if (ln.Contains("\"-L")) { //We ignore the library search paths } if (ln.Contains(" -l:")) { referencedFrameworks.Add(_FrameworkLocator.LocateFrameworkForLibraryFile(ln.Replace("\"", "").Trim(' ', '\\'))); } Match m = Regex.Match(ln, @"([\w]+)[ \t]*:=[ \t]*([$(\w)/]*)"); if (m.Success) { lstConstDir.Add(m.Groups[1].Value, m.Groups[2].Value); } } if (lstFileInc.Where(f => f.Contains("$")).Count() > 0) { throw new Exception("Path contains macros " + string.Join(", ", lstFileInc.Where(f => f.Contains("$")))); } vs.IncludeDirectories = lstFileInc.Distinct().ToArray(); vs.PreprocessorMacros = lstDef.ToArray(); vs.SourceFiles = lstFileC.Distinct().ToArray(); vs.Configuration = new VendorSampleConfiguration { Frameworks = referencedFrameworks.Where(f => f != null).ToArray(), }; if (vs.Configuration.Frameworks.Contains("com.sysprogs.arm.ti.cc3220.freertos")) { AddConfigurationEntries(ref vs.Configuration.Configuration, "com.sysprogs.bspoptions.cc3220.freertos.heap=heap_4", "com.sysprogs.bspoptions.cc3220.freertos.portcore=CM4F"); AddConfigurationEntries(ref vs.Configuration.MCUConfiguration, "com.sysprogs.bspoptions.arm.floatmode=-mfloat-abi=hard"); } if (vs.Configuration.Frameworks.Contains("com.sysprogs.arm.ti.cc3220.mqtt")) { AddConfigurationEntries(ref vs.Configuration.Configuration, "com.sysprogs.bspoptions.MQTT_Client=1", "com.sysprogs.bspoptions.MQTT_Server=1"); } const string BoardSuffix = "_LAUNCHXL"; vs.DeviceID = nameFile.Split('\\').Last(component => component.EndsWith(BoardSuffix, StringComparison.InvariantCultureIgnoreCase)); vs.DeviceID = vs.DeviceID.Substring(0, vs.DeviceID.Length - BoardSuffix.Length); if (File.ReadAllLines(Path.Combine(aCurDir, "Makefile")).Where(ln => ln.StartsWith("NAME")).Count() == 0) { vs.UserFriendlyName = "noname"; } else { vs.UserFriendlyName = File.ReadAllLines(Path.Combine(aCurDir, "Makefile")).Single(ln => ln.StartsWith("NAME")).Split('=')[1].Trim(' ').ToUpper(); } var relativePathComponents = relativePath.Split('\\'); vs.UserFriendlyName += "-" + relativePathComponents[0]; return(vs); }
protected override ParsedVendorSamples ParseVendorSamples(string SDKdir, IVendorSampleFilter filter) { /* * Since most of the original SDK samples only consist of a handful of files, we use a very simplified logic to enumerate them: * 1. Locate all "Makefile" and "readme.txt" files. * 2. Discard those that don't have .c files in the same directory, or have multiple directories with .c files. * 3. Depending on the config files stored in the same directory, we pick one of the 3 predefined profiles (wlan, bluetooth, periph). * The profiles come from manually created VisualGDB projects and specify a minimum viable configuration to build basic samples. * * Then, we try building all samples discovered via this simplified algorithm, and the successfully built ones into the BSP. */ var sampleBase = Path.Combine(SDKdir, "Examples"); var allFiles = Directory.GetFiles(sampleBase, "*.*", SearchOption.AllDirectories); List <VendorSample> vendorSamples = new List <VendorSample>(); var wlanConfig = XmlTools.LoadObject <EmbeddedProfile>(Path.Combine(RulesDirectory, "wlan.xml")); var bareConfig = XmlTools.LoadObject <EmbeddedProfile>(Path.Combine(RulesDirectory, "periph.xml")); var btConfig = XmlTools.LoadObject <EmbeddedProfile>(Path.Combine(RulesDirectory, "bluetooth.xml")); foreach (var dir in allFiles.Where(f => Path.GetFileName(f) == "Makefile" || Path.GetFileName(f).ToLower() == "readme.txt").Select(Path.GetDirectoryName).Distinct()) { var matchingSources = allFiles.Where(f => Path.GetExtension(f) == ".c" && f.StartsWith(dir + "\\")).ToArray(); var matchingDirs = matchingSources.Select(Path.GetDirectoryName).Distinct().ToArray(); if (matchingDirs.Length != 1) { continue; } string name = Path.GetFileName(dir); string macros = null; EmbeddedProfile matchingProfile; if (File.Exists(Path.Combine(dir, "rsi_ble_config.h"))) { matchingProfile = btConfig; macros = "BT_BDR_MODE=0"; } if (File.Exists(Path.Combine(dir, "rsi_wlan_config.h"))) { matchingProfile = wlanConfig; } else { matchingProfile = bareConfig; macros = "__SYSTICK"; } var sample = new VendorSample { DeviceID = "RS14100", SourceFiles = matchingSources, UserFriendlyName = name, InternalUniqueID = dir.Substring(SDKdir.Length).TrimStart('\\').Replace('\\', '_'), Path = dir, IncludeDirectories = new[] { dir }, VirtualPath = Path.GetDirectoryName(dir).Substring(SDKdir.Length).TrimStart('\\'), Configuration = matchingProfile.ToConfiguration(), }; if (File.Exists(Path.Combine(dir, "readme.txt"))) { sample.Description = File.ReadAllText(Path.Combine(dir, "readme.txt")); } if (macros != null) { sample.PreprocessorMacros = macros.Split(';'); } vendorSamples.Add(sample); } return(new ParsedVendorSamples { VendorSamples = vendorSamples.ToArray() }); }
public VendorSample BuildVendorSample(string rootDir, string boardName, SpecializedDevice device, string package, HashSet <string> allComponentIDs, HashSet <string> implicitFrameworks) { Dictionary <string, string> properties = new Dictionary <string, string>(); if (!string.IsNullOrEmpty(ExplicitFPUSetting)) { properties["com.sysprogs.bspoptions.arm.floatmode"] = ExplicitFPUSetting.Contains("hard") ? "-mfloat-abi=hard" : "-mfloat-abi=soft"; } string sampleName = ID; if (!string.IsNullOrEmpty(RelativePath)) { string[] relativePathComponents = RelativePath.Split('/'); if (relativePathComponents.Length > 3 && relativePathComponents[0] == "boards") { string expectedPrefix = relativePathComponents[1] + "_" + relativePathComponents[2] + "_"; if (sampleName.StartsWith(expectedPrefix)) { sampleName = sampleName.Substring(expectedPrefix.Length); } } } VendorSample sample = new VendorSample { DeviceID = device.MakeMCUID(package), UserFriendlyName = sampleName, InternalUniqueID = ID, Description = Description, BoardName = boardName, Configuration = new VendorSampleConfiguration { Frameworks = Dependencies.Where(d => allComponentIDs.Contains(d)).Select(d => ParsedComponent.FrameworkIDPrefix + d).Concat(implicitFrameworks).Distinct().ToArray(), MCUConfiguration = new PropertyDictionary2(properties) }, VirtualPath = Category, PreprocessorMacros = Defines, NoImplicitCopy = true }; List <string> sources = new List <string>(), headers = new List <string>(); HashSet <string> includeDirectories = new HashSet <string>(); string[] matchingPathComponents = null; foreach (var lst in SourceLists) { foreach (var file in lst.LocateAllFiles(device, rootDir)) { var bspPath = file.GetBSPPath(); UpdateMatchingPathComponents(bspPath, ref matchingPathComponents); file.UpdateIncludeDirectoryList(includeDirectories); switch (file.Type) { case SourceType.Library: case SourceType.Source: sources.Add(bspPath); break; case SourceType.Header: headers.Add(bspPath); break; case SourceType.LinkerScript: sample.LinkerScript = bspPath; break; } } } sample.CLanguageStandard = MapLanguageStandard(LanguageStandard); sample.LDFLAGS = string.Join(" ", AdvancedLinkerOptions.Where(f => f.StartsWith("--defsym")).Select(f => "-Wl," + f).ToArray()); if (sample.LDFLAGS == "") { sample.LDFLAGS = null; } if (matchingPathComponents != null) { sample.Path = string.Join("/", matchingPathComponents); } sample.SourceFiles = sources.ToArray(); sample.HeaderFiles = headers.ToArray(); sample.IncludeDirectories = includeDirectories.ToArray(); return(sample); }
public static ParsedSDK ParseKSDKManifest(string sdkDirectory, IWarningSink sink) { string[] manifestFiles = Directory.GetFiles(sdkDirectory, "*manifest.xml"); if (manifestFiles.Length < 1) { throw new Exception($"No manifest files in {sdkDirectory}"); } string manifestFile = Directory.GetFiles(sdkDirectory, "*manifest.xml")[0]; List <VendorSample> vsl = new List <VendorSample>(); XmlDocument doc = new XmlDocument(); doc.Load(manifestFile); List <MCU> mcus = new List <MCU>(); List <MCUFamily> families = new List <MCUFamily>(); List <ParsedComponent> allFrameworks = new List <ParsedComponent>(); bool linkerScriptHandled = false; List <string> allFiles = new List <string>(); Dictionary <string, ParsedDevice> deviceDict = new Dictionary <string, ParsedDevice>(); Dictionary <string, EmbeddedFramework> frameworkDict = new Dictionary <string, EmbeddedFramework>(); List <FileCondition> allConditions = new List <FileCondition>(); string fwPrefix = "com.sysprogs.ksdk2x_imported."; HashSet <string> alwaysIncludedFrameworks = new HashSet <string>(); // HashSet<string> alwaysExcludedFrameworks = new HashSet<string>(); List <string> lstdevAll = new List <string>(); List <CopiedFile> cfs = new List <CopiedFile>(); var dictCopiedFile = new ListDictionary <string, CopiedFile>(); var dictAddIncludeDir = new ListDictionary <string, string>(); foreach (XmlElement devNode in doc.SelectNodes("//devices/device")) { lstdevAll.Add(new ParsedDevice(devNode, sdkDirectory).DeviceName); } foreach (XmlElement devNode in doc.SelectNodes("//devices/device")) { ParsedDevice dev = new ParsedDevice(devNode, sdkDirectory); var mcuFamily = dev.ToMCUFamily(); int FLASHSize, RAMSize; int.TryParse((devNode.SelectSingleNode("memory/@flash_size_kb")?.Value ?? ""), out FLASHSize); int.TryParse((devNode.SelectSingleNode("memory/@ram_size_kb")?.Value ?? ""), out RAMSize); FLASHSize *= 1024; RAMSize *= 1024; families.Add(mcuFamily); string svdFile = null; //Map each component to an instance of EmbeddedFramework foreach (XmlNode componentNode in doc.SelectNodes($"//components/component")) { string componentName = componentNode.SelectSingleNode("@name")?.Value ?? ""; string componentType = componentNode.SelectSingleNode("@type")?.Value ?? ""; string device = componentNode.SelectSingleNode("@device")?.Value ?? ""; string idComponent = componentNode.SelectSingleNode("@id")?.Value ?? ""; device = idComponent.Split('.').Last(); if (device != dev.DeviceName && (lstdevAll.Contains(device))) { continue; } switch (componentType) { case "documentation": case "SCR": case "EULA": continue; case "debugger": case "linker": { List <string> relPaths = new List <string>(); bool isDebug = componentType == "debugger"; string sourceType = isDebug ? "debug" : "linker"; foreach (var src in componentNode.SelectNodes($"source[@type='{sourceType}' and @toolchain='armgcc']").OfType <XmlElement>().Select(e => new ParsedSource(e, dev))) { foreach (var fn in src.AllFiles) { relPaths.Add(fn.RelativePath); } } if (relPaths.Count > 0) { if (isDebug) { svdFile = relPaths[0]; } else if (!linkerScriptHandled) { linkerScriptHandled = true; if (relPaths.Count == 1) { mcuFamily.CompilationFlags.LinkerScript = "$$SYS:BSP_ROOT$$/" + relPaths[0]; } else { const string optionID = "com.sysprogs.imported.ksdk2x.linker_script"; mcuFamily.CompilationFlags.LinkerScript = $"$$SYS:BSP_ROOT$$/$${optionID}$$"; if ((mcuFamily.ConfigurableProperties?.PropertyGroups?.Count ?? 0) == 0) { mcuFamily.ConfigurableProperties = new PropertyList { PropertyGroups = new List <PropertyGroup> { new PropertyGroup() } } } ; mcuFamily.ConfigurableProperties.PropertyGroups[0].Properties.Add(new PropertyEntry.Enumerated { UniqueID = optionID, Name = "Linker script", AllowFreeEntry = false, SuggestionList = relPaths.Select(p => new PropertyEntry.Enumerated.Suggestion { InternalValue = p, UserFriendlyName = Path.GetFileName(p) }).ToArray() }); } } } } continue; case "CMSIS": //KSDK 2.x defines a Include_xxx framework for each possible CMSIS core. Those frameworks are redundant (normal 'Include' framework references the same include path) and should be removed to avoid confusion. if (componentName.StartsWith("Include_")) { continue; } if (idComponent == "platform.CMSIS_Driver") { continue; } if (componentName == "Include") { alwaysIncludedFrameworks.Add(fwPrefix + componentName); //!!! +"."+dev.DeviceName); } if (idComponent == "platform.CMSIS") { alwaysIncludedFrameworks.Add(fwPrefix + idComponent); //!!! + "." + dev.DeviceName); } break; case "project_template": continue; default: break; } List <string> headerFiles = new List <string>(); List <string> includeDirectories = new List <string>(); List <string> sourceFiles = new List <string>(); List <string> libFiles = new List <string>(); var IDFr = fwPrefix + idComponent; foreach (ParsedSource src in componentNode.SelectNodes("source").OfType <XmlElement>().Select(e => new ParsedSource(e, dev))) { if (src.Exclude) { continue; } if (src.Type == "c_include") { includeDirectories.Add(src.BSPPath); } foreach (var file in src.AllFiles) { if (file.BSPPath.EndsWith("ucosii.c") && !componentName.Contains("ucosii")) { continue; } if (file.BSPPath.EndsWith("ucosiii.c") && !componentName.Contains("ucosiii")) { continue; } if (file.BSPPath.Contains("freertos")) { allConditions.Add(new FileCondition { FilePath = file.BSPPath, ConditionToInclude = new Condition.ReferencesFramework { FrameworkID = fwPrefix + "middleware.freertos." + dev.DeviceName } }); } if (src.TargetPath != "") { dictCopiedFile.Add(IDFr, new CopiedFile { SourcePath = file.BSPPath, TargetPath = src.TargetPath + "/" + Path.GetFileName(file.BSPPath) }); foreach (XmlElement patch in componentNode.SelectNodes("include_paths/include_path")) { dictAddIncludeDir.Add(IDFr, patch.GetAttribute("path")); } } if (src.Type == "lib") { libFiles.Add(file.BSPPath); } if (src.Type == "src" || src.Type == "asm_include") { sourceFiles.Add(file.BSPPath); } else if (src.Type == "c_include") { headerFiles.Add(file.BSPPath); } } } foreach (XmlElement patch in componentNode.SelectNodes("include_paths/include_path")) { includeDirectories.Add(patch.GetAttribute("path")); } string[] dependencyList = componentNode.Attributes?.GetNamedItem("dependency")?.Value?.Split(' ') ?.Select(id => fwPrefix + id) ?.ToArray() ?? new string[0]; var FilterRegex = device.Length > 5 ? $"^{device.Substring(0, 5)}.*" : $"^{device}.*"; //MK02F MK22F if (device.Length == 0) { FilterRegex = ""; } EmbeddedFramework fw = new EmbeddedFramework { ID = $"{IDFr}", MCUFilterRegex = FilterRegex, UserFriendlyName = $"{componentName} ({componentType})", ProjectFolderName = componentName, AdditionalSourceFiles = sourceFiles.Distinct().ToArray(), AdditionalHeaderFiles = headerFiles.Distinct().ToArray(), RequiredFrameworks = dependencyList, AdditionalIncludeDirs = includeDirectories.Distinct().ToArray(), AdditionalLibraries = libFiles.ToArray(), AdditionalPreprocessorMacros = componentNode.SelectNodes("defines/define").OfType <XmlElement>().Select(el => new ParsedDefine(el).Definition).ToArray(), }; if (componentName == "freertos" && componentType == "OS") { fw.AdditionalPreprocessorMacros = LoadedBSP.Combine(fw.AdditionalPreprocessorMacros, "USE_RTOS=1;USE_FREERTOS".Split(';')); fw.ConfigurableProperties = new PropertyList { PropertyGroups = new List <PropertyGroup>() { new PropertyGroup { Properties = new List <PropertyEntry>() { new PropertyEntry.Enumerated { Name = "FreeRTOS Heap Implementation", UniqueID = "com.sysprogs.bspoptions.stm32.freertos.heap", DefaultEntryIndex = 3, SuggestionList = new PropertyEntry.Enumerated.Suggestion[] { new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_1", UserFriendlyName = "Heap1 - no support for freeing" }, new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_2", UserFriendlyName = "Heap2 - no block consolidation" }, new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_3", UserFriendlyName = "Heap3 - use newlib malloc()/free()" }, new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_4", UserFriendlyName = "Heap4 - contiguous heap area" }, new PropertyEntry.Enumerated.Suggestion { InternalValue = "heap_5", UserFriendlyName = "Heap5 - scattered heap area" }, } } } } } }; foreach (var fn in fw.AdditionalSourceFiles) { string name = Path.GetFileName(fn); if (name.StartsWith("heap_")) { allConditions.Add(new FileCondition { FilePath = fn, ConditionToInclude = new Condition.Equals { Expression = "$$com.sysprogs.bspoptions.stm32.freertos.heap$$", ExpectedValue = Path.GetFileNameWithoutExtension(fn) } }); } } } if (frameworkDict.ContainsKey(fw.ID)) { sink.LogWarning("Duplicate framework for " + fw.ID); continue; } frameworkDict[fw.ID] = fw; if (string.IsNullOrEmpty(fw.ID)) { sink.LogWarning($"Found a framework with empty ID. Skipping..."); continue; } if (string.IsNullOrEmpty(fw.UserFriendlyName)) { fw.UserFriendlyName = fw.ID; } allFrameworks.Add(new ParsedComponent { Framework = fw, OriginalType = componentType, OriginalName = componentName }); allFiles.AddRange(sourceFiles); allFiles.AddRange(headerFiles); } string deviceDefinitionFile = null; if (svdFile != null) { try { var mcuDef = SVDParser.ParseSVDFile(Path.Combine(sdkDirectory, svdFile), dev.DeviceName); deviceDefinitionFile = Path.ChangeExtension(svdFile, ".vgdbdevice"); XmlSerializer ser = new XmlSerializer(typeof(MCUDefinition)); using (var fs = File.Create(Path.Combine(sdkDirectory, Path.ChangeExtension(svdFile, ".vgdbdevice.gz")))) using (var gs = new GZipStream(fs, CompressionMode.Compress, true)) ser.Serialize(gs, new MCUDefinition(mcuDef)); } catch (Exception ex) { sink.LogWarning($"Failed to parse {svdFile}: {ex.Message}"); } } foreach (XmlNode packageNode in devNode.SelectNodes($"package/@name")) { string pkgName = packageNode?.Value; if (string.IsNullOrEmpty(pkgName)) { continue; } deviceDict[pkgName] = dev; mcus.Add(new MCU { ID = pkgName, UserFriendlyName = $"{pkgName} (KSDK 2.x)", FamilyID = mcuFamily.ID, FLASHSize = FLASHSize, RAMSize = RAMSize, CompilationFlags = new ToolFlags { PreprocessorMacros = new string[] { "CPU_" + pkgName }, }, MCUDefinitionFile = deviceDefinitionFile }); } } if (families.Count == 0) { throw new Exception("The selected KSDK contains no families"); } List <VendorSample> samples = new List <VendorSample>(); foreach (XmlElement boardNode in doc.SelectNodes("//boards/board")) { string boardName = boardNode.GetAttribute("name"); string deviceID = boardNode.GetAttribute("package"); ParsedDevice dev; if (!deviceDict.TryGetValue(deviceID, out dev)) { continue; } foreach (XmlElement directExampleNode in boardNode.SelectNodes("examples/example")) { var exampleNode = directExampleNode; var externalNode = exampleNode.SelectSingleNode("external/files"); if (externalNode != null) { var path = (externalNode.ParentNode as XmlElement)?.GetAttribute("path"); var mask = (externalNode as XmlElement)?.GetAttribute("mask"); if (path != null && mask != null) { { var sampleFiles = Directory.GetFiles(Path.Combine(sdkDirectory, path), mask); var fn = sampleFiles?.FirstOrDefault(); if (fn != null) { XmlDocument doc2 = new XmlDocument(); doc2.Load(fn); exampleNode = doc2.DocumentElement.SelectSingleNode("example") as XmlElement; if (exampleNode == null) { continue; } } } } } List <string> dependencyList = new List <string>(exampleNode.Attributes?.GetNamedItem("dependency")?.Value?.Split(' ') ?.Select(id => fwPrefix + id) ?? new string[0]); var name = exampleNode.GetAttribute("id") ?? "???"; dependencyList.AddRange(alwaysIncludedFrameworks); for (int i = 0; i < dependencyList.Count; i++) { EmbeddedFramework fw; if (frameworkDict.TryGetValue(dependencyList[i], out fw) && fw?.RequiredFrameworks != null) { dependencyList.AddRange(fw.RequiredFrameworks.Except(dependencyList)); } } List <string> dependencyList1 = new List <string>(dependencyList.Distinct()); List <CopiedFile> CopiedFileForSample = new List <CopiedFile>(); List <string> includeDirectories = new List <string>(); foreach (var fr1 in dependencyList1) { if (!dictCopiedFile.ContainsKey(fr1)) { continue; } var l = dictCopiedFile[fr1]; CopiedFileForSample.AddRange(l); if (dictAddIncludeDir.ContainsKey(fr1)) { includeDirectories.AddRange(dictAddIncludeDir[fr1]); } } List <PropertyDictionary2.KeyValue> CfgEntr = new List <PropertyDictionary2.KeyValue>(); string typFpu = "soft"; var tth = exampleNode.SelectSingleNode("toolchainSettings/toolchainSetting/option[@id='com.crt.advproject.gcc.fpu']")?.InnerText ?? "soft"; if (tth.Contains("hard")) { typFpu = "hard"; } CfgEntr.Add(new PropertyDictionary2.KeyValue { Key = "com.sysprogs.bspoptions.arm.floatmode", Value = "-mfloat-abi=" + typFpu }); VendorSample sample = new VendorSample { DeviceID = deviceID, UserFriendlyName = name, BoardName = boardName, Configuration = new VendorSampleConfiguration { Frameworks = dependencyList.Distinct().ToArray(), MCUConfiguration = new PropertyDictionary2 { Entries = CfgEntr.ToArray() } }, VirtualPath = exampleNode.GetAttribute("category"), ExtraFiles = CopiedFileForSample.Distinct().ToArray(), NoImplicitCopy = true }; List <string> headerFiles = new List <string>(); List <string> sourceFiles = new List <string>(); foreach (var cf in CopiedFileForSample.Distinct()) { includeDirectories.Add(Path.GetDirectoryName(cf.TargetPath)); } foreach (var src in exampleNode.SelectNodes("source").OfType <XmlElement>().Select(e => new ParsedSource(e, dev))) { foreach (var file in src.AllFiles) { if (src.Type == "src" || src.Type == "asm_include") { sourceFiles.Add(file.BSPPath); } else if (src.Type == "c_include") { headerFiles.Add(file.BSPPath); } if (src.Type == "lib") { sourceFiles.Add(file.BSPPath); } } } sample.PreprocessorMacros = exampleNode.SelectNodes("toolchainSettings/toolchainSetting/option[@id='gnu.c.compiler.option.preprocessor.def.symbols']/value").OfType <XmlElement>(). Select(node => node.InnerText.Replace("'\"", "'<").Replace("\"'", ">'")).ToArray(); sample.SourceFiles = sourceFiles.ToArray(); sample.HeaderFiles = headerFiles.ToArray(); if (sourceFiles.Count == 0 && headerFiles.Count == 0) { continue; } string[] matchingComponents = null; foreach (var fn in sourceFiles.Concat(headerFiles)) { string[] components = fn.Split('/', '\\'); if (matchingComponents == null) { matchingComponents = components; } else { int matches = CountMatches(matchingComponents, components); if (matches < matchingComponents.Length) { Array.Resize(ref matchingComponents, matches); } } } if (matchingComponents != null) { sample.Path = string.Join("/", matchingComponents); } foreach (var hf in headerFiles) { int c = hf.LastIndexOf('/'); includeDirectories.Add(hf.Substring(0, c)); } sample.IncludeDirectories = includeDirectories.Distinct().ToArray(); samples.Add(sample); } } return(new ParsedSDK { BSP = new BoardSupportPackage { PackageID = "com.sysprogs.imported.ksdk2x." + families[0].ID, PackageDescription = "Imported KSDK 2.x for " + families[0].ID, PackageVersion = doc.SelectSingleNode("//ksdk/@version")?.Value ?? "unknown", GNUTargetID = "arm-eabi", Frameworks = allFrameworks.Where(f => f.OriginalType != "project_template").Select(f => f.Framework).ToArray(), MCUFamilies = families.ToArray(), SupportedMCUs = mcus.ToArray(), FileConditions = allConditions.ToArray(), VendorSampleCatalogName = "KSDK Samples", EmbeddedSamples = allFrameworks.Where(f => f.OriginalType == "project_template").Select(f => f.ToProjectSample(alwaysIncludedFrameworks)).ToArray(), }, VendorSampleDirectory = new VendorSampleDirectory { Samples = samples.ToArray() } }); }
static VendorSample ParseDependFiles(string ExamplDir, string namelog) { VendorSample vs = new VendorSample(); List <string> lstFileC = new List <string>(); List <string> lstFileInc = new List <string>(); List <string> splitArgs = new List <string>(); List <string> lstDef = new List <string>(); Boolean flBoot = false; //--------log parser--- foreach (var ln in File.ReadAllLines(namelog)) { if (ln.Contains("xtensa-esp32-elf-gcc") && ln.Contains("bootloader.elf")) { flBoot = true; } if (!flBoot) { continue; } if (ln.Contains("bootloader_random.c")) { continue; } string ln1 = ln.Replace("-I ", "-I"); while (ln1.Contains("-I ")) { ln1 = ln1.Replace("-I ", "-I"); } while (ln1.Contains("-D ")) { ln1 = ln1.Replace("-D ", "-D"); } if (!ln1.Contains("xtensa-esp32-elf-gcc") && !ln1.Contains("xtensa-esp32-elf-c++")) { continue; } if (!ln1.Contains(" -C ") && !ln1.Contains(" -c ")) { continue; } // Get Arguments int munArg; IntPtr ptrToSplitArgs = CommandLineToArgvW(ln1, out munArg); if (ptrToSplitArgs == IntPtr.Zero) { throw new Exception("no arg"); } for (int i = 0; i < munArg; i++) { string arg = Marshal.PtrToStringUni( Marshal.ReadIntPtr(ptrToSplitArgs, i * IntPtr.Size)); arg = arg.Replace('\'', '\"'); if (!splitArgs.Contains(arg)) { splitArgs.Add(arg); } } // Processing arguments lstFileInc.AddRange(string.Join(" ", splitArgs.Where(ar => ar.StartsWith("-I"))).Split(new string[] { "-I" }, StringSplitOptions.RemoveEmptyEntries)); lstDef.AddRange(string.Join(" ", splitArgs.Where(ar => ar.StartsWith("-D") && !ar.Contains("BOOTLOADER_BUILD"))).Split(new string[] { "-D" }, StringSplitOptions.RemoveEmptyEntries)); lstFileInc = lstFileInc.Distinct().ToList(); lstFileC.AddRange(splitArgs.Where(ar => (ar.EndsWith(".c") || ar.EndsWith(".cpp") || ar.ToLower().EndsWith(".s")))); if (splitArgs.Where(ar => ar.EndsWith(".c") || ar.EndsWith(".cpp") || ar.ToLower().EndsWith(".s")).Count() > 1) { throw new Exception("many source argumens"); } //arguments from file var fileArg = splitArgs.SingleOrDefault(ar => ar.StartsWith("@")); if (fileArg != null) { continue; } splitArgs.Clear(); } //------------------- if (lstFileC.Count == 0) { Console.WriteLine($"{namelog} No Source File"); return(null); } vs.PreprocessorMacros = lstDef.Distinct().ToArray(); vs.BoardName = "ESP32"; vs.DeviceID = "ESP32"; var dlC = lstFileC.Distinct().ToList(); //-------------------------- ChackRenameFiles(ref dlC, "$$SYS:BSP_ROOT$$"); ChackRenameFiles(ref lstFileInc, "$$SYS:BSP_ROOT$$"); int ind = ExamplDir.IndexOf("\\esp-idf.orig"); lstFileInc.Insert(1, $@"$$SYS:BSP_ROOT$$/..{ExamplDir.Remove(0, ind)}/build/include".Replace("\\", "/"));// sdkconfig.h vs.SourceFiles = dlC.Distinct().ToArray(); var lstFileInc1 = lstFileInc.Select(f => Path.GetDirectoryName(f)).Distinct(); vs.IncludeDirectories = lstFileInc.ToArray(); return(vs); }
public VendorSampleID(VendorSample sample) { SampleName = sample.UserFriendlyName; BoardNameOrDeviceID = sample.BoardName ?? sample.DeviceID; }
public static TestResult TestVendorSampleAndUpdateDependencies(LoadedBSP.LoadedMCU mcu, VendorSample vs, string mcuDir, string sampleDirPath, bool codeRequiresDebugInfoFlag, bool keepDirectoryAfterSuccessfulBuild) { if (Directory.Exists(mcuDir)) { Directory.Delete(mcuDir, true); } Directory.CreateDirectory(mcuDir); var configuredMCU = new LoadedBSP.ConfiguredMCU(mcu, GetDefaultPropertyValues(mcu.ExpandedMCU.ConfigurableProperties)); configuredMCU.Configuration["com.sysprogs.toolchainoptions.arm.libnosys"] = "--specs=nosys.specs"; if (configuredMCU.ExpandedMCU.FLASHSize == 0) { configuredMCU.Configuration["com.sysprogs.bspoptions.primary_memory"] = "sram"; } var entries = vs.Configuration.MCUConfiguration?.Entries; if (entries != null) { foreach (var e in entries) { configuredMCU.Configuration[e.Key] = e.Value; } } var bspDict = configuredMCU.BuildSystemDictionary(default(SystemDirectories)); bspDict["PROJECTNAME"] = "test"; if (sampleDirPath != null) { bspDict["SYS:VSAMPLE_DIR"] = sampleDirPath; } var prj = new GeneratedProject(configuredMCU, vs, mcuDir, bspDict, vs.Configuration.Frameworks ?? new string[0]); var projectCfg = PropertyDictionary2.ReadPropertyDictionary(vs.Configuration.MCUConfiguration); var frameworkCfg = PropertyDictionary2.ReadPropertyDictionary(vs.Configuration.Configuration); foreach (var k in projectCfg.Keys) { bspDict[k] = projectCfg[k]; } var frameworkIDs = vs.Configuration.Frameworks?.ToDictionary(fw => fw, fw => true); prj.AddBSPFilesToProject(bspDict, frameworkCfg, frameworkIDs); var flags = prj.GetToolFlags(bspDict, frameworkCfg, frameworkIDs); if (flags.LinkerScript != null && !Path.IsPathRooted(flags.LinkerScript)) { flags.LinkerScript = Path.Combine(VariableHelper.ExpandVariables(vs.Path, bspDict, frameworkCfg), flags.LinkerScript).Replace('\\', '/'); } //ToolFlags flags = new ToolFlags { CXXFLAGS = " ", COMMONFLAGS = "-mcpu=cortex-m3 -mthumb", LDFLAGS = "-Wl,-gc-sections -Wl,-Map," + "test.map", CFLAGS = "-ffunction-sections -Os -MD" }; if (!string.IsNullOrEmpty(vs.CLanguageStandard)) { flags.CFLAGS += $" -std={vs.CLanguageStandard}"; } if (!string.IsNullOrEmpty(vs.CPPLanguageStandard)) { flags.CXXFLAGS += $" -std={vs.CPPLanguageStandard}"; } flags.CFLAGS += " -MD"; flags.CXXFLAGS += " -MD"; if (codeRequiresDebugInfoFlag) { flags.CFLAGS += " -ggdb"; flags.CXXFLAGS += " -ggdb"; } flags.IncludeDirectories = LoadedBSP.Combine(flags.IncludeDirectories, vs.IncludeDirectories).Distinct().ToArray(); flags.PreprocessorMacros = LoadedBSP.Combine(flags.PreprocessorMacros, vs.PreprocessorMacros); flags.LDFLAGS = flags.LDFLAGS + " " + vs.LDFLAGS; flags = LoadedBSP.ConfiguredMCU.ExpandToolFlags(flags, bspDict, null); Dictionary <string, bool> sourceExtensions = new Dictionary <string, bool>(StringComparer.InvariantCultureIgnoreCase); sourceExtensions.Add("c", true); sourceExtensions.Add("cpp", true); sourceExtensions.Add("s", true); return(BuildAndRunValidationJob(mcu, mcuDir, false, null, prj, flags, sourceExtensions, null, null, vs, keepDirectoryAfterSuccessfulBuild)); }
protected override void AdjustVendorSampleProperties(VendorSample vs) { base.AdjustVendorSampleProperties(vs); vs.BSPReferencesAreCopyable = true; vs.SourceFiles = vs.SourceFiles.Where(s => !rgSystemFile.IsMatch(s)).ToArray(); }
public void OnSampleParsed(VendorSample sample) { }
public SingleSampleFilter(VendorSample existingSample) { _ExistingSample = existingSample; _Path = Path.GetFullPath(_ExistingSample.Path); }
static public List <VendorSample> GetInfoProjectFromMDK(string pDirPrj, string topLevelDir, List <string> extraIncludeDirs) { List <VendorSample> aLstVSampleOut = new List <VendorSample>(); int aCntTarget = 0; string aFilePrj = pDirPrj + "\\Project.uvprojx"; string aNamePrj = pDirPrj.Replace("\\MDK-ARM", ""); aNamePrj = aNamePrj.Substring(aNamePrj.LastIndexOf("\\") + 1); List <string> sourceFiles = new List <string>(); List <string> includeDirs = new List <string>(); bool flGetProperty = false; string aTarget = ""; VendorSample sample = new VendorSample(); foreach (var ln in File.ReadAllLines(aFilePrj)) { if (ln.Contains("<Target>")) { if (aCntTarget == 0) { sample = new VendorSample(); } aCntTarget++; } if (ln.Contains("</Target>")) { if (aCntTarget == 0) { throw new Exception("wrong tag Targets"); } else { aCntTarget--; } } if (ln.Contains("<Cads>")) { flGetProperty = true; } else if (ln.Contains("</Cads>")) { flGetProperty = false; } Match m = Regex.Match(ln, "[ \t]*<Device>(.*)</Device>[ \t]*"); if (m.Success) { sample.DeviceID = m.Groups[1].Value; if (sample.DeviceID.EndsWith("x")) { sample.DeviceID = sample.DeviceID.Remove(sample.DeviceID.Length - 2, 2); } } m = Regex.Match(ln, "[ \t]*<TargetName>(.*)</TargetName>[ \t]*"); if (m.Success) { aTarget = m.Groups[1].Value; } MatchCollection m1 = Regex.Matches(ln, @"[ ]*<FilePath>([\w\-:\\./]*)</FilePath>[ ]*"); foreach (Match mc in m1) { string filePath = mc.Groups[1].Value; if (filePath.StartsWith(@"./") || filePath.StartsWith(@".\")) { filePath = pDirPrj + filePath.Substring(1); } if (filePath.EndsWith(".s", StringComparison.InvariantCultureIgnoreCase)) { continue; } if (filePath.EndsWith(".lib", StringComparison.InvariantCultureIgnoreCase)) { filePath = filePath.Replace("_Keil.lib", "_GCC.a"); if (!File.Exists(Path.Combine(pDirPrj, filePath))) { continue; } } if (!sourceFiles.Contains(filePath)) { sourceFiles.Add(filePath); } } if (flGetProperty) { m = Regex.Match(ln, "[ \t]*<IncludePath>(.*)</IncludePath>[ \t]*"); if (m.Success && m.Groups[1].Value != "") { sample.IncludeDirectories = m.Groups[1].Value.Split(';').Select(d => d.TrimEnd('/', '\\')).ToArray(); } m = Regex.Match(ln, "[ \t]*<Define>(.*)</Define>[ \t]*"); if (m.Success && m.Groups[1].Value != "") { sample.PreprocessorMacros = m.Groups[1].Value.Split(','); } } if (ln.Contains("</Target>") && aCntTarget == 0) { sample.Path = Path.GetDirectoryName(pDirPrj); sample.UserFriendlyName = aNamePrj; sample.BoardName = aTarget; sample.SourceFiles = ToAbsolutePath(pDirPrj, topLevelDir, sourceFiles).ToArray(); foreach (var fl in sample.IncludeDirectories) { includeDirs.Add(fl); } includeDirs.AddRange(extraIncludeDirs); sample.IncludeDirectories = ToAbsolutePath(pDirPrj, topLevelDir, includeDirs).ToArray(); string readmeFile = Path.Combine(pDirPrj, @"..\readme.txt"); if (File.Exists(readmeFile)) { string readmeContents = File.ReadAllText(readmeFile); Regex rgTitle = new Regex(@"@page[ \t]+[^ \t]+[ \t]+([^ \t][^@]*)\r\n *\r\n", RegexOptions.Singleline); m = rgTitle.Match(readmeContents); if (m.Success) { sample.Description = m.Groups[1].Value; } } aLstVSampleOut.Add(sample); } } return(aLstVSampleOut); }
protected virtual void OnVendorSampleParsed(VendorSample sample, CommonConfigurationOptions options) { }
static public List<VendorSample> GetInfoProjectFromMDK(string pDirPrj, string topLevelDir, List<string> extraIncludeDirs) { List<VendorSample> aLstVSampleOut = new List<VendorSample>(); int aCntTarget = 0; string aFilePrj = pDirPrj + "\\Project.uvprojx"; string aNamePrj = pDirPrj.Replace("\\MDK-ARM", ""); aNamePrj = aNamePrj.Substring(aNamePrj.LastIndexOf("\\") + 1); List<string> sourceFiles = new List<string>(); List<string> includeDirs = new List<string>(); bool flGetProperty = false; string aTarget = ""; VendorSample aSimpleOut = new VendorSample(); foreach (var ln in File.ReadAllLines(aFilePrj)) { if (ln.Contains("<Target>")) { if (aCntTarget == 0) aSimpleOut = new VendorSample(); aCntTarget++; } if (ln.Contains("</Target>")) if (aCntTarget == 0) throw new Exception("wrong tag Targets"); else aCntTarget--; if (ln.Contains("<Cads>")) flGetProperty = true; else if (ln.Contains("</Cads>")) flGetProperty = false; Match m = Regex.Match(ln, "[ \t]*<Device>(.*)</Device>[ \t]*"); if (m.Success) { aSimpleOut.DeviceID = m.Groups[1].Value; if (aSimpleOut.DeviceID.EndsWith("x")) aSimpleOut.DeviceID = aSimpleOut.DeviceID.Remove(aSimpleOut.DeviceID.Length - 2, 2); } m = Regex.Match(ln, "[ \t]*<TargetName>(.*)</TargetName>[ \t]*"); if (m.Success) aTarget = m.Groups[1].Value; MatchCollection m1 = Regex.Matches(ln, @"[ ]*<FilePath>([\w\-:\\./]*)</FilePath>[ ]*"); foreach (Match mc in m1) { string filePath = mc.Groups[1].Value; if (filePath.StartsWith(@"./") || filePath.StartsWith(@".\")) filePath = pDirPrj + filePath.Substring(1); if (filePath.EndsWith(".s", StringComparison.InvariantCultureIgnoreCase)) continue; if (!sourceFiles.Contains(filePath)) sourceFiles.Add(filePath); } if (flGetProperty) { m = Regex.Match(ln, "[ \t]*<IncludePath>(.*)</IncludePath>[ \t]*"); if (m.Success && m.Groups[1].Value != "") aSimpleOut.IncludeDirectories = m.Groups[1].Value.Split(';'); m = Regex.Match(ln, "[ \t]*<Define>(.*)</Define>[ \t]*"); if (m.Success && m.Groups[1].Value != "") aSimpleOut.PreprocessorMacros = m.Groups[1].Value.Split(','); } if (ln.Contains("</Target>") && aCntTarget == 0) { aSimpleOut.Path = Path.GetDirectoryName(pDirPrj); aSimpleOut.UserFriendlyName = aNamePrj; aSimpleOut.BoardName = aTarget; aSimpleOut.SourceFiles = ToAbsolutePath(pDirPrj, topLevelDir, sourceFiles).ToArray(); foreach (var fl in aSimpleOut.IncludeDirectories) includeDirs.Add(fl); includeDirs.AddRange(extraIncludeDirs); aSimpleOut.IncludeDirectories = ToAbsolutePath(pDirPrj, topLevelDir, includeDirs).ToArray(); string readmeFile = Path.Combine(pDirPrj, @"..\readme.txt"); if (File.Exists(readmeFile)) { string readmeContents = File.ReadAllText(readmeFile); Regex rgTitle = new Regex(@"@page[ \t]+[^ \t]+[ \t]+([^ \t][^@]*)\r\n *\r\n", RegexOptions.Singleline); m = rgTitle.Match(readmeContents); if (m.Success) { aSimpleOut.Description = m.Groups[1].Value; } } aLstVSampleOut.Add(aSimpleOut); } } return aLstVSampleOut; }
//----------------------------------------------- static List <VendorSample> ParseVendorSamples(string SDKdir) { string[] ExampleDirs = Directory.GetFiles(Path.Combine(SDKdir, $@"esp-idf.orig\examples"), "Makefile", SearchOption.AllDirectories).ToArray(); List <VendorSample> allSamples = new List <VendorSample>(); var count = 0; int FaildSamlesdef = 0; foreach (var makfile in ExampleDirs) { var mainexamplDir = Path.GetDirectoryName(makfile); string nameExampl = mainexamplDir.Substring(mainexamplDir.IndexOf("examples") + 9).Replace("Makefile", "").Replace('\\', '-'); /* * if (count == 3) * break; * count++; */ var nameLog = Path.Combine(Path.GetDirectoryName(mainexamplDir), "Logs", $"{nameExampl}.log"); if (!Directory.Exists(Path.Combine(Path.GetDirectoryName(mainexamplDir), "Logs"))) { Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(mainexamplDir), "Logs")); } if (File.Exists(nameLog)) { continue; } if (Directory.Exists(Path.Combine(Path.GetFullPath(mainexamplDir), "build"))) { if (Directory.GetFiles(Path.Combine(Path.GetFullPath(mainexamplDir), "build"), "*.elf").Count() > 0) { Console.WriteLine(mainexamplDir + " elf exist"); //continue; Directory.Delete(Path.Combine(Path.GetFullPath(mainexamplDir), "build"), true);// new compiling! } try { Directory.Delete(Path.Combine(Path.GetFullPath(mainexamplDir), "build"), true); } catch (Exception ex) { Console.WriteLine("No delete folder " + mainexamplDir + "-" + ex.Message); continue; } } Process compiler = new Process(); DateTime start = DateTime.Now; Console.WriteLine($"Compiling {nameExampl} defconfig ..."); string DirMake = mainexamplDir.Replace('\\', '/'); compiler.StartInfo.FileName = @"c:/sysgcc/esp32/bin/bash.exe"; compiler.StartInfo.Arguments = $" --login -c \"make VERBOSE=1 -C {DirMake} defconfig >" + nameLog.Replace(".", "def.") + " 2>&1 \""; compiler.StartInfo.UseShellExecute = false; compiler.StartInfo.WorkingDirectory = Path.GetDirectoryName($"c:\\SysGCC\\esp32\\bin"); compiler.EnableRaisingEvents = true; compiler.Start(); compiler.WaitForExit(); Console.WriteLine($"[{(DateTime.Now - start).TotalMilliseconds:f0} msec]"); bool buildSucceeded; buildSucceeded = compiler.ExitCode == 0; if (!buildSucceeded) { FaildSamlesdef++; FaildSamles++; Console.WriteLine($"fail {FaildSamlesdef} compil defcongig {nameExampl} ..."); continue; } start = DateTime.Now; Console.WriteLine($"Compiling {nameExampl} ..."); compiler.StartInfo.FileName = @"c:/sysgcc/esp32/bin/bash.exe"; compiler.StartInfo.Arguments = $"--login -c \"make VERBOSE=1 -C {DirMake} >" + nameLog.Replace('\\', '/') + " 2>&1\""; compiler.StartInfo.UseShellExecute = false; compiler.StartInfo.WorkingDirectory = Path.GetDirectoryName(@"c:\SysGCC\esp32\bin"); compiler.StartInfo.WorkingDirectory = Path.GetDirectoryName($"c:\\SysGCC\\esp32\\bin"); compiler.EnableRaisingEvents = true; compiler.Start(); compiler.WaitForExit(); Console.WriteLine($"[{(DateTime.Now - start).TotalMilliseconds:f0} msec]"); CntSamles++; buildSucceeded = compiler.ExitCode == 0; Console.ForegroundColor = ConsoleColor.Green; if (!buildSucceeded) { if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } FaildSamles++; Console.ForegroundColor = ConsoleColor.Red; File.Copy(nameLog, Path.Combine(outputDir, $"FaildLogs{nameExampl.Replace('\\', '-')}"), true); } ToLog(string.Format("{2}: {0} - {1} (Failed: {3})", nameExampl, buildSucceeded ? "Succes" : "Failed ", CntSamles, FaildSamles)); Console.ForegroundColor = ConsoleColor.Gray; if (!buildSucceeded) { continue; } } Console.WriteLine($"Total fail compil defcongig {FaildSamlesdef}"); Console.WriteLine($"Total fail compil {FaildSamles}"); count = 0; foreach (var makfile in ExampleDirs) { var mainexamplDir = Path.GetDirectoryName(makfile); string nameExampl = mainexamplDir.Substring(mainexamplDir.IndexOf("examples") + 9).Replace("Makefile", "").Replace('\\', '-'); /* * if (count == 1) * break; * count++; */ var nameLog = Path.Combine(Path.GetDirectoryName(mainexamplDir), "Logs", $"{nameExampl}.log"); if (!File.Exists(nameLog)) { Console.WriteLine($"No Log file {1}", Path.GetDirectoryName(nameLog)); continue; } Console.WriteLine($"Start parser { nameExampl}"); VendorSample vs = ParseDependFiles(mainexamplDir, nameLog); if (vs == null) { continue; } string[] frs = { "noFrameworks" }; vs.CLanguageStandard = "gnu99"; vs.CPPLanguageStandard = "gnu++11"; vs.UserFriendlyName = nameExampl; vs.Configuration.Frameworks = frs.ToArray();//null; allSamples.Add(vs); //Clear //File.Delete(Path.Combine(compiler.StartInfo.WorkingDirectory, "log.txt")); //Directory.Delete(Path.Combine(compiler.StartInfo.WorkingDirectory, "_build"), true);*/ } return(allSamples); }
protected override void AdjustVendorSampleProperties(VendorSample vs) { base.AdjustVendorSampleProperties(vs); vs.SourceFiles = vs.SourceFiles.Where(s => !IsNonGCCFile(vs, s)).ToArray(); }
//----------------------------------------------- static VendorSample ParseNativeBuildLog(string namelog) { VendorSample vs = new VendorSample(); List <string> lstFileC = new List <string>(); List <string> lstFileInc = new List <string>(); List <string> splitArgs = new List <string>(); List <string> lstDef = new List <string>(); string aCurDir = Path.GetDirectoryName(namelog); foreach (var ln in File.ReadAllLines(namelog)) { if (!ln.Contains(toolchainDir)) { continue; } // Get Arguments int munArg; IntPtr ptrToSplitArgs = CommandLineToArgvW(ln, out munArg); if (ptrToSplitArgs == IntPtr.Zero) { throw new Exception("no arg"); } for (int i = 0; i < munArg; i++) { string arg = Marshal.PtrToStringUni( Marshal.ReadIntPtr(ptrToSplitArgs, i * IntPtr.Size)); if (!splitArgs.Contains(arg)) { splitArgs.Add(arg); } } } // Processing arguments lstFileInc.AddRange(string.Join(" ", splitArgs.Where(ar => ar.StartsWith("-I"))).Split(new string[] { "-I" }, StringSplitOptions.RemoveEmptyEntries)); lstDef.AddRange(string.Join(" ", splitArgs.Where(ar => ar.StartsWith("-D"))).Split(new string[] { "-D" }, StringSplitOptions.RemoveEmptyEntries)); lstFileC.AddRange(splitArgs.Where(ar => ar.EndsWith(".c") && !ar.Contains(@"components/toolchain/"))); //arguments from file var fileArg = splitArgs.SingleOrDefault(ar => ar.StartsWith("@")); if (fileArg != null) { var Libs = from t in File.ReadAllText(Path.Combine(aCurDir, fileArg.Substring(1))).Split(' ') where t.EndsWith(".a") orderby t select t; lstFileC.AddRange(Libs); } BuildAbsolutePath(aCurDir, ref lstFileInc); BuildAbsolutePath(aCurDir, ref lstFileC); var aProjectName = File.ReadAllLines(Path.Combine(aCurDir, "Makefile")).Single(ln => ln.StartsWith("PROJECT_NAME")).Split('=')[1].Trim(' ').ToUpper(); var fl = File.ReadAllText(Path.Combine(aCurDir, "Makefile")); if (!fl.Contains("SOFTDEVICE_PRESENT")) { vs.Configuration.MCUConfiguration = new PropertyDictionary2 { Entries = new PropertyDictionary2.KeyValue[] { new PropertyDictionary2.KeyValue { Key = "com.sysprogs.bspoptions.nrf5x.softdevice", Value = "nosoftdev" } }.ToArray() }; } else { var n = lstFileC.FindIndex(fi => fi.Contains("/softdevice_handler.c")); if (n >= 0) { lstFileC.RemoveAt(n); } } vs.IncludeDirectories = lstFileInc.ToArray(); vs.PreprocessorMacros = lstDef.ToArray(); vs.SourceFiles = lstFileC.ToArray(); vs.DeviceID = File.ReadAllLines(Path.Combine(aCurDir, "Makefile")).Single(ln => ln.StartsWith("TARGETS")).Split('=')[1].Trim(' ').ToUpper(); vs.UserFriendlyName = aProjectName; return(vs); }
public static ParsedSDK ParseKSDKManifest(string sdkDirectory, IWarningSink sink) { string[] manifestFiles = Directory.GetFiles(sdkDirectory, "*manifest.xml"); if (manifestFiles.Length < 1) throw new Exception($"No manifest files in {sdkDirectory}"); string manifestFile = Directory.GetFiles(sdkDirectory, "*manifest.xml")[0]; List<VendorSample> vsl = new List<VendorSample>(); XmlDocument doc = new XmlDocument(); doc.Load(manifestFile); List<MCU> mcus = new List<MCU>(); List<MCUFamily> families = new List<MCUFamily>(); List<ParsedComponent> allFrameworks = new List<ParsedComponent>(); bool linkerScriptHandled = false; List<string> allFiles = new List<string>(); Dictionary<string, ParsedDevice> deviceDict = new Dictionary<string, ParsedDevice>(); Dictionary<string, EmbeddedFramework> frameworkDict = new Dictionary<string, EmbeddedFramework>(); List<FileCondition> allConditions = new List<FileCondition>(); string fwPrefix = "com.sysprogs.ksdk2x_imported."; HashSet<string> alwaysIncludedFrameworks = new HashSet<string>(); foreach (XmlElement devNode in doc.SelectNodes("//devices/device")) { ParsedDevice dev = new ParsedDevice(devNode, sdkDirectory); var mcuFamily = dev.ToMCUFamily(); int FLASHSize, RAMSize; int.TryParse((devNode.SelectSingleNode("memory/@flash_size_kb")?.Value ?? ""), out FLASHSize); int.TryParse((devNode.SelectSingleNode("memory/@ram_size_kb")?.Value ?? ""), out RAMSize); FLASHSize *= 1024; RAMSize *= 1024; families.Add(mcuFamily); string svdFile = null; //Map each component to an instance of EmbeddedFramework foreach (XmlNode componentNode in doc.SelectNodes($"//components/component")) { string componentName = componentNode.SelectSingleNode("@name")?.Value ?? ""; string componentType = componentNode.SelectSingleNode("@type")?.Value ?? ""; string device = componentNode.SelectSingleNode("@device")?.Value ?? ""; switch (componentType) { case "documentation": case "SCR": case "EULA": continue; case "debugger": case "linker": { List<string> relPaths = new List<string>(); bool isDebug = componentType == "debugger"; string sourceType = isDebug ? "debug" : "linker"; foreach (var src in componentNode.SelectNodes($"source[@type='{sourceType}']").OfType<XmlElement>().Select(e => new ParsedSource(e, dev))) { foreach (var fn in src.AllFiles) { relPaths.Add(fn.RelativePath); } } if (relPaths.Count > 0) { if (isDebug) svdFile = relPaths[0]; else if (!linkerScriptHandled) { linkerScriptHandled = true; if (relPaths.Count == 1) mcuFamily.CompilationFlags.LinkerScript = "$$SYS:BSP_ROOT$$/" + relPaths[0]; else { const string optionID = "com.sysprogs.imported.ksdk2x.linker_script"; mcuFamily.CompilationFlags.LinkerScript = $"$$SYS:BSP_ROOT$$/$${optionID}$$"; mcuFamily.ConfigurableProperties.PropertyGroups[0].Properties.Add(new PropertyEntry.Enumerated { UniqueID = optionID, Name = "Linker script", AllowFreeEntry = false, SuggestionList = relPaths.Select(p => new PropertyEntry.Enumerated.Suggestion { InternalValue = p, UserFriendlyName = Path.GetFileName(p) }).ToArray() }); } } } } continue; case "CMSIS": //KSDK 2.x defines a Include_xxx framework for each possible CMSIS core. Those frameworks are redundant (normal 'Include' framework references the same include path) and should be removed to avoid confusion. if (componentName.StartsWith("Include_")) continue; if (componentName == "Include") alwaysIncludedFrameworks.Add(fwPrefix + componentName); break; default: break; } List<string> headerFiles = new List<string>(); List<string> includeDirectories = new List<string>(); List<string> sourceFiles = new List<string>(); foreach (ParsedSource src in componentNode.SelectNodes("source").OfType<XmlElement>().Select(e => new ParsedSource(e, dev))) { if (src.Type == "c_include") includeDirectories.Add(src.BSPPath); foreach (var file in src.AllFiles) { if (src.Type == "src" || src.Type == "asm_include") sourceFiles.Add(file.BSPPath); else if (src.Type == "c_include") headerFiles.Add(file.BSPPath); } } if (componentName == "clock" && componentType == "driver") alwaysIncludedFrameworks.Add(fwPrefix + componentName); string[] dependencyList = componentNode.Attributes?.GetNamedItem("dependency")?.Value?.Split(' ') ?.Select(id => fwPrefix + id) ?.ToArray() ?? new string[0]; EmbeddedFramework fw = new EmbeddedFramework { ID = $"{fwPrefix}{componentName}", UserFriendlyName = $"{componentName} ({componentType})", ProjectFolderName = componentName, AdditionalSourceFiles = sourceFiles.Distinct().ToArray(), AdditionalHeaderFiles = headerFiles.Distinct().ToArray(), RequiredFrameworks = dependencyList, AdditionalIncludeDirs = includeDirectories.Distinct().ToArray(), AdditionalPreprocessorMacros = componentNode.SelectNodes("defines/define").OfType<XmlElement>().Select(el => new ParsedDefine(el).Definition).ToArray(), }; if (componentName == "freertos" && componentType == "OS") { fw.AdditionalPreprocessorMacros = LoadedBSP.Combine(fw.AdditionalPreprocessorMacros, "USE_RTOS=1;USE_FREERTOS".Split(';')); fw.ConfigurableProperties = new PropertyList { PropertyGroups = new List<PropertyGroup>() { new PropertyGroup { Properties = new List<PropertyEntry>() { new PropertyEntry.Enumerated { Name = "FreeRTOS Heap Implementation", UniqueID = "com.sysprogs.bspoptions.stm32.freertos.heap", DefaultEntryIndex = 3, SuggestionList = new PropertyEntry.Enumerated.Suggestion[] { new PropertyEntry.Enumerated.Suggestion{InternalValue = "heap_1", UserFriendlyName = "Heap1 - no support for freeing"}, new PropertyEntry.Enumerated.Suggestion{InternalValue = "heap_2", UserFriendlyName = "Heap2 - no block consolidation"}, new PropertyEntry.Enumerated.Suggestion{InternalValue = "heap_3", UserFriendlyName = "Heap3 - use newlib malloc()/free()"}, new PropertyEntry.Enumerated.Suggestion{InternalValue = "heap_4", UserFriendlyName = "Heap4 - contiguous heap area"}, new PropertyEntry.Enumerated.Suggestion{InternalValue = "heap_5", UserFriendlyName = "Heap5 - scattered heap area"}, } } } } } }; foreach(var fn in fw.AdditionalSourceFiles) { string name = Path.GetFileName(fn); if (name.StartsWith("heap_")) { allConditions.Add(new FileCondition { FilePath = fn, ConditionToInclude = new Condition.Equals { Expression = "$$com.sysprogs.bspoptions.stm32.freertos.heap$$", ExpectedValue = Path.GetFileNameWithoutExtension(fn) } }); } } } if (frameworkDict.ContainsKey(fw.ID)) { sink.LogWarning("Duplicate framework for " + fw.ID); continue; } frameworkDict[fw.ID] = fw; if (string.IsNullOrEmpty(fw.ID)) { sink.LogWarning($"Found a framework with empty ID. Skipping..."); continue; } if (string.IsNullOrEmpty(fw.UserFriendlyName)) fw.UserFriendlyName = fw.ID; allFrameworks.Add(new ParsedComponent { Framework = fw, OriginalType = componentType, OriginalName = componentName }); allFiles.AddRange(sourceFiles); allFiles.AddRange(headerFiles); } string deviceDefinitionFile = null; if (svdFile != null) { try { var mcuDef = SVDParser.ParseSVDFile(Path.Combine(sdkDirectory, svdFile), dev.DeviceName); deviceDefinitionFile = Path.ChangeExtension(svdFile, ".vgdbdevice"); XmlSerializer ser = new XmlSerializer(typeof(MCUDefinition)); using (var fs = File.Create(Path.Combine(sdkDirectory, Path.ChangeExtension(svdFile, ".vgdbdevice.gz")))) using (var gs = new GZipStream(fs, CompressionMode.Compress, true)) ser.Serialize(gs, new MCUDefinition(mcuDef)); } catch (Exception ex) { sink.LogWarning($"Failed to parse {svdFile}: {ex.Message}"); } } foreach (XmlNode packageNode in devNode.SelectNodes($"package/@name")) { string pkgName = packageNode?.Value; if (string.IsNullOrEmpty(pkgName)) continue; deviceDict[pkgName] = dev; mcus.Add(new MCU { ID = pkgName, UserFriendlyName = $"{pkgName} (KSDK 2.x)", FamilyID = mcuFamily.ID, FLASHSize = FLASHSize, RAMSize = RAMSize, CompilationFlags = new ToolFlags { PreprocessorMacros = new string[] { "CPU_" + pkgName } }, MCUDefinitionFile = deviceDefinitionFile }); } } if (families.Count == 0) throw new Exception("The selected KSDK contains no families"); List<VendorSample> samples = new List<VendorSample>(); foreach (XmlElement boardNode in doc.SelectNodes("//boards/board")) { string boardName = boardNode.GetAttribute("name"); string deviceID = boardNode.GetAttribute("package"); ParsedDevice dev; if (!deviceDict.TryGetValue(deviceID, out dev)) continue; foreach (XmlElement exampleNode in boardNode.SelectNodes("examples/example")) { List<string> dependencyList = new List<string>(exampleNode.Attributes?.GetNamedItem("dependency")?.Value?.Split(' ') ?.Select(id => fwPrefix + id) ?? new string[0]); dependencyList.AddRange(alwaysIncludedFrameworks); for (int i = 0; i < dependencyList.Count; i++) { EmbeddedFramework fw; if (frameworkDict.TryGetValue(dependencyList[i], out fw) && fw?.RequiredFrameworks != null) dependencyList.AddRange(fw.RequiredFrameworks.Except(dependencyList)); } VendorSample sample = new VendorSample { DeviceID = deviceID, UserFriendlyName = exampleNode.GetAttribute("name") ?? "???", BoardName = boardName, Configuration = new VendorSampleConfiguration { Frameworks = dependencyList.ToArray() }, VirtualPath = exampleNode.GetAttribute("category"), NoImplicitCopy = true }; List<string> headerFiles = new List<string>(); List<string> includeDirectories = new List<string>(); List<string> sourceFiles = new List<string>(); foreach (var src in exampleNode.SelectNodes("source").OfType<XmlElement>().Select(e => new ParsedSource(e, dev))) { foreach (var file in src.AllFiles) { if (src.Type == "src" || src.Type == "asm_include") sourceFiles.Add(file.BSPPath); else if (src.Type == "c_include") headerFiles.Add(file.BSPPath); } } sample.SourceFiles = sourceFiles.ToArray(); sample.HeaderFiles = headerFiles.ToArray(); if (sourceFiles.Count == 0 && headerFiles.Count == 0) continue; string[] matchingComponents = null; foreach (var fn in sourceFiles.Concat(headerFiles)) { string[] components = fn.Split('/', '\\'); if (matchingComponents == null) matchingComponents = components; else { int matches = CountMatches(matchingComponents, components); if (matches < matchingComponents.Length) Array.Resize(ref matchingComponents, matches); } } if (matchingComponents != null) sample.Path = string.Join("/", matchingComponents); samples.Add(sample); } } return new ParsedSDK { BSP = new BoardSupportPackage { PackageID = "com.sysprogs.imported.ksdk2x." + families[0].ID, PackageDescription = "Imported KSDK 2.x for " + families[0].ID, PackageVersion = doc.SelectSingleNode("//ksdk/@version")?.Value ?? "unknown", GNUTargetID = "arm-eabi", Frameworks = allFrameworks.Where(f => f.OriginalType != "project_template").Select(f => f.Framework).ToArray(), MCUFamilies = families.ToArray(), SupportedMCUs = mcus.ToArray(), FileConditions = allFiles .Where(f => f.IndexOf("freertos", StringComparison.InvariantCultureIgnoreCase) != -1) .Select(f => new FileCondition { FilePath = f, ConditionToInclude = new Condition.ReferencesFramework { FrameworkID = fwPrefix + "freertos" } }) .Concat(allConditions) .ToArray(), VendorSampleCatalogName = "KSDK Samples", EmbeddedSamples = allFrameworks.Where(f => f.OriginalType == "project_template").Select(f => f.ToProjectSample(alwaysIncludedFrameworks)).ToArray(), }, VendorSampleDirectory = new VendorSampleDirectory { Samples = samples.ToArray() } }; }
static public List <VendorSample> GetInfoProjectFromMDK(string pDirPrj, string topLevelDir, string boardName, List <string> extraIncludeDirs) { List <VendorSample> aLstVSampleOut = new List <VendorSample>(); int aCntTarget = 0; string aFilePrj = Directory.GetFiles(pDirPrj, "*.uvprojx")[0]; string aNamePrj = Path.GetFileName(Path.GetDirectoryName(pDirPrj)); List <string> sourceFiles = new List <string>(); List <string> includeDirs = new List <string>(); bool flGetProperty = false; string aTarget = ""; VendorSample sample = new VendorSample(); foreach (var ln in File.ReadAllLines(aFilePrj)) { if (ln.Contains("<Target>")) { if (aCntTarget == 0) { sample = new VendorSample(); } aCntTarget++; } if (ln.Contains("</Target>")) { if (aCntTarget == 0) { throw new Exception("wrong tag Targets"); } else { aCntTarget--; } } if (ln.Contains("<Cads>")) { flGetProperty = true; } else if (ln.Contains("</Cads>")) { flGetProperty = false; } Match m = Regex.Match(ln, "[ \t]*<Device>(.*)</Device>[ \t]*"); if (m.Success) { sample.DeviceID = m.Groups[1].Value; if (sample.DeviceID.EndsWith("x")) { sample.DeviceID = sample.DeviceID.Remove(sample.DeviceID.Length - 2, 2); } } m = Regex.Match(ln, "[ \t]*<TargetName>(.*)</TargetName>[ \t]*"); if (m.Success) { aTarget = m.Groups[1].Value; } MatchCollection m1 = Regex.Matches(ln, @"[ ]*<FilePath>([\w\-:\\./]*)</FilePath>[ ]*"); foreach (Match mc in m1) { string filePath = mc.Groups[1].Value; if (filePath.StartsWith(@"./") || filePath.StartsWith(@".\")) { filePath = pDirPrj + filePath.Substring(1); } if (filePath.EndsWith(".s", StringComparison.InvariantCultureIgnoreCase)) { continue; } if (filePath.EndsWith(".lib", StringComparison.InvariantCultureIgnoreCase)) { filePath = filePath.Replace("_Keil_wc16.lib", "_GCC_wc32.a"); filePath = filePath.Replace("_Keil.lib", "_GCC.a"); filePath = filePath.Replace("_Keil_ARGB.lib", "_GCC_ARGB.a"); filePath = filePath.Replace(@"Keil\touchgfx_core.lib", @"gcc\libtouchgfx-float-abi-hard.a"); if (!File.Exists(Path.Combine(pDirPrj, filePath))) { continue; } } if (filePath.EndsWith(".a", StringComparison.InvariantCultureIgnoreCase) && filePath.IndexOf("_IAR", StringComparison.InvariantCultureIgnoreCase) != -1) { filePath = filePath.Replace("_IAR_ARGB.a", "_GCC_ARGB.a"); if (!File.Exists(Path.Combine(pDirPrj, filePath))) { continue; } } if (filePath.EndsWith(".a", StringComparison.InvariantCultureIgnoreCase)) { filePath = filePath.Replace("_wc16", "_wc32"); } if (!sourceFiles.Contains(filePath)) { sourceFiles.Add(filePath); } } if (flGetProperty) { m = Regex.Match(ln, "[ \t]*<IncludePath>(.*)</IncludePath>[ \t]*"); if (m.Success && m.Groups[1].Value != "") { sample.IncludeDirectories = m.Groups[1].Value.Split(';').Select(FixIncludePath).ToArray(); } m = Regex.Match(ln, "[ \t]*<Define>(.*)</Define>[ \t]*"); if (m.Success && m.Groups[1].Value != "") { sample.PreprocessorMacros = m.Groups[1].Value.Replace(">", ">").Replace("<", "<").Split(',').Select(t => t.Trim()).Where(t => t != "").ToArray(); for (int i = 0; i < sample.PreprocessorMacros.Length; i++) { if (sample.PreprocessorMacros[i].Contains("\"<")) { //This is likely the MBEDTLS_CONFIG_FILE="<mbedtls_config.h>" macro. We need to remove the quotes, as VisualGDB will automatically escape it anyway. sample.PreprocessorMacros[i] = sample.PreprocessorMacros[i].Replace("\"<", "<").Replace(">\"", ">"); } } } } if (ln.Contains("</Target>") && aCntTarget == 0) { sample.Path = Path.GetDirectoryName(pDirPrj); sample.UserFriendlyName = aNamePrj; AppendSamplePrefixFromPath(ref sample.UserFriendlyName, pDirPrj); sample.BoardName = aTarget; sample.SourceFiles = ToAbsolutePath(pDirPrj, topLevelDir, sourceFiles).ToArray(); foreach (var fl in sample.IncludeDirectories) { includeDirs.Add(fl); } includeDirs.AddRange(extraIncludeDirs); sample.IncludeDirectories = ToAbsolutePath(pDirPrj, topLevelDir, includeDirs).ToArray(); string readmeFile = Path.Combine(pDirPrj, @"..\readme.txt"); if (File.Exists(readmeFile)) { string readmeContents = File.ReadAllText(readmeFile); Regex rgTitle = new Regex(@"@page[ \t]+[^ \t]+[ \t]+([^ \t][^@]*)\r\n *\r\n", RegexOptions.Singleline); m = rgTitle.Match(readmeContents); if (m.Success) { sample.Description = m.Groups[1].Value; } } var fsdataCustom = sample.SourceFiles.FirstOrDefault(f => Path.GetFileName(f).ToLower() == "fsdata_custom.c"); if (fsdataCustom != null) { var lines = File.ReadAllLines(Path.Combine(Path.GetDirectoryName(fsdataCustom), "fs.c")); if (lines.Contains("#include \"fsdata.c\"")) { sample.SourceFiles = sample.SourceFiles.Except(new[] { fsdataCustom }).ToArray(); } else { //Should not happen Debug.Assert(false); } } var syscallsFile = Path.Combine(sample.Path, "SW4STM32", "syscalls.c"); if (File.Exists(syscallsFile)) { //This file is included in some samples to handle I/O redirection. Since it is GCC-specific, it's not referenced by the Keil project file we are parsing. sample.SourceFiles = sample.SourceFiles.Concat(new[] { syscallsFile }).ToArray(); } aLstVSampleOut.Add(sample); } } if (aLstVSampleOut.Count == 1) { aLstVSampleOut[0].BoardName = boardName; //In some example projects, the target name is defined incorrectly } else { foreach (var s in aLstVSampleOut) { s.BoardName = boardName + "-" + s.BoardName; } } return(aLstVSampleOut); }
protected override void AdjustVendorSampleProperties(VendorSample vs) { base.AdjustVendorSampleProperties(vs); vs.BSPReferencesAreCopyable = true; }
public void Run(string[] args) { string SDKdir = null; string specificSampleName = null; RunMode mode = RunMode.Invalid; foreach (var arg in args) { string singlePrefix = "/single:"; if (arg.StartsWith(singlePrefix, StringComparison.InvariantCultureIgnoreCase)) { mode = RunMode.SingleSample; specificSampleName = arg.Substring(singlePrefix.Length); } else if (arg.StartsWith("/")) { mode = Enum.GetValues(typeof(RunMode)).OfType <RunMode>().First(v => v.ToString().ToLower() == arg.Substring(1).ToLower()); } else { SDKdir = arg; } } if (SDKdir == null || mode == RunMode.Invalid) { Console.WriteLine($"Usage: {Path.GetFileName(Assembly.GetEntryAssembly().Location)} <mode> <SW package directory>"); Console.WriteLine($"Modes:"); Console.WriteLine($" /incremental - Only retest/rebuild previously failed samples."); Console.WriteLine($" This doesn't update the BSP archive."); Console.WriteLine($" /release - Reuse cached definitions, retest all samples. Update BSP."); Console.WriteLine($" /cleanRelease - Reparse/retest all samples. Update BSP."); Console.WriteLine($" /updateErrors - Re-categorize errors based on KnownProblems.xml"); Console.WriteLine($" /single:<name> - Run all phases of just one sample."); Console.WriteLine($"Press any key to continue..."); Console.ReadKey(); Environment.ExitCode = 1; return; } if (mode == RunMode.Incremental) { Console.WriteLine("*********************** WARNING ************************"); Console.WriteLine("* Vendor sample parser is running in incremental mode. *"); Console.WriteLine("* Only retested samples will be saved to BSP! *"); Console.WriteLine("* Re-run in /release mode to build a releasable BSP. *"); Console.WriteLine("********************************************************"); } if (mode == RunMode.UpdateErrors) { foreach (var rec in _Report.Records) { } XmlTools.SaveObject(_Report, ReportFile); return; } string archiveName = string.Format("{0}-{1}.vgdbxbsp", BSP.BSP.PackageID.Split('.').Last(), BSP.BSP.PackageVersion); string archiveFilePath = Path.Combine(BSPDirectory, archiveName); if (File.Exists(archiveFilePath)) { File.Delete(archiveFilePath); } string sampleListFile = Path.Combine(CacheDirectory, "Samples.xml"); var sampleDir = BuildOrLoadSampleDirectoryAndUpdateReportForFailedSamples(sampleListFile, SDKdir, mode, specificSampleName); Dictionary <VendorSampleID, string> encounteredIDs = new Dictionary <VendorSampleID, string>(); foreach (var vs in sampleDir.Samples) { var id = new VendorSampleID(vs); if (encounteredIDs.TryGetValue(id, out var dir)) { throw new Exception("Duplicate sample for " + id); } encounteredIDs[new VendorSampleID(vs)] = vs.Path; var rec = _Report.ProvideEntryForSample(new VendorSampleID(vs)); if (rec.LastSucceededPass < VendorSamplePass.InitialParse) { rec.LastSucceededPass = VendorSamplePass.InitialParse; } } //We cache unadjusted sample definitions to allow tweaking the adjusting code without the need to reparse everything. Console.WriteLine("Adjusting sample properties..."); foreach (var vs in sampleDir.Samples) { AdjustVendorSampleProperties(vs); if (vs.Path == null) { throw new Exception("Missing sample path for " + vs.UserFriendlyName); } } VendorSample[] pass1Queue, insertionQueue; switch (mode) { case RunMode.Incremental: pass1Queue = insertionQueue = sampleDir.Samples.Where(s => _Report.ShouldBuildIncrementally(new VendorSampleID(s), VendorSamplePass.InPlaceBuild)).ToArray(); break; case RunMode.Release: insertionQueue = sampleDir.Samples; if (sampleDir.Samples.FirstOrDefault(s => s.AllDependencies != null) == null) { pass1Queue = sampleDir.Samples; } else { pass1Queue = new VendorSample[0]; } break; case RunMode.CleanRelease: pass1Queue = insertionQueue = sampleDir.Samples; break; case RunMode.SingleSample: pass1Queue = insertionQueue = sampleDir.Samples.Where(s => new VendorSampleID(s).ToString() == specificSampleName).ToArray(); if (pass1Queue.Length == 0) { throw new Exception("No samples match " + specificSampleName); } break; default: throw new Exception("Invalid run mode"); } if (pass1Queue.Length > 0) { //Test the raw VendorSamples in-place and store AllDependencies TestVendorSamplesAndUpdateReportAndDependencies(pass1Queue, null, VendorSamplePass.InPlaceBuild, vs => _Report.HasSampleFailed(new VendorSampleID(vs)), validationFlags: BSPValidationFlags.ResolveNameCollisions); foreach (var vs in pass1Queue) { if (vs.Path == null) { throw new Exception("Missing sample path for " + vs.UserFriendlyName); } } sampleDir.ToolchainDirectory = ToolchainDirectory; sampleDir.BSPDirectory = Path.GetFullPath(BSPDirectory); XmlTools.SaveObject(sampleDir, sampleListFile); } //Insert the samples into the generated BSP var relocator = CreateRelocator(sampleDir); var copiedFiles = relocator.InsertVendorSamplesIntoBSP(sampleDir, insertionQueue, BSPDirectory); var bsp = XmlTools.LoadObject <BoardSupportPackage>(Path.Combine(BSPDirectory, LoadedBSP.PackageFileName)); bsp.VendorSampleDirectoryPath = VendorSampleDirectoryName; bsp.VendorSampleCatalogName = VendorSampleCatalogName; XmlTools.SaveObject(bsp, Path.Combine(BSPDirectory, LoadedBSP.PackageFileName)); if (mode != RunMode.Incremental && mode != RunMode.SingleSample) { Console.WriteLine("Creating new BSP archive..."); string statFile = Path.ChangeExtension(archiveName, ".xml"); TarPacker.PackDirectoryToTGZ(BSPDirectory, archiveFilePath, fn => Path.GetExtension(fn).ToLower() != ".vgdbxbsp" && Path.GetFileName(fn) != statFile); } var vendorSampleListInBSP = Path.Combine(BSPDirectory, VendorSampleDirectoryName, "VendorSamples.xml"); // Finally verify that everything builds var expandedSamples = XmlTools.LoadObject <VendorSampleDirectory>(vendorSampleListInBSP); expandedSamples.Path = Path.GetFullPath(Path.Combine(BSPDirectory, VendorSampleDirectoryName)); var finalStats = TestVendorSamplesAndUpdateReportAndDependencies(expandedSamples.Samples, expandedSamples.Path, VendorSamplePass.RelocatedBuild); XmlTools.SaveObject(_Report, ReportFile); if (mode == RunMode.Incremental || mode == RunMode.SingleSample) { Console.WriteLine($"Deleting incomplete {vendorSampleListInBSP}...\n***Re-run in /release mode to produce a valid BSP."); File.Delete(vendorSampleListInBSP); //Incremental mode only places the samples that are currently built. } if (finalStats.Failed == 0) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine($"All {finalStats.Total} tests passed during final pass."); } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"{finalStats.Failed} out of {finalStats.Total} tests failed during final pass."); } Console.ResetColor(); Console.WriteLine("============================================="); Console.WriteLine($"Overall statistics for v{BSP.BSP.PackageVersion}:"); List <KeyValuePair <string, string> > fields = new List <KeyValuePair <string, string> >(); fields.Add(new KeyValuePair <string, string>("Total samples discovered:", sampleDir.Samples.Length.ToString())); int unparsableSamples = _Report.Records.Count(r => r.LastSucceededPass == VendorSamplePass.None); int failedAtFirstBuild = _Report.Records.Count(r => r.LastSucceededPass == VendorSamplePass.InitialParse && r.BuildFailedExplicitly); int failedAtSecondBuild = _Report.Records.Count(r => r.LastSucceededPass == VendorSamplePass.InPlaceBuild && r.BuildFailedExplicitly); fields.Add(new KeyValuePair <string, string>("Failed during initial parse attempt:", $"{unparsableSamples}/{sampleDir.Samples.Length} ({unparsableSamples * 100.0 / sampleDir.Samples.Length:f1}%)")); fields.Add(new KeyValuePair <string, string>("Failed during in-place build:", $"{failedAtFirstBuild}/{sampleDir.Samples.Length} ({failedAtFirstBuild * 100.0 / sampleDir.Samples.Length:f1}%)")); fields.Add(new KeyValuePair <string, string>("Failed during relocated build:", $"{failedAtSecondBuild}/{sampleDir.Samples.Length} ({failedAtSecondBuild * 100.0 / sampleDir.Samples.Length:f1}%)")); if (mode != RunMode.Incremental) { fields.Add(new KeyValuePair <string, string>("Inserted into BSP:", expandedSamples.Samples.Length.ToString())); } OutputKeyValueList(fields); if (finalStats.Failed > 0 && mode != RunMode.Incremental) { throw new Exception("Some of the vendor samples have failed the final test. Fix this before releasing the BSP."); } Console.WriteLine("Press any key to continue..."); Console.ReadKey(); }
VendorSample ParseNativeBuildLog(string namelog, string SDKdir, string sampleID) { VendorSample vs = new VendorSample { InternalUniqueID = sampleID }; List <string> lstFileC = new List <string>(); List <string> lstFileInc = new List <string>(); List <string> splitArgs = new List <string>(); List <string> preprocessorMacros = new List <string>(); string aCurDir = Path.GetDirectoryName(namelog); foreach (var ln in File.ReadAllLines(namelog)) { if (ln.Replace('\\', '/').IndexOf(ToolchainDirectory.Replace('\\', '/'), StringComparison.InvariantCultureIgnoreCase) == -1) { continue; } // Get Arguments int munArg; IntPtr ptrToSplitArgs = CommandLineToArgvW(ln, out munArg); if (ptrToSplitArgs == IntPtr.Zero) { throw new Exception("no arg"); } for (int i = 0; i < munArg; i++) { string arg = Marshal.PtrToStringUni( Marshal.ReadIntPtr(ptrToSplitArgs, i * IntPtr.Size)); if (!splitArgs.Contains(arg)) { splitArgs.Add(arg); } } } // Processing arguments lstFileInc.AddRange(splitArgs.Where(ar => ar.StartsWith("-I")).Select(a => a.Substring(2).Trim())); preprocessorMacros.AddRange(splitArgs.Where(ar => ar.StartsWith("-D")).Select(a => a.Substring(2).Trim())); lstFileC.AddRange(splitArgs.Where(ar => (ar.EndsWith(".c") || ar.EndsWith(".s", StringComparison.InvariantCultureIgnoreCase)) && !ar.Contains(@"components/toolchain/") && !ar.Contains(@"gcc_startup"))); vs.CLanguageStandard = "c99"; //arguments from file var fileArg = splitArgs.SingleOrDefault(ar => ar.StartsWith("@")); if (fileArg != null) { var Libs = from t in File.ReadAllText(Path.Combine(aCurDir, fileArg.Substring(1))).Split(' ') where t.EndsWith(".a") orderby t select t; lstFileC.AddRange(Libs); } BuildAbsolutePath(aCurDir, ref lstFileInc); BuildAbsolutePath(aCurDir, ref lstFileC); var aProjectName = File.ReadAllLines(Path.Combine(aCurDir, "Makefile")).Single(ln => ln.StartsWith("PROJECT_NAME")).Split('=')[1].Trim(' ').ToUpper(); vs.DeviceID = File.ReadAllLines(Path.Combine(aCurDir, "Makefile")).Single(ln => ln.StartsWith("TARGETS")).Split('=')[1].Trim(' ').ToUpper(); var softdeviceProperty = BSP.BSP.SupportedMCUs.First(m => vs.DeviceID.StartsWith(m.ID, StringComparison.InvariantCultureIgnoreCase)).ConfigurableProperties.PropertyGroups.SelectMany(g => g.Properties).FirstOrDefault(p => p.UniqueID == "com.sysprogs.bspoptions.nrf5x.softdevice") as PropertyEntry.Enumerated; if (softdeviceProperty == null) { throw new Exception("Failed to locate softdevice for property" + vs.DeviceID); } string softdevice = softdeviceProperty.SuggestionList.FirstOrDefault(e => preprocessorMacros.Contains(e.InternalValue))?.InternalValue; if (!preprocessorMacros.Contains("SOFTDEVICE_PRESENT")) { //This is a special 'serialization mode' sample that defines -DSxxx, but not -DSOFTDEVICE_PRESENT, that is not supported by our BSP yet. softdevice = null; } vs.Configuration.MCUConfiguration = new PropertyDictionary2 { Entries = new PropertyDictionary2.KeyValue[] { new PropertyDictionary2.KeyValue { Key = "com.sysprogs.bspoptions.nrf5x.softdevice", Value = softdevice ?? "nosoftdev" } }.ToArray() }; if (softdevice != null) { var n = lstFileC.FindIndex(fi => fi.Contains("/softdevice_handler.c")); if (n >= 0) { lstFileC.RemoveAt(n); } } if (Directory.GetFiles(aCurDir, "*.ld").Count() > 0) { vs.LinkerScript = Directory.GetFiles(aCurDir, "*.ld")[0]; } vs.IncludeDirectories = lstFileInc.ToArray(); vs.PreprocessorMacros = preprocessorMacros.ToArray(); vs.SourceFiles = lstFileC.ToArray(); vs.UserFriendlyName = aProjectName; vs.NoImplicitCopy = true; return(vs); }