From 5686e210cd4dc2e2da98bb2ecb794d302fa035aa Mon Sep 17 00:00:00 2001 From: Aaron Jomy Date: Tue, 18 Aug 2026 12:46:46 +0200 Subject: [PATCH] [interop] Resolve libclangCppInterOp relative to libcppjit at runtime --- CMakeLists.txt | 14 ++++++++------ src/interop/interop_wrapper.cxx | 29 +++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fc4d087..03eaeff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,10 +95,11 @@ execute_process( OUTPUT_STRIP_TRAILING_WHITESPACE ) if(_python_platlib) - set(CPPINTEROP_INSTALL_DIR "${_python_platlib}/cppjit_backend") + set(CPPINTEROP_INSTALL_PREFIX "${_python_platlib}") else() - set(CPPINTEROP_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/cppjit_backend") + set(CPPINTEROP_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") endif() +set(CPPINTEROP_INSTALL_DIR "${CPPINTEROP_INSTALL_PREFIX}/cppjit_backend") # Include cmake for CppInterOp config and build using ExternalProject. include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/AddCppInterOp.cmake) @@ -114,11 +115,12 @@ set(INTEROP_SOURCES add_library(cppjit SHARED ${CPYRT_SOURCES} ${INTEROP_SOURCES}) add_dependencies(cppjit CppInterOp) -# The exact library file the wrapper dlopens and the include dir the -# interpreter boot requires. +# The wrapper anchors these relative spellings at its own load location, +# falling back to the install prefix (see cppinterop_paths()). target_compile_definitions(cppjit PRIVATE - CPPINTEROP_LIBRARY="${CPPINTEROP_INSTALL_DIR}/lib/libclangCppInterOp${CMAKE_SHARED_LIBRARY_SUFFIX}" - CPPINTEROP_INCLUDE_DIR="${CPPINTEROP_INSTALL_DIR}/include" + CPPINTEROP_INSTALL_PREFIX="${CPPINTEROP_INSTALL_PREFIX}" + CPPINTEROP_LIBRARY="cppjit_backend/lib/libclangCppInterOp${CMAKE_SHARED_LIBRARY_SUFFIX}" + CPPINTEROP_INCLUDE_DIR="cppjit_backend/include" ) target_include_directories(cppjit PRIVATE diff --git a/src/interop/interop_wrapper.cxx b/src/interop/interop_wrapper.cxx index c55bc05..7d0cd26 100644 --- a/src/interop/interop_wrapper.cxx +++ b/src/interop/interop_wrapper.cxx @@ -23,6 +23,7 @@ using namespace cppjit; #include #include // for getenv #include +#include #include #include #include @@ -74,13 +75,37 @@ static inline bool is_integral(std::string& s) { }) == s.end(); } +struct InterOpPaths { + std::string Library; + std::string IncludeDir; +}; + +// One relative layout, two anchors: prefer CppInterOp next to our own load +// location so wheels relocate; fall back to the build-time install prefix. +static InterOpPaths cppinterop_paths() { + std::filesystem::path anchor = CPPINTEROP_INSTALL_PREFIX; +#ifndef _WIN32 + Dl_info info; + if (dladdr((void*)&cppinterop_paths, &info) && info.dli_fname) { + const std::filesystem::path here = + std::filesystem::path(info.dli_fname).parent_path(); + std::error_code ec; + if (std::filesystem::exists(here / CPPINTEROP_LIBRARY, ec)) + anchor = here; + } +#endif + return {(anchor / CPPINTEROP_LIBRARY).string(), + (anchor / CPPINTEROP_INCLUDE_DIR).string()}; +} + class ApplicationStarter { interop::TInterp_t Interp; public: ApplicationStarter() { std::lock_guard Lock(InterOpMutex); - if (!Cpp::LoadDispatchAPI(CPPINTEROP_LIBRARY)) { + const InterOpPaths Paths = cppinterop_paths(); + if (!Cpp::LoadDispatchAPI(Paths.Library.c_str())) { std::cerr << "[cppjit-backend] Failed to load CppInterOp" << std::endl; return; } @@ -123,7 +148,7 @@ class ApplicationStarter { Cpp::Process(s.str().c_str()); } - Cpp::AddIncludePath(CPPINTEROP_INCLUDE_DIR); + Cpp::AddIncludePath(Paths.IncludeDir.c_str()); Cpp::LoadLibrary("libstdc++", /* lookup= */ true); // load frequently used headers