Big Clang DLL, plug-in mechanism revision

Hi,

May I solicit some feedback on the work I’ve done for these two issues?

Basically I’m attacking the problem from two separate angles, doing the following changes in two separate trees.

In one, I revised the plug-in mechanism, dumbing it down a bit, to avoid the problems encountered on Windows where the plug-in registry referenced in the plug-in DLL doesn’t connect with the plug-in registry in the clang executable. I say dumbing it down a bit because it uses a more basic vector of structures for storing the plugin name and a callback function for creating the action node. The original patch was kind of old, so I updated it, using one new file from the other tree for the __cdeclspec(dllexport) wrapper. Note that I left in the original plug-in registry stuff side-by-side. I tested it the earlier version on both Windows and Linux. It still has the potential problem of the plug-in not having access to everything in the clang executable, which can only be resolved by using a big Clang DLL. Here’s the patches for this change:

http://www.jtlanguage.com/xfer/plugin_llvm_patch.txt
http://www.jtlanguage.com/xfer/plugin_clang_patch.txt

In the other, I did the ground work for creating a big Clang DLL from all the LLVM and Clang sources used in the original Clang executable. It currently only exports a small subset of the functions, mostly only those needed to get the Clang and other executables to link correctly. I’ll recap the scheme later in this email, revising and pasting info from my original messages, with some updates. The clang.exe executable links and runs, though there is some dependency problem I don’t understand yet when doing the “ALL_BUILD”. In running the tests, some of the Index tests fail for unknown reasons. Otherwise, without the cmake “LLVM_BUILD_DLL” option, the normal build and test results are unchanged. Yesterday I tested the patch on Linux and fixed a couple of compile problems. Basically, this shows that the basic big DLL mechanism works, and that all that is needed is to add the rest of the “*_LINKAGE” tags and fix the dependency and Index test problems. Here’s the patches for this change:

http://www.jtlanguage.com/xfer/dll_llvm_patch.txt
http://www.jtlanguage.com/xfer/dll_clang_patch.txt

Note that the big Clang DLL does not automatically fix the original problem of the plug-in registry, as the needed internal registry symbols are not exported. So the full solution of fixing the plug-in registry mechanism probably requires both of these changes, the first for the registering mechanism, and the second for allowing the plug-in to full access of the Clang code and data.

Basically I’m looking for feedback on these two schemes, or a go-ahead with checking in what I have so far, for a staged adoption. Because the DLL scheme still needs a lot of work in adding the “*_LINKAGE” tags to so many declarations, I want to find out if the owners of the respective systems approve of these changes, rather than continuing with all the work and finding that it will not be used. I know it’s a pretty big change, and Windows-specific, but I think it’s important enough to try.

I’m thinking I could check in what I have at present (with any changes required), which has the build changes and the new module-common headers, and the subset of “_LINKAGE" tag additions that let the link succeed, and then check in the remaining changes in smaller batches, as I add the remaining "_LINKAGE” tags.

I’m not sure how the big Clang DLL fits into the long-term scheme of things, whether it remains a special build option on Windows, or becomes the mainstream version. For now just leave it as a special build option. I’m also not sure if any other LLVM modules should be in the DLL, and whether there should also be a separate LLVM DLL. I started doing a little work on this, but didn’t include it here.

So here’s stuff from the original email for the DLL stuff revisions, as I missed a description of something I did on the LLVM side in the cmake files, and I hadn’t gotten the unit test mechanism to work at all. Sorry for the verbosity; I’m just trying to be complete:

The scheme is meant to satisfy the following design goals/constraints:

  1. Create a single Windows DLL including the main Clang and LLVM modules needed for a compiler and other tools, such that it’s the only module you need to link against (from the Clang/LLVM project).

  2. Preserve the current module organization and build, leaving the static-library and other platform’s shared library versions as they are. (This leaves open the option of creating per-module Windows DLLS in the future.)

  3. Enable Clang plug-ins to share the code and data space with the Clang or other tool executables.

  4. Make the “big” DLL version optional by means of cmake arguments given upon running cmake. (I’m not sure of the criteria for deciding whether to make it the default for Windows or not.)

