so on rust, you can static link crt, this is useful especially for windows since there’s a requirement for c dlls that you have to install manually. this isn’t good for my game
with that said, i also wanna keep libc dynamically linked on linux so no issues arise.
i’m also intending on keeping full cross compilation support
i understand that this post is probably a question from the fact that it’s in the Help category and describes the edges of a problem statement.
however, there isn’t actually a question here, which might make it more difficult for people to help you. for example, are you asking whether it’s possible to statically link libc (is this the same as crt for you?) in a Zig project? or are you asking for pointers on how to go about setting your build.zig to take advantage of this possibility? have you gotten stuck somewhere along the process?
I don’t know what the question is either, but I’ll go ahead and say that static linking the crt on Windows doesn’t work at the moment, because Zig uses MinGW, which only supports dynamic linking. Furthermore, Windows, overall, only supports dynamic linking, because syscalls aren’t stable.
Static linking on Linux is feasible and highly recommended.
So it looks like you got it backwards.
Rust standard library requires C runtime library (crt) to operate.
Zig standard library calls the operating system directly without using the C runtime library for both linux and windows. But if you have C dependencies you need to link to the C runtime.
Starting with Windows 10 the universal C runtime is shipped with Windows and is updated by the system using windows update. And zig uses the universal C runtime
my understanding is that zig can link against MSVC libc! unfortunately i forgot whether there was some obstruction for cross-compiling to link against MSVC that required manual intervention or if there are licensing issues preventing Zig from linking against it out of the box…
So it seems that when link_mode is .static (which is the default for the generic windows-msvc target), Zig is statically linking the crt libraries (as described here).
If you are still concerned, you can take a look at dumpbin.exe /imports your_exe.exe to check the resulting executable. My experiments show the same results for a printf hello world program as when compiling with cl.exe /MT except Zig also links against ntdll.dll
AFAIK this is not recommended anymore since around Windows 10 and the ‘Universal C Runtime’ (UCRT), e.g. the UCRT DLL installation is now managed centrally by the Windows Update Process, and not expected to be done by an application (unless you need to support older Windows versions than 10)
I still prefer linking the CRT statically though, it’s just less hassle all around.
But as far as I understand, binaries built with _-windows-gnu build and statically link the mingw “gnu” part, and just link against the universal crt. So there is no need to install anything to run the produced binaries (at least since Windows 10).
I use xwin and VC-LTL5 in my project. xwin provides an MSVC environment for cross-compiling, and VC-LTL5 can make the exe built on MSVC link only to ucrtbase.dll (which is included with Windows).
Just to be clear, the imported DLLs you’re seeing here are system DLLs that are always present, and they’re only there because MinGW-w64 requires them. The MinGW-w64 CRT code is still statically linked into your EXE; there is no run-time dependency on non-Microsoft DLLs.
They are not system DLLs (other than Kernel32). They are vcredist, short for visual c runtime redistributable, which is microsoft’s convoluted name for dynamically linked libc. Although they’re from Microsoft, they are not system DLLs because they are not the main interface to Windows (Kernel32 is). In fact, until a short while ago, they were not necessarily present in a Windows installation. The user had to install the infamous vcredist and vcppredist, which would cause a gigantic list of vcredist in the programs list, each one for a slightly different version of it. Since Windows 10, they are now managed as part of windows updates.
Like I mentioned in my edit, compiling with static and targetting msvc gets rid of them (except kernel32), just like compiling with msvc itself with the static flag, which proves they are not necessary.
Mingw did not implement libc for windows, which is why they only offer the dynamically linked version of it.
I’m only speaking about Windows 10+ here because the Zig standard library doesn’t officially support anything older than that. So from our perspective, we do regard the API set DLLs as system-provided.
MinGW-w64 requires those DLLs when used in the “typical” UCRT mode. There is another mode that links directly against ucrtbase.dll instead, but we don’t currently support that because using the API set DLLs is the recommended practice by Microsoft. We probably could relatively easily if there’s demand, though.
Either way, when using MinGW-w64 with UCRT, there’s still a ton of CRT code that gets linked into your EXE/DLL statically in the form of mingw32.lib, which is what I was getting at. It’s just not a “pure” static link because it ultimately needs to depend on the system UCRT in some way. But there’s no dynamic dependency on MinGW-specific DLLs or anything like that.