Skip to content

clc: retrieve libclang path at runtime.

What does this MR?

While cross compiling, libclang path is retrieved at runtime using libdl.

Why?

I wanted to use rusticl in an embedded context (on a Khadas Vim3 card). When using clpeak the following error message appeared:

“Build Log: <built-in>:1:10: fatal error: 'opencl-c-base.h' file not found”.

This file is required during a rusticl runtime compilation. In clc_helpers.cpp.

However, the header is not found because its path is wrong. Indeed, when compiling mesa, the variable DLLVM_LIB_DIR is incorrectly defined. This variable is used at runtime to retrive the headers using the following steps:

auto libclang_path = fs::path(LLVM_LIB_DIR) / "libclang.so";
auto clang_res_path = fs::path(clang::driver::Driver::GetResourcesPath(libclang_path.string(), CLANG_RESOURCE_DIR)) / "include";
c->getHeaderSearchOpts().ResourceDir = clang_res_path.string();
#if LLVM_VERSION_MAJOR >= 15
   c->getPreprocessorOpts().Includes.push_back("opencl-c-base.h");
#else
   c->getPreprocessorOpts().Includes.push_back("opencl-c.h");
#endif

clang::driver::Driver::GetResourcesPath() is a function that retrive the libclang resource dir based on a given binary or library. It works by following these steps:

  • Retrieve the parent file of the libclang library.
  • Adds CLANG_RESOURCE_DIR to the path if the variable is non-zero. (This variable allow you to modify the path relative to the library path, it is therefore zero by default.)
  • Calculate the parent directory.
  • Add lib<CLANG_LIBDIR_SUFFIX>.
  • Add “clang”.
  • Add Clang version.
// static
std::string Driver::GetResourcesPath(StringRef BinaryPath,
                                    StringRef CustomResourceDir) {
 // Since the resource directory is embedded in the module hash, it's important
 // that all places that need it call this function, so that they get the
 // exact same string ("a/../b/" and "b/" get different hashes, for example).


 // Dir is bin/ or lib/, depending on where BinaryPath is.
 std::string Dir = std::string(llvm::sys::path::parent_path(BinaryPath));


 SmallString<128> P(Dir);
 if (CustomResourceDir != "") {
   llvm::sys::path::append(P, CustomResourceDir);
 } else {
   // On Windows, libclang.dll is in bin/.
   // On non-Windows, libclang.so/.dylib is in lib/.
   // With a static-library build of libclang, LibClangPath will contain the
   // path of the embedding binary, which for LLVM binaries will be in bin/.
   // ../lib gets us to lib/ in both cases.
   P = llvm::sys::path::parent_path(Dir);
   llvm::sys::path::append(P, Twine("lib") + CLANG_LIBDIR_SUFFIX, "clang",
                           CLANG_VERSION_STRING);
 }

 return std::string(P.str());
}

The opencl-c-base path is therefore calculated relative to the LLVM_LIB_DIR variable which is an host absolute path. This variable is defined by meson during mesa's compilation and is initialized to llvm_libdir:

src/compiler/clc/meson.build :

_libclc_cpp_args = ['-DLLVM_LIB_DIR="@0@"'.format(llvm_libdir)]

How does this MR fixes the issue?

llvm_libdir can't be modified because it is used when cross-compiling on the host machine by the meson.build at the root of mesa. Moreover, LLVM_LIB_DIR can't be set to an arbitrary path as we don't know the path of the libclang library on the target.

The solution is to retrieve the libclang path at runtime using libdl. This is done by using the dladdr function which returns information about a loaded library. The path to the libclang library can therefore be retrieved using one of its functions (e.g. clang::getClangFullVersion). The dlinfo function can't be used here as we don't know the name of the libclang library (libclang.so.X or libclang-cpp.so.X).

For the moment, only the UNIX version is implemented.

Commit message:

clc: retrieve libclang path at runtime.

LLVM_LIB_DIR is a variable used for runtime compilations.When cross compiling, LLVM_LIB_DIR must be set to thelibclang path on the target. So, this path should notbe retrieved during compilation but at runtime.

dladdr uses an address to search for a loaded library.If a library is found, it returns information about it.The path to the libclang library can therefore beretrieved using one of its functions. This is usefulbecause we don't know the name of the libclang library (libclang.so.X or libclang-cpp.so.X)

Fixes: e22491c8 ("clc: fetch clang resource dir at runtime")

Signed-off-by: Antoine Coutant antoine.coutant@smile.fr

Edited by Antoine Coutant

Merge request reports