These are the build changes, with respect to the cmake build tool:

  1. A “BUILD_LLVM_DLL” configuration flag is added to the cmake build, such that specifying “-DBUILD_LLVM_DLL=ON” in the cmake command line will enable the big-DLL build. By default it is off.

  2. Factor out the common portions of the “add_clang_library” into “add_clang_library_common”.

  3. Modify the cmake macro “add_clang_library” to collect the source file full path strings in a new target property.

  4. Add a new “add_clang_dll” cmake macro for creating the big DLL. This macro operates like “add_clang_library”, but always builds a DLL target, and doesn’t collect the source paths. It also passes “LLVM_USE_DLL” and “LLVM_EXPORTS” defines to the compiler, to enable the symbol exports to be described later.

  5. Create a new “ClangDLL” project under tools/clang/lib for creating the big DLL, which uses the new “add_clang_dll” macro.

  6. Add new “set_clang_components” and “set_clang_llvm_components” cmake macros for use in conjunction with “add_clang_executable” to collect the Clang and LLVM components, as opposed to setting “LLVM_USED_LIBS” and “LLVM_LINK_COMPONENTS” directory. (These macros will substitute the big DLL for the component libraries.)

  7. Modify “add_clang_executable” to pass an “LLVM_USE_DLL” define to the compiler if the big-DLL version is enabled. This define enables the symbol imports/exports to be described later.

  8. (new) Do similar changes to the LLVM-side cmake macros, such as chaning add_llvm_library to collect the sources.

  9. Update the clang executable, interpreter, and PrintFunctionNames projects to use the new and revised cmake macros.

The source changes mainly consist of adding “(moduleNameUppercase)_LINKAGE” macro instances to the declarations of the classes, functions, and other symbols to be exported/imported, and new header files that define these macros. These changes can be summarized as follows:

  1. A new “(moduleName)Common.h” file is added to each LLVM and Clang module include directory. This file defines a “(moduleNameUppercase)_LINKAGE” macro for that component module. This macro expands to nothing for the non-big-DLL version (“LLVM_USE_DLL” is not defined to the compiler), or to the LLVM_EXPORT macro when building the DLL (“Clang_EXPORTS” or “LLVM_EXPORTS” or “(moduleName)_EXPORTS” is defined), or to the LLVM_IMPORT macro when building against the DLL (“LLVM_USE_DLL” is defined). This include file will be included by any headers in the component needing the “(moduleNameUppercase)_LINKAGE” macro.

  2. A new “LLVMCommon.h” file is added to the include/llvm directory under the root to define “LLVM_EXPORT” and “LLVM_IMPORT” macros that wrap the Visual C++ “__declspec(dllexport)” and “__declspec(dllimport)” directives, as well as to define the “LLVMCORE_LINKAGE” macro. This file will be included by all the “(moduleName)Common.h” files for the LLVM components.

  3. A new “ClangCommon.h” file is added to the tools/clang/include/clang directory. It just includes the “LLVMCommon.h” file, and will be included by the “(moduleName)Common.h” files for the Clang components.

In my experimental version, I added most of the “(moduleName)Common.h” files, but I only added the “(moduleNameUppercase)_LINKAGE” macro instance to some of the symbols, at least the ones needed by the Clang driver and interpreter to link.

Caveats:

  1. The ALL_BUILD project build breaks on some missing .inc files from the X86 target project. I think this has to do with an inherent dependency problem in the cmake build. Even though the “(target)CodeGenTable_gen” project dependency is added to the DLL, the .inc files are not created before the DLL link. I will look into this. A rebuild of the “clang” project does work, as that was the focus of my experiment. The interpreter might build too, as it did earlier.

  2. Several of the “Index” tests don’t pass. I haven’t figured out why yet.

  3. As I mentioned, I only exported some of the symbols, those needed to get the clang executables to build. A big edit (manual or automated) will be needed to add the “(moduleNameUppercase)_LINKAGE” macros to the rest of the symbols, and any needed “(moduleName)Common.h” headers not yet created.

  4. I only enabled the X86 target in LLVM (the default for the Windows build in general), for the purpose of this experiment. The other targets will need to be done as well.

  5. I tried running the PrintFunctionNames plugin, but there’s still a disconnect between the registry referenced by the plugin and the one in the big DLL. I didn’t look into it deep enough yet, but I’m guessing it has something to do with the template mechanism used not being exported. I’m not even sure how to export it. But I think the better solution is to switch to the simplified plugin mechanism I provided a patch for in a previous post (and which I’m still waiting for a review fornudge-nudge).

  6. In building on Windows with the big DLL mechanism enabled, there are a lot of “class ‘someTemplateClass<_Ty>’ needs to have dll-interface to be used by clients of class ‘someClass’” warnings. These just need to have some extra template specialization declarations with the “*_LINKAGE” tag.

