libclang cannot find its resource dir on linux?

Hi,

I have a small test program that behaves differently on linux and mac:

     CXIndex idx = clang_createIndex(1, 1);
    struct CXUnsavedFile unsaved[1];
    unsaved[0].Filename = "tst.c";
    unsaved[0].Contents = "#include <xmmintrin.h>\n";
    unsaved[0].Length = strlen(unsaved[0].Contents);
    CXTranslationUnit tu = clang_parseTranslationUnit(idx, "tst.c", 0, 0, unsaved, 1, 0);

On macos, the translation unit is fine: when running clang_getInclusions on it, I get the full path of xmmintrin.h. However, on linux this fails with "tst.c:1:10: fatal error: 'xmmintrin.h' file not found". Running it on the command-line works fine though.

So, is this expected behaviour, or a bug?

-- Erik.

This is a known problem for external tools and is a huge pain. The underlying problem is that the resource dir is looked up relative to the current executable. This works fine for clang which is installed in the right place so that this works.

The exact path that it looks up relative to the executable can be found in CompilerInvocation::GetResourcesPath in lib/Frontend/CompilerInvocation.cpp <http://clang.llvm.org/doxygen/CompilerInvocation_8cpp_source.html#l00895>.

Here are 3 ways to work around this:

  1. Put your executable in the same place as the clang binary.
  2. Copy/symlink the resource dir to the same relative location from your executable as they are from the clang binary.
  3. Pass the argument -resource-dir /path/to/resource/dir. It is a clang -cc1 argument so you need to use the -Xclang prefix to pass it, i.e. -Xclang -resource-dir -Xclang /path/to/resource/dir.

– Sean Silva

This is a known problem for external tools and is a huge pain. The
underlying problem is that the resource dir is looked up relative to the
current executable. This works fine for clang which is installed in the
right place so that this works.

The exact path that it looks up relative to the executable can be found in
CompilerInvocation::GetResourcesPath in lib/Frontend/CompilerInvocation.cpp
<http://clang.llvm.org/doxygen/CompilerInvocation_8cpp_source.html#l00895>.

Here are 3 ways to work around this:

1. Put your executable in the same place as the clang binary.
2. Copy/symlink the resource dir to the same relative location from your
executable as they are from the clang binary.
3. Pass the argument `-resource-dir /path/to/resource/dir`. It is a `clang
-cc1` argument so you need to use the `-Xclang` prefix to pass it, i.e.
`-Xclang -resource-dir -Xclang /path/to/resource/dir`.

There is a fourth one, which I came up with as a good-enough workaround:

Ask clang for the include paths, i.e.:

clang -xc++ -E -v /dev/null

That gives you a list of built-in search paths, including in my case:
/usr/bin/../lib/clang/3.3/include

So you can parse the above command once, then pass these paths via -I to
clang.

The advantage I see here is that you don't have to know the resource dir in
advance, but can simply ask clang for it.

Well, the whole reason for that code snippet was to ask libclang for its resource path, so I can pass it around. Asking the clang executable means that linux users need to have that installed, while they might not use it at all.

And the reason for passing around the resource path, is because of problems with libstdc++4.8 that comes with the gcc toolchain, and its use of intrinsics. See my other post for that.

-- Erik.