From af300055a7646eb08de5b32d1755538031e4a518 Mon Sep 17 00:00:00 2001 From: youben11 Date: Tue, 12 Apr 2022 12:17:42 +0100 Subject: [PATCH] fix(macos): update dependency after compiling dylib when dellocate is used to include dependencies in python wheels, the runtime library will have an id that is prefixed with /DLC, and that path doesn't exist. So when generated libraries won't be able to find it during load time. To solve this, we change the dep in the generated library to be relative to the rpath which should be set correctly during linking. This shouldn't have an impact when /DLC/concrete/.dylibs/* isn't a dependecy in the first place (when not using python). also set rpath when linking to RT lib --- .../concretelang/Support/LLVMEmitFile.h | 2 + compiler/lib/Support/CompilerEngine.cpp | 53 +++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/compiler/include/concretelang/Support/LLVMEmitFile.h b/compiler/include/concretelang/Support/LLVMEmitFile.h index 9701b4e91..506ef89b5 100644 --- a/compiler/include/concretelang/Support/LLVMEmitFile.h +++ b/compiler/include/concretelang/Support/LLVMEmitFile.h @@ -11,6 +11,8 @@ namespace concretelang { llvm::Error emitObject(llvm::Module &module, std::string objectPath); +llvm::Error callCmd(std::string cmd); + llvm::Error emitLibrary(std::vector objectsPath, std::string libraryPath, std::string linker, diff --git a/compiler/lib/Support/CompilerEngine.cpp b/compiler/lib/Support/CompilerEngine.cpp index cbdd91085..11e521e18 100644 --- a/compiler/lib/Support/CompilerEngine.cpp +++ b/compiler/lib/Support/CompilerEngine.cpp @@ -624,13 +624,39 @@ llvm::Expected CompilerEngine::Library::emit( llvm::Expected CompilerEngine::Library::emitShared() { std::vector extraArgs; + std::string fullRuntimeLibraryName = ""; +#ifdef __APPLE__ + // to issue the command for fixing the runtime dependency of the generated lib + bool fixRuntimeDep = false; +#endif if (!runtimeLibraryPath.empty()) { - extraArgs.push_back(runtimeLibraryPath); -#ifndef __APPLE__ // LINUX // Getting the parent dir should work on Linux and Mac std::size_t rpathLastPos = runtimeLibraryPath.find_last_of("/"); + std::string rpath = ""; + std::string runtimeLibraryName = ""; if (rpathLastPos != std::string::npos) { - std::string rpath = runtimeLibraryPath.substr(0, rpathLastPos); + rpath = runtimeLibraryPath.substr(0, rpathLastPos); + fullRuntimeLibraryName = runtimeLibraryPath.substr( + rpathLastPos + 1, runtimeLibraryPath.length()); + // runtimeLibraryName is part of fullRuntimeLibraryName = + // lib(runtimeLibraryName).dylib + runtimeLibraryName = + removeDotExt(fullRuntimeLibraryName, DOT_SHARED_LIB_EXT); + if (runtimeLibraryName.rfind("lib", 0) == 0) { // starts with lib + runtimeLibraryName = + runtimeLibraryName.substr(3, runtimeLibraryName.length()); + } + } +#ifdef __APPLE__ + if (!rpath.empty() && !runtimeLibraryName.empty()) { + fixRuntimeDep = true; + extraArgs.push_back("-l" + runtimeLibraryName); + extraArgs.push_back("-L" + rpath); + extraArgs.push_back("-rpath " + rpath); + } +#else // Linux + extraArgs.push_back(runtimeLibraryPath); + if (!rpath.empty()) { extraArgs.push_back("-rpath=" + rpath); // Use RPATH instead of RUNPATH for transitive dependencies extraArgs.push_back("--disable-new-dtags"); @@ -640,7 +666,28 @@ llvm::Expected CompilerEngine::Library::emitShared() { auto path = emit(DOT_SHARED_LIB_EXT, LINKER + LINKER_SHARED_OPT, extraArgs); if (path) { sharedLibraryPath = path.get(); +#ifdef __APPLE__ + // when dellocate is used to include dependencies in python wheels, the + // runtime library will have an id that is prefixed with /DLC, and that path + // doesn't exist. So when generated libraries won't be able to find it + // during load time. To solve this, we change the dep in the generated + // library to be relative to the rpath which should be set correctly during + // linking. This shouldn't have an impact when /DLC/concrete/.dylibs/* isn't + // a dependecy in the first place (when not using python). + if (fixRuntimeDep) { + std::string fixRuntimeDepCmd = "install_name_tool -change " + "/DLC/concrete/.dylibs/" + + fullRuntimeLibraryName + " @rpath/" + + fullRuntimeLibraryName + " " + + sharedLibraryPath; + auto error = mlir::concretelang::callCmd(fixRuntimeDepCmd); + if (error) { + return std::move(error); + } + } +#endif } + return path; }