Skip to content

Commit bd35343

Browse files
Migrate all the .csproj files to SDK format
- Created convertToSDK script in Build folder - Updated mkall.targets RestoreNuGet to use dotnet restore - Update mkall.targets to use dotnet restore instead of old NuGet restore - Update build scripts to use RestorePackages target
1 parent a5d09f4 commit bd35343

10 files changed

Lines changed: 749 additions & 161 deletions

File tree

Build/FieldWorks.proj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,4 @@
3636
<Import Project="Installer.targets" Condition="'$(OS)'=='Windows_NT'"/>
3737
<Import Project="LocalLibrary.targets"/>
3838
<Import Project="Localize.targets"/>
39-
<Import Project="NuGet.targets"/>
4039
</Project>

Build/NuGet.targets

Lines changed: 0 additions & 52 deletions
This file was deleted.

Build/Src/FwBuildTasks/CollectTargets.cs

Lines changed: 166 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,26 @@ public override bool Execute()
2424
{
2525
try
2626
{
27+
Log.LogMessage(MessageImportance.Normal, "Starting GenerateFwTargets task...");
2728
var gen = new CollectTargets(Log, ToolsVersion);
2829
gen.Generate();
30+
Log.LogMessage(MessageImportance.Normal, "GenerateFwTargets task completed successfully.");
2931
return true;
3032
}
31-
catch (CollectTargets.StopTaskException)
33+
catch (CollectTargets.StopTaskException ex)
3234
{
35+
Log.LogError("GenerateFwTargets task failed.");
36+
if (ex.InnerException != null)
37+
{
38+
Log.LogError("Inner exception: {0}", ex.InnerException.Message);
39+
Log.LogError("Stack trace: {0}", ex.InnerException.StackTrace);
40+
}
41+
return false;
42+
}
43+
catch (Exception ex)
44+
{
45+
Log.LogError("GenerateFwTargets task failed with unexpected exception: {0}", ex.Message);
46+
Log.LogError("Stack trace: {0}", ex.StackTrace);
3347
return false;
3448
}
3549
}
@@ -82,16 +96,22 @@ public CollectTargets(TaskLoggingHelper log, string toolsVersion)
8296
/// </summary>
8397
public void Generate()
8498
{
99+
Log.LogMessage(MessageImportance.Normal, "Collecting project information from Src directory...");
85100
var infoSrc = new DirectoryInfo(Path.Combine(m_fwroot, "Src"));
86101
CollectInfo(infoSrc);
102+
87103
// These projects from Lib had nant targets. They really should be under Src.
104+
Log.LogMessage(MessageImportance.Normal, "Collecting project information from Lib directories...");
88105
var infoEth = new DirectoryInfo(Path.Combine(m_fwroot, "Lib/src/Ethnologue"));
89106
CollectInfo(infoEth);
90107
var infoScr2 = new DirectoryInfo(Path.Combine(m_fwroot, "Lib/src/ScrChecks"));
91108
CollectInfo(infoScr2);
92109
var infoObj = new DirectoryInfo(Path.Combine(m_fwroot, "Lib/src/ObjectBrowser"));
93110
CollectInfo(infoObj);
111+
112+
Log.LogMessage(MessageImportance.Normal, "Found {0} projects. Writing target files...", m_mapProjFile.Count);
94113
WriteTargetFiles();
114+
Log.LogMessage(MessageImportance.Normal, "Target file generation completed.");
95115
}
96116