You can search on “CMakeLists.txt” and “.cmake” to see the cmake file changes, or “Common.h” to see the new headers. Most of the rest of the changes are just the adding of the “(moduleNameUppercase)_LINKAGE” macros to the class and function definitions.

Thanks!

-John

John Thompson <john.thompson.jtsoftware@gmail.com> writes:

[snip]

You can search on "CMakeLists.txt" and ".cmake" to see the cmake file
changes, or "Common.h" to see the new headers. Most of the rest of the
changes are just the adding of the "(moduleNameUppercase)_LINKAGE" macros to
the class and function definitions.

My area is the cmake build. Before reviewing your changes I'll wait for
the approval by those who decide on the big picture and by the Windows
experts. That said, I'm pretty sure that the cmake part will be the
least controversial piece of the patch.

Hello John,

2. A new "LLVMCommon.h" file is added to the include/llvm directory under
the root to define "LLVM_EXPORT" and "LLVM_IMPORT" macros that wrap the
Visual C++ "__declspec(dllexport)" and "__declspec(dllimport)" directives,
as well as to define the "LLVMCORE_LINKAGE" macro. This file will be
included by all the "(moduleName)Common.h" files for the LLVM components.

This looks really ugly and error-prone. I believe that people will
forgot to add these linkage macros while adding new classes.
Maybe there is some alternative way of exporting the stuff?

Anton,

Thanks for the response.

I agree.

However, forgetting a linkage tag is not too serious, as long as it’s not one of the symbos that the driver or other client references. If a client runs into it, it’s just a simple fix of finding the symbol and adding the tag.

One possiblity might be to write a tool to rewrite .obj files, changing the linkage internally. But given the proprietary nature of the format, it seems like a bad idea, if not just difficult.

One thing I don’t know is if the __declspec method will still reach the 2^16 limit on exports. The solution then would probably to prioritize the classes, and not export the more internal classes.

Another method might be some variation on the method Óscar tried, of creating a tool or script to walk a .map file and create a .def file with exports in it. Add an option to the tool to input a file with a list of names to be used as partial match patterns, omitting names that don’t contain the match pattern, assuming the name mangling preserves at least that much in each symbol name.

Of course this has the same problem of forgetting to add the patterns.

My preference is the more direct method of the linkage tags, which I’m already used to from past Windows work.

-John

Hi,

May I solicit some feedback on the work I’ve done for these two issues?

Basically I’m attacking the problem from two separate angles, doing the following changes in two separate trees.

In one, I revised the plug-in mechanism, dumbing it down a bit, to avoid the problems encountered on Windows where the plug-in registry referenced in the plug-in DLL doesn’t connect with the plug-in registry in the clang executable. I say dumbing it down a bit because it uses a more basic vector of structures for storing the plugin name and a callback function for creating the action node. The original patch was kind of old, so I updated it, using one new file from the other tree for the __cdeclspec(dllexport) wrapper. Note that I left in the original plug-in registry stuff side-by-side. I tested it the earlier version on both Windows and Linux. It still has the potential problem of the plug-in not having access to everything in the clang executable, which can only be resolved by using a big Clang DLL. Here’s the patches for this change:

http://www.jtlanguage.com/xfer/plugin_llvm_patch.txt
http://www.jtlanguage.com/xfer/plugin_clang_patch.txt

