-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
Follow up to #18091
Unfortunately,
LLVMSupport.libhas its own dependencies onshell32'sSHGetKnownFolderPath/SHFileOperationWandole32'sCoTaskMemFree:
- https://github.com/llvm/llvm-project/blob/083a53971758c6f9bbd448eeb9c5d839661e3f68/llvm/lib/Support/Windows/Path.inc#L1363
- https://github.com/llvm/llvm-project/blob/083a53971758c6f9bbd448eeb9c5d839661e3f68/llvm/lib/Support/Windows/Path.inc#L1436-L1440
which means that when building Zig with LLVM enabled, we inherit those dependencies and the slow process initialization returns, even if the
shell32/ole32functions aren't called. So, there's no actual gain in process initialization at all in status-quo Zig.
In the meantime, there is a potential avenue to explore with regards to
-delayloadwhich is what LLVM uses to avoid the process initialization cost of theshell32/ole32dependency. I haven't put much effort into investigating this or if/how it could be utilized by Zig, but it might be possible. My naive attempt at building LLVM from source with MSVC and then building Zig with that didn't seem to get the-delayloadto carry over, but again I didn't look too closely/try much of anything.
The -delayload approach can definitely work. I've got a proof-of-concept LLVM-enabled compiler without shell32.dll/ole32.dll dependencies built by doing the following:
- Generating
shell32.lib/ole32.libviadlltoolas outlined here: https://github.com/AustinWise/delay-load-mingwshell32.def:EXPORTS SHGetKnownFolderPath SHFileOperationWdlltool --input-def shell32.def --output-delaylib shell32.lib --dllname shell32.dll
ole32.def:EXPORTS CoTaskMemFreedlltool --input-def ole32.def --output-delaylib ole32.lib --dllname ole32.dll
zig build -p stage4-debug -Denable-llvm -Dno-lib --verbose-link- Took the giant
lld-linkinvocation and copied it into a.batfile- note: this relies on there being no spaces in any of the
.libpaths; if any of the.libfilepaths have spaces you'll have to quote them
- note: this relies on there being no spaces in any of the
- Replaced the path to
shell32.libandole32.libwith the path to the.libfiles generated bydlltool - Added
-delayload:ole32.dll -delayload:shell32.dllto the command - Replaced the
-OUT:path with a path outside of the cache directory, e.g.-OUT:C:\Users\Ryan\Programming\Zig\zig\build\zig-delayload.exe
- Took the giant
- Ran the batch file with
lld-linkin my PATH
The result:
No shell32.dll / ole32.dll
> dumpbin /DEPENDENTS /nologo ".\zig-delay.exe"
Image has the following dependencies:
ADVAPI32.dll
KERNEL32.dll
msvcrt.dll
ntdll.dll
WS2_32.dll
CRYPT32.dll
VERSION.dll
However, I have a feeling this might explode if the shell32/ole32 functions are called from within LLVM, as I think delayimp needs to be linked and it's not being linked currently. I was able to get the test in https://github.com/AustinWise/delay-load-mingw confirmed to work with clang and lld-link via:
clang -o testdelay-clang.exe testdelay.c -ldelayimp -lversion -Wl,-delayload:version.dll -fuse-ld=lld
but I think it's using delayimp.lib from MSVC.
Things that need to be figured out:
- Need to confirm that the delayed loading part actually works, i.e. the shell32/ole32 functions within LLVM need to actually be called to ensure that the dlls get loaded properly and everything still works.
- Need to figure out a way to get LLVM to call the relevant functions, or will need to write some custom code that calls e.g.
home_directory - Alternatively, if it can be proven that the code paths in LLVM that call the shell32/ole32 functions cannot be reached from the Zig compiler, then we could scrap delayload and go with a simpler route of providing dummy symbols for the functions
- Need to figure out a way to get LLVM to call the relevant functions, or will need to write some custom code that calls e.g.
- Need to remove the dependency on
dlltoolto generate the.libfiles - Need to support
-delayloadlinker flags properly and use them when building the Zig compiler - Need to check that this solution works for both the
gnuandmsvcABI targets, or make it work for both ABI targets