Skip to content

Actually eliminate the shell32.dll/ole32.dll dependency when LLVM is enabled #18108

@squeek502

Description

@squeek502

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:
      EXPORTS
       CoTaskMemFree
      
      • 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementSolving this issue will likely involve adding new logic or components to the codebase.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions