Clang plugins on Windows

I am trying to build clang plugins on windows. I have a large cross platform (Linux/Windows) project and I am in the works of modernizing it. The project heavily relies on custom in-house build tools that analyse c++ code and generate some more. I was thinking that clang (as a compiler) supports both platforms and allows you to build plugins for it, so I would move the project from using platform specific compilers and custom build tools to a full clang toolchain. I would like to use clang for both compiling the project and rewrite the build tools as clang plugins. Seemed like a great idea.

  • I have cloned the llvm-project from github (llvm 12).
  • Then I have generated Visual Studio project files for the llvm-project with this cmake command
    cmake -G "Visual Studio 16" -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON -DLLVM_TARGETS_TO_BUILD=X86 -DCLANG_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=install ...\llvm-project\llvm
  • Then I have built the solution using the MSVC compiler, in release configuration for x64 architecture. The project compiles successfully. Both clang, lld and the example clang plugin, PrintFunctionNames have successfully been built.
  • Now it was time to invoke and test the example plugin. I have tried both ways to use the plugin:
clang -cc1 -load PrintFunctionNames.dll -plugin print-fns test.cpp
clang -c -Xclang -load -Xclang PrintFunctionNames.dll -Xclang -plugin -Xclang print-fns test.cpp

The error:
While these commands work, that is, the plugin is loaded and it runs as expected, using clang++ in the command results in a error: unable to find plugin 'print-fns'. Moreover, using the plugin and building a executable (removing the -c option) gives a linker error (1136) invalid or corrupt file.

I have tried to replicate the PrintFunctionNames plugin out of tree as well, following this github repository. While I have managed to build it out of tree, the errors are the same: it only works with clang and not clang++ and no binaries can be built while using the plugin due to the link error.

Am I doing something wrong? What could possibly be the reason behind the different results from using clang/clang++? I always thought that they are the same driver, just they have different presets for linking with the c/c++ stdlib. Does anyone have any hints on how to get plugins working? There seems to be no documentation on building plugins for Windows.

References:
export symbols option

1 Like

I have also posted a question echoing my issues on stackoverflow. While I wouldn’t call what I got a “solution”, but I think I have resolved the linking errors, thus the plugin can be used while compiling sources. clang++ still refuses to work though.

Here is my stackoverflow thread

I have the same problem Did you get it settled?

No, clang plugins is not supported on windows, see https://reviews.llvm.org/D16761

Hi @compnerd!

We chatted at the LLVM developers meeting about the eventual support of plugins on Windows. IIRC, you mentioned that you had a set of local patches that go a long way towards that goal and there was somebody interested to share some of the work.

Could you elaborate more what needs to be done. I am thinking of submitting a google summer of code project on this topic and your input would be of great help!

Best, Vassil

Hi @vvassilev!

Yes, I did have a differential up on Phabricator which annotated the symbols for LLVMSupport as a first step. The general work that needs to be done is to annotate all the public API surface with __declspec(dllexport) or __attribute__((__visibility__("default"))) (or __attribute__((__visibility__("protected"))) on Linux) if they are being built as a dynamically linked library (and nothing if being built statically). When the library is being consumed the attribute on the same declaration must be __declspec(dllimport) or the same spelling for the GNU version for ELF and MachO. Note that the attribute changes between the implementation and consumer and between static and dynamic linking. This is normally controlled by expansion to a macro.

I have also written a tool to help identify the public surface at GitHub - compnerd/ids: Interface Analysis Utility.

@tstellar was looking at the annotations and had made some progress but I believe his work also had stalled.

Part of the problem with the patch that I had put up was that although it did enable at least getting LLVMSupport prepared for dynamic linking, it also exposed latent ODR violation due to vague linkage being applied to certain cl::opt declarations. We would need to address that as part of the clean up and attribution.

@compnerd, thanks for the detailed information. I was thinking to create a GSoC project in that area, would you and @tstellar interested to co-mentor? I can take most of the administrative work and questions but I will need experts on advanced ones…

Sure, I would be happy to co-mentor if someone were to take on this challenge.

Can we come up with a 3 paragraph project description and we can take it from there?

cc: @akorobeynikov

1 Like

I’m not sure I can help mentor, but I could help someone get started. I have a working prototype for shared library builds on Windows., and I have heavily modified @compnerd’s tool so that doing rebases is manageable. It would be great if there was someone with dedicated time to help push this over the finish line.

@tstellar ooh, I’d be interested in the changes to the tool! I think that if there are things we can do to make it more useful, we should do so. I think that once the annotations is done, it might be a good thing to use to quickly sanity check new changes to the LLVM sources.

For what it’s worth, I’d love to help out with this in any way that would be useful. I’m actively working on a couple projects that would benefit greatly from the reduced binary sizes that come with this.