In the other, I did the ground work for creating a big Clang DLL from all the LLVM and Clang sources used in the original Clang executable. It currently only exports a small subset of the functions, mostly only those needed to get the Clang and other executables to link correctly. I’ll recap the scheme later in this email, revising and pasting info from my original messages, with some updates. The clang.exe executable links and runs, though there is some dependency problem I don’t understand yet when doing the “ALL_BUILD”. In running the tests, some of the Index tests fail for unknown reasons. Otherwise, without the cmake “LLVM_BUILD_DLL” option, the normal build and test results are unchanged. Yesterday I tested the patch on Linux and fixed a couple of compile problems. Basically, this shows that the basic big DLL mechanism works, and that all that is needed is to add the rest of the “*_LINKAGE” tags and fix the dependency and Index test problems. Here’s the patches for this change:

http://www.jtlanguage.com/xfer/dll_llvm_patch.txt
http://www.jtlanguage.com/xfer/dll_clang_patch.txt

Note that the big Clang DLL does not automatically fix the original problem of the plug-in registry, as the needed internal registry symbols are not exported. So the full solution of fixing the plug-in registry mechanism probably requires both of these changes, the first for the registering mechanism, and the second for allowing the plug-in to full access of the Clang code and data.

Basically I’m looking for feedback on these two schemes, or a go-ahead with checking in what I have so far, for a staged adoption. Because the DLL scheme still needs a lot of work in adding the “*_LINKAGE” tags to so many declarations, I want to find out if the owners of the respective systems approve of these changes, rather than continuing with all the work and finding that it will not be used. I know it’s a pretty big change, and Windows-specific, but I think it’s important enough to try.

I’m thinking I could check in what I have at present (with any changes required), which has the build changes and the new module-common headers, and the subset of “_LINKAGE" tag additions that let the link succeed, and then check in the remaining changes in smaller batches, as I add the remaining "_LINKAGE” tags.

I’m not sure how the big Clang DLL fits into the long-term scheme of things, whether it remains a special build option on Windows, or becomes the mainstream version. For now just leave it as a special build option. I’m also not sure if any other LLVM modules should be in the DLL, and whether there should also be a separate LLVM DLL. I started doing a little work on this, but didn’t include it here.

So here’s stuff from the original email for the DLL stuff revisions, as I missed a description of something I did on the LLVM side in the cmake files, and I hadn’t gotten the unit test mechanism to work at all. Sorry for the verbosity; I’m just trying to be complete:

The scheme is meant to satisfy the following design goals/constraints:

  1. Create a single Windows DLL including the main Clang and LLVM modules needed for a compiler and other tools, such that it’s the only module you need to link against (from the Clang/LLVM project).

  2. Preserve the current module organization and build, leaving the static-library and other platform’s shared library versions as they are. (This leaves open the option of creating per-module Windows DLLS in the future.)

  3. Enable Clang plug-ins to share the code and data space with the Clang or other tool executables.

  4. Make the “big” DLL version optional by means of cmake arguments given upon running cmake. (I’m not sure of the criteria for deciding whether to make it the default for Windows or not.)

These are the build changes, with respect to the cmake build tool:

  1. A “BUILD_LLVM_DLL” configuration flag is added to the cmake build, such that specifying “-DBUILD_LLVM_DLL=ON” in the cmake command line will enable the big-DLL build. By default it is off.

  2. Factor out the common portions of the “add_clang_library” into “add_clang_library_common”.

  3. Modify the cmake macro “add_clang_library” to collect the source file full path strings in a new target property.

  4. Add a new “add_clang_dll” cmake macro for creating the big DLL. This macro operates like “add_clang_library”, but always builds a DLL target, and doesn’t collect the source paths. It also passes “LLVM_USE_DLL” and “LLVM_EXPORTS” defines to the compiler, to enable the symbol exports to be described later.

  5. Create a new “ClangDLL” project under tools/clang/lib for creating the big DLL, which uses the new “add_clang_dll” macro.

  6. Add new “set_clang_components” and “set_clang_llvm_components” cmake macros for use in conjunction with “add_clang_executable” to collect the Clang and LLVM components, as opposed to setting “LLVM_USED_LIBS” and “LLVM_LINK_COMPONENTS” directory. (These macros will substitute the big DLL for the component libraries.)

  7. Modify “add_clang_executable” to pass an “LLVM_USE_DLL” define to the compiler if the big-DLL version is enabled. This define enables the symbol imports/exports to be described later.

  8. (new) Do similar changes to the LLVM-side cmake macros, such as chaning add_llvm_library to collect the sources.

  9. Update the clang executable, interpreter, and PrintFunctionNames projects to use the new and revised cmake macros.

