[lldb] Symlink the Clang resource directory to the LLDB build directory in standalone...
authorRaphael Isemann <teemperor@gmail.com>
Tue, 6 Oct 2020 07:27:24 +0000 (09:27 +0200)
committerRaphael Isemann <teemperor@gmail.com>
Tue, 6 Oct 2020 07:28:39 +0000 (09:28 +0200)
When doing a standalone build (i.e., building just LLDB against an existing
LLVM/Clang installation), LLDB is currently unable to find any Clang resource
directory that contains all the builtin headers we need to parse real source
code. This causes several tests that actually parse source code on disk within
the expression parser to fail (most notably nearly all the import-std-module
tests).

The reason why LLDB can't find the resource directory is that we search based on
the path of the LLDB shared library path. We assumed that the Clang resource
directory is in the same prefix and has the same relative path to the LLDB
shared library (e.g., `../clang/10.0.0/include`). However for a standalone build
where the existing Clang can be anywhere on the disk, so we can't just rely on
the hardcoded relative paths to the LLDB shared library.

It seems we can either solve this by copying the resource directory to the LLDB
installation, symlinking it there or we pass the path to the Clang installation
to the code that is trying to find the resource directory. When building the
LLDB framework we currently copy the resource directory over to the framework
folder (this is why the import-std-module are not failing on the Green Dragon
standalone bot).

This patch symlinks the resource directory of Clang into the LLDB build
directory. The reason for that is simply that this is only needed when running
LLDB from the build directory. Once LLDB and Clang/LLVM are installed the
already existing logic can find the Clang resource directory by searching
relative to the LLDB shared library.

Reviewed By: kastiglione, JDevlieghere

Differential Revision: https://reviews.llvm.org/D88581

lldb/cmake/modules/LLDBConfig.cmake
lldb/cmake/modules/LLDBFramework.cmake
lldb/source/API/CMakeLists.txt

index af94e6e..5fbc898 100644 (file)
@@ -250,6 +250,30 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
   endif()
 endif()
 
+
+# If LLDB is building against a prebuilt Clang, then the Clang resource
+# directory that LLDB is using for its embedded Clang instance needs to point
+# to the resource directory of the used Clang installation.
+if (NOT TARGET clang-resource-headers)
+  set(LLDB_CLANG_RESOURCE_DIR_NAME "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}")
+  # Iterate over the possible places where the external resource directory
+  # could be and pick the first that exists.
+  foreach(CANDIDATE "${Clang_DIR}/../.." "${LLVM_DIR}" "${LLVM_LIBRARY_DIRS}"
+                    "${LLVM_BUILD_LIBRARY_DIR}"
+                    "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}")
+    # Build the resource directory path by appending 'clang/<version number>'.
+    set(CANDIDATE_RESOURCE_DIR "${CANDIDATE}/clang/${LLDB_CLANG_RESOURCE_DIR_NAME}")
+    if (IS_DIRECTORY "${CANDIDATE_RESOURCE_DIR}")
+      set(LLDB_EXTERNAL_CLANG_RESOURCE_DIR "${CANDIDATE_RESOURCE_DIR}")
+      break()
+    endif()
+  endforeach()
+
+  if (NOT LLDB_EXTERNAL_CLANG_RESOURCE_DIR)
+    message(FATAL_ERROR "Expected directory for clang-resource headers not found: ${LLDB_EXTERNAL_CLANG_RESOURCE_DIR}")
+  endif()
+endif()
+
 # Find Apple-specific libraries or frameworks that may be needed.
 if (APPLE)
   if(NOT APPLE_EMBEDDED)
index 43af71b..2fb059a 100644 (file)
@@ -110,20 +110,7 @@ if(NOT APPLE_EMBEDDED)
     add_dependencies(liblldb clang-resource-headers)
     set(clang_resource_headers_dir $<TARGET_PROPERTY:clang-resource-headers,RUNTIME_OUTPUT_DIRECTORY>)
   else()
-    # In standalone builds try the best possible guess
-    if(Clang_DIR)
-      set(clang_lib_dir ${Clang_DIR}/../..)
-    elseif(LLVM_DIR)
-      set(clang_lib_dir ${LLVM_DIR}/../..)
-    elseif(LLVM_LIBRARY_DIRS)
-      set(clang_lib_dir ${LLVM_LIBRARY_DIRS})
-    elseif(LLVM_BUILD_LIBRARY_DIR)
-      set(clang_lib_dir ${LLVM_BUILD_LIBRARY_DIR})
-    elseif(LLVM_BINARY_DIR)
-      set(clang_lib_dir ${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
-    endif()
-    set(clang_version ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH})
-    set(clang_resource_headers_dir ${clang_lib_dir}/clang/${clang_version}/include)
+    set(clang_resource_headers_dir ${LLDB_EXTERNAL_CLANG_RESOURCE_DIR}/include)
     if(NOT EXISTS ${clang_resource_headers_dir})
       message(WARNING "Expected directory for clang-resource headers not found: ${clang_resource_headers_dir}")
     endif()
index aeb1f15..a7d6592 100644 (file)
@@ -195,8 +195,27 @@ else()
   )
 endif()
 
-if (NOT LLDB_BUILT_STANDALONE)
+# The Clang expression parser in LLDB requires the Clang resource directory to function.
+if (TARGET clang-resource-headers)
+  # If building alongside Clang, just add a dependency to ensure it is build together with liblldb.
   add_dependencies(liblldb clang-resource-headers)
+else()
+  # In a standalone build create a symlink from the LLDB library directory that points to the
+  # resource directory in the Clang library directory. LLDB searches relative to its install path,
+  # and the symlink is created in the same relative path as the resource directory of Clang when
+  # building alongside Clang.
+  # When building the LLDB framework, this isn't necessary as there we copy everything we need into
+  # the framework (including the Clang resourece directory).
+  if(NOT LLDB_BUILD_FRAMEWORK)
+    set(LLDB_CLANG_RESOURCE_DIR_PARENT "$<TARGET_FILE_DIR:liblldb>/clang")
+    file(MAKE_DIRECTORY "${LLDB_CLANG_RESOURCE_DIR_PARENT}")
+    add_custom_command(TARGET liblldb POST_BUILD
+      COMMENT "Linking Clang resource dir into LLDB build directory: ${LLDB_CLANG_RESOURCE_DIR_PARENT}"
+      COMMAND ${CMAKE_COMMAND} -E make_directory "${LLDB_CLANG_RESOURCE_DIR_PARENT}"
+      COMMAND ${CMAKE_COMMAND} -E create_symlink "${LLDB_EXTERNAL_CLANG_RESOURCE_DIR}"
+              "${LLDB_CLANG_RESOURCE_DIR_PARENT}/${LLDB_CLANG_RESOURCE_DIR_NAME}"
+    )
+  endif()
 endif()
 
 if(LLDB_BUILD_FRAMEWORK)