diff --git a/Directory.Build.targets b/Directory.Build.targets
index cd68fb94f4fe99..26d5238e9cb56a 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -12,7 +12,6 @@
-
diff --git a/eng/python.targets b/eng/python.targets
deleted file mode 100644
index 3f933fdfea0eb1..00000000000000
--- a/eng/python.targets
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- <_PythonLocationScript>-c "import sys; sys.stdout.write(sys.executable)"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
index 3d2947219a4780..1549d763810098 100644
--- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -314,30 +314,7 @@
-
-
-
-
- src\System\Diagnostics\Eventing\NativeRuntimeEventSource.Generated.cs
-
-
+
+
-
-
-
-
-
- <_PythonWarningParameter>-Wall
- <_PythonWarningParameter Condition="'$(MSBuildTreatWarningsAsErrors)' == 'true'">$(_PythonWarningParameter) -Werror
- <_EventingSourceFileDirectory>%(EventingSourceFile.RootDir)%(EventingSourceFile.Directory)
- <_EventingSourceFileDirectory Condition="HasTrailingSlash('$(_EventingSourceFileDirectory)')">$(_EventingSourceFileDirectory.TrimEnd('\'))
-
-
-
-
-
-
-
-
-
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
index d7f5454259ee61..b3c050d2d2194c 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
@@ -565,34 +565,8 @@
-
-
-
-
-
- src\System\Diagnostics\Eventing\NativeRuntimeEventSource.Generated.cs
-
-
+
+
+
-
-
-
-
-
- <_PythonWarningParameter>-Wall
- <_PythonWarningParameter Condition="'$(MSBuildTreatWarningsAsErrors)' == 'true'">$(_PythonWarningParameter) -Werror
- <_EventingSourceFileDirectory>%(EventingSourceFile.RootDir)%(EventingSourceFile.Directory)
- <_EventingSourceFileDirectory Condition="HasTrailingSlash('$(_EventingSourceFileDirectory)')">$(_EventingSourceFileDirectory.TrimEnd('\'))
-
-
-
-
-
-
-
-
diff --git a/src/coreclr/scripts/genRuntimeEventSources.py b/src/coreclr/scripts/genRuntimeEventSources.py
deleted file mode 100644
index ed13eeec7238ea..00000000000000
--- a/src/coreclr/scripts/genRuntimeEventSources.py
+++ /dev/null
@@ -1,484 +0,0 @@
-#
-## Licensed to the .NET Foundation under one or more agreements.
-## The .NET Foundation licenses this file to you under the MIT license.
-#
-
-import os
-import xml.dom.minidom as DOM
-from utilities import open_for_update, parseInclusionList
-import argparse
-import sys
-
-generatedCodeFileHeader="""// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/**********************************************************************
-
-DO NOT MODIFY. AUTOGENERATED FILE.
-This file is generated by /src/coreclr/scripts/genRuntimeEventSources.py
-
-**********************************************************************/
-"""
-
-########################################################################
-# START CONFIGURATION
-########################################################################
-manifestsToGenerate = {
- "Microsoft-Windows-DotNETRuntime" : "NativeRuntimeEventSource.Generated.cs"
-}
-
-providerNameToClassNameMap = {
- "Microsoft-Windows-DotNETRuntime" : "NativeRuntimeEventSource"
-}
-
-manifestTypeToCSharpTypeMap = {
- "win:UInt8" : "byte",
- "win:UInt16" : "ushort",
- "win:UInt32" : "uint",
- "win:UInt64" : "ulong",
- "win:Int32" : "int",
- "win:Int64" : "long",
- "win:Pointer" : "IntPtr",
- "win:UnicodeString" : "string",
- "win:Binary" : "byte[]",
- "win:Double" : "double",
- "win:Boolean" : "bool",
- "win:GUID" : "Guid",
-}
-
-overrideEnumBackingTypes = {
- "Microsoft-Windows-DotNETRuntime" : {
- "GCSuspendEEReasonMap" : "win:UInt32",
- "GCRootKindMap" : "win:UInt32"
- }
-}
-########################################################################
-# END CONFIGURATION
-########################################################################
-
-tabText = ""
-
-def increaseTabLevel():
- global tabText
- tabText += " "
-
-def decreaseTabLevel():
- global tabText
- tabText = tabText[:-4]
-
-def writeOutput(outputFile, str):
- outputFile.write(tabText + str)
-
-def getCSharpTypeFromManifestType(manifestType):
- return manifestTypeToCSharpTypeMap[manifestType]
-
-def getManifestsToGenerate():
- return manifestsToGenerate
-
-def includeEvent(inclusionList, providerName, eventName):
- if len(inclusionList) == 0:
- return True
- if providerName in inclusionList and eventName in inclusionList[providerName]:
- return True
- elif providerName in inclusionList and "*" in inclusionList[providerName]:
- return True
- elif "*" in inclusionList and eventName in inclusionList["*"]:
- return True
- elif "*" in inclusionList and "*" in inclusionList["*"]:
- return True
- else:
- return False
-
-def generateEvent(eventNode, providerNode, outputFile, stringTable):
-
- # Some threading events are defined manually in NativeRuntimeEventSource.Threading.cs
- symbol = eventNode.getAttribute("symbol")
- if any(s in symbol for s in ["ThreadPool", "Contention", "WaitHandle"]):
- return
-
- evtLevel = eventNode.getAttribute("level")[4:]
- evtKeywords = ""
- # Write the event attribute.
- writeOutput(outputFile, "[Event("+ eventNode.getAttribute("value") + ", Version = " + eventNode.getAttribute("version") + ", Level = EventLevel." + evtLevel)
-
- # Not all events have keywords specified, and some have multiple keywords specified.
- keywords = eventNode.getAttribute("keywords")
- if keywords:
- if " " not in keywords:
- outputFile.write(", Keywords = Keywords." + keywords)
- evtKeywords = "Keywords." + keywords
- else:
- keywords = keywords.split()
- outputFile.write(", Keywords = ")
- for keywordIndex in range(len(keywords)):
- evtKeywords += "Keywords." + keywords[keywordIndex]
- if keywordIndex < (len(keywords) - 1):
- evtKeywords += " | "
- outputFile.write(evtKeywords)
- outputFile.write(")]\n")
-
- # Get the template for the event.
- templateNode = None
- templateKey = eventNode.getAttribute("template")
- if templateKey is not None:
- for node in providerNode.getElementsByTagName("templates"):
- templatesNode = node
- break
- for node in templatesNode.getElementsByTagName("template"):
- if node.getAttribute("tid") == templateKey:
- templateNode = node
- break
-
- # Write the beginning of the method signature.
- writeOutput(outputFile, "private void " + eventNode.getAttribute("symbol") + "(")
-
- # Write the function signature.
- argumentCount = 0
- if templateNode is not None:
- argumentNodes = templateNode.childNodes
-
- # Calculate the number of arguments.
- for argumentNode in argumentNodes:
- if argumentNode.nodeName == "data":
- if argumentNode.getAttribute("inType") != "win:Binary" and argumentNode.getAttribute("inType") != "win:AnsiString" and argumentNode.getAttribute("count") == "":
- argumentCount += 1
- else:
- break
- elif argumentNode.nodeName == "struct":
- break
-
- argumentsProcessed = 0
- for argumentIndex in range(len(argumentNodes)):
- argumentNode = argumentNodes[argumentIndex]
- if argumentNode.nodeName == "data":
- argumentName = argumentNode.getAttribute("name")
- argumentInType = argumentNode.getAttribute("inType")
-
- #### Disable enums until they are needed ####
- # argumentMap = argumentNode.getAttribute("map")
- # if not argumentMap:
- # argumentCSharpType = getCSharpTypeFromManifestType(argumentInType)
- # else:
- # argumentCSharpType = argumentMap[:-3]
- #### Disable enums until they are needed ####
-
- argumentCSharpType = getCSharpTypeFromManifestType(argumentInType)
- outputFile.write(argumentCSharpType + " " + argumentName)
- argumentsProcessed += 1
- if argumentsProcessed < argumentCount:
- outputFile.write(", ")
- if argumentsProcessed == argumentCount:
- break
-
- outputFile.write(")\n")
- writeOutput(outputFile, "{\n")
-
- increaseTabLevel()
- writeOutput(outputFile, "// To have this event be emitted from managed side, refer to NativeRuntimeEventSource.cs\n")
- writeOutput(outputFile, "throw new NotImplementedException();\n")
- decreaseTabLevel()
- writeOutput(outputFile, "}\n\n")
-
-
-def generateEvents(providerNode, outputFile, stringTable, inclusion_list):
-
- providerName = providerNode.getAttribute("name")
-
- # Get the events element.
- for node in providerNode.getElementsByTagName("events"):
- eventsNode = node
- break
-
- # Get the list of event nodes.
- eventNodes = eventsNode.getElementsByTagName("event")
-
- # Build a list of events to be emitted. This is where old versions of events are stripped.
- # key = eventID, value = version
- eventList = dict()
- for eventNode in eventNodes:
- eventName = eventNode.getAttribute('symbol')
- if not includeEvent(inclusion_list, providerName, eventName):
- continue
-
- eventID = eventNode.getAttribute("value")
- eventVersion = eventNode.getAttribute("version")
- eventList[eventID] = eventVersion
-
- # Iterate over each event node and process it.
- # Only emit events for the latest version of the event, otherwise EventSource initialization will fail.
- for eventNode in eventNodes:
- eventName = eventNode.getAttribute('symbol')
- if not includeEvent(inclusion_list, providerName, eventName):
- continue
-
- eventID = eventNode.getAttribute("value")
- eventVersion = eventNode.getAttribute("version")
- if eventID in eventList and eventList[eventID] == eventVersion:
- generateEvent(eventNode, providerNode, outputFile, stringTable)
- elif eventID not in eventList:
- raise ValueError("eventID could not be found in the list of events to emit.", eventID)
-
-def generateValueMapEnums(providerNode, outputFile, stringTable, enumTypeMap):
-
- # Get the maps element.
- for node in providerNode.getElementsByTagName("maps"):
- mapsNode = node
- break
-
- # Iterate over each map and create an enum out of it.
- for valueMapNode in mapsNode.getElementsByTagName("valueMap"):
-
- # Get the backing type of the enum.
- typeName = enumTypeMap[valueMapNode.getAttribute("name")]
- if typeName is None:
- raise ValueError("No mapping from mapName to enum backing type.", valueMapNode.getAttribute("name"))
-
- enumType = getCSharpTypeFromManifestType(typeName)
- writeOutput(outputFile, "public enum " + valueMapNode.getAttribute("name")[:-3] + " : " + enumType + "\n")
- writeOutput(outputFile, "{\n")
- increaseTabLevel()
- for mapNode in valueMapNode.getElementsByTagName("map"):
- # Each map value has a message, which we should use as the enum value.
- messageKey = mapNode.getAttribute("message")[9:-1]
- writeOutput(outputFile, stringTable[messageKey] + " = " + mapNode.getAttribute("value") + ",\n")
- decreaseTabLevel()
- writeOutput(outputFile, "}\n\n")
-
-def generateBitMapEnums(providerNode, outputFile, stringTable, enumTypeMap):
-
- # Get the maps element.
- for node in providerNode.getElementsByTagName("maps"):
- mapsNode = node
- break
-
- # Iterate over each map and create an enum out of it.
- for valueMapNode in mapsNode.getElementsByTagName("bitMap"):
-
- # Get the backing type of the enum.
- typeName = enumTypeMap[valueMapNode.getAttribute("name")]
- if typeName is None:
- raise ValueError("No mapping from mapName to enum backing type.", valueMapNode.getAttribute("name"))
-
- enumType = getCSharpTypeFromManifestType(typeName)
- writeOutput(outputFile, "[Flags]\n")
- writeOutput(outputFile, "public enum " + valueMapNode.getAttribute("name")[:-3] + " : " + enumType + "\n")
- writeOutput(outputFile, "{\n")
- increaseTabLevel()
- for mapNode in valueMapNode.getElementsByTagName("map"):
- # Each map value has a message, which we should use as the enum value.
- messageKey = mapNode.getAttribute("message")[9:-1]
- writeOutput(outputFile, stringTable[messageKey] + " = " + mapNode.getAttribute("value") + ",\n")
- decreaseTabLevel()
- writeOutput(outputFile, "}\n\n")
-
-def generateEnumTypeMap(providerNode):
-
- providerName = providerNode.getAttribute("name")
- templatesNodes = providerNode.getElementsByTagName("templates")
- templatesNode = templatesNodes[0]
- mapsNodes = providerNode.getElementsByTagName("maps")
-
- # Keep a list of mapName -> inType.
- # This map contains the first inType seen for the specified mapName.
- typeMap = dict()
-
- # There are a couple of maps that are used by multiple events but have different backing types.
- # Because only one of the uses will be consumed by EventSource/EventListener we can hack the backing type here
- # and suppress the warning that we'd otherwise get.
- overrideTypeMap = dict()
- if providerName in overrideEnumBackingTypes:
- overrideTypeMap = overrideEnumBackingTypes[providerName]
-
- for mapsNode in mapsNodes:
- for valueMapNode in mapsNode.getElementsByTagName("valueMap"):
- mapName = valueMapNode.getAttribute("name")
- dataNodes = templatesNode.getElementsByTagName("data")
-
- # If we've never seen the map used, save its usage with the inType.
- # If we have seen the map used, make sure that the inType saved previously matches the current inType.
- for dataNode in dataNodes:
- if dataNode.getAttribute("map") == mapName:
- if mapName in overrideTypeMap:
- typeMap[mapName] = overrideTypeMap[mapName]
- elif mapName in typeMap and typeMap[mapName] != dataNode.getAttribute("inType"):
- print("WARNING: Map " + mapName + " is used multiple times with different types. This may cause functional bugs in tracing.")
- elif not mapName in typeMap:
- typeMap[mapName] = dataNode.getAttribute("inType")
- for bitMapNode in mapsNode.getElementsByTagName("bitMap"):
- mapName = bitMapNode.getAttribute("name")
- dataNodes = templatesNode.getElementsByTagName("data")
-
- # If we've never seen the map used, save its usage with the inType.
- # If we have seen the map used, make sure that the inType saved previously matches the current inType.
- for dataNode in dataNodes:
- if dataNode.getAttribute("map") == mapName:
- if mapName in overrideTypeMap:
- typeMap[mapName] = overrideTypeMap[mapName]
- elif mapName in typeMap and typeMap[mapName] != dataNode.getAttribute("inType"):
- print("Map " + mapName + " is used multiple times with different types.")
- elif not mapName in typeMap:
- typeMap[mapName] = dataNode.getAttribute("inType")
-
- return typeMap
-
-def generateKeywordsClass(providerNode, outputFile, inclusion_list):
-
- providerName = providerNode.getAttribute("name")
-
- # Get the events element.
- for node in providerNode.getElementsByTagName("events"):
- eventsNode = node
- break
-
- # Get the list of event nodes.
- eventNodes = eventsNode.getElementsByTagName("event")
-
- # Build the list of used keywords
- keywordSet = set()
- for eventNode in eventNodes:
- eventName = eventNode.getAttribute('symbol')
- if not includeEvent(inclusion_list, providerName, eventName):
- continue
-
- # Not all events have keywords specified, and some have multiple keywords specified.
- keywords = eventNode.getAttribute("keywords")
- if keywords:
- keywordSet = keywordSet.union(keywords.split())
-
- # Find the keywords element.
- for node in providerNode.getElementsByTagName("keywords"):
- keywordsNode = node
- break;
-
- writeOutput(outputFile, "public static class Keywords\n")
- writeOutput(outputFile, "{\n")
- increaseTabLevel()
-
- for keywordNode in keywordsNode.getElementsByTagName("keyword"):
- keywordName = keywordNode.getAttribute("name")
- if keywordName not in keywordSet:
- continue;
-
- writeOutput(outputFile, "public const EventKeywords " + keywordName + " = (EventKeywords)" + keywordNode.getAttribute("mask") + ";\n")
-
- decreaseTabLevel()
- writeOutput(outputFile, "}\n\n")
-
-def loadStringTable(manifest):
-
- # Create the string table dictionary.
- stringTable = dict()
-
- # Get the string table element.
- for node in manifest.getElementsByTagName("stringTable"):
- stringTableNode = node
- break
-
- # Iterate through each string and save it.
- for stringElem in stringTableNode.getElementsByTagName("string"):
- stringTable[stringElem.getAttribute("id")] = stringElem.getAttribute("value")
-
- return stringTable
-
-def generateEventSources(manifestFullPath, intermediatesDirFullPath, inclusion_list):
-
- # Open the manifest for reading.
- manifest = DOM.parse(manifestFullPath)
-
- # Load the string table.
- stringTable = loadStringTable(manifest)
-
- # Iterate over each provider that we want to generate an EventSource for.
- for providerName, outputFileName in getManifestsToGenerate().items():
- for node in manifest.getElementsByTagName("provider"):
- if node.getAttribute("name") == providerName:
- providerNode = node
- break
-
- if providerNode is None:
- raise ValueError("Unable to find provider node.", providerName)
-
- # Generate a full path to the output file and open the file for open_for_update.
- outputFilePath = os.path.join(intermediatesDirFullPath, outputFileName)
- with open_for_update(outputFilePath) as outputFile:
-
- # Write the license header.
- writeOutput(outputFile, generatedCodeFileHeader)
-
- # Write the class header.
- header = """
-using System;
-
-namespace System.Diagnostics.Tracing
-{
-"""
- writeOutput(outputFile, header)
- increaseTabLevel()
-
- className = providerNameToClassNameMap[providerName]
- writeOutput(outputFile, "internal sealed partial class " + className + " : EventSource\n")
- writeOutput(outputFile, "{\n")
- increaseTabLevel()
-
- # Write the keywords class.
- generateKeywordsClass(providerNode, outputFile, inclusion_list)
-
- #### Disable enums until they are needed ####
- # Generate the enum type map.
- # This determines what the backing type for each enum should be.
- # enumTypeMap = generateEnumTypeMap(providerNode)
-
- # Generate enums for value maps.
- # generateValueMapEnums(providerNode, outputFile, stringTable, enumTypeMap)
-
- # Generate enums for bit maps.
- # generateBitMapEnums(providerNode, outputFile, stringTable, enumTypeMap)
- #### Disable enums until they are needed ####
-
- # Generate events.
- generateEvents(providerNode, outputFile, stringTable, inclusion_list)
-
- # Write the class footer.
- decreaseTabLevel()
- writeOutput(outputFile, "}\n")
- decreaseTabLevel()
- writeOutput(outputFile, "}\n")
-
-def main(argv):
-
- # Parse command line arguments.
- parser = argparse.ArgumentParser(
- description="Generates C# EventSource classes that represent the runtime's native event providers.")
-
- required = parser.add_argument_group('required arguments')
- required.add_argument('--man', type=str, required=True,
- help='full path to manifest containing the description of events')
- required.add_argument('--intermediate', type=str, required=True,
- help='full path to eventprovider intermediate directory')
- required.add_argument('--inc', type=str,default="",
- help='full path to inclusion list')
- args, unknown = parser.parse_known_args(argv)
- if unknown:
- print('Unknown argument(s): ', ', '.join(unknown))
- return 1
-
- manifestFullPath = args.man
- intermediatesDirFullPath = args.intermediate
- inclusion_filename = args.inc
-
- # Ensure the intermediates directory exists.
- try:
- os.makedirs(intermediatesDirFullPath)
- except OSError:
- if not os.path.isdir(intermediatesDirFullPath):
- raise
-
- inclusion_list = parseInclusionList(inclusion_filename)
-
- # Generate event sources.
- generateEventSources(manifestFullPath, intermediatesDirFullPath, inclusion_list)
- return 0
-
-if __name__ == '__main__':
- return_code = main(sys.argv[1:])
- sys.exit(return_code)
diff --git a/src/libraries/System.Private.CoreLib/gen/NativeRuntimeEventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/NativeRuntimeEventSourceGenerator.cs
new file mode 100644
index 00000000000000..5d8c66a600857e
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/gen/NativeRuntimeEventSourceGenerator.cs
@@ -0,0 +1,424 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Xml.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Text;
+
+namespace Generators
+{
+ [Generator]
+ public sealed class NativeRuntimeEventSourceGenerator : IIncrementalGenerator
+ {
+ private static readonly XNamespace EventNs = "http://schemas.microsoft.com/win/2004/08/events";
+
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ IncrementalValuesProvider manifestFiles = context.AdditionalTextsProvider.Where(f => f.Path.EndsWith(".man", StringComparison.OrdinalIgnoreCase));
+ IncrementalValuesProvider inclusionFiles = context.AdditionalTextsProvider.Where(f => f.Path.EndsWith(".lst", StringComparison.OrdinalIgnoreCase));
+
+ IncrementalValuesProvider<(AdditionalText Left, System.Collections.Immutable.ImmutableArray Right)> combined = manifestFiles.Combine(inclusionFiles.Collect());
+
+ context.RegisterSourceOutput(combined, (spc, tuple) =>
+ {
+ AdditionalText manifestFile = tuple.Left;
+ System.Collections.Immutable.ImmutableArray inclusionFiles = tuple.Right;
+ string manifestText = manifestFile.GetText(spc.CancellationToken)?.ToString();
+ if (string.IsNullOrEmpty(manifestText))
+ {
+ return;
+ }
+
+ var manifest = XDocument.Parse(manifestText);
+
+ string inclusionText = inclusionFiles.FirstOrDefault()?.GetText(spc.CancellationToken)?.ToString();
+
+ Dictionary> inclusionList = ParseInclusionListFromString(inclusionText);
+
+ foreach (KeyValuePair kvp in manifestsToGenerate)
+ {
+ string providerName = kvp.Key;
+ string className = providerNameToClassNameMap[providerName];
+ XElement? providerNode = manifest
+ .Descendants(EventNs + "provider")
+ .FirstOrDefault(e => (string)e.Attribute("name") == providerName);
+
+ if (providerNode is null)
+ {
+ continue;
+ }
+
+ string source = GenerateEventSourceClass(providerNode, className, inclusionList);
+ spc.AddSource($"{className}.g.cs", SourceText.From(source, System.Text.Encoding.UTF8));
+ }
+ });
+ }
+
+ private static Dictionary> ParseInclusionListFromString(string? inclusionText)
+ {
+ Dictionary> inclusionList = [];
+ if (string.IsNullOrEmpty(inclusionText))
+ {
+ return inclusionList;
+ }
+
+ using var reader = new StringReader(inclusionText);
+ string line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ string trimmed = line.Trim();
+ if (string.IsNullOrEmpty(trimmed) || trimmed.StartsWith("#"))
+ {
+ continue;
+ }
+
+ string[] tokens = trimmed.Split(':');
+ if (tokens.Length == 0)
+ {
+ continue;
+ }
+
+ if (tokens.Length > 2)
+ {
+ continue;
+ }
+
+ string providerName, eventName;
+ if (tokens.Length == 2)
+ {
+ providerName = tokens[0];
+ eventName = tokens[1];
+ }
+ else
+ {
+ providerName = "*";
+ eventName = tokens[0];
+ }
+ if (!inclusionList.TryGetValue(providerName, out HashSet? value))
+ {
+ value = [];
+ inclusionList[providerName] = value;
+ }
+
+ value.Add(eventName);
+ }
+ return inclusionList;
+ }
+
+ private static bool IncludeEvent(Dictionary> inclusionList, string providerName, string eventName)
+ {
+ if (inclusionList == null || inclusionList.Count == 0)
+ {
+ return true;
+ }
+
+ if (inclusionList.TryGetValue(providerName, out HashSet? events) && events.Contains(eventName))
+ {
+ return true;
+ }
+
+ if (inclusionList.TryGetValue("*", out HashSet? wildcardEvents) && wildcardEvents.Contains(eventName))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static string GenerateEventSourceClass(XElement providerNode, string className, Dictionary> inclusionList)
+ {
+ var sw = new StringWriter();
+
+ sw.WriteLine($$"""
+ // Licensed to the .NET Foundation under one or more agreements.
+ // The .NET Foundation licenses this file to you under the MIT license.
+ //
+
+ using System;
+
+ namespace System.Diagnostics.Tracing
+ {
+ internal sealed partial class {{className}} : EventSource
+ {
+ """);
+
+ GenerateKeywordsClass(providerNode, sw, inclusionList);
+ GenerateEventMethods(providerNode, sw, inclusionList);
+
+ sw.WriteLine("""
+ }
+ }
+ """);
+ return sw.ToString();
+ }
+
+ private static void GenerateKeywordsClass(XElement providerNode, StringWriter writer, Dictionary> inclusionList)
+ {
+ string? providerName = providerNode.Attribute("name")?.Value;
+
+ if (providerName is null)
+ {
+ return;
+ }
+
+ XElement eventsNode = providerNode.Element(EventNs + "events");
+ if (eventsNode is null)
+ {
+ return;
+ }
+
+ IEnumerable eventNodes = eventsNode.Elements(EventNs + "event");
+ var usedKeywords = new HashSet();
+ foreach (XElement? eventNode in eventNodes)
+ {
+ string? eventName = eventNode.Attribute("symbol")?.Value;
+
+ if (eventName is null
+ || !IncludeEvent(inclusionList, providerName, eventName))
+ {
+ continue;
+ }
+
+ string? keywords = eventNode.Attribute("keywords")?.Value;
+ if (!string.IsNullOrEmpty(keywords))
+ {
+ foreach (string? kw in keywords.Split([' '], StringSplitOptions.RemoveEmptyEntries))
+ {
+ usedKeywords.Add(kw);
+ }
+ }
+ }
+ XElement? keywordsNode = providerNode.Element(EventNs + "keywords");
+ if (keywordsNode is null)
+ {
+ return;
+ }
+
+ writer.WriteLine("""
+ public static class Keywords
+ {
+ """);
+
+ foreach (XElement keywordNode in keywordsNode.Elements(EventNs + "keyword"))
+ {
+ string? name = keywordNode.Attribute("name")?.Value;
+ string? mask = keywordNode.Attribute("mask")?.Value;
+ if (name is not null && mask is not null && usedKeywords.Contains(name))
+ {
+ writer.WriteLine($" public const EventKeywords {name} = (EventKeywords){mask};");
+ }
+ }
+
+ writer.WriteLine("""
+ }
+
+ """);
+ }
+
+ private static void GenerateEventMethods(XElement providerNode, StringWriter writer, Dictionary> inclusionList)
+ {
+ string? providerName = providerNode.Attribute("name")?.Value;
+
+ if (providerName is null)
+ {
+ return;
+ }
+
+ XElement eventsNode = providerNode.Element(EventNs + "events");
+ if (eventsNode == null)
+ {
+ return;
+ }
+
+ var eventNodes = eventsNode.Elements(EventNs + "event").ToList();
+ XElement templatesNode = providerNode.Element(EventNs + "templates");
+ var templateDict = new Dictionary();
+ if (templatesNode != null)
+ {
+ foreach (XElement? template in templatesNode.Elements(EventNs + "template"))
+ {
+ string? name = template.Attribute("tid")?.Value;
+ if (!string.IsNullOrEmpty(name))
+ {
+ templateDict[name] = template;
+ }
+ }
+ }
+
+ // Build a dictionary of eventID -> latest version
+ Dictionary latestEventVersions = [];
+ foreach (XElement? eventNode in eventNodes)
+ {
+ string? eventName = eventNode.Attribute("symbol")?.Value;
+ if (eventName is null
+ || !IncludeEvent(inclusionList, providerName, eventName))
+ {
+ continue;
+ }
+
+ string? eventId = eventNode.Attribute("value")?.Value;
+ string? version = eventNode.Attribute("version")?.Value;
+ if (eventId is not null && version is not null)
+ {
+ if (!latestEventVersions.TryGetValue(eventId, out string? existingVersion) || string.CompareOrdinal(version, existingVersion) > 0)
+ {
+ latestEventVersions[eventId] = version;
+ }
+ }
+ }
+
+ foreach (XElement? eventNode in eventNodes)
+ {
+ string? eventName = eventNode.Attribute("symbol")?.Value;
+ if (eventName is null
+ || !IncludeEvent(inclusionList, providerName, eventName))
+ {
+ continue;
+ }
+
+ if (IsEventManuallyHandled(eventName))
+ {
+ continue;
+ }
+
+ string? eventId = eventNode.Attribute("value")?.Value;
+ string? version = eventNode.Attribute("version")?.Value;
+ // Only emit the event if it is the latest version for this eventId
+ if (eventId is null || version is null || latestEventVersions[eventId] != version)
+ {
+ continue;
+ }
+
+ string? level = eventNode.Attribute("level")?.Value;
+ IEnumerable? keywords = eventNode
+ .Attribute("keywords")
+ ?.Value
+ .ToString()
+ .Split([' '], StringSplitOptions.RemoveEmptyEntries)
+ .Select(k => $"Keywords.{k}");
+
+ writer.Write($" [Event({eventId}, Version = {version}, Level = EventLevel.{level?.Replace("win:", "")}");
+
+ if (keywords?.Any() == true)
+ {
+ writer.Write($", Keywords = {string.Join(" | ", keywords)}");
+ }
+
+ writer.WriteLine(")]");
+
+ // Write the method signature
+ writer.Write($" private void {eventName}(");
+
+ string? templateValue = eventNode.Attribute("template")?.Value;
+
+ if (!string.IsNullOrEmpty(templateValue)
+ && templateDict.TryGetValue(templateValue, out XElement? template))
+ {
+ IEnumerable dataNodes = template.Elements(EventNs + "data").ToArray();
+ var paramList = new List();
+
+ // Calculate the number of arguments to emit.
+ // COMPAT: Cut the parameter list at any binary or ansi string arguments,
+ // or if the count attribute is set on any of the parameters.
+ int numArgumentsToEmit = 0;
+ foreach (XElement data in dataNodes)
+ {
+ string? paramType = data.Attribute("inType")?.Value.ToString();
+
+ if (paramType is "win:Binary" or "win:AnsiString")
+ {
+ break;
+ }
+
+ if (!string.IsNullOrEmpty(data.Attribute("count")?.Value))
+ {
+ break;
+ }
+
+ numArgumentsToEmit++;
+ }
+
+ foreach (XElement data in dataNodes)
+ {
+ if (numArgumentsToEmit-- <= 0)
+ {
+ break;
+ }
+
+ string? paramType = data.Attribute("inType")?.Value;
+ string? paramName = data.Attribute("name")?.Value;
+ if (paramType is not null && paramName is not null
+ && manifestTypeToCSharpTypeMap.TryGetValue(paramType, out string? csType))
+ {
+ paramList.Add($"{csType} {paramName}");
+ }
+ else if (paramType is not null && paramName is not null)
+ {
+ paramList.Add($"object {paramName}");
+ }
+ }
+ writer.Write(string.Join(", ", paramList));
+ }
+
+ writer.WriteLine("""
+ )
+ {
+ // To have this event be emitted from managed side, refer to NativeRuntimeEventSource.cs
+ throw new NotImplementedException();
+ }
+
+ """);
+ }
+ }
+
+ private static bool IsEventManuallyHandled(string eventName)
+ {
+ foreach (string handledEvent in manuallyHandledEventSymbols)
+ {
+ if (eventName.StartsWith(handledEvent, StringComparison.Ordinal))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static readonly Dictionary manifestsToGenerate = new()
+ {
+ { "Microsoft-Windows-DotNETRuntime", "NativeRuntimeEventSource.Generated.cs" }
+ };
+
+ private static readonly Dictionary providerNameToClassNameMap = new()
+ {
+ { "Microsoft-Windows-DotNETRuntime", "NativeRuntimeEventSource" }
+ };
+
+ private static readonly Dictionary manifestTypeToCSharpTypeMap = new()
+ {
+ { "win:UInt8", "byte" },
+ { "win:UInt16", "ushort" },
+ { "win:UInt32", "uint" },
+ { "win:UInt64", "ulong" },
+ { "win:Int32", "int" },
+ { "win:Int64", "long" },
+ { "win:Pointer", "IntPtr" },
+ { "win:UnicodeString", "string" },
+ { "win:Binary", "byte[]" },
+ { "win:Double", "double" },
+ { "win:Boolean", "bool" },
+ { "win:GUID", "Guid" },
+ };
+
+ private static readonly List manuallyHandledEventSymbols =
+ [
+ // Some threading events are defined manually in NativeRuntimeEventSource.Threading.cs
+ "ThreadPool",
+ "Contention",
+ "WaitHandle"
+ ];
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj
index 9abeb30c867e03..bb2ffa89ff7f3d 100644
--- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj
+++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj
@@ -2,6 +2,7 @@
netstandard2.0
$(NoWarn);CS3001
+ true
$(DefineConstants);STABILIZE_PACKAGE_VERSION
@@ -13,6 +14,7 @@
+
@@ -20,7 +22,7 @@
-
+
diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
index 5167fbe87959f9..3bcb19fc3ac2e7 100644
--- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -311,33 +311,7 @@
-
-
-
-
- src\System\Diagnostics\Eventing\NativeRuntimeEventSource.Generated.cs
-
-
+
+
-
-
-
-
-
- <_PythonWarningParameter>-Wall
- <_PythonWarningParameter Condition="'$(MSBuildTreatWarningsAsErrors)' == 'true'">$(_PythonWarningParameter) -Werror
- <_EventingSourceFileDirectory>%(EventingSourceFile.RootDir)%(EventingSourceFile.Directory)
- <_EventingSourceFileDirectory Condition="HasTrailingSlash('$(_EventingSourceFileDirectory)')">$(_EventingSourceFileDirectory.TrimEnd('\'))
-
-
-
-
-
-
-
-