Skip to content

Conversation

@chelcassanova
Copy link
Contributor

On some cross compile builds, the tool is not correctly set and the command that runs the tool has an empty path for the tool, causing the build to fail. We can setup the tool as a build host tool using setup_host_tool.

@llvmbot
Copy link
Member

llvmbot commented Jul 31, 2025

@llvm/pr-subscribers-lldb

Author: Chelsea Cassanova (chelcassanova)

Changes

On some cross compile builds, the tool is not correctly set and the command that runs the tool has an empty path for the tool, causing the build to fail. We can setup the tool as a build host tool using setup_host_tool.


Full diff: https://github.com/llvm/llvm-project/pull/151603.diff

2 Files Affected:

  • (modified) lldb/cmake/modules/LLDBConfig.cmake (+8-16)
  • (modified) lldb/tools/lldb-rpc-gen/CMakeLists.txt (+7-2)
diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake
index fc84e581cc188..88b4eca4112ce 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -326,27 +326,19 @@ endif()
 # In a cross-compile build, we need to skip building the generated
 # lldb-rpc sources in the first phase of host build so that they can
 # get built using the just-built Clang toolchain in the second phase.
-if (NOT DEFINED LLDB_CAN_USE_LLDB_RPC_SERVER)
-  set(LLDB_CAN_USE_LLDB_RPC_SERVER OFF)
+if ((CMAKE_CROSSCOMPILING OR LLVM_HOST_TRIPLE MATCHES "${LLVM_DEFAULT_TARGET_TRIPLE}") AND
+    CMAKE_SYSTEM_NAME MATCHES "AIX|Android|Darwin|FreeBSD|Linux|NetBSD|OpenBSD|Windows")
+  set(LLDB_CAN_USE_LLDB_RPC_SERVER ON)
 else()
-  if ((CMAKE_CROSSCOMPILING OR LLVM_HOST_TRIPLE MATCHES "${LLVM_DEFAULT_TARGET_TRIPLE}") AND
-      CMAKE_SYSTEM_NAME MATCHES "AIX|Android|Darwin|FreeBSD|Linux|NetBSD|OpenBSD|Windows")
-    set(LLDB_CAN_USE_LLDB_RPC_SERVER ON)
-  else()
-    set(LLDB_CAN_USE_LLDB_RPC_SERVER OFF)
-  endif()
+  set(LLDB_CAN_USE_LLDB_RPC_SERVER OFF)
 endif()
 
 
-if (NOT DEFINED LLDB_BUILD_LLDBRPC)
-  set(LLDB_BUILD_LLDBRPC OFF)
+if (CMAKE_CROSSCOMPILING)
+  set(LLDB_BUILD_LLDBRPC OFF CACHE BOOL "")
+  get_host_tool_path(lldb-rpc-gen LLDB_RPC_GEN_EXE lldb_rpc_gen_exe lldb_rpc_gen_target)
 else()
-  if (CMAKE_CROSSCOMPILING)
-    set(LLDB_BUILD_LLDBRPC OFF CACHE BOOL "")
-    get_host_tool_path(lldb-rpc-gen LLDB_RPC_GEN_EXE lldb_rpc_gen_exe lldb_rpc_gen_target)
-  else()
-    set(LLDB_BUILD_LLDBRPC ON CACHE BOOL "")
-  endif()
+  set(LLDB_BUILD_LLDBRPC ON CACHE BOOL "")
 endif()
 
 include(LLDBGenerateConfig)
diff --git a/lldb/tools/lldb-rpc-gen/CMakeLists.txt b/lldb/tools/lldb-rpc-gen/CMakeLists.txt
index 65b76431d1bea..4b2e5d7483a59 100644
--- a/lldb/tools/lldb-rpc-gen/CMakeLists.txt
+++ b/lldb/tools/lldb-rpc-gen/CMakeLists.txt
@@ -18,6 +18,11 @@ add_lldb_tool(lldb-rpc-gen
       Support
   )
 
