Add CppInterOp API dispatch mechanism#730
Add CppInterOp API dispatch mechanism#730aaronj0 wants to merge 13 commits intocompiler-research:mainfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #730 +/- ##
==========================================
+ Coverage 79.07% 79.10% +0.03%
==========================================
Files 9 11 +2
Lines 3899 3929 +30
==========================================
+ Hits 3083 3108 +25
- Misses 816 821 +5
🚀 New features to boost your workflow:
|
e259123 to
badab56
Compare
badab56 to
3f72c0b
Compare
3f72c0b to
624d59a
Compare
624d59a to
460f493
Compare
3b9e2b4 to
795db00
Compare
795db00 to
a768abb
Compare
include/CppInterOp/CppDispatch.h
Outdated
| #include <vector> | ||
|
|
||
| #include <cstdlib> | ||
| #include <dlfcn.h> |
There was a problem hiding this comment.
needs something like:
#ifdef _WIN32
#include <io.h>
#include <Psapi.h>
#define RTLD_DEFAULT ((void *)::GetModuleHandle(NULL))
//#define dlsym(library, function_name) ::GetProcAddress((HMODULE)library, function_name)
#define dlopen(library_name, flags) ::LoadLibrary(library_name)
#define dlclose(library) ::FreeLibrary((HMODULE)library)
#endifThere was a problem hiding this comment.
The windows specific code has been added and compiled but is untested due to the absence of a shared lib build on the CI (or so it seems) The CppInterOpDispatch test executable is not built.
My requested changes have been dealt with now.
c33a4cb to
5628d1c
Compare
cb0f6ea to
f8d869a
Compare
|
TODO:
|
| static const std::unordered_map<std::string_view, CppFnPtrTy> | ||
| DispatchMap = { | ||
| #define DISPATCH_API(name, type) {#name, (CppFnPtrTy) static_cast<type>(&CppImpl::name)}, | ||
| CPPINTEROP_API_TABLE |
There was a problem hiding this comment.
warning: do not use C-style cast to convert between unrelated types [cppcoreguidelines-pro-type-cstyle-cast]
CPPINTEROP_API_TABLE
^Additional context
include/CppInterOp/Dispatch.h:44: expanded from macro 'CPPINTEROP_API_TABLE'
DISPATCH_API(CreateInterpreter, decltype(&CppImpl::CreateInterpreter)) \
^lib/CppInterOp/Dispatch.cpp:7: expanded from macro 'DISPATCH_API'
#define DISPATCH_API(name, type) {#name, (CppFnPtrTy) static_cast<type>(&CppImpl::name)},
^
lib/CppInterOp/Dispatch.cpp
Outdated
| #undef DISPATCH_API | ||
| }; | ||
|
|
||
| static inline CppFnPtrTy _cppinterop_get_proc_address(const char* funcName) { |
There was a problem hiding this comment.
warning: declaration uses identifier '_cppinterop_get_proc_address', which is reserved in the global namespace [bugprone-reserved-identifier]
static inline CppFnPtrTy _cppinterop_get_proc_address(const char* funcName) {
^this fix will not be applied because it overlaps with another fix
lib/CppInterOp/Dispatch.cpp
Outdated
| #undef DISPATCH_API | ||
| }; | ||
|
|
||
| static inline CppFnPtrTy _cppinterop_get_proc_address(const char* funcName) { |
There was a problem hiding this comment.
warning: invalid case style for function '_cppinterop_get_proc_address' [readability-identifier-naming]
static inline CppFnPtrTy _cppinterop_get_proc_address(const char* funcName) {
^this fix will not be applied because it overlaps with another fix
| "test_func<<<1,1>>>();", false)) | ||
| return false; | ||
| intptr_t result = Cpp::Evaluate("(bool)cudaGetLastError()"); | ||
| intptr_t result = Cpp::Evaluate("(bool)cudaGetLastError()", nullptr); |
There was a problem hiding this comment.
warning: no header providing "intptr_t" is directly included [misc-include-cleaner]
unittests/CppInterOp/CUDATest.cpp:5:
+ #include <cstdint>| TYPED_TEST(CppInterOpTest, FunctionReflectionTestGetClassMethods) { | ||
| // Reusable empty template args vector. In the dispatch mode, passing an empty initializer list {} | ||
| // does not work since the compiler cannot deduce the type for a function pointer | ||
| std::vector<Cpp::TemplateArgInfo> empty_templ_args = {}; |
There was a problem hiding this comment.
warning: no header providing "std::vector" is directly included [misc-include-cleaner]
unittests/CppInterOp/FunctionReflectionTest.cpp:16:
+ #include <vector>| std::vector<Cpp::TemplateArgInfo> args1 = {C.IntTy.getAsOpaquePtr()}; | ||
| std::vector<Cpp::TemplateArgInfo> args2 = { | ||
| Cpp::GetVariableType(Cpp::GetNamed("a"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr))}; |
| std::vector<Cpp::TemplateArgInfo> args4 = { | ||
| Cpp::GetVariableType(Cpp::GetNamed("a")), | ||
| Cpp::GetVariableType(Cpp::GetNamed("a"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr)), |
| Cpp::GetVariableType(Cpp::GetNamed("a")), | ||
| Cpp::GetVariableType(Cpp::GetNamed("a"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr))}; |
| std::vector<Cpp::TemplateArgInfo> args1 = { | ||
| Cpp::GetVariableType(Cpp::GetNamed("a")), | ||
| Cpp::GetVariableType(Cpp::GetNamed("a"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr)), |
| Cpp::GetVariableType(Cpp::GetNamed("a")), | ||
| Cpp::GetVariableType(Cpp::GetNamed("a"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr))}; |
This defines the mechanism which enables dispatching of the CppInterOp API without linking to it, preventing any LLVM or Clang symbols from being leaked into the client application. Can be used to deploy CppInterOp in an environment where dynamic linking is not favourable and the only option is dlopen'ing `libClangCppInterOp.so` with `RTLD_LOCAL`
Rename CppInterOpDispatch -> CppDispatch, Address more review comments and drop `DECLARE_CPP` style macros
…atch.h With the introduction of the CppStatic namespace we conditionally alias `Cpp` to the implementation provided by CppInterOp.h (link to clangCppInterOp.so) or CppDispatch (dlopen the dylib with RTLD_LOCAL) This is an intentional ODR violation but remains consistent with our API model.
Gives the mechanism complete coverage. Now runs CppInterOpTests and CppInterOpDispatchTests
This patch also improves the readability of the test run log: ``` 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.Interpreter_IncludePaths 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.Interpreter_IncludePaths (0 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.Interpreter_CodeCompletion 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.Interpreter_CodeCompletion (86 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.Interpreter_ExternalInterpreter 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.Interpreter_ExternalInterpreter (1123 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.Jit_InsertOrReplaceJitSymbol 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.Jit_InsertOrReplaceJitSymbol (56 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.Jit_StreamRedirect 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.Jit_StreamRedirect (0 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.Jit_StreamRedirectJIT 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.Jit_StreamRedirectJIT (154 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.ScopeReflection_IsEnumScope 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.ScopeReflection_IsEnumScope (21 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.ScopeReflection_IsEnumConstant ``` instead of: ``` 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.InterpreterTestIncludePaths 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.InterpreterTestIncludePaths (0 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.InterpreterTestCodeCompletion 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.InterpreterTestCodeCompletion (86 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.InterpreterTestExternalInterpreter 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.InterpreterTestExternalInterpreter (1123 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.JitTestInsertOrReplaceJitSymbol 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.JitTestInsertOrReplaceJitSymbol (56 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.JitTestStreamRedirect 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.JitTestStreamRedirect (0 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.JitTestStreamRedirectJIT 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.JitTestStreamRedirectJIT (154 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.ScopeReflectionTestIsEnumScope 2: [ OK ] CppInterOpDispatchTest/InProcessJIT.ScopeReflectionTestIsEnumScope (21 ms) 2: [ RUN ] CppInterOpDispatchTest/InProcessJIT.ScopeReflectionTestIsEnumConstant ``` We repeated the word "Test" twice and the lack of a spacer made it hard to read. Since this patch changes the TYPED_TEST line to use `CPPINTEROP_TEST_MODE` instead of `CppInterOpTest` this is a good opportunity to improve this without bloating the history
Simplify the unittest cmake logic on top of compiler-research#770 clang-format, clang-tidy suggestions
ef70115 to
2f7bb0b
Compare
include/CppInterOp/Dispatch.h
Outdated
| } // end namespace CppAPIType | ||
|
|
||
| namespace CppInternal { | ||
| namespace Dispatch { |
There was a problem hiding this comment.
warning: nested namespaces can be concatenated [modernize-concat-nested-namespaces]
| namespace Dispatch { | |
| namespace CppInternal::Dispatch { |
include/CppInterOp/Dispatch.h:264:
- } // namespace Dispatch
- } // namespace CppInternal
+ } // namespace CppInternal::Dispatch| static const std::unordered_map<std::string_view, CppFnPtrTy> | ||
| DispatchMap = { | ||
| #define DISPATCH_API(name, type) {#name, (CppFnPtrTy) static_cast<type>(&CppImpl::name)}, | ||
| CPPINTEROP_API_TABLE |
There was a problem hiding this comment.
warning: do not use C-style cast to convert between unrelated types [cppcoreguidelines-pro-type-cstyle-cast]
CPPINTEROP_API_TABLE
^Additional context
include/CppInterOp/Dispatch.h:48: expanded from macro 'CPPINTEROP_API_TABLE'
DISPATCH_API(CreateInterpreter, decltype(&CppImpl::CreateInterpreter)) \
^lib/CppInterOp/Dispatch.cpp:7: expanded from macro 'DISPATCH_API'
#define DISPATCH_API(name, type) {#name, (CppFnPtrTy) static_cast<type>(&CppImpl::name)},
^| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; | ||
| std::vector<Cpp::TemplateArgInfo> args2 = { | ||
| Cpp::GetVariableType(Cpp::GetNamed("a")), C.IntTy.getAsOpaquePtr()}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), C.IntTy.getAsOpaquePtr()}; |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), C.IntTy.getAsOpaquePtr()}; | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr)), C.IntTy.getAsOpaquePtr()}; |
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), C.IntTy.getAsOpaquePtr()}; | ||
| std::vector<Cpp::TemplateArgInfo> args3 = { | ||
| Cpp::GetVariableType(Cpp::GetNamed("a")), C.DoubleTy.getAsOpaquePtr()}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), C.DoubleTy.getAsOpaquePtr()}; |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), C.DoubleTy.getAsOpaquePtr()}; | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr)), C.DoubleTy.getAsOpaquePtr()}; |
| Cpp::GetOperator( | ||
| Cpp::GetScopeFromType(Cpp::GetVariableType(Cpp::GetNamed("a"))), | ||
| Cpp::Operator::OP_Minus, candidates); | ||
| Cpp::GetScopeFromType(Cpp::GetVariableType(Cpp::GetNamed("a", 0))), |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetScopeFromType(Cpp::GetVariableType(Cpp::GetNamed("a", 0))), | |
| Cpp::GetScopeFromType(Cpp::GetVariableType(Cpp::GetNamed("a", nullptr))), |
|
|
||
| std::vector<Cpp::TemplateArgInfo> args4 = { | ||
| Cpp::GetVariableType(Cpp::GetNamed("a"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr))}; |
| std::vector<Cpp::TemplateArgInfo> args2 = {C.IntTy.getAsOpaquePtr()}; | ||
| std::vector<Cpp::TemplateArgInfo> args3 = { | ||
| Cpp::GetVariableType(Cpp::GetNamed("a"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr))}; |
| std::vector<Cpp::TemplateArgInfo> args4 = { | ||
| Cpp::GetVariableType(Cpp::GetNamed("a")), | ||
| Cpp::GetVariableType(Cpp::GetNamed("b"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr)), |
| Cpp::GetVariableType(Cpp::GetNamed("a")), | ||
| Cpp::GetVariableType(Cpp::GetNamed("b"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), | ||
| Cpp::GetVariableType(Cpp::GetNamed("b", 0))}; |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("b", 0))}; | |
| Cpp::GetVariableType(Cpp::GetNamed("b", nullptr))}; |
| std::vector<Cpp::TemplateArgInfo> args5 = { | ||
| Cpp::GetVariableType(Cpp::GetNamed("a")), | ||
| Cpp::GetVariableType(Cpp::GetNamed("a"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr)), |
|
Not sure how dynamic loading works on emscripten but the following error indicates something wrong with that step for the dispatch test executable: |
| static const std::unordered_map<std::string_view, CppFnPtrTy> | ||
| DispatchMap = { | ||
| #define DISPATCH_API(name, type) {#name, (CppFnPtrTy) static_cast<type>(&CppImpl::name)}, | ||
| CPPINTEROP_API_TABLE |
There was a problem hiding this comment.
warning: do not use C-style cast to convert between unrelated types [cppcoreguidelines-pro-type-cstyle-cast]
CPPINTEROP_API_TABLE
^Additional context
include/CppInterOp/Dispatch.h:48: expanded from macro 'CPPINTEROP_API_TABLE'
DISPATCH_API(CreateInterpreter, decltype(&CppImpl::CreateInterpreter)) \
^lib/CppInterOp/Dispatch.cpp:8: expanded from macro 'DISPATCH_API'
#define DISPATCH_API(name, type) {#name, (CppFnPtrTy) static_cast<type>(&CppImpl::name)},
^| Cpp::GetVariableType(Cpp::GetNamed("a")), | ||
| Cpp::GetVariableType(Cpp::GetNamed("a"))}; | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0)), | ||
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::GetVariableType(Cpp::GetNamed("a", 0))}; | |
| Cpp::GetVariableType(Cpp::GetNamed("a", nullptr))}; |
| auto S = clang_getDefaultConstructor(make_scope(Decls[0], I)); | ||
| void* object_c = nullptr; | ||
| clang_invoke(S, &object_c, nullptr, 0, nullptr); | ||
| clang_invoke(S, &object_c, nullptr, 0, 0); |
There was a problem hiding this comment.
warning: multilevel pointer conversion from 'void **' to 'void *', please use explicit cast [bugprone-multi-level-implicit-pointer-conversion]
clang_invoke(S, &object_c, nullptr, 0, 0);
^| auto S = clang_getDefaultConstructor(make_scope(Decls[0], I)); | ||
| void* object_c = nullptr; | ||
| clang_invoke(S, &object_c, nullptr, 0, nullptr); | ||
| clang_invoke(S, &object_c, nullptr, 0, 0); |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| clang_invoke(S, &object_c, nullptr, 0, 0); | |
| clang_invoke(S, &object_c, nullptr, 0, nullptr); |
| EXPECT_TRUE(FCI1.getKind() == Cpp::JitCall::kGenericCall); | ||
| Cpp::JitCall FCI2 = | ||
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f2")); | ||
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f2", 0)); |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f2", 0)); | |
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f2", nullptr)); |
| EXPECT_TRUE(FCI2.getKind() == Cpp::JitCall::kGenericCall); | ||
| Cpp::JitCall FCI3 = | ||
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f3", Cpp::GetNamed("NS"))); | ||
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f3", Cpp::GetNamed("NS", 0))); |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f3", Cpp::GetNamed("NS", 0))); | |
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f3", Cpp::GetNamed("NS", nullptr))); |
| EXPECT_TRUE(FCI3.getKind() == Cpp::JitCall::kGenericCall); | ||
| Cpp::JitCall FCI4 = | ||
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f4", Cpp::GetNamed("NS"))); | ||
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f4", Cpp::GetNamed("NS", 0))); |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f4", Cpp::GetNamed("NS", 0))); | |
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f4", Cpp::GetNamed("NS", nullptr))); |
|
|
||
| Cpp::JitCall FCI5 = | ||
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f5", Cpp::GetNamed("NS"))); | ||
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f5", Cpp::GetNamed("NS", 0))); |
There was a problem hiding this comment.
warning: use nullptr [modernize-use-nullptr]
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f5", Cpp::GetNamed("NS", 0))); | |
| Cpp::MakeFunctionCallable(Cpp::GetNamed("f5", Cpp::GetNamed("NS", nullptr))); |
| )"); | ||
|
|
||
| clang::NamedDecl *ClassC = (clang::NamedDecl*)Cpp::GetNamed("C"); | ||
| clang::NamedDecl *ClassC = (clang::NamedDecl*)Cpp::GetNamed("C", 0); |
There was a problem hiding this comment.
warning: do not use C-style cast to convert between unrelated types [cppcoreguidelines-pro-type-cstyle-cast]
clang::NamedDecl *ClassC = (clang::NamedDecl*)Cpp::GetNamed("C", 0);
^| )"); | ||
|
|
||
| clang::NamedDecl *ClassC = (clang::NamedDecl*)Cpp::GetNamed("C"); | ||
| clang::NamedDecl *ClassC = (clang::NamedDecl*)Cpp::GetNamed("C", 0); |
There was a problem hiding this comment.
warning: no header providing "clang::NamedDecl" is directly included [misc-include-cleaner]
clang::NamedDecl *ClassC = (clang::NamedDecl*)Cpp::GetNamed("C", 0);
^|
This PR is closed in favour of a fresh one, since the history is bloated, and the page metadata is too large for github to load on the browser consistently. We should also see cleaner clang-tidy reports |
This PR defines the mechanism which enables dispatching CppInterOp's API without linking to it, preventing any LLVM or Clang symbols from being leaked into the client application.
This allows us to run cppyy without linking to CppInterOp motivated by the use case in ROOT. Can be used to deploy CppInterOp in an environment where dynamic linking is not favourable and the only option is dlopen'ing
libClangCppInterOp.sowithRTLD_LOCAL