97117
/// <summary>
@@ -100,11 +120,20 @@ public void Generate()
100120
private void CollectInfo(DirectoryInfo dirInfo)
101121
{
102122
if (dirInfo == null || !dirInfo.Exists)
123+
{
124+
Log.LogMessage(MessageImportance.Low, "Directory does not exist: {0}", dirInfo?.FullName ?? "null");
103125
return;
126+
}
127+
128+
Log.LogMessage(MessageImportance.Low, "Scanning directory: {0}", dirInfo.FullName);
129+
104130
foreach (var fi in dirInfo.GetFiles())
105131
{
106132
if (fi.Name.EndsWith(".csproj") && fi.Exists)
133+
{
134+
Log.LogMessage(MessageImportance.Low, "Processing project file: {0}", fi.FullName);
107135
ProcessCsProjFile(fi.FullName);
136+
}
108137
}
109138
foreach (var diSub in dirInfo.GetDirectories())
110139
CollectInfo(diSub);
@@ -165,7 +194,7 @@ private void ProcessCsProjFile(string filename)
165194
// here: we use the same .csproj file on both Windows and Linux
166195
// and so it contains backslashes in the name which is a valid
167196
// character on Linux.
168-
var i0 = projectName.LastIndexOfAny(new[] {'\\', '/'});
197+
var i0 = projectName.LastIndexOfAny(new[] { '\\', '/' });
169198
if (i0 >= 0)
170199
projectName = projectName.Substring(i0 + 1);
171200
projectName = projectName.Replace(".csproj", "");
@@ -212,14 +241,62 @@ private string AssemblyName
212241
{
213242
get
214243
{
215-
var name = m_csprojFile.SelectSingleNode("/c:Project/c:PropertyGroup/c:AssemblyName",
216-
m_namespaceMgr);
217-
var type = m_csprojFile.SelectSingleNode("/c:Project/c:PropertyGroup/c:OutputType",
218-
m_namespaceMgr);
244+
// Try SDK-style project first (no namespace)
245+
var name = m_csprojFile.SelectSingleNode("/Project/PropertyGroup/AssemblyName");
246+
var type = m_csprojFile.SelectSingleNode("/Project/PropertyGroup/OutputType");
247+
248+
// If not found, try old-style project with namespace
249+
if (name == null)
250+
{
251+
name = m_csprojFile.SelectSingleNode("/c:Project/c:PropertyGroup/c:AssemblyName", m_namespaceMgr);
252+
type = m_csprojFile.SelectSingleNode("/c:Project/c:PropertyGroup/c:OutputType", m_namespaceMgr);
253+
}
254+
255+
// Default extension is .dll (for Library output type or when OutputType is not specified)
219256
string extension = ".dll";
220-
if (type.InnerText == "WinExe" || type.InnerText == "Exe")
257+
if (type != null && (type.InnerText == "WinExe" || type.InnerText == "Exe"))
221258
extension = ".exe";
222-
return name.InnerText + extension;
259+
260+
if (name != null)
261+
return name.InnerText + extension;
262+
263+
// If AssemblyName is not found, this shouldn't happen but return a safe default
264+
Log.LogWarning("AssemblyName not found in project file, using default");
265+
return "Unknown" + extension;
266+
}
267+
}
268+
269+
/// <summary>
270+
/// Gets the assembly name for a specific project by name.
271+
/// </summary>
272+
/// <param name="projectName">The name of the project</param>
273+
/// <returns>The assembly name with extension</returns>
274+
private string GetAssemblyNameForProject(string projectName)
275+
{
276+
if (!m_mapProjFile.ContainsKey(projectName))
277+
{
278+
Log.LogWarning($"Project {projectName} not found in project map");
279+
return projectName + ".dll";
280+
}
281+
282+
var projectPath = m_mapProjFile[projectName];
283+
var savedCsprojFile = m_csprojFile;
284+
285+
try
286+
{
287+
// Load the specific project file
288+
LoadProjectFile(projectPath);
289+
return AssemblyName;
290+
}
291+
catch (Exception ex)
292+
{
293+
Log.LogWarning($"Failed to load project file {projectPath}: {ex.Message}");
294+
return projectName + ".dll";
295+
}
296+
finally
297+
{
298+
// Restore the original project file
299+
m_csprojFile = savedCsprojFile;
223300
}
224301
}
225302

@@ -230,12 +307,33 @@ private XmlNodeList ConfigNodes
230307
{
231308
get
232309
{
310+
// Try SDK-style first (no namespace)
311+
var nodes = m_csprojFile.SelectNodes("//PropertyGroup[DefineConstants]");
312+
if (nodes.Count > 0)
313+
return nodes;
314+
315+
// Fall back to legacy format with namespace
233316
return m_csprojFile.SelectNodes("/c:Project/c:PropertyGroup[c:DefineConstants]",
234317
m_namespaceMgr);
235318
}
236319
}
237320

238-
private string GetProjectSubDir(string project)
321+
/// <summary>
322+
/// Get DefineConstants value from a PropertyGroup node
323+
/// </summary>
324+
private string GetDefineConstants(XmlNode node)
325+
{
326+
// Try SDK-style first (no namespace)
327+
var defineConstantsElement = node.SelectSingleNode("DefineConstants");
328+
if (defineConstantsElement != null)
329+
return defineConstantsElement.InnerText;
330+
331+
// Fall back to legacy format with namespace
332+
var legacyElement = node.SelectSingleNode("c:DefineConstants", m_namespaceMgr);
333+
return legacyElement?.InnerText ?? "";
334+
}
335+
336+
public string GetProjectSubDir(string project)
239337
{
240338
var projectSubDir = Path.GetDirectoryName(m_mapProjFile[project]);
241339
projectSubDir = projectSubDir.Substring(m_fwroot.Length);
@@ -275,6 +373,7 @@ private static bool IsMono
275373
private void WriteTargetFiles()
276374
{
277375
var targetsFile = Path.Combine(m_fwroot, "Build/FieldWorks.targets");
376+
string currentProject = null;
278377
try
279378
{
280379
// Write all the C# targets and their dependencies.
@@ -289,6 +388,7 @@ private void WriteTargetFiles()
289388
writer.WriteLine();
290389
foreach (var project in m_mapProjFile.Keys)
291390
{
391+
currentProject = project;
292392
LoadProjectFile(m_mapProjFile[project]);
293393

294394
var isTestProject = project.EndsWith("Tests") || project == "TestManager";
@@ -300,22 +400,26 @@ private void WriteTargetFiles()
300400
var configs = new Dictionary<string, string>();
301401
foreach (XmlNode node in ConfigNodes)
302402
{
303-
var condition = node.Attributes["Condition"].InnerText;
403+
var condition = node.Attributes["Condition"]?.InnerText;
404+
if (condition == null)
405+
{
406+
continue;
407+
}
304408
var tmp = condition.Substring(condition.IndexOf("==") + 2).Trim().Trim('\'');
305409
var configuration = tmp.Substring(0, tmp.IndexOf("|"));
306410

307411
// Add configuration only once even if same configuration is contained
308412
// for multiple platforms, e.g. for AnyCpu and x64.
309413
if (configs.ContainsKey(configuration))
310414
{
311-
if (configs[configuration] != node.SelectSingleNode("c:DefineConstants", m_namespaceMgr).InnerText.Replace(";", " "))
415+
if (configs[configuration] != GetDefineConstants(node).Replace(";", " "))
312416
{
313417
Log.LogError("Configuration {0} for project {1} is defined several times " +
314418
"but contains differing values for DefineConstants.", configuration, project);
315419
}
316420
continue;
317421
}
318-
configs.Add(configuration, node.SelectSingleNode("c:DefineConstants", m_namespaceMgr).InnerText.Replace(";", " "));
422+
configs.Add(configuration, GetDefineConstants(node).Replace(";", " "));
319423

320424
writer.WriteLine("\t\t<When Condition=\" '$(config-capital)' == '{0}' \">", configuration);
321425
writer.WriteLine("\t\t\t<PropertyGroup>");
@@ -328,7 +432,7 @@ private void WriteTargetFiles()
328432
otherwiseBldr.AppendLine("\t\t<Otherwise>");
329433
otherwiseBldr.AppendLine("\t\t\t<PropertyGroup>");
330434
otherwiseBldr.AppendLine(string.Format("\t\t\t\t<{0}Defines>{1} CODE_ANALYSIS</{0}Defines>", project,
331-
node.SelectSingleNode("c:DefineConstants", m_namespaceMgr).InnerText.Replace(";", " ")));
435+
GetDefineConstants(node).Replace(";", " ")));
332436
otherwiseBldr.AppendLine("\t\t\t</PropertyGroup>");
333437
otherwiseBldr.AppendLine("\t\t</Otherwise>");
334438
otherwiseAdded = true;
@@ -372,7 +476,7 @@ private void WriteTargetFiles()
372476
writer.WriteLine("\t\t\tProperties=\"$(msbuild-props);IntermediateOutputPath=$(dir-fwobj){0}{1}{0};DefineConstants=$({2}Defines);$(warningsAsErrors);WarningLevel=4;LcmArtifactsDir=$(LcmArtifactsDir)\"/>",
373477
Path.DirectorySeparatorChar, GetProjectSubDir(project), project);
374478
// <Clouseau> verification task
375-
writer.WriteLine($"\t\t<Clouseau Condition=\"'$(Configuration)' == 'Debug'\" AssemblyPathname=\"$(dir-outputBase)/{AssemblyName}\"/>");
479+
writer.WriteLine($"\t\t<Clouseau Condition=\"'$(Configuration)' == 'Debug'\" AssemblyPathname=\"$(dir-outputBase)/{GetAssemblyNameForProject(project)}\"/>");
376480

377481
if (isTestProject)
378482
{
@@ -396,7 +500,7 @@ private void WriteTargetFiles()
396500
writer.WriteLine($"\t\t<Message Text=\"Finished building {project}.\" Condition=\"'$(action)'!='test'\"/>");
397501
writer.WriteLine($"\t\t<Message Text=\"Finished building {project} and running tests.\" Condition=\"'$(action)'=='test'\"/>");
398502
// Generate dotCover task
399-
GenerateDotCoverTask(writer, new[] {project}, $"{project}.coverage.xml");
503+
GenerateDotCoverTask(writer, new[] { project }, $"{project}.coverage.xml");
400504
}
401505
else
402506
{
@@ -448,12 +552,56 @@ private void WriteTargetFiles()
448552
writer.Close();
449553
}
450554
Console.WriteLine("Created {0}", targetsFile);
555+
556+
// Always output the generated file content for debugging
557+
if (File.Exists(targetsFile))
558+
{
559+
Log.LogMessage(MessageImportance.High, "Generated targets file content:");
560+
try
561+
{
562+
var content = File.ReadAllText(targetsFile);
563+
Log.LogMessage(MessageImportance.High, content);
564+
}
565+
catch (Exception readEx)
566+
{
567+
Log.LogError("Failed to read targets file for debugging: {0}", readEx.Message);
568+
}
569+
}
451570
}
452571
catch (Exception e)
453572
{
573+
Log.LogError("Error occurred while writing target file {0}: {1}", currentProject, e.Message);
574+
Log.LogError("Stack trace: {0}", e.StackTrace);
575+
576+
// Output the generated file content for debugging
577+
if (File.Exists(targetsFile))
578+
{
579+
Log.LogError("Generated targets file content:");
580+
try
581+
{
582+
var content = File.ReadAllText(targetsFile);
583+
Log.LogError(content);
584+
}
585+
catch (Exception readEx)
586+
{
587+
Log.LogError("Failed to read targets file for debugging: {0}", readEx.Message);
588+
}
589+
}
590+
454591
var badFile = targetsFile + ".bad";
455-
File.Move(targetsFile, badFile);
456-
Console.WriteLine("Failed to Create FieldWorks.targets bad result stored in {0}", badFile);
592+
try
593+
{
594+
if (File.Exists(badFile))
595+
File.Delete(badFile);
596+
File.Move(targetsFile, badFile);
597+
Log.LogMessage(MessageImportance.High, "Failed to create FieldWorks.targets, bad result stored in {0}", badFile);
598+
Console.WriteLine("Failed to Create FieldWorks.targets bad result stored in {0}", badFile);
599+
}
600+
catch (Exception moveEx)
601+
{
602+
Log.LogError("Failed to move bad targets file: {0}", moveEx.Message);
603+
}
604+
457605
throw new StopTaskException(e);
458606
}
459607
}
@@ -494,7 +642,7 @@ int TimeoutForProject(string project)
494642
}
495643
}
496644
}
497-
return (m_timeoutMap.ContainsKey(project) ? m_timeoutMap[project] : m_timeoutMap["default"])*1000;
645+
return (m_timeoutMap.ContainsKey(project) ? m_timeoutMap[project] : m_timeoutMap["default"]) * 1000;
498646
}
499647
}
500648
}

0 commit comments

Comments
 (0)