Follow up to #18091
Unfortunately, LLVMSupport.lib has its own dependencies on shell32's SHGetKnownFolderPath/SHFileOperationW and ole32's CoTaskMemFree:
which means that when building Zig with LLVM enabled, we inherit those dependencies and the slow process initialization returns, even if the shell32/ole32 functions 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 -delayload which is what LLVM uses to avoid the process initialization cost of the shell32/ole32 dependency. 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 -delayload to 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.lib via dlltool as outlined here: https://github.com/AustinWise/delay-load-mingw
shell32.def:
EXPORTS
SHGetKnownFolderPath
SHFileOperationW
dlltool --input-def shell32.def --output-delaylib shell32.lib --dllname shell32.dll
ole32.def:
dlltool --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-link invocation and copied it into a .bat file
- note: this relies on there being no spaces in any of the
.lib paths; if any of the .lib filepaths have spaces you'll have to quote them
- Replaced the path to
shell32.lib and ole32.lib with the path to the .lib files generated by dlltool
- Added
-delayload:ole32.dll -delayload:shell32.dll to 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
- Ran the batch file with
lld-link in 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 remove the dependency on
dlltool to generate the .lib files
- Need to support
-delayload linker flags properly and use them when building the Zig compiler
- Need to check that this solution works for both the
gnu and msvc ABI targets, or make it work for both ABI targets
Follow up to #18091
The
-delayloadapproach can definitely work. I've got a proof-of-concept LLVM-enabled compiler without shell32.dll/ole32.dll dependencies built by doing the following:shell32.lib/ole32.libviadlltoolas outlined here: https://github.com/AustinWise/delay-load-mingwshell32.def:dlltool --input-def shell32.def --output-delaylib shell32.lib --dllname shell32.dllole32.def:dlltool --input-def ole32.def --output-delaylib ole32.lib --dllname ole32.dllzig build -p stage4-debug -Denable-llvm -Dno-lib --verbose-linklld-linkinvocation and copied it into a.batfile.libpaths; if any of the.libfilepaths have spaces you'll have to quote themshell32.libandole32.libwith the path to the.libfiles generated bydlltool-delayload:ole32.dll -delayload:shell32.dllto the command-OUT:path with a path outside of the cache directory, e.g.-OUT:C:\Users\Ryan\Programming\Zig\zig\build\zig-delayload.exelld-linkin my PATHThe result:
No
shell32.dll/ole32.dllHowever, I have a feeling this might explode if the
shell32/ole32functions are called from within LLVM, as I thinkdelayimpneeds 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 withclangandlld-linkvia:but I think it's using
delayimp.libfrom MSVC.Things that need to be figured out:
home_directorydlltoolto generate the.libfiles-delayloadlinker flags properly and use them when building the Zig compilergnuandmsvcABI targets, or make it work for both ABI targets