public MCUFamilyBuilder(BSPBuilder bspBuilder, FamilyDefinition definition) { bspBuilder.ExpandVariables(ref definition.PrimaryHeaderDir); bspBuilder.ExpandVariables(ref definition.StartupFileDir); if (definition.SmartSamples != null) { foreach (var simple in definition.SmartSamples) { for (int count = 0; count < simple.AdditionalSources?.Count(); count++) { string addSource = simple.AdditionalSources[count];; bspBuilder.ExpandAdditionalVariables(ref simple.AdditionalSources[count], definition.AdditionalSystemVars); } } } BSP = bspBuilder; Definition = definition; if (string.IsNullOrEmpty(definition.FamilySubdirectory)) { FamilyFilePrefix = ""; } else { FamilyFilePrefix = definition.FamilySubdirectory + "/"; } }
public FrameworkLocator(string sdkDir, string rulesDir) { _AllFilesInSDK = Directory.GetFiles(sdkDir, "*", SearchOption.AllDirectories).Select(f => f.Substring(sdkDir.Length + 1).Replace('\\', '/')).ToArray(); _FamilyDefinition = XmlTools.LoadObject <FamilyDefinition>(Path.Combine(rulesDir, "CommonFiles.xml")); _AllFrameworks = _FamilyDefinition.AdditionalFrameworks.Concat(_FamilyDefinition.AdditionalFrameworkTemplates.SelectMany(t => t.Expand())).ToArray(); #if UNUSED var allFiles = File.ReadAllLines(@"e:\temp\libs.txt"); var unresolvedLibs = allFiles.Where(f => DoLookupFrameworkIDForLibraryFile(f) == null).ToArray(); Console.WriteLine($"Found {unresolvedLibs.Length} unresolved libraries:"); foreach (var lib in unresolvedLibs) { Console.WriteLine("\t" + lib); } #endif }
public void GenerateRulesForFamily(FamilyDefinition family) { foreach (var fw in family.AdditionalFrameworks) { foreach (var job in fw.CopyJobs) { string[] attrs = job.VendorSpecificAttributes?.Split('|'); if (attrs?.Contains("GenerateConditionsForPrebuiltLibraries") == true) { GenerateConditionsForPrebuiltLibraries(family, fw, job); } if (attrs?.Contains("GenerateConditionsForSubdirs") == true) { GenerateConditionsForSubdirs(family, fw, job); } } } GenerateBLEFrameworks(family); }
private void CreateMCUFamilyBuilders() { var mcuFamilyBuilders = new List <MCUFamilyBuilder>(); foreach (var deviceDirectory in Directory.GetDirectories(Directories.InputDir + "\\" + DEVICES_FOLDER)) { var deviceName = deviceDirectory.Substring(deviceDirectory.LastIndexOf(Path.DirectorySeparatorChar) + 1); if (deviceName[0] != 'M') { throw new Exception("Unexpected device name"); } var mcuFamilyName = deviceName.Substring(1); var familyDefinition = new FamilyDefinition(); familyDefinition.Name = mcuFamilyName; familyDefinition.FamilySubdirectory = mcuFamilyName; familyDefinition.PrimaryHeaderDir = deviceDirectory; familyDefinition.Subfamilies = new MCUClassifier[0]; mcuFamilyBuilders.Add(new MCUFamilyBuilder(this, familyDefinition)); } _mcuFamilyBuilders = mcuFamilyBuilders; }
public STM32MP1FamilyBuilder(BSPBuilder bspBuilder, FamilyDefinition definition) : base(bspBuilder, definition) { }
public NordicFamilyBuilder(BSPBuilder bspBuilder, FamilyDefinition definition) : base(bspBuilder, definition) { }
/* * As of February 2019, some of the STM32 software packages provide legacy versions of the regular HAL source files (e.g. stm32f1xx_hal_can.c) that are mutually exclusive * with the regular versions of the same files. Instead of hardcoding the specific files for specific families, we detect it programmatically and generate the necessary * rules on-the-fly in this function. */ public void InsertLegacyHALRulesIfNecessary(FamilyDefinition fam, ReverseFileConditionBuilder reverseFileConditions) { var halFramework = fam.AdditionalFrameworks.FirstOrDefault(f => f.ClassID == "com.sysprogs.arm.stm32.hal") ?? throw new Exception(fam.Name + " defines no HAL framework"); var primaryJob = halFramework.CopyJobs.First(); string srcDir = primaryJob.SourceFolder + @"\Src"; ExpandVariables(ref srcDir); if (!Directory.Exists(srcDir)) { throw new Exception($"The first job for the HAL framework for {fam.Name} does not correspond to the normal source collection"); } var legacyDir = srcDir + @"\Legacy"; if (Directory.Exists(legacyDir)) { var fileNames = Directory.GetFiles(legacyDir).Select(Path.GetFileName).ToArray(); string settingName = "com.sysprogs.stm32.legacy_hal_src"; List <string> moduleNames = new List <string>(); foreach (var file in fileNames) { if (!File.Exists(Path.Combine(legacyDir, file))) { throw new Exception($"{Path.Combine(legacyDir, file)} does not have a corresponding non-legacy file"); } moduleNames.Add(Path.GetFileNameWithoutExtension(file.Substring(file.LastIndexOf('_') + 1)).ToUpper()); primaryJob.SimpleFileConditions = (primaryJob.SimpleFileConditions ?? new string[0]).Concat(new[] { $@"Src\\Legacy\\{file}: $${settingName}$$ == 1", $@"Src\\{file}: $${settingName}$$ != 1", }).ToArray(); } if (halFramework.ConfigurableProperties == null) { halFramework.ConfigurableProperties = new PropertyList { PropertyGroups = new List <PropertyGroup> { new PropertyGroup() } } } ; halFramework.ConfigurableProperties.PropertyGroups[0].Properties.Add(new PropertyEntry.Enumerated { UniqueID = settingName, Name = "HAL Driver Sources for " + string.Join(" ,", moduleNames), SuggestionList = new PropertyEntry.Enumerated.Suggestion[] { new PropertyEntry.Enumerated.Suggestion { InternalValue = "", UserFriendlyName = "Default" }, new PropertyEntry.Enumerated.Suggestion { InternalValue = "1", UserFriendlyName = "Legacy" } } }); } Regex rgLegacyDefineCheck = new Regex(@"#if( defined|def)[ \(]+(USE_LEGACY|USE_HAL_LEGACY)"); string legacyDefineName = null; foreach (var line in File.ReadAllLines(Directory.GetFiles(srcDir + @"\..\Inc", "stm32*hal_def.h")[0])) { var m = rgLegacyDefineCheck.Match(line); if (m.Success) { legacyDefineName = m.Groups[2].Value; } } if (legacyDefineName != null) { if (halFramework.ConfigurableProperties == null) { halFramework.ConfigurableProperties = new PropertyList { PropertyGroups = new List <PropertyGroup> { new PropertyGroup() } } } ; halFramework.ConfigurableProperties.PropertyGroups[0].Properties.Add(new PropertyEntry.Boolean { UniqueID = "com.sysprogs.bspoptions.stm32.hal_legacy", Name = "Support legacy HAL API", ValueForTrue = legacyDefineName, DefaultValue = true, }); halFramework.CopyJobs[0].PreprocessorMacros += ";$$com.sysprogs.bspoptions.stm32.hal_legacy$$"; reverseFileConditions?.GetHandleForFramework(halFramework)?.AttachMinimalConfigurationValue("com.sysprogs.bspoptions.stm32.hal_legacy", ""); } } }
private void GenerateConditionsForSubdirs(FamilyDefinition family, Framework fw, CopyJob job) { HashSet <string> explicitlyMentionedDirectories = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); HashSet <string> excludedSubdirectories = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); foreach (var cond in job.SmartFileConditions ?? new string[0]) { var def = SmartPropertyDefinition.Parse(cond, null); foreach (var item in def.Items) { int idx = item.Key.IndexOf('\\'); if (idx != -1) { explicitlyMentionedDirectories.Add(item.Key.Substring(0, idx)); } } } Regex rgExcludedSubdir = new Regex(@"-([^\\]+)\\\*$"); foreach (var cond in (job.FilesToCopy + ";" + job.ProjectInclusionMask).Split(';')) { var m = rgExcludedSubdir.Match(cond); if (m.Success) { excludedSubdirectories.Add(m.Groups[1].Value); } } List <string> generatedSmartFileConditions = new List <string>(); foreach (var dir in Directory.GetDirectories(_Builder.ExpandVariables(job.SourceFolder))) { string name = Path.GetFileName(dir); if (explicitlyMentionedDirectories.Contains(name)) { continue; } if (excludedSubdirectories.Contains(name)) { continue; } generatedSmartFileConditions.Add($"-{name}|{name}\\\\.*"); if (!_FrameworkConditions.TryGetValue(fw.ID, out var conditions)) { _FrameworkConditions[fw.ID] = conditions = new GeneratedFrameworkConditions { TargetPath = $"$$SYS:BSP_ROOT$$/{family.FamilySubdirectory}/{job.TargetFolder}".Replace('\\', '/') } } ; conditions.ConditionalSubdirectories.Add(name); } job.SmartFileConditions = (job.SmartFileConditions ?? new string[0]).Concat(generatedSmartFileConditions).OrderBy(c => c.ToLower().TrimStart('-')).ToArray(); } void GenerateBLEFrameworks(FamilyDefinition family) { List <Framework> bleFrameworks = new List <Framework>(); string famBase = family.Name.Substring(0, 5).ToLower(); HashSet <string> discoveredSubdirs = new HashSet <string>(); string baseDir = Path.Combine(family.PrimaryHeaderDir, @"..\..\..\components\ble"); foreach (var subdir in Directory.GetDirectories(baseDir)) { discoveredSubdirs.Add(Path.GetFileName(subdir)); } foreach (var subdir in Directory.GetDirectories(Path.Combine(baseDir, "ble_services"))) { discoveredSubdirs.Add(Path.Combine("ble_services", Path.GetFileName(subdir))); } foreach (var name in new[] { "ble_services", "common", "peer_manager", "nrf_ble_gatt" }) { discoveredSubdirs.Remove(name); } foreach (var dir in discoveredSubdirs) { string desc = FetchDescriptionFromDirectory(Path.Combine(baseDir, dir)) ?? throw new Exception("Failed to load description of " + dir); if (desc.StartsWith("BLE")) { desc = desc.Substring(3).Trim(); } string virtualFolderName = "BLE " + desc; desc = "Bluetooth LE - " + desc; string id = Path.GetFileName(dir); if (id.StartsWith("experimental_")) { id = id.Substring(13); } if (!id.StartsWith("ble_") && !id.StartsWith("nrf_ble")) { id = "ble_" + id; } /*if (dir.StartsWith("ble_services\\", StringComparison.CurrentCultureIgnoreCase)) * { * int idx = id.IndexOf("ble_"); * if (idx == -1) * id = "ble_svc_" + id; * else * id = id.Insert(idx + 4, "svc_"); * }*/ bleFrameworks.Add(new Framework { Name = string.Format("{0} ({1})", desc, Path.GetFileName(dir)), ID = "com.sysprogs.arm.nordic." + famBase + "." + id, ClassID = "com.sysprogs.arm.nordic.nrfx." + id, ProjectFolderName = virtualFolderName, DefaultEnabled = false, CopyJobs = new CopyJob[] { new CopyJob { SourceFolder = Path.Combine(baseDir, dir), TargetFolder = @"components\ble\" + dir, FilesToCopy = "-*_nrf51.c;*.c;*.h", } } }); } family.AdditionalFrameworks = family.AdditionalFrameworks.Concat(bleFrameworks).OrderBy(fw => fw.Name).ToArray(); }
private void GenerateConditionsForPrebuiltLibraries(FamilyDefinition family, Framework fw, CopyJob job) { var srcDir = Path.GetFullPath(_Builder.ExpandVariables(job.SourceFolder)); var allLibraries = Directory.GetFiles(srcDir, "*.a", SearchOption.AllDirectories) .Select(l => l.Substring(srcDir.Length).TrimStart('\\')).ToArray(); var conditions = new[] { new PrebuiltLibraryCondition("hard-float", "com.sysprogs.bspoptions.arm.floatmode", "-mfloat-abi=hard", "soft-float"), new PrebuiltLibraryCondition("no-interrupts", "com.sysprogs.bspoptions.nrf5x.interrupts", "no"), new PrebuiltLibraryCondition("short-wchar", "com.sysprogs.bspoptions.nrf5x.wchar", "-fshort-wchar"), }; Dictionary <string, PrebuiltLibraryCondition> conditionsByFolder = new Dictionary <string, PrebuiltLibraryCondition>(); foreach (var cond in conditions) { conditionsByFolder[cond.Folder] = cond; if (cond.InverseFolder != null) { conditionsByFolder[cond.InverseFolder] = cond; } } foreach (var grp in allLibraries.GroupBy(l => l.Substring(0, l.IndexOf('\\')), StringComparer.InvariantCultureIgnoreCase)) { HashSet <PrebuiltLibraryCondition> allConditionsInGroup = new HashSet <PrebuiltLibraryCondition>(); List <ConstructedLibraryCondition> libs = new List <ConstructedLibraryCondition>(); foreach (var lib in grp) { List <string> components = lib.Split('\\').ToList(); int libComponent = components.IndexOf("lib"); if (libComponent < 0) { throw new Exception($"Cannot build a list of conditional folders. {lib} does not contain 'lib' in the path."); } components.RemoveRange(0, libComponent + 1); string cortexPrefix = "cortex-"; if (!components[0].StartsWith(cortexPrefix)) { throw new Exception($"Relative path to {lib} does not start with 'cortex-'"); } string cortexCore = components[0].Substring(cortexPrefix.Length); components.RemoveAt(0); components.RemoveAt(components.Count - 1); foreach (var cmp in components) { if (!conditionsByFolder.TryGetValue(cmp, out var cond)) { throw new Exception($"Don't know how to map '{cmp}' to a prebuilt library condition"); } allConditionsInGroup.Add(cond); } libs.Add(new ConstructedLibraryCondition { Library = $"$$SYS:BSP_ROOT$$/{family.FamilySubdirectory}/{job.TargetFolder}/" + lib.Replace('\\', '/'), PathComponents = components.ToArray(), Core = cortexCore }); } foreach (var lib in libs) { List <Condition> finalConditions = new List <Condition>(); finalConditions.Add(new Condition.Equals { Expression = "$$com.sysprogs.bspoptions.nrf5x.cortex$$", ExpectedValue = lib.Core }); foreach (var usedCond in allConditionsInGroup) { var eqCond = new Condition.Equals { Expression = $"$${usedCond.Variable}$$", ExpectedValue = usedCond.Value }; if (lib.PathComponents.Contains(usedCond.Folder)) { finalConditions.Add(eqCond); } else { finalConditions.Add(new Condition.Not { Argument = eqCond }); } } FileCondition cond = new FileCondition { FilePath = lib.Library, ConditionToInclude = new Condition.And { Arguments = finalConditions.ToArray() } }; _Builder.AddFileCondition(cond); } } }