[clang] [clang][ssaf] Don't try to link SSAFExamplePlugin on Windows (PR #191401)

Martin Storsjö via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 10 05:47:56 PDT 2026


mstorsjo wrote:

> Our intention was that we should be able to insert into an `llvm::Registry` from the plugin. I suspect, that is the undefined symbol.

No, not quite.

When linking this plugin, it actually _does_ link against the shared libLLVM dylib. But it doesn't link against any clang libraries in any form, which ends up as the undefined symbols.

> I'll admit that I've never developed for Windows, and I'm also not too familiar with TU-local statics and dynamic loaders. Could you please share a bit more insights?

None of this has anything to do with TU-local statics and dynamic loaders. It only has to do with how to link shared libraries.

On ELF and MachO, you can link a shared library, with references that are undefined at link time. When loading the shared library at runtime, the linker then looks up and sees if those symbols are found somewhere in the global symbol name space of the process, and if not, it rejects loading it.

On PE-COFF, every shared library must have every symbol resolved at static link time, if not the linker errors out. There's no such lookup at runtime later.

On ELF, it's possible to add something like `-Wl,--no-undefined` to tell the linker to refuse to link a shared library if not all symbols are found at link time; this gets you something very similar to the PE-COFF model.

> We wanted our tool to support some shape or form of plugins even on Windows. While that is not in the short term plans, after this I have doubts if that is feasible.

It is totally possible to build plugins on Windows, but it requires you to link with dylibs.

When using dylibs, all the common shared state (such as `llvm::Registry`) is in one single copy, in libLLVM, and similarly all clang code is in a `libclang-cpp.{so,dylib,dll}`. When building with dylibs enabled, then the static LLVM libraries are not linked in, but instead the LLVM cmake machinery replaces linking the static llvm libraries with linking against libLLVM.

Then you'd have the main tool (clang etc) linking against libclang-cpp.{so,dylib,dll} and libLLVM.{so,dylib.dll}, and the plugin also linking against the same libclang-cpp and libLLVM; then plugins work just fine.

It _may_ also be possible to have plugins on ELF, where the plugins themselves don't link against libclang-cpp and libLLVM, but just have unresolved undefined symbols. In this case, the host executable (which may be e.g. a clang executable built with dylibs disabled, i.e. all the shared state is in the statically linked LLVM libraries inside the clang executable) provides the symbols, which fulfill the undefined symbols when loading the plugin.

AFAIK LLVM/Clang plugins work in at least the former (dylib mode), but it's possible that they also work in the latter form (undefined references). Plugins on Windows only work in the former mode.

But it seems like this test plugin tries to force things into explicitly linking in the latter style (not linking in libLLVM etc) with undefined references, even when building with dylibs enabled.

I would suggest looking at how other existing plugins are built. In my fresh build tree for Windows, I do see that I have `CheckerOptionHandlingAnalyzerPlugin.dll`, `SampleAnalyzerPlugin.dll` and `CheckerDependencyHandlingAnalyzerPlugin.dll` built just fine.


https://github.com/llvm/llvm-project/pull/191401


More information about the cfe-commits mailing list