New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Runtime loading dxcompiler on mac/linux #2680
Comments
I looked into some aspects of this over a year ago at this point. I'm afraid I don't remember terribly many details. I can tell you that the way dxc is linked for Linux and MacOS is rather fragile in part due to these GUIDs. There may be another way to generate them that makes this possible. I think @ehsannas (when he gets back from leave) and/or @jaebaek are probably the ones to ask about it at this point. Worth noting, during my investigation, I was solely considering how better to link the dxc compiler. Loading the dxcompiler library directly might evade some of these problems. There are some allocators that get need to get initialized that were occasionally missed as well. |
@rellensb If you don't mind, how are you linking against dxc on linux in the first place? I can't seem to be able to resolve the references to |
@pow2clk thanks for the reply. I've patched in a string lookup locally which seems to be working ok, but it'd be good to work out an upstream solution if possible. @jkunstwald in terms of compile time linking? Nothing special, just regular linking against the .so (eg. assuming gcc: |
@rellensb Thank you! Forcing |
Hey @rellensb ! Sorry for the delay. I was on leave for a while. Were you able to use dlopen without linking the lib? If you were able to get it working with some code changes, please feel free to make a pull-request. Your contributions would be much appreciated. I currently don't have the bandwidth to do this work. (side note: There has been some improvement in the generation of UUIDs (#2796)) |
@ehsannas I'm particularly interested in a method that retains compatibility with external FFI wrappers (from other languages) that dlopen the library and rely on passing a full UUID (which, afaik, is the intended usecase). While #2796 gives a consistent hash those wrappers need changes to pass the hash instead of pointer to UUID when using a GCC-compiled DXC. As it stands the virtual interfaces are incompatible too (on clang as well; either padding, virtual destructor or something else: allow me to validate what it is). After locally playing with this for some time, here are my thoughts:
Then, the nitty-gritty details on how I came to the final implementation adhering to those rules: The existing macros are updated to take a rewritten variant of the GUID. These are returned as
Unfortunately Yet this relies on specifying the UUID twice - in different formats - which is not ideal. Fortunately some macro magic allows a struct header to be created that generates the When this question (for #1342) was posted over at dotnet the suggestion came up to use a trait type with template specializations that contains these IIDs. This is used in the final revision with the advantage that inherited types do not need to be passed through the macro, because it doesn't emit the opening brace struct MyImplementationForICustomInterface : public IMyCustomInterface {
// ...
};
// The following is expected to return the IID of IMyCustomInterface, as MyImplementationForICustomInterface is simply an implementation of that interface which does not have an IID itself:
auto unknown_uuid = __uuidof(MyImplementationForICustomInterface);
// Error: No template specialization for TInterfaceIids<MyImplementationForICustomInterface> This seems to be a valid usecase where an implementation creates various specializations of the same interface by means of sub-classing. All changes can be found on this branch that compiles and runs on GCC and Clang on Linux, and MSVC on Windows. This branch includes a couple picks to reduce warnings (though more are needed, GCC and Clang are pretty verbose about this project), as well as the necessary updates to Looking forward to your thoughts and suggestions! |
Hi @MarijnS95 Do I understand correctly that usages of |
Hi @ehsannas: All instances of The issue lies specifically in the use of subclasses that themselves don't carry an IID. I don't know how common (if at all) this case is. See the code example given in my comment. EDIT: Apologies for the confusion, looks like I totally messed up that section while rewriting the comment. It is now rewritten to mention this subclass specialization explicitly. |
Oh I see. Let me take a closer look at this later this week. Thanks |
@MarijnS95 Sorry for the delay. What you have done looks reasonable to me. Would you please post a pull-request? We can add any improvement suggestions there. Thanks! |
@ehsannas took me some time as well to set up the PR, you can find it here now: #3062 As for the vtable issue, the problem is VTable in GDB(gdb) info vtbl this->m_Library
vtable for 'DxcLibrary' @ 0x7ffff7cbc5f8 (subobject @ 0x5555556bb9e0):
[0]: 0x7ffff6a56d40 <DxcLibrary::QueryInterface(_GUID const&, void**)>
[1]: 0x7ffff6a56d20 <DxcLibrary::AddRef()>
[2]: 0x7ffff6a56d30 <DxcLibrary::Release()>
[3]: 0x7ffff6b36bc0 <IUnknown::~IUnknown()> // Complete object destructor
[4]: 0x7ffff6a57130 <DxcLibrary::~DxcLibrary()> // Deleting destructor
[5]: 0x7ffff6a56d50 <DxcLibrary::SetMalloc(IMalloc*)>
[6]: 0x7ffff6a56d60 <DxcLibrary::CreateBlobFromBlob(IDxcBlob*, unsigned int, unsigned int, IDxcBlob**)>
[7]: 0x7ffff6a56d70 <DxcLibrary::CreateBlobFromFile(wchar_t const*, unsigned int*, IDxcBlobEncoding**)>
[8]: 0x7ffff6a56d80 <DxcLibrary::CreateBlobWithEncodingFromPinned(void const*, unsigned int, unsigned int, IDxcBlobEncoding**)>
[9]: 0x7ffff6a56d90 <DxcLibrary::CreateBlobWithEncodingOnHeapCopy(void const*, unsigned int, unsigned int, IDxcBlobEncoding**)>
[10]: 0x7ffff6a56da0 <DxcLibrary::CreateBlobWithEncodingOnMalloc(void const*, IMalloc*, unsigned int, unsigned int, IDxcBlobEncoding**)>
[11]: 0x7ffff6a56db0 <DxcLibrary::CreateIncludeHandler(IDxcIncludeHandler**)>
[12]: 0x7ffff6a56dc0 <DxcLibrary::CreateStreamFromBlobReadOnly(IDxcBlob*, IStream**)>
[13]: 0x7ffff6a56dd0 <DxcLibrary::GetBlobAsUtf8(IDxcBlob*, IDxcBlobEncoding**)>
[14]: 0x7ffff6a56e90 <DxcLibrary::GetBlobAsUtf16(IDxcBlob*, IDxcBlobEncoding**)> This breaks vtable layout and requires external wrappers (in a different language, not compiled with dxc headers) to insert extra padding, as we do in our Rust wrapper here. The destructors are actively used in Perhaps the destructor can be removed or replaced with a nonvirtual one (with the resulting warning disabled) that is directly called, followed by an explicit free? |
Thanks for pushing this forward everyone! |
Hi, I'm wondering if there's currently a supported way to dlopen dxcompiler on mac/linux without linking against the lib. There doesn't seem to be a way to grab the REFIID for types without having access to the static
Interface::Interface_ID
symbol which will be name mangled.Would adding an exported C function that can do a lookup be a viable option, or is there some existing workaround that I've missed?
The text was updated successfully, but these errors were encountered: