SettingsFromBuiltProject RetrieveSettingsFromBuiltProject(ProjectImportParameters parameters, IProjectImportService service) { string[] linkerScripts, indFiles; for (; ;) { linkerScripts = Directory.GetFiles(Path.GetDirectoryName(parameters.ProjectFile), Path.GetFileNameWithoutExtension(parameters.ProjectFile) + ".ld", SearchOption.AllDirectories); if (linkerScripts.Length == 0) { linkerScripts = Directory.GetFiles(Path.GetDirectoryName(parameters.ProjectFile), "*.ld", SearchOption.AllDirectories); } if (linkerScripts.Length != 0 || service.Context != ProjectImporterInvocationContext.Wizard) { break; } switch (service.GUI.AbortRetryIgnore("Could not find the generated linker script under the project directory. Please try building the project with CrossWorks first.")) { case System.Windows.Forms.DialogResult.Abort: throw new OperationCanceledException(); case System.Windows.Forms.DialogResult.Retry: continue; default: break; } break; } for (; ;) { indFiles = Directory.GetFiles(Path.GetDirectoryName(parameters.ProjectFile), Path.GetFileNameWithoutExtension(parameters.ProjectFile) + ".ind", SearchOption.AllDirectories); if (indFiles.Length == 0) { indFiles = Directory.GetFiles(Path.GetDirectoryName(parameters.ProjectFile), "*.ind", SearchOption.AllDirectories); } if (indFiles.Length != 0 || service.Context != ProjectImporterInvocationContext.Wizard) { break; } switch (service.GUI.AbortRetryIgnore("Could not find the generated input list (.ind) under the project directory. Please try building the project with CrossWorks first.")) { case System.Windows.Forms.DialogResult.Abort: throw new OperationCanceledException(); case System.Windows.Forms.DialogResult.Retry: continue; default: break; } break; } SettingsFromBuiltProject result = new SettingsFromBuiltProject(); result.LinkerScript = linkerScripts.FirstOrDefault(); List <string> inputs = new List <string>(); foreach (var fn in indFiles) { try { foreach (var rawLine in File.ReadAllLines(fn)) { string line = rawLine.Trim(' ', '\t', '\"'); try { if (Path.IsPathRooted(line) && File.Exists(line)) { inputs.Add(line); } } catch { } } } catch (Exception ex) { service.Logger.LogException(ex, "failed to load " + fn); } } result.AdditionalInputs = inputs.ToArray(); return(result); }
public ImportedExternalProject ImportProject(ProjectImportParameters parameters, IProjectImportService service) { Dictionary <string, string> systemDirectories = new Dictionary <string, string>(); var key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Rowley Associates Limited\CrossWorks for ARM\Installer"); service.Logger.LogLine("Detecting CrossWorks directory..."); string crossWorksDir = null; if (key != null) { foreach (var kn in key.GetSubKeyNames().OrderByDescending(k => k)) { service.Logger.LogLine($"Checking {kn}..."); using (var subkey = key.OpenSubKey(kn + @"\OrganizationDefaults")) { var destDir = subkey?.GetValue("DestDir") as string; if (destDir != null && Directory.Exists(destDir)) { service.Logger.LogLine($"Found {destDir}"); systemDirectories["StudioDir"] = crossWorksDir = destDir; break; } } } } service.Logger.LogLine("Detecting CrossWorks AppData directory..."); var appDataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Rowley Associates Limited\CrossWorks for ARM"); foreach (var subdir in Directory.GetDirectories(appDataDir).OrderByDescending(d => d)) { string packagesDir = Path.Combine(subdir, "packages"); service.Logger.LogLine($"Trying {subdir}..."); if (Directory.Exists(packagesDir)) { service.Logger.LogLine($"Found {packagesDir}"); systemDirectories["TargetsDir"] = packagesDir + @"\targets"; systemDirectories["PackagesDir"] = packagesDir; break; } } systemDirectories["ProjectDir"] = Path.GetDirectoryName(parameters.ProjectFile); systemDirectories["LibExt"] = ""; XmlDocument xml = new XmlDocument(); xml.Load(parameters.ProjectFile); var project = xml.DocumentElement.SelectSingleNode("project") as XmlElement ?? throw new Exception("Could not find the project element"); var commonConfig = project.SelectSingleNode("configuration[@Name='Common']") as XmlElement ?? throw new Exception("Could not find the common configuration element"); string deviceName = commonConfig.GetAttribute("Target"); if (string.IsNullOrEmpty(deviceName)) { throw new Exception("Target name is unspecified"); } string[] internalMacros = commonConfig.GetAttribute("macros")?.Split(';'); string vectorFile = null; foreach (var im in internalMacros ?? new string[0]) { int idx = im.IndexOf('='); if (idx != -1) { string mk = im.Substring(0, idx).Trim(); string mv = im.Substring(idx + 1).Trim(); systemDirectories[mk] = mv; if (mk == "DeviceVectorsFile") { vectorFile = mv; } } } string[] macros = commonConfig.GetAttribute("c_preprocessor_definitions")?.Split(';'); string[] includeDirs = (commonConfig.GetAttribute("c_system_include_directories") + ";" + commonConfig.GetAttribute("c_user_include_directories"))?.Split(';'); if (crossWorksDir != null) { includeDirs = includeDirs.Concat(new[] { crossWorksDir + "/include" }).ToArray(); } string[] additionalLinkerInputs = commonConfig.GetAttribute("linker_additional_files")?.Split(';'); macros = macros.Concat(new[] { "__CROSSWORKS_ARM", "STARTUP_FROM_RESET" }).ToArray(); if (vectorFile != null) { macros = macros.Concat(new[] { $"__VECTORS=\"{vectorFile}\"" }).ToArray(); } string frequency = commonConfig.GetAttribute("oscillator_frequency"); if (frequency?.EndsWith("MHz") == true && int.TryParse(frequency.Substring(0, frequency.Length - 3), out int frequencyInMhz)) { macros = macros.Concat(new[] { "OSCILLATOR_CLOCK_FREQUENCY=" + (frequencyInMhz * 1000000) }).ToArray(); } ImportedExternalProject.ConstructedVirtualDirectory rootDir = new ImportedExternalProject.ConstructedVirtualDirectory(); var expander = service.CreateVariableExpander(systemDirectories, VariableExpansionSyntax.Makefile); SettingsFromBuiltProject extraSettings = RetrieveSettingsFromBuiltProject(parameters, service); if (extraSettings.AdditionalInputs != null) { foreach (var input in extraSettings.AdditionalInputs) { rootDir.AddFile(input, false); } } foreach (var lib in additionalLinkerInputs) { var mappedPath = ExpandVariables(lib, expander, service); if (!string.IsNullOrEmpty(mappedPath)) { rootDir.AddFile(mappedPath, false); } } ImportProjectFolderRecursively(project, rootDir, parameters, expander, service); 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 = new PropertyDictionary2 { Entries = new[] { new PropertyDictionary2.KeyValue { Key = "com.sysprogs.mcuoptions.ignore_startup_file", Value = "1" } } }, Configurations = new[] { new ImportedExternalProject.ImportedConfiguration { Settings = new ImportedExternalProject.InvariantProjectBuildSettings { IncludeDirectories = includeDirs?.Select(d => ExpandVariables(d, expander, service))?.Where(d => !string.IsNullOrEmpty(d))?.ToArray(), PreprocessorMacros = macros, ExtraLDFLAGS = new[] { "-nostdlib -Wl,-u_vectors -Wl,-ereset_handler " }, LinkerScript = extraSettings.LinkerScript, }, } } }); }