This is all CMake stuff, which sounds okay in principle. Óscar is more qualified to review these changes than the rest of us.

The source changes mainly consist of adding “(moduleNameUppercase)_LINKAGE” macro instances to the declarations of the classes, functions, and other symbols to be exported/imported, and new header files that define these macros. These changes can be summarized as follows:

  1. A new “(moduleName)Common.h” file is added to each LLVM and Clang module include directory. This file defines a “(moduleNameUppercase)_LINKAGE” macro for that component module. This macro expands to nothing for the non-big-DLL version (“LLVM_USE_DLL” is not defined to the compiler), or to the LLVM_EXPORT macro when building the DLL (“Clang_EXPORTS” or “LLVM_EXPORTS” or “(moduleName)_EXPORTS” is defined), or to the LLVM_IMPORT macro when building against the DLL (“LLVM_USE_DLL” is defined). This include file will be included by any headers in the component needing the “(moduleNameUppercase)_LINKAGE” macro.

  2. A new “LLVMCommon.h” file is added to the include/llvm directory under the root to define “LLVM_EXPORT” and “LLVM_IMPORT” macros that wrap the Visual C++ “__declspec(dllexport)” and “__declspec(dllimport)” directives, as well as to define the “LLVMCORE_LINKAGE” macro. This file will be included by all the “(moduleName)Common.h” files for the LLVM components.

  3. A new “ClangCommon.h” file is added to the tools/clang/include/clang directory. It just includes the “LLVMCommon.h” file, and will be included by the “(moduleName)Common.h” files for the Clang components.

In my experimental version, I added most of the “(moduleName)Common.h” files, but I only added the “(moduleNameUppercase)_LINKAGE” macro instance to some of the symbols, at least the ones needed by the Clang driver and interpreter to link.

Ugh. Alas, I’ve never seen another solution that actually works properly on Windows, so I can live with dllimport/dllexport scattered everywhere. Someone is going to have to be vigilant to ensure that these new _LINKAGE macros get added to new classes and functions as they go into the source base, since the vast majority of current LLVM and Clang developers won’t be using LLVM/Clang in this way.

Caveats:

  1. The ALL_BUILD project build breaks on some missing .inc files from the X86 target project. I think this has to do with an inherent dependency problem in the cmake build. Even though the “(target)CodeGenTable_gen” project dependency is added to the DLL, the .inc files are not created before the DLL link. I will look into this. A rebuild of the “clang” project does work, as that was the focus of my experiment. The interpreter might build too, as it did earlier.

  2. Several of the “Index” tests don’t pass. I haven’t figured out why yet.

The Index tests are based on the libclang DLL, which itself is a standalone DLL containing most of Clang (without code-generation).

  1. As I mentioned, I only exported some of the symbols, those needed to get the clang executables to build. A big edit (manual or automated) will be needed to add the “(moduleNameUppercase)_LINKAGE” macros to the rest of the symbols, and any needed “(moduleName)Common.h” headers not yet created.

  2. I only enabled the X86 target in LLVM (the default for the Windows build in general), for the purpose of this experiment. The other targets will need to be done as well.

  3. I tried running the PrintFunctionNames plugin, but there’s still a disconnect between the registry referenced by the plugin and the one in the big DLL. I didn’t look into it deep enough yet, but I’m guessing it has something to do with the template mechanism used not being exported. I’m not even sure how to export it. But I think the better solution is to switch to the simplified plugin mechanism I provided a patch for in a previous post (and which I’m still waiting for a review fornudge-nudge).

I think we need to understand what’s going on here, first. Making it possible to build plugins on Windows is an important aspect of this work, and we’d like to be sure that we got it right before we go and annotate the whole code-base.

  1. In building on Windows with the big DLL mechanism enabled, there are a lot of “class ‘someTemplateClass<_Ty>’ needs to have dll-interface to be used by clients of class ‘someClass’” warnings. These just need to have some extra template specialization declarations with the “*_LINKAGE” tag.

