Skip to content

Commit

Permalink
Use Clang builtin headers in-place
Browse files Browse the repository at this point in the history
We would copy the Clang builtin headers by replicating one of Clang's
targets (clang-resource-headers), poorly.

Instead, build a -resource-dir argument implicitly on IWYU startup to
point directly to the Clang headers.

The path to the headers are computed by the Clang Driver, based on the
Clang binary path, resolved by CMake.

The recipe for getting the Clang binary path varies a bit between build
modes:

* In standalone mode, we can get it using get_property(... LOCATION)
* In external-project mode, we can get it using <$TARGET_FILE>

In external-project mode, the binary path points inside the build tree,
so make sure we depend on the clang-resource-headers target there, so
the headers are copied into the build tree before IWYU is built.
  • Loading branch information
kimgr committed Jul 15, 2024
1 parent 5208611 commit b03f60a
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 31 deletions.
47 changes: 16 additions & 31 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,26 @@ if (iwyu_standalone_build)
${LLVM_INCLUDE_DIRS}
${CLANG_INCLUDE_DIRS}
)

# Get the clang target full output path (standalone)
get_property(iwyu_clang_binary_path TARGET clang PROPERTY LOCATION)
else()
set(iwyu_llvm_dir ${CMAKE_SOURCE_DIR})
set(iwyu_include_dirs
${LLVM_SOURCE_DIR}/include
${LLVM_EXTERNAL_CLANG_SOURCE_DIR}/include
${LLVM_BINARY_DIR}/include
${LLVM_BINARY_DIR}/tools/clang/include
)
)
# Get the clang target full output path (part of LLVM tree)
set(iwyu_clang_binary_path "$<TARGET_FILE:clang>")
endif()

message(STATUS
"IWYU: configuring for LLVM ${LLVM_VERSION} from ${iwyu_llvm_dir}")

message(STATUS "IWYU: clang is in: ${iwyu_clang_binary_path}")

# The good default is given by the llvm toolchain installation itself, but still
# in case both static and shared libraries are available, allow to override that
# default.
Expand All @@ -51,33 +58,6 @@ option(IWYU_LINK_CLANG_DYLIB

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# Synthesize clang-resource-headers target if necessary.
if (NOT TARGET clang-resource-headers)
# Use only LLVM_VERSION_MAJOR for the resource directory structure; some
# platforms include suffix in LLVM_VERSION.
set(clang_headers_src "${LLVM_LIBRARY_DIR}/clang/${LLVM_VERSION_MAJOR}/include")
set(clang_headers_dst "${CMAKE_BINARY_DIR}/lib/clang/${LLVM_VERSION_MAJOR}/include")

file(GLOB_RECURSE in_files RELATIVE "${clang_headers_src}"
"${clang_headers_src}/*"
)

set(out_files)
foreach (file ${in_files})
set(src "${clang_headers_src}/${file}")
set(dst "${clang_headers_dst}/${file}")

add_custom_command(OUTPUT "${dst}"
DEPENDS "${src}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${src}" "${dst}"
COMMENT "Copying ${src}..."
)
list(APPEND out_files "${dst}")
endforeach()

add_custom_target(clang-resource-headers ALL DEPENDS ${out_files})
endif()

# Pick up Git revision so we can report it in version information.
include(FindGit)
if (GIT_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
Expand Down Expand Up @@ -116,9 +96,13 @@ add_llvm_executable(include-what-you-use
iwyu_verrs.cc
)

# Add a dependency on clang-resource-headers to ensure the builtin headers are
# available when IWYU is executed from the build dir.
add_dependencies(include-what-you-use clang-resource-headers)

# When building as part of LLVM, add a dependency on clang-resource-headers to
# ensure the builtin headers are available when IWYU is executed from the build
# dir.
if (NOT iwyu_standalone_build)
add_dependencies(include-what-you-use clang-resource-headers)
endif()

# LLVM requires C++17, so follow suit.
set_target_properties(include-what-you-use PROPERTIES
Expand All @@ -132,6 +116,7 @@ separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
target_compile_definitions(include-what-you-use PRIVATE
${LLVM_DEFINITIONS_LIST}
IWYU_GIT_REV="${iwyu_git_rev}"
IWYU_CLANG_BINARY_PATH="${iwyu_clang_binary_path}"
)
target_include_directories(include-what-you-use PRIVATE
${iwyu_include_dirs}
Expand Down
8 changes: 8 additions & 0 deletions iwyu_driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,14 @@ bool ExecuteAction(int argc, const char** argv,
args.push_back("-Qunused-arguments");
}

// Use the full Clang binary path provided by CMake to compute Clang's
// resource dir, which is the base for the compiler built-in headers (stddef.h
// and friends). Add an explicit -resource-dir argument to tell IWYU to look
// there, instead of computing its own.
std::string resource_dir = Driver::GetResourcesPath(IWYU_CLANG_BINARY_PATH);
args.push_back("-resource-dir");
args.push_back(resource_dir.c_str());

// Build a compilation, get the job list and filter out irrelevant jobs.
unique_ptr<Compilation> compilation(driver.BuildCompilation(args));
if (!compilation)
Expand Down

0 comments on commit b03f60a

Please sign in to comment.