# wine-mono, built fully from source for a native aarch64 host with ARM64EC support. # # Unlike Fedora's wine-mono.spec (ExcludeArch: aarch64, x86/x86_64-only, # system mingw32/64 gcc, WpfGfx disabled), this spec targets exactly what this # repo is for: running natively on an aarch64 (e.g. Asahi Linux) build host and # producing the "arm64" flavour of wine-mono (which itself bundles x86 + arm64 # + arm64ec Windows-side support, matching upstream's own "arm64" release # tarball/msi). Building on aarch64 is not a hack: wine-mono's own GNUmakefile # auto-detects `uname -m` and switches to a native arm64 image build # (NATIVE_arm64=1 NATIVE_arm64ec=1) - this is the *intended* codepath, just # one Fedora's own spec never exercises because it hardcodes x86 mingw tools. # # To get arm64/arm64ec Windows-target cross compilation we use the same # llvm-mingw toolchain upstream's own CI uses (mstorsjo/llvm-mingw), staged # offline below, instead of Fedora's system mingw32/64 packages (which only # target i686/x86_64 and can't produce arm64ec code at all). Because we have # a real clang/lld cross toolchain, WpfGfx (native WPF rendering) is left # enabled instead of being disabled like Fedora does ("requires LLVM"). # # wine-mono has no upstream "make dist" style flattened source tarball that # includes its ~9 git submodules; its own release src.tar.xz is built on an # x86_64 CI runner and bundles an x86_64-hosted llvm-mingw, which is useless # to us here. So %prep reassembles the full source tree itself: the top-level # repo plus every submodule (and *their* submodules, recursively, where # actually needed - see the externals table below) at the commit pinned by # the wine-mono-%{version} tag, all pre-fetched into Source lines so the # build never touches the network. # # CAUTION for anyone bumping %{version} (including via `mx-rpm -U`): every # commit pinned in the externals table below is specific to this tag. A tag # bump alone will *not* update them - the build will silently use stale # submodule content. Re-derive each pin via: # curl -s https://api.github.com/repos/wine-mono/wine-mono/contents/?ref=wine-mono- (top-level submodules) # curl -s https://api.github.com/repos/wine-mono/mono/contents/external?ref= (nested mono externals) # curl -s "https://gitlab.winehq.org/api/v4/projects/mono%2Fbdwgc/repository/tree?ref=&per_page=100" (libatomic_ops) # (each returns a "sha"/"id" that IS the pinned commit of that submodule). %undefine _auto_set_build_flags %undefine _hardened_build %global forgeurl https://github.com/wine-mono/wine-mono %global tag wine-mono-%{version} Name: wine-mono Version: 11.3.0 Release: 1%{?dist} Summary: Mono library required for Wine, built with ARM64EC support # Same license set as Fedora's wine-mono.spec: wine-mono itself is a # combination of many differently-licensed upstream projects (Mono, FNA, # WinForms, WPF, SDL3, FAudio, ...). License: GPL-2.0-or-later AND LGPL-2.1-only AND MIT AND BSD-4-Clause-UC AND MS-PL AND MPL-1.1 URL: https://github.com/wine-mono/wine-mono Source0: %{forgeurl}/archive/%{tag}/%{name}-%{tag}.tar.gz # Same fix Fedora carries: some libc's iconv() takes a const inbuf, others # (glibc included, depending on version/_GNU_SOURCE) don't; upstream's cast # only compiles cleanly on NetBSD/AIX. Cheap, harmless if unneeded. Patch0: wine-mono-iconv.patch %{lua: -- Every external below is a git submodule (possibly a submodule *of* a -- submodule) pinned to the exact commit wine-mono-11.3.0 uses. wine-mono's -- "mono" submodule alone has 21 further submodules; mono's own build system -- (mcs's bootstrap profile-check, its class library set, native interop -- shims, ...) reaches into most of them even for a plain `make image`, in -- ways not obvious from wine-mono's own makefiles - several were only found -- by real trial-and-error build failures (roslyn-binaries, cecil, ...), so -- at this point all of mono's externals are included rather than -- hand-picking a subset again. The one deliberate omission is "vstests" -- (a top-level wine-mono submodule, not a mono external): it's only used by -- the `tests`/`tests-zip` targets, which this spec doesn't build. local externals = { -- top-level wine-mono submodules { host="github", owner="wine-mono", name="mono", ref="73610cc7350b7b51dd3bde3323a8ae28eaf5f7fc", path="mono" }, { host="github", owner="wine-mono", name="FNA", ref="c36487f36ab67f66691132b9b178ed4ed1365d0a", path="FNA" }, { host="github", owner="wine-mono", name="FNA.NetStub", ref="68c0af20c386bf70c298a8df9154bd22c5f0ff88", path="FNA.NetStub" }, { host="github", owner="wine-mono", name="winforms", ref="d53511fb4bfd0b9a4e5cbfcf3f77eddcd4a8ecff", path="winforms" }, { host="github", owner="wine-mono", name="winforms-datavisualization", ref="4e1ff0ff0529382d365e1f1632681febe04efb63", path="winforms-datavisualization" }, { host="github", owner="wine-mono", name="wpf", ref="9178bf7cb4d5d33dfd36f0611153c9f95a337595", path="wpf" }, { host="github", owner="wine-mono", name="monoDX", ref="7bf8e8f5ecdc6d920a89916b89db8a39d4de7279", path="monoDX" }, -- monolite: prebuilt mcs.exe used to bootstrap-compile mono's own C# -- class libraries without a chicken-and-egg C# compiler problem. { host="github", owner="wine-mono", name="monolite-binaries", ref="0938815ce68c8630b1faf21e5735258a5dfc62aa", path="monolite" }, -- nested submodules of FNA/ (FNA/.gitmodules), pinned to what wine-mono's -- "FNA" commit above itself pins. FNA/lib/FNAMF is a plain directory in -- FNA (not a submodule), so it's already included with FNA itself. -- SDL2-CS/SDL3-CS are needed by FNA's own managed (C#) build even though -- wine-mono replaces FNA's native SDL/audio libs with its own -- faudio.make/fna3d.make/sdl3.make (confirmed by a real build failure: -- `error CS2001: Source file 'lib/SDL2-CS/src/SDL2.cs' could not be -- found`); Theorafile/dav1dfile included for the same reason preemptively. { host="github", owner="FNA-XNA", name="FAudio", ref="c54eb8f1223fe3b89e46ce929dbc3fd1a0601029", path="FNA/lib/FAudio" }, { host="github", owner="FNA-XNA", name="FNA3D", ref="32401479a3ab5bd6b2e7f786e87bf4166aa03b0f", path="FNA/lib/FNA3D" }, { host="github", owner="flibitijibibo", name="SDL2-CS", ref="1eb20e5c690aee9a5188ba9cf06207295c51d935", path="FNA/lib/SDL2-CS" }, { host="github", owner="flibitijibibo", name="SDL3-CS", ref="9bdcf5de2af86bf764a9ca3c42821c1a099ef150", path="FNA/lib/SDL3-CS" }, { host="github", owner="FNA-XNA", name="Theorafile", ref="3497e1a3cda1fa1ce79256f20e210fd08aec546f", path="FNA/lib/Theorafile" }, { host="github", owner="MoonsideGames", name="dav1dfile", ref="a1377b49d6b69097357618bde87b0294e32dc313", path="FNA/lib/dav1dfile" }, -- nested submodule of FNA/lib/FNA3D (FNA3D/.gitmodules) { host="github", owner="icculus", name="mojoshader", ref="6333f74dbd5644789a63e903816441b16c1e8b60", path="FNA/lib/FNA3D/MojoShader" }, -- nested submodules of mono/ (mono/.gitmodules), pinned to what -- wine-mono's "mono" commit above itself pins { host="gitlab", name="boringssl", ref="3e6fe145e23d0fc5e9529702fc28f70851b09af4", path="mono/external/boringssl" }, -- bdwgc: mono defaults support_boehm=yes on a plain Linux host build -- (only disabled for our mingw cross builds, via --disable-boehm in -- mono.make), so the native mono-unix bootstrap does configure it. { host="gitlab", name="bdwgc", ref="17a5cfb1e779798cd597701c5e1571fbe9571162", path="mono/external/bdwgc" }, { host="github", owner="wine-mono", name="reference-assemblies", ref="eb33e216f039c0edc4f1406266af3ced6f44be1f", path="mono/external/binary-reference-assemblies" }, -- cecil: Mono.Cecil.dll is built as one of mono-unix's own class library -- targets (also used by genfilehashes.exe/fixuparch.exe/monoDX). { host="github", owner="mono", name="cecil", ref="8021f3fbe75715a1762e725594d8c00cce3679d8", path="mono/external/cecil" }, -- roslyn-binaries: despite --without-compiler-server (which only disables -- the persistent csc.exe *server* daemon), mcs/build/rules.make's -- STANDALONE_CSC_LOCATION still points here unconditionally as the -- bootstrap C# compiler for the very first ("build" tools) profile - -- confirmed by a real build failure (`Cannot open assembly -- .../roslyn-binaries/Microsoft.Net.Compilers/3.9.0/csc.exe`) before this -- was added. wine-mono's own "monolite" submodule only bootstraps later, -- higher-level profile builds, not this first one. { host="github", owner="mono", name="roslyn-binaries", ref="1c6482470cd219dcc7503259a20f26a1723f20ec", path="mono/external/roslyn-binaries" }, -- corefx: corlib.dll alone (mono/mcs/class/corlib) sources from dozens of -- separate corefx project subtrees (Common, System.Collections, -- System.Memory, System.Runtime.Extensions, ...), on top of -- src/Native (mono-unix's libSystem.Native.so) and -- src/System.DirectoryServices.AccountManagement - trying to sparse-fetch -- an accurate subset isn't practical, but the whole mirror is a modest -- ~25MB, so just fetch all of it. { host="gitlab", name="corefx", ref="290d27ab8adb9f437ceeb82dbd0a36f01efad6ad", path="mono/external/corefx" }, -- Remaining mono/ externals (see comment above): included for -- completeness rather than re-deriving which ones are load-bearing one -- build failure at a time. { host="github", owner="mono", name="aspnetwebstack", ref="e77b12e6cc5ed260a98447f609e887337e44e299", path="mono/external/aspnetwebstack" }, { host="github", owner="mono", name="Newtonsoft.Json", ref="471c3e0803a9f40a0acc8aeceb31de6ff93a52c4", path="mono/external/Newtonsoft.Json" }, { host="github", owner="mono", name="rx", ref="b29a4b0fda609e0af33ff54ed13652b6ccf0e05e", path="mono/external/rx" }, { host="github", owner="mono", name="ikvm-fork", ref="08266ac8c0b620cc929ffaeb1f23ac37629ce825", path="mono/external/ikvm" }, { host="github", owner="mono", name="ikdasm", ref="f0fd66ea063929ef5d51aafdb10832164835bb0f", path="mono/external/ikdasm" }, { host="gitlab", name="NUnitLite", ref="b78250c687e8fb34327cb1ce4a44a718677a48ec", path="mono/external/nunit-lite" }, { host="github", owner="mono", name="NuGet.BuildTasks", ref="99558479578b1d6af0f443bb411bc3520fcbae5c", path="mono/external/nuget-buildtasks" }, -- cecil-legacy: same upstream repo as cecil above, pinned to a different -- (older, mono-legacy-0.9.5 branch) commit for this specific external path. { host="github", owner="mono", name="cecil", ref="33d50b874fd527118bc361d83de3d494e8bb55e1", path="mono/external/cecil-legacy" }, { host="github", owner="mono", name="bockbuild", ref="1c3bc7a1d43557e47fbc91f38da250ab7506815e", path="mono/external/bockbuild" }, { host="github", owner="mono", name="linker", ref="ed4a9413489aa29a70e41f94c3dac5621099f734", path="mono/external/linker" }, { host="github", owner="mono", name="corert", ref="11136ad55767485063226be08cfbd32ed574ca43", path="mono/external/corert" }, { host="github", owner="mono", name="xunit-binaries", ref="8f6e62e1c016dfb15420852e220e07091923734a", path="mono/external/xunit-binaries" }, { host="gitlab", name="api-doc-tools", ref="65e455a9436c6290489e8218c10fd15c09c4c777", path="mono/external/api-doc-tools" }, { host="github", owner="mono", name="api-snapshot", ref="dbe583ec8e5cbc384e41f2e6fd631b01658b783d", path="mono/external/api-snapshot" }, { host="github", owner="mono", name="illinker-test-assets", ref="ec9eb51af2eb07dbe50a2724db826bf3bfb930a6", path="mono/external/illinker-test-assets" }, -- nested submodule of mono/external/bdwgc (bdwgc/.gitmodules) { host="github", owner="Unity-Technologies", name="libatomic_ops", ref="7e44a3b8dcf457207d6394e4e52e327189155e4f", path="mono/external/bdwgc/libatomic_ops" }, } function external_url(s) if s.host == "github" then return string.format("https://github.com/%s/%s/archive/%s.tar.gz", s.owner, s.name, s.ref) elseif s.host == "gitlab" then return string.format("https://gitlab.winehq.org/mono/%s/-/archive/%s/%s-%s.tar.gz", s.name, s.ref, s.name, s.ref) elseif s.host == "gitlab-sparse" then -- rpm derives %{SOURCEn}'s local filename from the URL path, which gets -- mangled by the ?sha=&path= query string here; pin it explicitly with -- the standard #/name.tar.gz fragment convention. Slug in the subpath -- too, since multiple sparse fetches of the same repo@ref (different -- subpath) would otherwise collide on one local filename. local slug = s.subpath:gsub("[^%w]+", "-") return string.format("https://gitlab.winehq.org/api/v4/projects/mono%%2F%s/repository/archive.tar.gz?sha=%s&path=%s#/%s-%s-%s-sparse.tar.gz", s.name, s.ref, s.subpath, s.name, s.ref, slug) end end for i, s in ipairs(externals) do si = 10 + i print(string.format("Source%d: %s", si, external_url(s)).."\n") end function print_setup_externals() for i, s in ipairs(externals) do si = 10 + i print(string.format("mkdir -p %s", s.path).."\n") print(string.format("tar -xzf %s --strip-components=1 -C %s", rpm.expand("%{SOURCE"..si.."}"), s.path).."\n") end end } # llvm-mingw: the same clang/lld-based cross toolchain wine-mono's own # GNUmakefile (llvm.make) fetches automatically when AUTO_LLVM_MINGW=1 (the # default) - covers i686-w64-mingw32, x86_64-w64-mingw32, aarch64-w64-mingw32 # and arm64ec-w64-mingw32 from a single install, which is why we use it # instead of Fedora's mingw32/64-only system packages. Version pinned to # whatever llvm.make's FETCH_LLVM_MINGW_VERSION says for this wine-mono tag; # bump together with it. Host-arch tarball (aarch64), since this build runs # natively on an aarch64 host. Source200: https://github.com/mstorsjo/llvm-mingw/releases/download/20260616/llvm-mingw-20260616-ucrt-ubuntu-22.04-aarch64.tar.xz BuildRequires: autoconf BuildRequires: automake BuildRequires: libtool BuildRequires: cmake BuildRequires: gcc BuildRequires: gcc-c++ BuildRequires: make BuildRequires: pkgconfig BuildRequires: gettext BuildRequires: libgdiplus BuildRequires: python3 BuildRequires: dos2unix BuildRequires: util-linux # winemsibuilder/cabarc (msi tooling, unused by the plain `image` target we # build) and winebuild (used by wpf.make to build the arm64ec import lib). BuildRequires: wine-core BuildRequires: wine-devel Requires: wine-filesystem # Bundles FNA, FAudio, SDL3, FNA3D, BoringSSL (BTLS), bdwgc, and reference # assemblies from the .NET Framework / corefx - see the externals table # above for exact versions. %description Windows Mono runtime required for Wine, providing the managed .NET Framework 4.8.1-and-earlier compatible CLR that Wine's built-in mscoree.dll loads. Built from source for aarch64 with native ARM64EC support (as well as x86 support), unlike the Fedora package which only targets x86/x86_64 build hosts. %prep %setup -q -n %{name}-%{tag} %{lua: print_setup_externals()} # Patch0 touches mono/mono/eglib/giconv.c, so it must apply after the mono # submodule above is extracted. %patch -P 0 -p1 # Pre-stage the llvm-mingw toolchain exactly where llvm.make expects to find # it already extracted (llvm-mingw--ucrt-ubuntu-22.04-$(uname -m)/.dir), # so its fetch rule sees it as up to date at parse time and never runs wget. mkdir -p llvm-mingw-20260616-ucrt-ubuntu-22.04-aarch64 tar -xJf %{SOURCE200} --strip-components=1 -C llvm-mingw-20260616-ucrt-ubuntu-22.04-aarch64 touch llvm-mingw-20260616-ucrt-ubuntu-22.04-aarch64/.dir # Fix all Python shebangs (mirrors Fedora's spec) find . -name '*.py' -exec sed -i '1s@^#!.*python.*@#!%{__python3}@' {} + sed -i 's/GENMDESC_PRG=python/GENMDESC_PRG=python3/' mono/mono/mini/Makefile.am.in # workaround coreutils 9.2 "cp -n" behavior change (RHBZ#2208129), # https://github.com/madewokherd/wine-mono/issues/164 sed -i 's~cp -n $(IMAGEDIR)/lib/mono/4.8-api/\*.dll $(IMAGEDIR)/lib/mono/4.5/~cp -n $(IMAGEDIR)/lib/mono/4.8-api/\*.dll $(IMAGEDIR)/lib/mono/4.5/ || true~' mono.make # CRLF line endings in shipped shell scripts break `sh` in the container # build (wine bug 48937) find . -name '*.sh' -exec dos2unix -q {} + %build export BTLS_CFLAGS="-fPIC" export CPPFLAGS_FOR_BTLS="-fPIC" # Work around a SIGSEGV crashing the native mono-unix runtime while # cross-compiling the win32-targeted class libraries, seen across repeated # runs - most often right around CustomMarshalers.dll/System.Net.Http.dll, # always with a threadpool/GC frame in the managed stacktrace when one is # captured. Not a source-specific bug (the exact assembly varies run to # run), and forcing non-concurrent GC alone didn't fix it. Also force # preemptive (signal-based) thread suspension instead of mono's newer # cooperative/hybrid suspend, since cooperative suspend's stack-scanning at # safepoints has a history of aarch64-specific bugs across runtimes. export MONO_GC_PARAMS="major=marksweep" export MONO_THREADS_SUSPEND="preemptive" # Debug info as DWARF (objcopy --add-gnu-debuglink), not CodeView/.pdb - # matches Fedora's proven-working choice. echo "PREFER_DWARF_SYMBOLS=1" > user-config.make # ENABLE_DOTNET_CORE_WPFGFX is left at its default (1): unlike Fedora we # have a real clang/lld cross toolchain via the staged llvm-mingw, so native # WPF rendering doesn't need to be disabled. # ARCH is auto-detected from `uname -m` by GNUmakefile itself (aarch64 here), # which is what selects the native arm64(+arm64ec+x86) image composition - # no target needs to be forced. # # -j4: the very first successful end-to-end run (reaching %install cleanly) # used -j4 and never hit the intermittent mono-unix SIGSEGV described above; # it only started appearing on later, slower reruns, so it isn't tied to # this parallelism level. Kept at 4 (not %{?_smp_mflags}'s full nproc) to # leave headroom on a shared/busy host. make -j4 image %install rm -rf %{buildroot} mkdir -p %{buildroot}%{_datadir}/wine/mono/wine-mono-%{version}/ cp -rp image/* %{buildroot}%{_datadir}/wine/mono/wine-mono-%{version}/ %files %define debug_package %{nil} %license COPYING %doc README.md %{_datadir}/wine/mono/wine-mono-%{version}/ %changelog %autochangelog