> From: Greg Steuck <gne...@openbsd.org> > Date: Sun, 13 Feb 2022 22:37:13 -0800 > > To give a sense of the kind of change required to get the feature I > want, see the patch at the end. The change in DriverUtils.cpp is just to > show that the same function is hiding in there. > > If this looks like a good direction, I can cleanup the code and maybe it > could be shared, though I'm not sure where this would belong. Maybe a > new tiny library of such wrappers to maintain in our tree? > > Thanks > Greg > > P.S. Naturally, once I install this patched cc, ghci is suddenly very > happy.
Something like this was rejected upstream. The solution would be to add symlinks like all the other OSes do. But Theo doesn't like that. > Greg Steuck <gne...@openbsd.org> writes: > > > Since OpenBSD always uses .so.major.minor I observe GHCi running into > > trouble when resolving -l on its own. The way it tries to find the > > shared object to load is by relying on `cc --print-file-name`. I see > > this: > > $ ghci -v -lc++ > > ... > > Search directories (gcc): > > *** systool:linker: > > *** gcc: > > cc -Wl,-z,wxneeded --print-file-name 'libc++.so' > > !!! systool:linker: finished in 0.00 milliseconds, allocated 0.059 megabytes > > *** systool:linker: > > *** gcc: > > cc -Wl,-z,wxneeded --print-file-name 'liblibc++.so' > > !!! systool:linker: finished in 0.00 milliseconds, allocated 0.054 megabytes > > *** systool:linker: > > *** gcc: > > cc -Wl,-z,wxneeded --print-file-name 'c++.lib' > > > > Which never succeeds, because the only way this could work is if ghc > > knew the version number: > > % cc --print-file-name 'libc++.so.9.0' > > /usr/lib/libc++.so.9.0 > > > > It feels like I need to somehow convince cc --print-file-name to get in > > here: > > ports/devel/llvm/patches/patch-tools_lld_ELF_DriverUtils_cpp > > > > Would it be a good idea to extend clang's --print-file-name in such a > > way that both versioned and unversioned variations work? I.e. make the > > second command works the same as the first one below? > > > > % cc --print-file-name libc++.so.9.0 > > /usr/lib/libc++.so.9.0 > > % cc --print-file-name libc++.so > > libc++.so > > > > Thanks > > Greg > > >From 825207a1ec5b0f0941bf5a624a862c9f460ddf94 Mon Sep 17 00:00:00 2001 > From: Greg Steuck <g...@nest.cx> > Date: Sun, 13 Feb 2022 22:28:43 -0800 > Subject: [PATCH] Find --print-file-name versioned lib.so's for the given short > name > > This is a complement of the major.minor finding logic in DriverUtils. > To make things more obviously related the same code was extracted into > a function which was copied modulo namespaces and minor parameter > adjustments > --- > gnu/llvm/clang/lib/Driver/Driver.cpp | 54 ++++++++++++++++++++++++-- > gnu/llvm/lld/ELF/DriverUtils.cpp | 57 +++++++++++++++------------- > 2 files changed, 82 insertions(+), 29 deletions(-) > > diff --git a/gnu/llvm/clang/lib/Driver/Driver.cpp > b/gnu/llvm/clang/lib/Driver/Driver.cpp > index 94a7553e273..cdf95ac6c9f 100644 > --- a/gnu/llvm/clang/lib/Driver/Driver.cpp > +++ b/gnu/llvm/clang/lib/Driver/Driver.cpp > @@ -5089,7 +5089,50 @@ const char *Driver::GetNamedOutputPath(Compilation &C, > const JobAction &JA, > } > } > > + > +namespace { > +static Optional<std::string> findFile(StringRef path1, const Twine &path2) { > + SmallString<128> s; > + llvm::sys::path::append(s, path1, path2); > + > + if (llvm::sys::fs::exists(s)) > + return std::string(s); > + return None; > +} > + > +llvm::Optional<std::string> findMajMinShlib(StringRef dir, StringRef > libNameSo) { > + // Handle OpenBSD-style maj/min shlib scheme > + llvm::SmallString<128> Scratch; > + const StringRef LibName = (libNameSo + ".").toStringRef(Scratch); > + int MaxMaj = -1, MaxMin = -1; > + std::error_code EC; > + for (llvm::sys::fs::directory_iterator LI(dir, EC), LE; > + LI != LE; LI = LI.increment(EC)) { > + StringRef FilePath = LI->path(); > + StringRef FileName = llvm::sys::path::filename(FilePath); > + if (!(FileName.startswith(LibName))) > + continue; > + std::pair<StringRef, StringRef> MajMin = > + FileName.substr(LibName.size()).split('.'); > + int Maj, Min; > + if (MajMin.first.getAsInteger(10, Maj) || Maj < 0) > + continue; > + if (MajMin.second.getAsInteger(10, Min) || Min < 0) > + continue; > + if (Maj > MaxMaj) > + MaxMaj = Maj, MaxMin = Min; > + if (MaxMaj == Maj && Min > MaxMin) > + MaxMin = Min; > + } > + if (MaxMaj >= 0) > + return findFile(dir, LibName + Twine(MaxMaj) + "." + Twine(MaxMin)); > + return None; > +} > + > +} > + > std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const { > + const bool lookForLibDotSo = Name.startswith("lib") && > Name.endswith(".so"); > // Search for Name in a list of paths. > auto SearchPaths = [&](const llvm::SmallVectorImpl<std::string> &P) > -> llvm::Optional<std::string> { > @@ -5099,9 +5142,14 @@ std::string Driver::GetFilePath(StringRef Name, const > ToolChain &TC) const { > if (Dir.empty()) > continue; > SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir); > - llvm::sys::path::append(P, Name); > - if (llvm::sys::fs::exists(Twine(P))) > - return std::string(P); > + if (!lookForLibDotSo) { > + llvm::sys::path::append(P, Name); > + if (llvm::sys::fs::exists(Twine(P))) > + return std::string(P); > + } else { > + if (auto s = findMajMinShlib(P, Name)) > + return std::string(*s); > + } > } > return None; > }; > diff --git a/gnu/llvm/lld/ELF/DriverUtils.cpp > b/gnu/llvm/lld/ELF/DriverUtils.cpp > index 6b164e30677..2b88ed3d3b3 100644 > --- a/gnu/llvm/lld/ELF/DriverUtils.cpp > +++ b/gnu/llvm/lld/ELF/DriverUtils.cpp > @@ -230,6 +230,35 @@ Optional<std::string> elf::findFromSearchPaths(StringRef > path) { > return None; > } > > +Optional<std::string> findMajMinShlib(StringRef dir, StringRef name) { > + // Handle OpenBSD-style maj/min shlib scheme > + llvm::SmallString<128> Scratch; > + const StringRef LibName = ("lib" + name + ".so.").toStringRef(Scratch); > + int MaxMaj = -1, MaxMin = -1; > + std::error_code EC; > + for (fs::directory_iterator LI(dir, EC), LE; > + LI != LE; LI = LI.increment(EC)) { > + StringRef FilePath = LI->path(); > + StringRef FileName = path::filename(FilePath); > + if (!(FileName.startswith(LibName))) > + continue; > + std::pair<StringRef, StringRef> MajMin = > + FileName.substr(LibName.size()).split('.'); > + int Maj, Min; > + if (MajMin.first.getAsInteger(10, Maj) || Maj < 0) > + continue; > + if (MajMin.second.getAsInteger(10, Min) || Min < 0) > + continue; > + if (Maj > MaxMaj) > + MaxMaj = Maj, MaxMin = Min; > + if (MaxMaj == Maj && Min > MaxMin) > + MaxMin = Min; > + } > + if (MaxMaj >= 0) > + return findFile(dir, LibName + Twine(MaxMaj) + "." + Twine(MaxMin)); > + return None; > +} > + > // This is for -l<basename>. We'll look for lib<basename>.so or > lib<basename>.a from > // search paths. > Optional<std::string> elf::searchLibraryBaseName(StringRef name) { > @@ -237,32 +266,8 @@ Optional<std::string> > elf::searchLibraryBaseName(StringRef name) { > if (!config->isStatic) { > if (Optional<std::string> s = findFile(dir, "lib" + name + ".so")) > return s; > - > - // Handle OpenBSD-style maj/min shlib scheme > - llvm::SmallString<128> Scratch; > - const StringRef LibName = ("lib" + name + ".so.").toStringRef(Scratch); > - int MaxMaj = -1, MaxMin = -1; > - std::error_code EC; > - for (fs::directory_iterator LI(dir, EC), LE; > - LI != LE; LI = LI.increment(EC)) { > - StringRef FilePath = LI->path(); > - StringRef FileName = path::filename(FilePath); > - if (!(FileName.startswith(LibName))) > - continue; > - std::pair<StringRef, StringRef> MajMin = > - FileName.substr(LibName.size()).split('.'); > - int Maj, Min; > - if (MajMin.first.getAsInteger(10, Maj) || Maj < 0) > - continue; > - if (MajMin.second.getAsInteger(10, Min) || Min < 0) > - continue; > - if (Maj > MaxMaj) > - MaxMaj = Maj, MaxMin = Min; > - if (MaxMaj == Maj && Min > MaxMin) > - MaxMin = Min; > - } > - if (MaxMaj >= 0) > - return findFile(dir, LibName + Twine(MaxMaj) + "." + Twine(MaxMin)); > + if (Optional<std::string> s = findMajMinShlib(dir, name)) > + return s; > } > if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) > return s; > -- > 2.35.1 > >