Okay.

In general, I’m in favor of moving forward on this. However, this kind of architectural thing is Chris’s domain, so I’d like to hear from him.

  • Doug

My collegue suggested that a clearer statement of the problems to be solved might help, since overall it was kind of spread out over a few threads over a couple of months.

  1. Plug-in registration. The current plug-in mechanism doesn’t work on Windows. Shared libraries work differently on Windows, such that building a plug-in DLL on windows doesn’t create a connection to the plug-in registry in the libraries used in the Clang executable. The result is that in running a plug-in like the PrintFunctionNames plug-in, there is no output becase the plug-in is adding an entry to a registry that exists only in it’s own data space.

My solution for this was to dumb-down the registry a bit, and to have the plug-in export a function to be called that creates and returns the plug-in action object.

Even if the big-DLL change in #2 is not acceptable, I strongly need the plug-in mechanism to work, as I wrote Lua-bindings plug-in, and I need to have it work on Windows. So it’s very important to me to either have this fix accepted, or get feedback on a more acceptable solution, or have someone else fix it.

  1. Big Clang DLL. If you build a plug-in or other shared library on Windows, the DLL is much like a position-independent executable in that it has it’s own code and data sections, with absolute addresses fixed up at runtime. When the DLL runs, it typically will only call versions of code and static data that live in the DLL itself. An exception is if you pass in an object with virtual function that is created in a separate executable. By means of the vtable, the virtual functions called will be those from the executable where the constructor lives.

If it is expected that the DLL will read or make changes to static data not explicitly or indirectly passed to it, this will not happen, as the DLL is only operating on it’s own data space, or the data pointers explicitly passed to it.

Fortunately, because both the Clang executable and the plug-ins are created using the DLL version of the VC++ runtime, plug-ins that don’t rely on static data from the main executable can still work (as my Lua bindings plug-in does). This means that values returned from calls like malloc can be freed from either the main executable or the DLL. But I fear that we might encounter other plug-ins that won’t work properly, without true sharing of the common code and data.

Again, I need at least #1, and hope it can go in soon (leaving in the old registry for a while until all plug-ins use the new mechanism). I don’t personally need #2, but I think it should be done, and I’m willing to do the work.

Thanks.

-John

Thanks for the reply, Doug.

I think we need to understand what’s going on here, first. Making it possible to build plugins on Windows is an important aspect of this work, and we’d like to be sure that we got it right before we go and annotate the whole code-base.

I’ll look further into caveats #1 (.inc dependency), #2 (Index tests), and #5 (registry mechanism exporting).

Question: If the Index stuff is put into the big DLL, that makes libclang redundant, or means the big DLL is the new libclang (but with all the other stuff exported too), doesn’t it? Or is there a reason to keep Index out of the big DLL?

If my registry replacement mechanism is acceptible, #5 is probably not needed. But it’s probably just finding the right definition inside the registry classes to export, though it might be possible that non-public accessiblity might prevent the export. But I’ll look into it further.

-John

I agree with Anton and personally am not too fond of dllimport/dllexport.
Could we live without the big Clang DLL and just get rid of the current static plug-in registration, replacing it with explicit plugin classes with virtual functions (whose objects get created in the plugin) ?

Also stepping back a bit, there’s a “tooling” effort going on that makes it easier to build custom tools without needing plugins, isn’t this a better way to go ?
Keep in mind that dynamically loading plugins is of reduced usefulness since we don’t have a stable API.

-Argyrios

I agree with Anton and personally am not too fond of dllimport/dllexport.
Could we live without the big Clang DLL and just get rid of the current static plug-in registration, replacing it with explicit plugin classes with virtual functions (whose objects get created in the plugin) ?

Also stepping back a bit, there’s a “tooling” effort going on that makes it easier to build custom tools without needing plugins, isn’t this a better way to go ?