-if (NOT DEFINED LLDB_RPC_GEN_EXE)
-  set(LLDB_RPC_GEN_EXE $<TARGET_FILE:lldb-rpc-gen> CACHE STRING "Executable that generates lldb-rpc-server")
+if (CMAKE_CROSSCOMPILING)
+  setup_host_tool(lldb-rpc-gen LLDB_RPC_GEN_EXE lldb_rpc_gen_exe lldb_rpc_gen_target)
+else()
+  if (NOT DEFINED LLDB_RPC_GEN_EXE)
+    set(LLDB_RPC_GEN_EXE $<TARGET_FILE:lldb-rpc-gen> CACHE STRING "Executable that generates lldb-rpc-server")
+  endif()
 endif()
+

@mstorsjo
Copy link
Member

mstorsjo commented Aug 1, 2025

On some cross compile builds, the tool is not correctly set and the command that runs the tool has an empty path for the tool, causing the build to fail.

I'd rather skip the "some" word here, this happens whenever cmake things we're cross compiling - it's not just an odd case of some cross compiles.

Copy link
Member

@mstorsjo mstorsjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't yet work as it should.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this enable this build configuration for macOS universal builds, where we still expect this to fail?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I had forgot to add that check in, my mistake.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem right to me. And in actual tests with cross builds, this still hits the same /bin/sh: 1: -p: not found error.

We shouldn't need any sort of if (CMAKE_CROSSCOMPILING) here at all - we should unconditionally use setup_host_tool. That cmake function then internally checks whether it can expect to use the just-built tool, or if it needs to do a nested build to produce a native lldb-rpc-gen that can be used instead. Again, have a look at the corresponding clang-tidy case - it doesn't have any such conditionals.

Then after that, you do need to modify the following code that actually uses lldb-rpc-gen too. It needs to call the tool ${lldb_rpc_gen_exe} instead of $<TARGET_FILE:lldb-rpc-gen>. This variable then contains the path of the right lldb-rpc-gen executable that should be used. And whenever you're using it, you need to add a dependency on ${lldb_rpc_gen_target}, which is the cmake/ninja target which produces ${lldb_rpc_gen_exe}, possibly through a nested cmake build.

See https://github.com/llvm/llvm-project/blob/llvmorg-22-init/clang-tools-extra/clang-tidy/misc/CMakeLists.txt#L12-L15 how this is done in the case of clang-tidy. I understand that lldb-rpc-gen is donig something more complicated here, but this needs to be hooked up in one way or another.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need any sort of if (CMAKE_CROSSCOMPILING) here at all - we should unconditionally use setup_host_tool. That cmake function then internally checks whether it can expect to use the just-built tool, or if it needs to do a nested build to produce a native lldb-rpc-gen that can be used instead. Again, have a look at the corresponding clang-tidy case - it doesn't have any such conditionals.

Then after that, you do need to modify the following code that actually uses lldb-rpc-gen too. It needs to call the tool ${lldb_rpc_gen_exe} instead of $&lt;TARGET_FILE:lldb-rpc-gen>. This variable then contains the path of the right lldb-rpc-gen executable that should be used. And whenever you're using it, you need to add a dependency on ${lldb_rpc_gen_target}, which is the cmake/ninja target which produces ${lldb_rpc_gen_exe}, possibly through a nested cmake build.

Noted, I hadn't realized that setup_host_tool could be used to replace how we setup the tool's binary entirely here, that is my mistake.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you unconditionally adopt setup_host_tool, you can also get rid of this manual variable for pointing to a prebuilt lldb-rpc-gen binary; the setup_host_tool (which internally calls get_host_tool_path) machinery automatically configures a similar cmake variable to let you manually override the path to the binary, and it also checks in the directory LLVM_NATIVE_TOOL_DIR if you happen to have a preexisting binary there, and then based on that decide to either compile a new one or use the existing one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted that the original way that we setup the binary can now be removed.

@mstorsjo
Copy link
Member

mstorsjo commented Aug 1, 2025

Now I've had time to study lldb-rpc-gen a little bit closer...

