## Motivation
We currently use mingw-w64 GCC 7.3.0 from the mingw-builds toolchain on the Binary Factory, which has quite old mingw-w64 headers and also an old GCC.
- `libjxl` uses `highway`, which requires AVX512F support that GCC 7.3.0 lacks.
(https://invent.kde.org/graphics/krita/-/merge_requests/1363)
- Updating to upstream ANGLE needs newer mingw-w64 headers.
(https://invent.kde.org/graphics/krita/-/merge_requests/1373)
An update of the Windows build toolchain is needed for these dependencies.
## Scope
This only concerns the build toolchain used on the KDE Binary Factory, and subsequently also other developers and contributors who use the prebuilt dependencies from the Binary Factory. Anyone can still build the dependencies and Krita on Windows with any supported toolchains.
## Choice of Toolchain
### Available Candidates
- mingw-builds GCC 11.2 rev1 [mingw-builds] [mingw-builds-release]
- https://github.com/niXman/mingw-builds-binaries/releases/download/11.2.0-rt_v9-rev1/x86_64-11.2.0-release-posix-seh-rt_v9-rev1.7z
- llvm-mingw LLVM 14 (20220323) [llvm-mingw]
- https://github.com/mstorsjo/llvm-mingw/releases/download/20220323/llvm-mingw-20220323-ucrt-x86_64.zip
- MSYS2, with MINGW64 environment
- MSYS2, with UCRT64 environment
- MSYS2, with CLANG64 environment
[mingw-builds]: https://github.com/niXman/mingw-builds
[mingw-builds-release]: https://github.com/niXman/mingw-builds-binaries/releases
[llvm-mingw]: https://github.com/mstorsjo/llvm-mingw
### Exclusion of MSVC
Amyspark had found several codegen performance regressions with MSVC in the past, therefore we cannot consider using it for releases until these issues have been resolved.
### msvcrt vs ucrt
`msvcrt.dll` was the C standard library from before and up to Microsoft Visual C++ 6.0. Since then, newer versions of Visual C++ used versioned DLLs (e.g. `msvcr70.dll`). Modern versions of Windows still include `msvcrt.dll` for use by system components and for compatibility with old programs compiled against Visual C++ 6.0. Officially, linking to `msvcrt.dll` is *not* supported, but since Microsoft is unlikely to break old programs it will likely still work for the foreseeable future.
Since `msvcrt` is stuck at Visual C++ 6.0, mingw-w64 provides its own replacement functions to replace some of the non-compliant parts in it.
Universal CRT (`ucrt`) is Microsoft's new C standard library which ships as part of Windows starting from Windows 10, and installable on Windows 7 through Windows 8.1. It conforms more closely to ISO C99 than the old `msvcrt`. Visual Studio started using it since VS2015. Mingw-w64 added support for `ucrt` but it needs to be enabled when building the toolchain.
I believe `ucrt` should be preferred. Mingw-w64's `ucrt` support is a bit young, but I am not too worried about that. Our embedded Python already requires `ucrt`, so we are not adding a new dependency.
Toolchains using `ucrt`:
- llvm-mingw
- MSYS2 UCRT64
- MSYS2 CLANG64
### libstdc++ vs libc++
`libstdc++` is the GNU C++ Library, while `libc++` is the C++ standard library implementation by LLVM developers. `libc++` is quite a bit younger, but it has been the default C++ standard library for macOS, FreeBSD and Android for some time, so it has also been widely used. In any case, neither is really native to Windows, so I don't think either one of them has an edge over the other.
I've seen comments that claim `libc++` performs worse than `libstdc++`, but I have not found any recent benchmarks that can prove or disprove this. Since we mostly use Qt's library classes over C++ standard library classes, I am willing to guess this would not affect Krita very much.
Toolchains using `libstdc++`:
- mingw-builds
- MSYS MINGW64
- MSYS UCRT64
Toolchains using `libc++`:
- llvm-mingw
- MSYS CLANG64
### Build Times
There isn't much of a noticeable difference in compile time between GCC and Clang on Windows. However, link time with `lld` from LLVM is an order of magnitude faster than GNU `ld`, which is quite noticeable when rebuilding only a small number of object files in the kritaui library.
Toolchains using `lld`:
- llvm-mingw
- MSYS CLANG64
Note: GCC-based toolchains *can* use lld but it requires some manual setup.
### Problems with MSYS2
#### Rolling Release
MSYS2 is a rolling release, which means it is difficult to pin the packages to specific versions. We may create an archive of the MSYS2 environment and use that as a "stable" toolchain, but this archive will not be easily reproducible with the exact versions of packages.
#### Included Shared Libraries
MSYS2 comes with certain libraries included or available as packages (gettext and OpenSSL for example), which is helpful in some way, because some libraries does not provide a native CMake build system (which we currently work around by either using prebuilt binaries or adapting the CMake build system from vcpkg). This however also ties shared libraries together with the toolchain. If we choose to deliver the toolchain as an archive, whenever we want to update these libraries we will need to update the whole toolchain.
### Miscellaneous Considerations
- mingw-w64 GCC is known to have a codegen bug that breaks the upstream ANGLE build, though we may patch it regardless of which toolchain is chosen for the Binary Factory. (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104862, https://bugs.chromium.org/p/angleproject/issues/detail?id=7179)
- The official Rust compiler may have issues working with llvm-based and/or ucrt-based mingw-w64 toolchains. (https://github.com/rust-lang/rust/issues/72241)
- Note however we do *not* actually require Rust. The only dependency that needs Rust is Rav1e, which is optional and not actually used on the Binary Factory for Windows and macOS. (They use `libaom` instead.)
- llvm-mingw supports cross-compiling for Windows aarch64 (MSVC can too, but mingw-builds or GCC can't), though we will need to adjust our build system for that to happen and I don't plan to do it soon.
- llvm-mingw and MSYS CLANG64 supports ASAN, though for best effect one needs to also build all deps locally with ASAN, so not really a concern with the Binary Factory, unless we also want to make nightly builds with ASAN.
- llvm-mingw supports producing .pdb debugging symbols which may allow us to get better crash reports for the Microsoft Store release. I don't really know how that works though and it also requires changing parts of the build process.
### Suggestion (personal opinion)
To be clear, I am partial towards a purpose-built standalone toolchain so my suggestion is biased. Considering the extra work needed to manage a MSYS2 build environment or toolchain (manual dependency updates) and the lack of tagged stable releases, I would not recommend using MSYS2 for the Binary Factory. This leaves mingw-builds and llvm-mingw. I am in favour of moving to `ucrt` instead of `msvcrt`. Therefore I would recommend switching to llvm-mingw.
## Action Plan
- Ask sysadmin to deploy the toolchain to the Windows builder.
- **Make sure we do not need to make another 5.0 bugfix release anymore.**
- Merge changes to dependencies:
- https://invent.kde.org/graphics/krita/-/merge_requests/1370
- https://invent.kde.org/graphics/krita/-/merge_requests/1404
- https://invent.kde.org/graphics/krita/-/merge_requests/1372 (merged)
- https://invent.kde.org/graphics/krita/-/merge_requests/1363
- Adjust the Binary Factory build pipelines of Krita to use the new toolchain.
- Confirm that the builds work normally.
- Write to kimageshop so others building on Windows and using the prebuilt deps can know about the change.
- Update build instructions in readme and the manual.