@@ -16,7 +16,135 @@ echo "============================================"
1616rm -rf " $OUTPUT_DIR "
1717mkdir -p " $OUTPUT_DIR "
1818
19- # Pack order: OpenGL/Skia first (no fork-to-fork deps), then Android/iOS
19+ # Step 1: Build Avalonia.Base first (we need the patched DLLs)
20+ echo " >> Building Avalonia.Base ..."
21+ dotnet pack " $SCRIPT_DIR /src/Avalonia.Base/Avalonia.Base.csproj" \
22+ -c " $CONFIGURATION " \
23+ -p:ForkVersion=" $FORK_VERSION " \
24+ -o " $OUTPUT_DIR "
25+ echo " "
26+
27+ # Step 2: Repackage the official Avalonia meta-package with our patched Avalonia.Base.dll.
28+ #
29+ # The official Avalonia nupkg bundles Avalonia.Base.dll (via Numerge).
30+ # We replace those DLLs with our patched build and re-version the package
31+ # so consumers get the fix without conflicting copies.
32+ NUGET_CACHE=" $HOME /.nuget/packages"
33+ OFFICIAL_NUPKG=" $NUGET_CACHE /avalonia/$BASE_VERSION /avalonia.$BASE_VERSION .nupkg"
34+
35+ if [ ! -f " $OFFICIAL_NUPKG " ]; then
36+ echo " >> Official Avalonia $BASE_VERSION not found in NuGet cache. Downloading..."
37+ mkdir -p " $NUGET_CACHE /avalonia/$BASE_VERSION "
38+ curl -sSL -o " $OFFICIAL_NUPKG " \
39+ " https://api.nuget.org/v3-flatcontainer/avalonia/$BASE_VERSION /avalonia.$BASE_VERSION .nupkg"
40+ if [ ! -f " $OFFICIAL_NUPKG " ]; then
41+ echo " ERROR: Failed to download Avalonia $BASE_VERSION from nuget.org"
42+ exit 1
43+ fi
44+ echo " Downloaded to $OFFICIAL_NUPKG "
45+ fi
46+
47+ echo " >> Repackaging official Avalonia $BASE_VERSION with patched Avalonia.Base DLLs..."
48+
49+ # Built DLLs from step 1
50+ BASE_BIN=" $SCRIPT_DIR /src/Avalonia.Base/bin/$CONFIGURATION "
51+
52+ python3 - " $OFFICIAL_NUPKG " " $BASE_BIN " " $OUTPUT_DIR " " $BASE_VERSION " " $FORK_VERSION " << 'PYEOF '
53+ import sys, os, zipfile, tempfile, shutil
54+ import xml.etree.ElementTree as ET
55+
56+ official_nupkg = sys.argv[1]
57+ base_bin = sys.argv[2]
58+ output_dir = sys.argv[3]
59+ base_version = sys.argv[4]
60+ fork_version = sys.argv[5]
61+
62+ # Map TFM folders in the nupkg to our build output directories
63+ TFM_MAP = {
64+ "net8.0": "net8.0",
65+ "net6.0": "net6.0",
66+ "netstandard2.0": "netstandard2.0",
67+ }
68+
69+ with tempfile.TemporaryDirectory() as tmpdir:
70+ # Extract official package
71+ with zipfile.ZipFile(official_nupkg, 'r') as z:
72+ z.extractall(tmpdir)
73+
74+ # Replace Avalonia.Base.dll in lib/ and ref/ for each TFM
75+ for nupkg_tfm, build_tfm in TFM_MAP.items():
76+ built_dll = os.path.join(base_bin, build_tfm, "Avalonia.Base.dll")
77+ built_xml = os.path.join(base_bin, build_tfm, "Avalonia.Base.xml")
78+
79+ if not os.path.exists(built_dll):
80+ print(f" WARNING: {built_dll} not found, skipping {nupkg_tfm}")
81+ continue
82+
83+ for prefix in ["lib", "ref"]:
84+ target_dll = os.path.join(tmpdir, prefix, nupkg_tfm, "Avalonia.Base.dll")
85+ target_xml = os.path.join(tmpdir, prefix, nupkg_tfm, "Avalonia.Base.xml")
86+
87+ if os.path.exists(target_dll):
88+ shutil.copy2(built_dll, target_dll)
89+ print(f" Replaced {prefix}/{nupkg_tfm}/Avalonia.Base.dll")
90+
91+ if os.path.exists(target_xml) and os.path.exists(built_xml):
92+ shutil.copy2(built_xml, target_xml)
93+ print(f" Replaced {prefix}/{nupkg_tfm}/Avalonia.Base.xml")
94+
95+ # Update version in nuspec
96+ nuspec_files = [f for f in os.listdir(tmpdir) if f.endswith(".nuspec")]
97+ if nuspec_files:
98+ nuspec_path = os.path.join(tmpdir, nuspec_files[0])
99+ tree = ET.parse(nuspec_path)
100+ root = tree.getroot()
101+
102+ # Find namespace
103+ ns = ""
104+ for uri in [
105+ "http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd",
106+ "http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd",
107+ "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd",
108+ ]:
109+ if root.find(f"{{{uri}}}metadata") is not None:
110+ ns = uri
111+ break
112+
113+ if ns:
114+ ET.register_namespace("", ns)
115+ metadata = root.find(f"{{{ns}}}metadata")
116+ version_el = metadata.find(f"{{{ns}}}version")
117+ if version_el is not None:
118+ version_el.text = fork_version
119+ print(f" Version: {base_version} -> {fork_version}")
120+
121+ tree.write(nuspec_path, xml_declaration=True, encoding="utf-8")
122+
123+ # Remove [Content_Types].xml signature files that NuGet will regenerate
124+ for f in [".signature.p7s"]:
125+ p = os.path.join(tmpdir, "package", f)
126+ if os.path.exists(p):
127+ os.remove(p)
128+
129+ # Repackage
130+ out_nupkg = os.path.join(output_dir, f"Avalonia.{fork_version}.nupkg")
131+ with zipfile.ZipFile(out_nupkg, 'w', zipfile.ZIP_DEFLATED) as zout:
132+ for dirpath, dirnames, filenames in os.walk(tmpdir):
133+ for fn in filenames:
134+ full = os.path.join(dirpath, fn)
135+ arcname = os.path.relpath(full, tmpdir)
136+ zout.write(full, arcname)
137+ print(f" Created {os.path.basename(out_nupkg)}")
138+ PYEOF
139+
140+ echo " "
141+
142+ # Remove the standalone Avalonia.Base nupkg — it's now inside the Avalonia meta-package
143+ rm -f " $OUTPUT_DIR " /Avalonia.Base.* .nupkg
144+ echo " >> Removed standalone Avalonia.Base nupkg (now bundled in Avalonia meta-package)"
145+ echo " "
146+
147+ # Step 3: Pack the remaining forked projects
20148PROJECTS=(
21149 " src/Avalonia.OpenGL/Avalonia.OpenGL.csproj"
22150 " src/Skia/Avalonia.Skia/Avalonia.Skia.csproj"
@@ -37,14 +165,14 @@ done
37165#
38166# The official Avalonia build uses Numerge to merge sub-packages into the
39167# Avalonia meta-package. These sub-packages don't exist on nuget.org:
40- # Avalonia.Base, Avalonia. Controls, Avalonia.DesignerSupport, Avalonia.OpenGL,
168+ # Avalonia.Controls, Avalonia.DesignerSupport, Avalonia.OpenGL,
41169# Avalonia.Metal, Avalonia.Vulkan, Avalonia.Dialogs, Avalonia.Markup,
42170# Avalonia.Markup.Xaml, Avalonia.MicroCom
43171#
44172# Our dotnet pack creates deps on these non-existent packages. We fix this by:
45- # 1. Removing deps on merged/bundled packages
46- # 2. Ensuring a dep on Avalonia >= base_version exists (it provides those DLLs )
47- # 3. Pinning Avalonia dep to base_version (not fork_version )
173+ # 1. Removing deps on merged/bundled packages (they're inside the Avalonia meta-package)
174+ # 2. Rewriting Avalonia deps to point to our fork version (since we now ship a forked Avalonia nupkg )
175+ # 3. Removing deps on Avalonia.Base (now bundled in our forked Avalonia meta-package )
48176
49177echo " >> Post-processing nupkgs..."
50178
@@ -82,6 +210,11 @@ def find_ns(root):
82210for fname in sorted(os.listdir(output_dir)):
83211 if not fname.endswith(".nupkg"):
84212 continue
213+ # Skip the repackaged Avalonia meta-package — already handled
214+ # Its filename is "Avalonia.<fork_version>.nupkg" (no sub-name like .Android, .Skia, etc.)
215+ pkg_name = fname.rsplit("." + fork_version, 1)[0] if ("." + fork_version) in fname else fname
216+ if pkg_name == "Avalonia":
217+ continue
85218 nupkg_path = os.path.join(output_dir, fname)
86219
87220 with tempfile.TemporaryDirectory() as tmpdir:
@@ -118,11 +251,11 @@ for fname in sorted(os.listdir(output_dir)):
118251
119252 if dep_id == "Avalonia":
120253 has_avalonia_dep = True
121- # Pin to base version (official meta-package on nuget.org)
122- if dep_ver = = fork_version:
123- dep.set("version", base_version )
254+ # Point to our forked Avalonia meta-package
255+ if dep_ver ! = fork_version:
256+ dep.set("version", fork_version )
124257 modified = True
125- print(f" {pkg_id}: Avalonia dep {fork_version } -> {base_version }")
258+ print(f" {pkg_id}: Avalonia dep {dep_ver } -> {fork_version }")
126259
127260 elif dep_id in MERGED:
128261 # Remove deps on packages bundled in the Avalonia meta-package
@@ -144,10 +277,10 @@ for fname in sorted(os.listdir(output_dir)):
144277 if needs_avalonia_dep and not has_avalonia_dep:
145278 new_dep = ET.SubElement(group, f"{{{ns}}}dependency")
146279 new_dep.set("id", "Avalonia")
147- new_dep.set("version", base_version )
280+ new_dep.set("version", fork_version )
148281 new_dep.set("exclude", "Build,Analyzers")
149282 modified = True
150- print(f" {pkg_id}: added dep on Avalonia {base_version }")
283+ print(f" {pkg_id}: added dep on Avalonia {fork_version }")
151284
152285 if modified:
153286 tree.write(nuspec_path, xml_declaration=True, encoding="utf-8")
@@ -169,4 +302,5 @@ ls -1 "$OUTPUT_DIR"/*.nupkg 2>/dev/null
169302echo " "
170303echo " Copy to your local feed and clean stale cache:"
171304echo " cp $OUTPUT_DIR /*.nupkg /opt/dev/local_nugets/"
172- echo " rm -rf ~/.nuget/packages/avalonia*/11.9.1"
305+ echo " rm -rf ~/.nuget/packages/avalonia/$FORK_VERSION "
306+ echo " rm -rf ~/.nuget/packages/avalonia.*/$FORK_VERSION "
0 commit comments