We’re using a plugin that runs in addition to normal codegen on the chrome buildbots (the -add-plugin flag). It outputs additional warnings ( http://www.chromium.org/developers/coding-style/chromium-style-checker-errors has a list if you’re curious). Running with the plugin slows down our build by a few seconds (a full build is 40 minutes, so it’s a very small percentage). Doing this with the tooling stuff would be both slower and more annoying. TL;DR: I think the plugin stuff is probably useful even when the tooling stuff is there.

Keep in mind that dynamically loading plugins is of reduced usefulness since we don’t have a stable API.

(I’m fine with breaking changes to the plugin api.)

I agree with Anton and personally am not too fond of dllimport/dllexport.
Could we live without the big Clang DLL and just get rid of the current static plug-in registration, replacing it with explicit plugin classes with virtual functions (whose objects get created in the plugin) ?

Also stepping back a bit, there’s a “tooling” effort going on that makes it easier to build custom tools without needing plugins, isn’t this a better way to go ?

We’re using a plugin that runs in addition to normal codegen on the chrome buildbots (the -add-plugin flag). It outputs additional warnings ( http://www.chromium.org/developers/coding-style/chromium-style-checker-errors has a list if you’re curious). Running with the plugin slows down our build by a few seconds (a full build is 40 minutes, so it’s a very small percentage). Doing this with the tooling stuff would be both slower and more annoying. TL;DR: I think the plugin stuff is probably useful even when the tooling stuff is there.

Ok, I’m only questioning the need for the big Clang DLL. We can get rid of the static registration using a “standardized” exported function from the plugin and a couple of virtual abstract classes.
Can we be more specific about what is the use case that the above will not suffice and we need a big DLL with all classes exported ?

Also stepping back a bit, there’s a “tooling” effort going on that makes it easier to build custom tools without needing plugins, isn’t this a better way to go ?

I probably need more information on the tooling mechanism. I looked at ClangTooling briefly, but am not sure how to use it. We could probably use an example of doing plug-in-like things, such as doing the same thing as PrintFunctionNames, but using the new tooling interface.

Can we be more specific about what is the use case that the above will not suffice and we need a big DLL with all classes exported ?

I don’t know enough about the tooling mechanism to do so. I also probably don’t know enough to give a specific use case other than the general disconnect between the plug-in DLL code and data, and that of the executable, that I described in general. And this would apply to other plug-in mechanisms too, such as the LLVM plug-ins, and the debugger. Could someone who knows more than I give an opinion?

For example, is there a possible case where the plug-in will need to access or change some state that is not accessible via the arguments passed to the action objects virtual members?

-John

Hi,

1. Plug-in registration. The current plug-in mechanism doesn't work on Windows. Shared libraries work differently on Windows, such that building a plug-in DLL on windows doesn't create a connection to the plug-in registry in the libraries used in the Clang executable. The result is that in running a plug-in like the PrintFunctionNames plug-in, there is no output becase the plug-in is adding an entry to a registry that exists only in it's own data space.
My solution for this was to dumb-down the registry a bit, and to have the plug-in export a function to be called that creates and returns the plug-in action object.

"fixing" the current implementation for dll is not to hard (I think) but need a little work. On would need to remove the following lines from the end of llvm/include/llvm/Support/Registry.h

Cedric,

Thanks for the reply.

I’m afraid I’m a bit template-dumb and don’t know how to do those declarations. Every syntax combination I tried either didn’t compile there, or elsewhere, the latter because the exported declarations would conflict with the “static node *Head, *Tail;” and “static listener *ListenerHead, *ListenerTail;” definitions inside the Registry template class. Can you give me an example?

Template trickiness like this is why I felt a less sophisticated plug-in registry mechanism would be better. But if you can show me how to do it per your suggestion, I’ll give it a try.

-John

Here are patches for clang and llvm which should solve the registration problem. I tested them on win7 VS2010 without dll and the test are ok [1]. Turn out there was only 3 registries, so very small code change. On linux, there may be some more, I didn't check. Also these patch are not commit quality (line length, CRLF, comment/placement of the code). However, they should solve your problem. Let me know if you still have undefined or duplicated symbol when using your dll.

Thank you for tackling the dll problem on windows and hopping this make it into trunk sometime soon.

Cédric

[1] I have 3 llvm test failling and 1 clang test but it was before I made any change

llvmregistry.patch (2.79 KB)

clangregistry.patch (1.3 KB)

Thanks, Cedric.

However, I still have the problem of how to export these members using the VC++ __declspec(dllexport) directive.

For example, for simplicity, if I define AST_LINKAGE as follows:

#define AST_LINKAGE __declspec(dllexport)

I get the following compile results for the following permutations (showing just the first declaration of the quadruple as an example):

1:
AST_LINKAGE template <>
llvm::Registry<clang::PluginASTAction,llvm::RegistryTraitsclang::PluginASTAction >::node*
llvm::Registry<clang::PluginASTAction,llvm::RegistryTraitsclang::PluginASTAction >::Head;

1>…\Frontend\FrontendAction.cpp(386) : warning C4091: ‘__declspec(dllexport)’ : ignored on left of ‘int’ when no variable is declared
1>…\Frontend\FrontendAction.cpp(386) : error C2143: syntax error : missing ‘;’ before ‘‘template<’’

2:
template <>
AST_LINKAGE llvm::Registry<clang::PluginASTAction,llvm::RegistryTraitsclang::PluginASTAction >::node*
llvm::Registry<clang::PluginASTAction,llvm::RegistryTraitsclang::PluginASTAction >::Head;

1>…\Frontend\FrontendAction.cpp(388) : error C2370: ‘Head’ : redefinition; different storage class
1> D:\Clang\llvmdll\include\llvm/Support/Registry.h(76) : see declaration of ‘Head’

3:
template <>
llvm::Registry<clang::PluginASTAction,llvm::RegistryTraitsclang::PluginASTAction >::node*
AST_LINKAGE llvm::Registry<clang::PluginASTAction,llvm::RegistryTraitsclang::PluginASTAction >::Head;

1>…\Frontend\FrontendAction.cpp(388) : error C2059: syntax error : ‘__declspec(dllexport)’

It seems that #2 is the likely candidate, but it conflicts with the declaration of Head in the Registry class.

Any ideas?

Thanks.

-John

Cédric,

I’ve updated my patches to include yours at:

http://www.jtlanguage.com/xfer/dll_llvm_patch.txt
http://www.jtlanguage.com/xfer/dll_clang_patch.txt

in case you want to play around with the whole thing.

Note, to enable the DLL build, you need to run:

cmake -G “Visual Studio 9 2008” -DCLANG_BUILD_EXAMPLES=ON -DLLVM_BUILD_DLL=ON .

Note also that just as you normally do when changing the cmake configuration, you should probably delete the CMakeCache.txt file from the llvm root before running the above.

This update also has the Index tests fixed, such that all Clang tests passed for me. Turns out I needed to handle passing in the repository version needed by the precompilation.

I still need to fix the .inc dependency problems in the build, though, which I’ll do next.

-John

Cédric,

I’ve integrated your changes and got the PrintFunctionNames plugin to work. Thank you so much!

I’ve updated my posted patches.

The only problem left that I know about is the .inc file dependency problem.

-John

Hi,

With the help of Cédric and Óscar, I’ve now got a minimal DLL version of Clang building and passing all the Clang tests, with plug-ins working on Windows also.

It’s still considered very experimental, with only enough symbols exported to build the executables, and not always edited cleanly, and the build mechanism is a little iffy, going under the covers to collect the sources files to build, but I think it’s enough to demonstrate that the mechanism works.

Therefore, I’d like to get some more discussion and review going, and get a descision as to whether you want to use this work in some form, and whether I should continue persuing it.

I’ve update the patches (after updating to revision 131695 of the trunk today):

http://www.jtlanguage.com/xfer/dll_llvm_patch.txt
http://www.jtlanguage.com/xfer/dll_clang_patch.txt

(If my web host is unresponsive, please wait a bit and try again.)

To configure cmake, delete the CMakeCache.txt file and run cmake as follows:

cmake -G “Visual Studio 9 2008” -DCLANG_BUILD_EXAMPLES=ON -DLLVM_BUILD_DLL=ON .

To see more details of what I’ve done, please see my May 9th and May 4th (2011) posts of the same subject.

Thanks.

-John