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]
- llvm-mingw LLVM 14 (20220323) [llvm-mingw]
- 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:
- 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.