> 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
> 
> 

Reply via email to