summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-03-17 22:39:04 +0800
committerruki <[email protected]>2026-03-17 22:39:04 +0800
commitf575c37eefe974965452e29ec19752f62236685a (patch)
tree5cd94a156787cda1ef3388fbd9adb3add2d26c29
parent701014b37d30227f2fa38ebe6ce344ab766513a2 (diff)
add csharp rule comments
-rw-r--r--xmake/rules/csharp/modules/csproj_generator.lua16
-rw-r--r--xmake/rules/csharp/modules/itemgroups.lua6
-rw-r--r--xmake/rules/csharp/modules/properties.lua10
-rw-r--r--xmake/rules/csharp/xmake.lua93
4 files changed, 124 insertions, 1 deletions
diff --git a/xmake/rules/csharp/modules/csproj_generator.lua b/xmake/rules/csharp/modules/csproj_generator.lua
index 6ee9cf152..8891c6c1e 100644
--- a/xmake/rules/csharp/modules/csproj_generator.lua
+++ b/xmake/rules/csharp/modules/csproj_generator.lua
@@ -22,6 +22,7 @@
import("properties", {alias = "csharp_properties"})
import("itemgroups", {alias = "csharp_itemgroups"})
+-- escape special xml characters
function _xml_escape(value)
value = tostring(value or "")
value = value:gsub("&", "&amp;")
@@ -32,6 +33,7 @@ function _xml_escape(value)
return value
end
+-- format key-value pairs as xml attributes string, e.g. ` Sdk="Microsoft.NET.Sdk"`
function _format_attributes(attrs)
if type(attrs) ~= "table" then
return ""
@@ -53,6 +55,7 @@ function _format_attributes(attrs)
return table.concat(chunks)
end
+-- get single csharp value from target:values(), with default fallback
function _get_csharp_value(target, name, defaultval)
local val = target:values(name)
if type(val) == "table" then
@@ -64,6 +67,7 @@ function _get_csharp_value(target, name, defaultval)
return val
end
+-- resolve a registry entry value, supports custom resolve function, list type and single value
function _resolve_registry_value(entry, target, context)
if entry.resolve then
return entry.resolve(context)
@@ -89,6 +93,7 @@ function _resolve_registry_value(entry, target, context)
return _get_csharp_value(target, entry.lua_key, entry.default)
end
+-- collect <Project> element attributes, e.g. Sdk="Microsoft.NET.Sdk"
function _collect_project_attributes(target, context, registry_entries)
local attrs = {}
for _, entry in ipairs(registry_entries) do
@@ -104,6 +109,7 @@ function _collect_project_attributes(target, context, registry_entries)
return attrs
end
+-- collect <PropertyGroup> entries from registered csharp.* properties
function _collect_property_entries(target, context, registry_entries)
local entries = {}
for _, entry in ipairs(registry_entries) do
@@ -119,6 +125,7 @@ function _collect_property_entries(target, context, registry_entries)
return entries
end
+-- normalize item entry to {xml, attrs, value} format
function _normalize_item_entry(item, default_xml)
if type(item) == "string" then
return {xml = default_xml, attrs = {Include = item}}
@@ -141,6 +148,7 @@ function _normalize_item_entry(item, default_xml)
return {xml = xml, attrs = attrs, value = item.value}
end
+-- collect <ItemGroup> entries (Compile, ProjectReference, PackageReference, ..)
function _collect_item_groups(context, registry_entries)
local groups = {}
local groupmap = {}
@@ -168,10 +176,12 @@ function _collect_item_groups(context, registry_entries)
return groups
end
+-- check if a property name is valid for xml element
function _is_valid_property_name(name)
return type(name) == "string" and name:match("^[A-Za-z_][A-Za-z0-9_.-]*$") ~= nil
end
+-- add a custom property entry, supports string and table(semicolon-joined) values
function _add_custom_property(entries, name, value)
if not _is_valid_property_name(name) then
return
@@ -199,6 +209,8 @@ function _add_custom_property(entries, name, value)
table.insert(entries, {xml = name, value = value})
end
+-- parse custom property from csharp.properties value item
+-- supports string format "Name=Value" and table format {name = .., value = ..}
function _add_custom_properties_from_item(entries, item)
if type(item) == "string" then
local name, value = item:match("^%s*([^=]+)%s*=(.*)$")
@@ -219,6 +231,7 @@ function _add_custom_properties_from_item(entries, item)
end
end
+-- collect custom properties from target:values("csharp.properties")
function _collect_custom_property_entries(target)
local entries = {}
for _, item in ipairs(table.wrap(target:values("csharp.properties"))) do
@@ -227,6 +240,7 @@ function _collect_custom_property_entries(target)
return entries
end
+-- render <PropertyGroup> section to file
function _render_property_group(file, entries)
if #entries == 0 then
return
@@ -238,6 +252,7 @@ function _render_property_group(file, entries)
file:print(" </PropertyGroup>")
end
+-- render <ItemGroup> sections to file
function _render_item_groups(file, item_groups)
for _, group in ipairs(item_groups) do
if #group.items > 0 then
@@ -255,6 +270,7 @@ function _render_item_groups(file, item_groups)
end
end
+-- generate .csproj file for the target, write to tmpfile first then copy if different
function main(target, csprojfile, opt)
opt = opt or {}
diff --git a/xmake/rules/csharp/modules/itemgroups.lua b/xmake/rules/csharp/modules/itemgroups.lua
index 785858024..6e939c6fd 100644
--- a/xmake/rules/csharp/modules/itemgroups.lua
+++ b/xmake/rules/csharp/modules/itemgroups.lua
@@ -18,6 +18,7 @@
-- @file itemsgroups.lua
--
+-- normalize path to relative and use forward slashes
function _normalize_relative(fromdir, targetpath)
local relpath = path.relative(targetpath, fromdir) or targetpath
if os.host() == "windows" then
@@ -26,6 +27,7 @@ function _normalize_relative(fromdir, targetpath)
return relpath
end
+-- collect .cs source files as relative paths to csprojdir
function _collect_cs_sourcefiles(context)
local csfiles = {}
for _, sourcefile in ipairs(context.target:sourcefiles()) do
@@ -38,6 +40,7 @@ function _collect_cs_sourcefiles(context)
return table.unique(csfiles)
end
+-- collect ProjectReference paths from dependency targets
function _collect_project_references(context)
local references = {}
for _, dep in ipairs(context.target:orderdeps()) do
@@ -50,6 +53,7 @@ function _collect_project_references(context)
return table.unique(references)
end
+-- extract nuget package name and version from package require string
function _get_nuget_info(pkg)
local requirestr = pkg:requirestr() or ""
local splitinfo = requirestr:trim():split("%s+")
@@ -84,6 +88,7 @@ function _get_nuget_info(pkg)
return pkgname, version
end
+-- collect PackageReference entries from nuget packages
function _collect_nuget_references(context)
local versions = {}
for _, pkg in ipairs(context.target:orderpkgs()) do
@@ -107,6 +112,7 @@ function _collect_nuget_references(context)
return references
end
+-- register all item group entries (Compile, ProjectReference, PackageReference)
function main()
local entries = {}
local function register(entry)
diff --git a/xmake/rules/csharp/modules/properties.lua b/xmake/rules/csharp/modules/properties.lua
index 6d392dbd8..eabebd006 100644
--- a/xmake/rules/csharp/modules/properties.lua
+++ b/xmake/rules/csharp/modules/properties.lua
@@ -18,10 +18,12 @@
-- @file properties.lua
--
+-- check if target has multi-target frameworks set
function _has_target_frameworks(context)
return #table.wrap(context.target:values("csharp.target_frameworks")) > 0
end
+-- get the first element if value is a table
function _first(value)
if type(value) == "table" then
return value[1]
@@ -29,11 +31,12 @@ function _first(value)
return value
end
+-- get single value from target:values()
function _get_target_value(target, name)
return _first(target:values(name))
end
-
+-- detect default target framework from dotnet sdk version, e.g. "net8.0"
function _get_default_target_framework(context)
local dotnet = _first(context.target:get("toolset.cs")) or "dotnet"
dotnet = tostring(dotnet)
@@ -69,6 +72,7 @@ function _get_default_target_framework(context)
return target_framework
end
+-- resolve target framework from user config or auto-detect from dotnet sdk
function _resolve_target_framework(context)
local target_framework = _get_target_value(context.target, "csharp.target_framework")
if target_framework ~= nil and #tostring(target_framework) > 0 then
@@ -77,6 +81,7 @@ function _resolve_target_framework(context)
return _get_default_target_framework(context)
end
+-- resolve assembly name from target basename
function _resolve_assembly_name(context)
local basename = context.target:basename()
if basename ~= nil and #tostring(basename) > 0 then
@@ -85,6 +90,7 @@ function _resolve_assembly_name(context)
end
+-- register a single-value csharp.* property entry
function _register_property(register, suffix, xml, default, extra)
local entry = table.join({
kind = "property",
@@ -95,6 +101,7 @@ function _register_property(register, suffix, xml, default, extra)
register(entry)
end
+-- register a list-value csharp.* property entry (semicolon-joined)
function _register_list_property(register, suffix, xml, extra)
local entry = table.join({
kind = "property",
@@ -106,6 +113,7 @@ function _register_list_property(register, suffix, xml, extra)
register(entry)
end
+-- register all csharp property and project attribute entries for csproj generation
function main()
local entries = {}
function register(entry)
diff --git a/xmake/rules/csharp/xmake.lua b/xmake/rules/csharp/xmake.lua
index f13003520..251a71ecd 100644
--- a/xmake/rules/csharp/xmake.lua
+++ b/xmake/rules/csharp/xmake.lua
@@ -18,6 +18,99 @@
-- @file xmake.lua
--
+-- User Configs:
+--
+-- The following `csharp.*` values can be set via `set_values()` in xmake.lua
+-- to customize the auto-generated .csproj file.
+--
+-- e.g.
+-- target("example")
+-- add_rules("csharp")
+-- add_files("src/*.cs")
+-- set_values("csharp.target_framework", "net8.0")
+-- set_values("csharp.nullable", "disable")
+-- set_values("csharp.allow_unsafe_blocks", "true")
+--
+-- Project:
+-- csharp.sdk - Project Sdk (default: Microsoft.NET.Sdk)
+--
+-- General:
+-- csharp.target_framework - e.g. "net8.0", auto-detected from dotnet sdk if not set
+-- csharp.target_frameworks - multi-target, e.g. {"net8.0", "net9.0"} (list, semicolon-joined)
+-- csharp.implicit_usings - ImplicitUsings (default: "enable")
+-- csharp.nullable - Nullable (default: "enable")
+-- csharp.lang_version - LangVersion, e.g. "12.0", "latest"
+-- csharp.root_namespace - RootNamespace
+-- csharp.enable_default_compile_items - EnableDefaultCompileItems (default: "false")
+-- csharp.enable_default_embedded_resource_items - EnableDefaultEmbeddedResourceItems
+-- csharp.enable_default_none_items - EnableDefaultNoneItems
+--
+-- Build:
+-- csharp.generate_assembly_info - GenerateAssemblyInfo
+-- csharp.deterministic - Deterministic
+-- csharp.prefer_32bit - Prefer32Bit
+-- csharp.allow_unsafe_blocks - AllowUnsafeBlocks
+-- csharp.check_for_overflow_underflow - CheckForOverflowUnderflow
+--
+-- Analysis:
+-- csharp.analysis_level - AnalysisLevel
+-- csharp.enable_net_analyzers - EnableNETAnalyzers
+-- csharp.enforce_code_style_in_build - EnforceCodeStyleInBuild
+-- csharp.warnings_as_errors - WarningsAsErrors (list)
+-- csharp.warnings_not_as_errors - WarningsNotAsErrors (list)
+-- csharp.error_log - ErrorLog
+-- csharp.generate_documentation_file - GenerateDocumentationFile
+-- csharp.documentation_file - DocumentationFile
+--
+-- Publish/Runtime:
+-- csharp.runtime_identifier - RuntimeIdentifier, e.g. "win-x64"
+-- csharp.runtime_identifiers - RuntimeIdentifiers (list)
+-- csharp.self_contained - SelfContained
+-- csharp.use_app_host - UseAppHost
+-- csharp.roll_forward - RollForward
+-- csharp.publish_single_file - PublishSingleFile
+-- csharp.publish_trimmed - PublishTrimmed
+-- csharp.trim_mode - TrimMode
+-- csharp.publish_ready_to_run - PublishReadyToRun
+-- csharp.invariant_globalization - InvariantGlobalization
+-- csharp.include_native_libraries_for_self_extract - IncludeNativeLibrariesForSelfExtract
+-- csharp.enable_compression_in_single_file - EnableCompressionInSingleFile
+-- csharp.publish_aot - PublishAot
+-- csharp.strip_symbols - StripSymbols
+-- csharp.enable_trim_analyzer - EnableTrimAnalyzer
+-- csharp.json_serializer_is_reflection_enabled_by_default - JsonSerializerIsReflectionEnabledByDefault
+-- csharp.satellite_resource_languages - SatelliteResourceLanguages (list)
+--
+-- Package Info:
+-- csharp.version - Version
+-- csharp.assembly_version - AssemblyVersion
+-- csharp.file_version - FileVersion
+-- csharp.informational_version - InformationalVersion
+-- csharp.package_id - PackageId
+-- csharp.authors - Authors
+-- csharp.company - Company
+-- csharp.product - Product
+-- csharp.description - Description
+-- csharp.copyright - Copyright
+-- csharp.repository_url - RepositoryUrl
+-- csharp.repository_type - RepositoryType
+-- csharp.package_license_expression - PackageLicenseExpression
+-- csharp.package_project_url - PackageProjectUrl
+-- csharp.neutral_language - NeutralLanguage
+-- csharp.enable_preview_features - EnablePreviewFeatures
+--
+-- Output:
+-- csharp.generate_runtime_configuration_files - GenerateRuntimeConfigurationFiles
+-- csharp.copy_local_lock_file_assemblies - CopyLocalLockFileAssemblies
+-- csharp.append_target_framework_to_output_path - AppendTargetFrameworkToOutputPath (default: "false")
+-- csharp.append_runtime_identifier_to_output_path - AppendRuntimeIdentifierToOutputPath (default: "false")
+-- csharp.produce_reference_assembly - ProduceReferenceAssembly
+-- csharp.disable_implicit_framework_references - DisableImplicitFrameworkReferences
+-- csharp.generate_target_framework_attribute - GenerateTargetFrameworkAttribute
+--
+-- Custom Properties (for arbitrary csproj properties not listed above):
+-- csharp.properties - e.g. set_values("csharp.properties", "MyProp=value")
+--
rule("csharp.build")
set_sourcekinds("cs")
on_config("config")