For myself and others, to clarify what lldb-rpc-gen does (as how command options flow into it that aren't immediately obvious): It is a tool that includes clang tooling libraries. It runs at the regular LLVM/LLDB build directory, reading compile_commans.json from there, then using them to figure out how to compile certain files, and use those to preprocess(?) and parse some LLDB headers.

This is in a rather large contrast to other existing build time code generation tools (like llvm-tblgen or clang-tidy-confusable-chars-gen); those are relatively small executables that on their own generate code to be used during the build - and those tools are mostly independent of the build environment.

Your initial attempts seem quite close to actually getting this right (already attempting to use get_host_tool_path etc), but both the initial attempt and this one missed one subtle detail: The cmake functions get_host_tool_path and setup_host_tool do take a cmake variable name LLDB_RPC_GEN_EXE as input, which allows the user to set this variable if they want to point to the tool, but it doesn't set the final path in that variable, but in a different variable.

I managed to simplify the setup of all this, and got a cross build to actually successfully build and use a nested cmake build to build lldb-rpc-gen, just like it does for other tools. My diff to achieve this looks like this:

diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig
.cmake
index 88b4eca4112c..f108110ff94b 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -334,11 +334,4 @@ else()
 endif()
 
 
-if (CMAKE_CROSSCOMPILING)
-  set(LLDB_BUILD_LLDBRPC OFF CACHE BOOL "")
-  get_host_tool_path(lldb-rpc-gen LLDB_RPC_GEN_EXE lldb_rpc_gen_exe lldb_rpc_gen_target)
-else()
-  set(LLDB_BUILD_LLDBRPC ON CACHE BOOL "")
-endif()
-
 include(LLDBGenerateConfig)
diff --git a/lldb/tools/CMakeLists.txt b/lldb/tools/CMakeLists.txt
index e2f039527ad7..d3096765ad8f 100644
--- a/lldb/tools/CMakeLists.txt
+++ b/lldb/tools/CMakeLists.txt
@@ -10,9 +10,7 @@ add_subdirectory(lldb-fuzzer EXCLUDE_FROM_ALL)
 
 add_lldb_tool_subdirectory(lldb-instr)
 add_lldb_tool_subdirectory(lldb-dap)
-if (LLDB_BUILD_LLDBRPC)
-  add_lldb_tool_subdirectory(lldb-rpc-gen)
-endif()
+add_lldb_tool_subdirectory(lldb-rpc-gen)
 if (LLDB_CAN_USE_LLDB_RPC_SERVER)
   add_subdirectory(lldb-rpc)
 endif()
diff --git a/lldb/tools/lldb-rpc-gen/CMakeLists.txt b/lldb/tools/lldb-rpc-gen/CMakeLists.txt
index 4b2e5d7483a5..7a50072865ab 100644
--- a/lldb/tools/lldb-rpc-gen/CMakeLists.txt
+++ b/lldb/tools/lldb-rpc-gen/CMakeLists.txt
@@ -18,11 +18,6 @@ add_lldb_tool(lldb-rpc-gen
       Support
   )
 
-if (CMAKE_CROSSCOMPILING)
-  setup_host_tool(lldb-rpc-gen LLDB_RPC_GEN_EXE lldb_rpc_gen_exe lldb_rpc_gen_target)
-else()
-  if (NOT DEFINED LLDB_RPC_GEN_EXE)
-    set(LLDB_RPC_GEN_EXE $<TARGET_FILE:lldb-rpc-gen> CACHE STRING "Executable that generates lldb-rpc-server")
-  endif()
-endif()
+add_dependencies(lldb-rpc-gen clang-resource-headers)
 
+setup_host_tool(lldb-rpc-gen LLDB_RPC_GEN_EXE lldb_rpc_gen_exe lldb_rpc_gen_target)
diff --git a/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake b/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake
index a4cacf8692a8..91188ca393a1 100644
--- a/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake
+++ b/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake
@@ -1,9 +1,3 @@
-if (NOT DEFINED LLDB_RPC_GEN_EXE)
-  message(FATAL_ERROR
-    "Unable to generate lldb-rpc sources because LLDB_RPC_GEN_EXE is not
-    defined. If you are cross-compiling, please build lldb-rpc-gen for your host
-    platform.")
-endif()
 set(lldb_rpc_generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
 set(lldb_rpc_server_generated_source_dir "${lldb_rpc_generated_dir}/server")
 
@@ -60,14 +54,14 @@ add_custom_command(OUTPUT ${lldb_rpc_gen_byproducts}
   COMMAND ${CMAKE_COMMAND} -E make_directory
     ${lldb_rpc_server_generated_source_dir}
 
-  COMMAND ${LLDB_RPC_GEN_EXE}
+  COMMAND ${lldb_rpc_gen_exe}
     -p ${CMAKE_BINARY_DIR}
     --output-dir=${lldb_rpc_generated_dir}
     ${sysroot_arg}
     --extra-arg="-USWIG"
     ${api_headers}
 
-  DEPENDS ${LLDB_RPC_GEN_EXE} ${api_headers}
+  DEPENDS ${lldb_rpc_gen_target} ${api_headers}
   COMMENT "Generating sources for lldb-rpc-server..."
   WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
 )

I had to add the dependency on clang-resource-headers, so that the tool <builddir>/NATIVE/bin/lldb-rpc-gen gets the clang resource headers it expects in <builddir>/NATIVE/lib/clang/<version>/include.

However, even with all this in place, I fear that it may be brittle - in particular during cross builds. (I wouldn't always assume that the clang tooling flawlessly would figure out the ins and outs if I'm using an unusual cross compiler.)

And secondly - building lldb-rpc-gen requires building most of LLVM and Clang, which adds a lot of extra work to cross builds. Currently, when cross compiling, it builds llvm-tblgen, clang-tblgen and lldb-tblgen and similar tools natively - which is extra overhead to the build. But this is usually just a couple hundred object files - so it's easier to just let cmake do that, rather than to fiddle with manually pointing to a preexisting native build (with the risk of it being out of sync etc). But here, this essentially would make the nested native build duplicate 70% of the whole llvm build - which is quite out of scope for what's probably expected.

I also see that the existing logic for setting up lldb-rpc here does seem to try to account for this to some extent:

# In a cross-compile build, we need to skip building the generated
# lldb-rpc sources in the first phase of host build so that they can
# get built using the just-built Clang toolchain in the second phase.
if ((CMAKE_CROSSCOMPILING OR LLVM_HOST_TRIPLE MATCHES "${LLVM_DEFAULT_TARGET_TRIPLE}") AND

But it's very unclear to me exactly how this is meant to work - the condition seems to miss a negation with regards to CMAKE_CROSS_COMPILING? (And the check for LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE seems unusual here - we don't normally check LLVM_DEFAULT_TARGET_TRIPLE like that - just checking CMAKE_CROSSCOMPILING should be enough.)

So we can probably do something like my inline diff above, to make the build succeed if we want to build this, but we probably should default to having this disabled in general:

diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake
index f108110ff94b..388e37d0da78 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -323,14 +323,16 @@ else()
     set(LLDB_CAN_USE_DEBUGSERVER OFF)
 endif()
 
-# In a cross-compile build, we need to skip building the generated
-# lldb-rpc sources in the first phase of host build so that they can
-# get built using the just-built Clang toolchain in the second phase.
-if ((CMAKE_CROSSCOMPILING OR LLVM_HOST_TRIPLE MATCHES "${LLVM_DEFAULT_TARGET_TRIPLE}") AND
-    CMAKE_SYSTEM_NAME MATCHES "AIX|Android|Darwin|FreeBSD|Linux|NetBSD|OpenBSD|Windows")
-  set(LLDB_CAN_USE_LLDB_RPC_SERVER ON)
-else()
-  set(LLDB_CAN_USE_LLDB_RPC_SERVER OFF)
+if (NOT DEFINED LLDB_CAN_USE_LLDB_RPC_SERVER)
+  # In a cross-compile build, we don't want to try to build a lldb-rpc-gen, as
+  # as that essentially forces rebuilding a whole separate native copy of clang.
+  # Allow the caller to set this variable manually to opt in/out of it.
+  if (NOT CMAKE_CROSSCOMPILING AND
+      CMAKE_SYSTEM_NAME MATCHES "AIX|Android|Darwin|FreeBSD|Linux|NetBSD|OpenBSD|Windows")
+    set(LLDB_CAN_USE_LLDB_RPC_SERVER ON)
+  else()
+    set(LLDB_CAN_USE_LLDB_RPC_SERVER OFF)
+  endif()
 endif()

@chelcassanova
Copy link
Contributor Author

Your initial attempts seem quite close to actually getting this right (already attempting to use get_host_tool_path etc), but both the initial attempt and this one missed one subtle detail: The cmake functions get_host_tool_path and setup_host_tool do take a cmake variable name LLDB_RPC_GEN_EXE as input, which allows the user to set this variable if they want to point to the tool, but it doesn't set the final path in that variable, but in a different variable.

Ah, so if I'm understanding correctly I'm still using LLDB_RPC_GEN_EXE as the variable for the tool path even though setup_host_tool is setting this up to be lldb_rpc_gen_exe.

But it's very unclear to me exactly how this is meant to work - the condition seems to miss a negation with regards to CMAKE_CROSS_COMPILING? (And the check for LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE seems unusual here - we don't normally check LLVM_DEFAULT_TARGET_TRIPLE like that - just checking CMAKE_CROSSCOMPILING should be enough.)

The original logic for cross compile builds was implemented to prevent an issue where the files generated from the rpc-gen tool were processed too early, before the Clang toolchain itself was also built: #148996 (comment), which would cause errors of missing includes of files like cstddef.

So we can probably do something like my inline diff above, to make the build succeed if we want to build this, but we probably should default to having this disabled in general:

Thank you very very much for the help, cross compile builds are configurations I haven't adjusted to working with yet so this is fairly new for me.

Also, for the universal binary issue, technically building for a universal binary is doing a cross compile build. To avoid the issue of there being 2 compile jobs when clang tooling expects 1, we could possibly modify the build such that in a universal build we only process the input header files for the host architecture.

@mstorsjo
Copy link
Member

mstorsjo commented Aug 1, 2025

Ah, so if I'm understanding correctly I'm still using LLDB_RPC_GEN_EXE as the variable for the tool path even though setup_host_tool is setting this up to be lldb_rpc_gen_exe.

Yes, as a user, if you want to point to a preexisting executable, you'd still set it in LLDB_RPC_GEN_EXE, but that variable is empty if the user didn't set anything, and then when the cmake functions either use the user supplied value, or a locally compiled one, the resolved value is set in lldb_rpc_gen_exe.

The original logic for cross compile builds was implemented to prevent an issue where the files generated from the rpc-gen tool were processed too early, before the Clang toolchain itself was also built: #148996 (comment), which would cause errors of missing includes of files like cstddef.

Right - yes, that's also what I meant with this possibly being brittle.

But this seems to assume that everybody's cross builds are done in some specific sequence, with regards to how LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE are set (in my case, I just cross build with one single step, and both of those are set to the same in that single stage) - so I'm not really sure if we can use them like this for detecting what kind of situation we are in.

The safest, with regards to cross builds, probably is to default to not enabling this when cross compiling, unless either LLDB_CAN_USE_LLDB_RPC_SERVER or LLDB_RPC_GEN_EXE is set by the user.

Also, for the universal binary issue, technically building for a universal binary is doing a cross compile build. To avoid the issue of there being 2 compile jobs when clang tooling expects 1, we could possibly modify the build such that in a universal build we only process the input header files for the host architecture.

Yes, but it's also (theoretically) possibly to be doing a universal build for 2 architectures, while neither of them is the native host one; so you can't generally assume that one of them is the host architecture. So for that case it's probably fine to just pick the first/any architecture out of the ones included.

@chelcassanova
Copy link
Contributor Author

Yes, as a user, if you want to point to a preexisting executable, you'd still set it in LLDB_RPC_GEN_EXE, but that variable is empty if the user didn't set anything, and then when the cmake functions either use the user supplied value, or a locally compiled one, the resolved value is set in lldb_rpc_gen_exe.

Noted, I'll change how we set the variable for the tool.

But this seems to assume that everybody's cross builds are done in some specific sequence, with regards to how LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE are set (in my case, I just cross build with one single step, and both of those are set to the same in that single stage) - so I'm not really sure if we can use them like this for detecting what kind of situation we are in.

The safest, with regards to cross builds, probably is to default to not enabling this when cross compiling, unless either LLDB_CAN_USE_LLDB_RPC_SERVER or LLDB_RPC_GEN_EXE is set by the user.

Given how many configurations there are to account for here this does look to be the best option.

Yes, but it's also (theoretically) possibly to be doing a universal build for 2 architectures, while neither of them is the native host one; so you can't generally assume that one of them is the host architecture. So for that case it's probably fine to just pick the first/any architecture out of the ones included.

Hm, I hadn't thought about it that way. In that case then we can modify this to process files for the first architecture for the header files.

On some cross compile builds, the tool is not correctly set and the
command that runs the tool has an empty path for the tool, causing the
build to fail. We can setup the tool as a build host tool using
setup_host_tool.
@chelcassanova chelcassanova force-pushed the fix-lldb-rpc-build-failures branch from 482c3f6 to 75ddbac Compare August 6, 2025 00:03
@vvereschaka
Copy link
Contributor

@chelcassanova @mstorsjo

But this seems to assume that everybody's cross builds are done in some specific sequence, with regards to how LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE are set (in my case, I just cross build with one single step, and both of those are set to the same in that single stage) - so I'm not really sure if we can use them like this for detecting what kind of situation we are in.

LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE is not for detecting the cross builds. This is necessary to detect the Clang cross toolchain build. This is "one-step" build that builds the host tools (non cross builds), such as clang/clang++/llvm-objcopy/etc, and the target libraries using just-built Clang compiler, such as compiler_rt/libc++/libc++abi/libunwind. The libraries will be cross compiled in case LLVM_HOST_TRIPLE != LLVM_DEFAULT_TARGET_TRIPLE. So, the simple CMAKE_CROSSCOMPILING does not work for detection of that kind of LLVM/Clang build configurations.

@vvereschaka
Copy link
Contributor

@chelcassanova the latest changes have the same problem with the header files for the cross toolchain builds.

@mstorsjo
Copy link
Member

mstorsjo commented Aug 6, 2025

@chelcassanova @mstorsjo

But this seems to assume that everybody's cross builds are done in some specific sequence, with regards to how LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE are set (in my case, I just cross build with one single step, and both of those are set to the same in that single stage) - so I'm not really sure if we can use them like this for detecting what kind of situation we are in.

LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE is not for detecting the cross builds. This is necessary to detect the Clang cross toolchain build. This is "one-step" build that builds the host tools (non cross builds), such as clang/clang++/llvm-objcopy/etc, and the target libraries using just-built Clang compiler, such as compiler_rt/libc++/libc++abi/libunwind. The libraries will be cross compiled in case LLVM_HOST_TRIPLE != LLVM_DEFAULT_TARGET_TRIPLE. So, the simple CMAKE_CROSSCOMPILING does not work for detection of that kind of LLVM/Clang build configurations.

Right - I see. But why does this build configuration have to affect whether it should build lldb-rpc-gen or not? Is it because the clang in this build can't manage to process the lldb headers (which are built for the current host)?

@vvereschaka
Copy link
Contributor

vvereschaka commented Aug 7, 2025

Right - I see. But why does this build configuration have to affect whether it should build lldb-rpc-gen or not? Is it because the clang in this build can't manage to process the lldb headers (which are built for the current host)?

Right, "the clang in this build can't manage to process the lldb headers" because they include the target c++ headers, which are not available yet on a moment of executing the lldb-rpc-gen tool during the cross-toolchain build.

(which are built for the current host)

They should work for the target host also.

A little more details:

  • we build a cross toolchain for the aarch64/linux target on x86_64/Windows or x86_64/Linux host. The final Clang supports only Aarch64 target and uses the target libc++ library.
  • also this build configuration uses the Aarch64/Linux SYSROOT with the header/libraries for the target aarch64 system (such as stdc and stdc++, but not libc++ that we want to get from the project tree).
  • the lldb-rpc-gen tool depends on the clang libs to scan the lldb headers, but in our configuration Clang will use just-built libc++ and its header files. We need to prepare the libc++ headers inside of the build tree before using clang++/lldb-rpc-gen.
  • because of lack of the build dependencies, the lldb-prc-gen tool gets ready and starts scanning the headers before the libc++ headers get prepared (and we get the fatal error: 'cstdio' file not found errors accordingly).
  • The lldb-rpc-gen tool cannot use the host libc++ headers because the host os/arch and the target os/arch can be completely different.

in addition:

  • as far as I know, there is no way to properly configure the build dependencies and run the lldb-rpc-gen tool after the builtins and runtimes builds get ready.
  • I know only one way to detect the cross toolchain build -- to compare LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE, -- but it is not working for some cases.

Something like that.

PS. Probably it is optimal to stop trying to detect all these known and unknown situations and manage building over option with OFF by default (may be except Darwin), but with consideration of the cross builds.

@mstorsjo
Copy link
Member

mstorsjo commented Aug 7, 2025

Right - I see. But why does this build configuration have to affect whether it should build lldb-rpc-gen or not? Is it because the clang in this build can't manage to process the lldb headers (which are built for the current host)?

Right, "the clang in this build can't manage to process the lldb headers" because they include the target c++ headers, which are not available yet on a moment of executing the lldb-rpc-gen tool during the cross-toolchain build.

Hmm, that's very odd. At the point when lldb-rpc-gen runs, it's supposed to try to parse the headers in the same way as the host compiler does, using the same C++ standard library as the host compiler does. Unless Clang is built with something like CLANG_DEFAULT_CXX_STDLIB=libc++ though, or a default config file used for all targets, - which then also would apply when using the same Clang (libraries) for the host.

  • the lldb-rpc-gen tool depends on the clang libs to scan the lldb headers, but in our configuration Clang will use just-built libc++ and its header files. We need to prepare the libc++ headers inside of the build tree before using clang++/lldb-rpc-gen.

Actually IMO the issue is the other way around; if the host build doesn't use libc++ headers, then the lldb-rpc-gen is supposed to parse headers in exactly the same way as the host build as well, not waiting for some target runtimes to be built.

in addition:

  • as far as I know, there is no way to properly configure the build dependencies and run the lldb-rpc-gen tool after the builtins and runtimes builds get ready.
  • I know only one way to detect the cross toolchain build -- to compare LLVM_HOST_TRIPLE and LLVM_DEFAULT_TARGET_TRIPLE, -- but it is not working for some cases.

That's maybe one indication, yes...

But as far as I can see, this really boils down to something else; it's not so much about cross vs not cross, it's about "can the currently built clang libraries be used for host compilation/parsing" - and target specific defaults like CLANG_DEFAULT_CXX_STDLIB=libc++ can be one of the factors that break that. Possibly many more as well. (The fact that your Clang build only supports targeting aarch64 might also factor in, but most of the Clang frontend doesn't require the LLVM backend, at least for parsing headers.)

Specifically the case about cross compiling LLVM itself, is another factor though, because if we'd enable building lldb-rpc-gen like we do for all other build-time code generation tools, like llvm-tblgen, then we end up duplicating 75% of the whole clang build - which we probably don't want to do.

PS. Probably it is optimal to stop trying to detect all these known and unknown situations and manage building over option with OFF by default (may be except Darwin), but with consideration of the cross builds.

Yes, I agree about that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants