Skip to content

Commit

Permalink
Use the dyld logic if we don't have library dependency information av…
Browse files Browse the repository at this point in the history
…ailable.

In cases where ACLiC builds a library without a rootmap file or a modulemap file
we have no reasonable way to detect what are the library dependencies.
Occasionally when loading a shared object the dynamic linker will tell us if
something is missing (via dlerror) but only on the intialization path.

This patch fixes ROOT-10637.
  • Loading branch information
vgvassilev committed Mar 28, 2020
1 parent 3572435 commit fd9cca9
Showing 1 changed file with 40 additions and 0 deletions.
40 changes: 40 additions & 0 deletions core/metacling/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3050,6 +3050,12 @@ Bool_t TCling::HasPCMForLibrary(const char *libname) const
ModuleName = llvm::sys::path::stem(ModuleName);
ModuleName.consume_front("lib");

// FIXME: In case when the modulemap is not yet loaded we will return the
// wrong result. Consider a call to HasPCMForLibrary(../test/libEvent.so)
// We will only load the modulemap for libEvent.so after we dlopen libEvent
// which may happen after calling this interface. Maybe we should also check
// if there is a Event.pcm file and a module.modulemap, load it and return
// true.
clang::ModuleMap &moduleMap = fInterpreter->getCI()->getPreprocessor().getHeaderSearchInfo().getModuleMap();
clang::Module *M = moduleMap.findModule(ModuleName);
return M && !M->IsMissingRequirement && M->getASTFile();
Expand Down Expand Up @@ -7176,6 +7182,31 @@ static std::string GetSharedLibImmediateDepsSlow(std::string lib,
}


static bool hasPrecomputedLibraryDeps(llvm::StringRef lib) {
// FIXME: Provide more robust discovery of rootmap files when `lib` is not
// with its full path.
if (gCling->HasPCMForLibrary(lib.data()))
return true;

// Check if we have parsed a rootmap file.
llvm::SmallString<256> rootmapName;
if (!lib.startswith("lib"))
rootmapName.append("lib");

rootmapName.append(llvm::sys::path::filename(lib));
llvm::sys::path::replace_extension(rootmapName, "rootmap");

if (gCling->GetRootMapFiles()->FindObject(rootmapName.c_str()))
return true;

// Perform a last resort by dropping the lib prefix.
llvm::StringRef rootmapNameNoLib = rootmapName.str();
if (rootmapNameNoLib.consume_front("lib"))
return gCling->GetRootMapFiles()->FindObject(rootmapNameNoLib.data());

return false;
}

////////////////////////////////////////////////////////////////////////////////
/// Get the list a libraries on which the specified lib depends. The
/// returned string contains as first element the lib itself.
Expand All @@ -7186,6 +7217,15 @@ static std::string GetSharedLibImmediateDepsSlow(std::string lib,

const char* TCling::GetSharedLibDeps(const char* lib, bool useDyld/* = false*/)
{
if (!useDyld && !hasPrecomputedLibraryDeps(lib)) {
// FIXME: As a future performance optimization see HasPCMForLibrary's FIXME.
useDyld = true;
if (gDebug > 2)
Warning("TCling::GetSharedLibDeps",
"Trying to load %s but its dependencies are unresolved.",
lib);
}

if (useDyld) {
std::string libs = GetSharedLibImmediateDepsSlow(lib, GetInterpreterImpl());
if (!libs.empty()) {
Expand Down

0 comments on commit fd9cca9

Please sign in to comment.