-
Notifications
You must be signed in to change notification settings - Fork 11.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: [cmake] Export CLANG_RESOURCE_DIR in ClangConfig #97197
Conversation
@llvm/pr-subscribers-clang Author: Kim Gräsman (kimgr) ChangesI recently opened #95747 to see if it would be advisable to expose Here's a patch to do the most naive thing I could think of, hopefully enough to trigger discussion. Open questions/concerns:
Full diff: https://github.com/llvm/llvm-project/pull/97197.diff 2 Files Affected:
diff --git a/clang/cmake/modules/CMakeLists.txt b/clang/cmake/modules/CMakeLists.txt
index d2d68121371bf..4b0a38bd0fc1e 100644
--- a/clang/cmake/modules/CMakeLists.txt
+++ b/clang/cmake/modules/CMakeLists.txt
@@ -2,6 +2,7 @@ include(GNUInstallPackageDir)
include(ExtendPath)
include(LLVMDistributionSupport)
include(FindPrefixFromConfig)
+include(GetClangResourceDir)
# Generate a list of CMake library targets so that other CMake projects can
# link against them. LLVM calls its version of this file LLVMExports.cmake, but
@@ -29,6 +30,10 @@ set(CLANG_CONFIG_INCLUDE_DIRS
"${CLANG_SOURCE_DIR}/include"
"${CLANG_BINARY_DIR}/include"
)
+
+get_clang_resource_dir(resource_builddir PREFIX ${CLANG_BINARY_DIR})
+set(CLANG_CONFIG_RESOURCE_DIR ${resource_builddir})
+
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/ClangConfig.cmake.in
${clang_cmake_builddir}/ClangConfig.cmake
@@ -60,6 +65,10 @@ extend_path(base_includedir "\${CLANG_INSTALL_PREFIX}" "${CMAKE_INSTALL_INCLUDED
set(CLANG_CONFIG_INCLUDE_DIRS
"${base_includedir}"
)
+
+get_clang_resource_dir(resource_installdir PREFIX ${CLANG_INSTALL_PREFIX})
+set(CLANG_CONFIG_RESOURCE_DIR "${resource_installdir}")
+
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/ClangConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/ClangConfig.cmake
diff --git a/clang/cmake/modules/ClangConfig.cmake.in b/clang/cmake/modules/ClangConfig.cmake.in
index 5f67681649c66..1b97e103c93ca 100644
--- a/clang/cmake/modules/ClangConfig.cmake.in
+++ b/clang/cmake/modules/ClangConfig.cmake.in
@@ -10,6 +10,7 @@ set(CLANG_EXPORTED_TARGETS "@CLANG_EXPORTS@")
set(CLANG_CMAKE_DIR "@CLANG_CONFIG_CMAKE_DIR@")
set(CLANG_INCLUDE_DIRS "@CLANG_CONFIG_INCLUDE_DIRS@")
set(CLANG_LINK_CLANG_DYLIB "@CLANG_LINK_CLANG_DYLIB@")
+set(CLANG_RESOURCE_DIR "@CLANG_CONFIG_RESOURCE_DIR@")
# Provide all our library targets to users.
@CLANG_CONFIG_INCLUDE_EXPORTS@
|
cc @llvm-beanz -- you seem to have done a fair bit with the LLVM CMake system. |
Is there a reason you need to collect those files for your build tree instead of using them from where Clang built/installed them? |
I think at the time we started doing this, Clang's builtin includes lookup basically did We support three build modes:
In the first case, depending on the For the latter two we synthesize a |
/// Takes the path to a binary that's either in bin/ or lib/ and returns
/// the path to clang's resource directory.
static std::string GetResourcesPath(StringRef BinaryPath,
StringRef CustomResourceDir = "");
With the function above the first two use cases should work fine if you just point at the clang installation. For the third case... Posting at where you grab clang from will work, but you can't install from that configuration. That's probably fine for development workflows but won't work if you're using it in your package distribution workflows. I'm not sure we should support that build configuration generally anyways. We have supported it because the Swift build system does unholy and awful things, but it's all a pile of hacks and it has lots of edge cases where it breaks. |
So, Swift actually has/had a similar issue. We embed a copy of clang in Swift, so we needed to find the corresponding clang resource headers and install them with our compiler which is why I wrote #88317 to expose them. It adds the clang-resource-headers as an interface library to the ClangConfig.cmake that gets loaded when you do # Find 'ClangConfig.cmake' and import its targets
find_package(Clang CONFIG REQUIRED)
# Pass the location as a header-search path to "SomeLibrary"
target_link_libraries(SomeLibrary PRIVATE clang-resource-headers)
# Alternatively, if you just want the location, it's available as a target-property:
get_target_property(CLANG_IMPORT_HEADERS clang-resource-headers INTERFACE_INCLUDE_DIRECTORIES) To install the |
@llvm-beanz Thanks! Yes, copying the headers does seem like a hack, in retrospect. I think I started down that path because I don't know how packaging works -- I had assumed I might have to bundle the headers with IWYU, but I guess the right procedure is to build against an installed Clang, wire the paths for that installation, and express a dependency in the resulting package? So is the recommendation to:
? @etcwilde Cool, that might be helpful! I don't need it on the include path, I need to somehow forward it into my tool so it will be able to find <stddef.h> and friends at runtime. Your last example appears to get the path in a form where that's possible, thanks! |
@kimgr you should be able to have CMake query the path of libclang and go from there. Something like: get_target_property(SHARED_LIB_DIR libclang RUNTIME_OUTPUT_DIRECTORY) That should give you the binary location of libclang, which should work for resolving the final path. |
@llvm-beanz Thanks for the pointers! Here's what I ended up with as a first step: I couldn't get the The |
Ah, in that mode I guess we could use the default behavior, and not override the resource dir. |
I don't think an implementation based on Here is an example on how this function is used in Clang: |
I think that the |
The path is already available through the exported |
I think that one has the full path to the compiler-supplied built-in headers, not the resource dir (which is basically its parent). We could do some path mangling, but that's what burned us in the first place. |
@tstellar @tuliom It seems to me almost all callers pass the one exception being:
I wonder if that last one is a bug...? If so, it seems it would be better to just fold |
Agreed.
Or making |
Binding that default value in Driver.h would leave it to external projects (using Clang) to resolve Also, looking at the use of It was originally added to the LLVM CMake in ffae4a6 and used in the subsequent 06067c5. I'm curious about these 'strange packaging environments" :) |
@kimgr Good points. I agree with you. |
@etcwilde's point above is that the get_target_property(CLANG_IMPORT_HEADERS clang-resource-headers INTERFACE_INCLUDE_DIRECTORIES) That should make this change unnecessary even in the case where you need the resource directory in CMake. |
I don't think so. As far as I can tell:
So I'm thinking even if the |
I don't see why you need a separate variable. We can't really help you with whatever is wrong with Debian's packages unless it is a bug caused by our build configurations. The change you're proposing in this PR could just as easily be impacted in some distro's packages. |
@llvm-beanz Thanks for clarifying! Yeah, I no longer think this PR has anything to offer. If you think it's future-proof to assume the interface include dir of clang-resource-headers is one level down from the resource dir, that works to polish and seed it into a hardwired |
The exported target is new and hasn't been in a release yet. It should be in LLVM-19 once it's released and Debian gets updated. Of course, this is also true of any other new thing that gets added now anyway. I am a little confused about what your goal is with the path manipulations though. The part of IWYU that is linked above is looking for the |
👍
Aren't we all 🙂? I think what I'm trying to achieve is a portable way to refer to or install the built-in headers to avoid spurious "<stddef.h> not found" errors. My current take is we can defer to clang packaging to put the headers on disk, and make them available to IWYU with a package dependency + some kind of header search path. I don't think we need anything else from the resource dir. |
#103388 was merged, I think I know how to work this now. Thanks everyone for helping! |
I recently opened #95747 to see if it would be advisable to expose
CLANG_RESOURCE_DIR
fromClangConfig.cmake
.Here's a patch to do the most naive thing I could think of, hopefully enough to trigger discussion.
Open questions/concerns:
ClangConfig.cmake
now definesCLANG_RESOURCE_DIR
-- will that interfere with the CMake system'sCLANG_RESOURCE_DIR
(which is e.g. baked into config.h)ClangConfig.cmake
isn't 100% clear to me, I guessed a little as to reasonable prefix paths