private void ImportProjectFolderRecursively(XmlElement projectOrFolder, ImportedExternalProject.ConstructedVirtualDirectory constructedDir, ProjectImportParameters parameters, IVariableExpander expander, IProjectImportService service) { foreach (var el in projectOrFolder.ChildNodes.OfType <XmlElement>()) { if (el.Name == "file") { string relPath = ExpandVariables(el.GetAttribute("file_name"), expander, service); if (!string.IsNullOrEmpty(relPath) && !relPath.EndsWith(".vec")) { string fullPath = Path.Combine(Path.GetDirectoryName(parameters.ProjectFile), relPath); constructedDir.AddFile(fullPath, relPath.EndsWith(".h", StringComparison.InvariantCultureIgnoreCase)); } } else if (el.Name == "folder") { string name = el.GetAttribute("Name"); if (string.IsNullOrEmpty(name)) { name = "Subfolder"; } if (name == "Source Files" || name == "Header Files") { //Visual Studio already provides filters for source/header files, so we don't need to specify them explicitly ImportProjectFolderRecursively(el, constructedDir, parameters, expander, service); } else { ImportProjectFolderRecursively(el, constructedDir.ProvideSudirectory(name), parameters, expander, service); } } } }
public ImportedExternalProject ImportProject(ProjectImportParameters parameters, IProjectImportService service) { XmlDocument xml = new XmlDocument(); xml.Load(parameters.ProjectFile); string deviceName = (xml.SelectSingleNode("package/generators/generator/select/@Dname") as XmlAttribute)?.Value; if (deviceName == null) { throw new Exception("Failed to extract the device name from " + deviceName); } HashSet <string> allHeaderDirs = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); string baseDir = Path.GetDirectoryName(parameters.ProjectFile); ImportedExternalProject.ConstructedVirtualDirectory rootDir = new ImportedExternalProject.ConstructedVirtualDirectory(); foreach (var file in xml.SelectNodes("package/generators/generator/project_files/file").OfType <XmlElement>()) { string category = file.GetAttribute("category"); string name = file.GetAttribute("name"); if (category == "header") { allHeaderDirs.Add(Path.GetDirectoryName(name)); } rootDir.AddFile(Path.Combine(baseDir, name), category == "header"); } bool hasFreeRTOS = false; foreach (var component in xml.SelectNodes("package/components/component").OfType <XmlElement>()) { string group = component.GetAttribute("Cgroup"); string subGroup = component.GetAttribute("Csub"); if (subGroup == "FREERTOS") { hasFreeRTOS = true; } foreach (var file in component.SelectNodes("files/file").OfType <XmlElement>()) { string category = file.GetAttribute("category"); string relativePath = file.GetAttribute("name"); string condition = file.GetAttribute("condition"); if (!string.IsNullOrEmpty(condition)) { if (condition == "FreeRTOS") { if (!hasFreeRTOS) { continue; } } else if (condition != "GCC Toolchain") { continue; //This is a IAR-only or Keil-only file } } int idx = relativePath.LastIndexOfAny(new[] { '\\', '/' }); string name, dir; if (idx == -1) { name = relativePath; dir = ""; } else { name = relativePath.Substring(idx + 1); dir = relativePath.Substring(0, idx); } if (category == "sourceAsm" && name.StartsWith("startup_", StringComparison.InvariantCultureIgnoreCase)) { continue; //VisualGDB provides its own startup files for STM32 devices that are compatible with STM32CubeMX-generated files } if (category == "header" && dir != "") { allHeaderDirs.Add(dir); } string path = group; if (!string.IsNullOrEmpty(subGroup)) { path += "/" + subGroup; } if (relativePath.Contains("*")) { string physicalDir = Path.Combine(baseDir, dir); if (Directory.Exists(physicalDir)) { foreach (var fn in Directory.GetFiles(physicalDir, name)) { rootDir.ProvideSudirectory(path).AddFile(fn, category == "header"); } } } else { rootDir.ProvideSudirectory(path).AddFile(Path.Combine(baseDir, relativePath), category == "header"); } } } List <string> macros = new List <string> { "$$com.sysprogs.bspoptions.primary_memory$$_layout", "$$com.sysprogs.stm32.hal_device_family$$" }; string[] includeDirs = allHeaderDirs.Select(d => Path.Combine(baseDir, d)).ToArray(); PropertyDictionary2 mcuConfiguration = null; if (hasFreeRTOS) { macros.Add("USE_FREERTOS"); ApplyFreeRTOSFixes(rootDir, ref includeDirs, ref mcuConfiguration); } Dictionary <string, string> temporaryExistingFileCollection = null; FixInvalidPathsRecursively(rootDir, baseDir, ref temporaryExistingFileCollection); deviceName = deviceName.TrimEnd('x'); deviceName = deviceName.Substring(0, deviceName.Length - 1); return(new ImportedExternalProject { DeviceNameMask = new Regex(deviceName.Replace("x", ".*") + ".*"), OriginalProjectFile = parameters.ProjectFile, RootDirectory = rootDir, GNUTargetID = "arm-eabi", ReferencedFrameworks = new string[0], //Unless this is explicitly specified, VisualGDB will try to reference the default frameworks (STM32 HAL) that will conflict with the STM32CubeMX-generated files. MCUConfiguration = mcuConfiguration, Configurations = new[] { new ImportedExternalProject.ImportedConfiguration { Settings = new ImportedExternalProject.InvariantProjectBuildSettings { IncludeDirectories = includeDirs, PreprocessorMacros = macros.ToArray() } } } }); }
public ImportedExternalProject ImportProject(ProjectImportParameters parameters, IProjectImportService service) { var parser = new ParserImpl(); List <VendorSample> result = new List <VendorSample>(); parser.ParseSingleProject(null, parameters.ProjectFile, null, null, null, SW4STM32ProjectParserBase.ProjectSubtype.Auto, result); if (result.Count == 0) { throw new Exception("Failed to parse the project file"); } ImportedExternalProject.ConstructedVirtualDirectory rootDir = new ImportedExternalProject.ConstructedVirtualDirectory(); Dictionary <string, string> physicalDirToVirtualPaths = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); var sample = result[0]; if (parser.OptionDictionary.TryGetValue(sample, out var opts) && opts.SourceFiles != null) { foreach (var sf in opts.SourceFiles) { string virtualDir = Path.GetDirectoryName(sf.VirtualPath); physicalDirToVirtualPaths[Path.GetDirectoryName(sf.FullPath)] = virtualDir; rootDir.ProvideSudirectory(virtualDir).AddFile(sf.FullPath, false); } } else { foreach (var src in sample.SourceFiles ?? new string[0]) { rootDir.AddFile(src, false); } } foreach (var src in sample.HeaderFiles ?? new string[0]) { if (physicalDirToVirtualPaths.TryGetValue(Path.GetDirectoryName(src), out string virtualDir)) { rootDir.ProvideSudirectory(virtualDir).AddFile(src, true); } else if (physicalDirToVirtualPaths.TryGetValue(Path.GetDirectoryName(src).Replace(@"\Inc", @"\Src"), out virtualDir)) { rootDir.ProvideSudirectory(virtualDir).AddFile(src, true); } else { rootDir.AddFile(src, true); } } return(new ImportedExternalProject { DeviceNameMask = new Regex(sample.DeviceID), OriginalProjectFile = parameters.ProjectFile, RootDirectory = rootDir, GNUTargetID = "arm-eabi", ReferencedFrameworks = new string[0], MCUConfiguration = sample.Configuration.MCUConfiguration, Configurations = new[] { new ImportedExternalProject.ImportedConfiguration { Settings = new ImportedExternalProject.InvariantProjectBuildSettings { IncludeDirectories = sample.IncludeDirectories, PreprocessorMacros = sample.PreprocessorMacros, LinkerScript = sample.LinkerScript, } } } }); }
public ImportedExternalProject ImportProject(ProjectImportParameters parameters, IProjectImportService service) { XmlDocument xml = new XmlDocument(); xml.Load(parameters.ProjectFile); var target = xml.SelectSingleNode("Project/Targets/Target") as XmlElement; if (target == null) { throw new Exception("Failed to locate the target node in " + parameters.ProjectFile); } string deviceName = (target.SelectSingleNode("TargetOption/TargetCommonOption/Device") as XmlElement)?.InnerText; if (deviceName == null) { throw new Exception("Failed to extract the device name from " + parameters.ProjectFile); } if (deviceName.EndsWith("x")) { deviceName = deviceName.TrimEnd('x'); deviceName = deviceName.Substring(0, deviceName.Length - 1); } string baseDir = Path.GetDirectoryName(parameters.ProjectFile); ImportedExternalProject.ConstructedVirtualDirectory rootDir = new ImportedExternalProject.ConstructedVirtualDirectory(); foreach (var group in target.SelectNodes("Groups/Group").OfType <XmlElement>()) { string virtualPath = group.SelectSingleNode("GroupName")?.InnerText; if (string.IsNullOrEmpty(virtualPath)) { continue; } var subdir = rootDir.ProvideSudirectory(virtualPath); foreach (var file in group.SelectNodes("Files/File").OfType <XmlElement>()) { string path = file.SelectSingleNode("FilePath")?.InnerText; string type = file.SelectSingleNode("FileType")?.InnerText; if (type == "2") { //This is an assembly file. Keil uses a different assembly syntax than GCC, so we cannot include this file into the project. //The end user will need to include a GCC-specific replacement manually (unless this is the startup file, in which case VisualGDB //automatically includes a GCC-compatible replacement). continue; } if (string.IsNullOrEmpty(path)) { continue; } var adjustedPath = TryAdjustPath(baseDir, path, service); subdir.AddFile(adjustedPath, type == "5"); } } List <string> macros = new List <string> { "$$com.sysprogs.bspoptions.primary_memory$$_layout" }; List <string> includeDirs = new List <string>(); var optionsNode = target.SelectSingleNode("TargetOption/TargetArmAds/Cads/VariousControls"); if (optionsNode != null) { macros.AddRange((optionsNode.SelectSingleNode("Define")?.InnerText ?? "").Split(',').Select(m => m.Trim())); includeDirs.AddRange((optionsNode.SelectSingleNode("IncludePath")?.InnerText ?? "") .Split(';') .Select(p => TryAdjustPath(baseDir, p.Trim(), service)) .Where(p => p != null)); } return(new ImportedExternalProject { DeviceNameMask = new Regex(deviceName.Replace("x", ".*") + ".*"), OriginalProjectFile = parameters.ProjectFile, RootDirectory = rootDir, GNUTargetID = "arm-eabi", ReferencedFrameworks = new string[0], //Unless this is explicitly specified, VisualGDB will try to reference the default frameworks (STM32 HAL) that will conflict with the STM32CubeMX-generated files. Configurations = new[] { new ImportedExternalProject.ImportedConfiguration { Settings = new ImportedExternalProject.InvariantProjectBuildSettings { IncludeDirectories = includeDirs.ToArray(), PreprocessorMacros = macros.ToArray() } } } }); }