| 51 | |
| 52 | |
| 53 | class HostTools(Tools): |
| 54 | def __init__(self) -> None: |
| 55 | super().__init__() |
| 56 | |
| 57 | self.cc = self.find_host_cc() |
| 58 | self.cc_is_clang = 'clang' in self.cc.name |
| 59 | |
| 60 | self.ar = self.find_host_ar() |
| 61 | self.cxx = self.find_host_cxx() |
| 62 | self.ld = self.find_host_ld() |
| 63 | self.ranlib = self.find_host_ranlib() |
| 64 | |
| 65 | def find_host_ar(self) -> Path: |
| 66 | # GNU ar is the default, no need for llvm-ar if using GCC |
| 67 | if not self.cc_is_clang: |
| 68 | return tc_build.utils.UNINIT_PATH |
| 69 | |
| 70 | if (ar := Path(self.cc.parent, 'llvm-ar')).exists(): |
| 71 | return ar |
| 72 | |
| 73 | return tc_build.utils.UNINIT_PATH |
| 74 | |
| 75 | def find_host_cc(self) -> Path: |
| 76 | # resolve() is called here and below to get /usr/lib/llvm-#/bin/... for |
| 77 | # versioned LLVM binaries on Debian and Ubuntu. We do not want to |
| 78 | # resolve a multicall binary though, as the symlink is how it works |
| 79 | # properly. |
| 80 | if tc_build.utils.path_is_set(cc := self.from_env('CC')): |
| 81 | return cc if cc_is_multicall(cc) else cc.resolve() |
| 82 | |
| 83 | # As a special case, see if the first clang command in PATH is a |
| 84 | # multicall binary, as there will be no clang-<ver> binary or symlink, |
| 85 | # so the versioned binary logic below may result in a clang-<ver> |
| 86 | # binary from PATH "overriding" the clang symlink to llvm. We generally |
| 87 | # want clang-<ver> to override clang though because clang-<ver> may be |
| 88 | # newer than a plain clang binary (such as when using apt.llvm.org). |
| 89 | if (clang := shutil.which('clang')) and cc_is_multicall(clang): |
| 90 | return Path(clang) |
| 91 | |
| 92 | possible_c_compilers = [*generate_versioned_binaries(), 'clang', 'gcc'] |
| 93 | for compiler in possible_c_compilers: |
| 94 | if cc := shutil.which(compiler): |
| 95 | break |
| 96 | else: |
| 97 | msg = 'Neither clang nor gcc could be found on your system?' |
| 98 | raise RuntimeError(msg) |
| 99 | |
| 100 | return Path(cc).resolve() # resolve() for Debian/Ubuntu variants |
| 101 | |
| 102 | def find_host_cxx(self) -> Path: |
| 103 | if tc_build.utils.path_is_set(cxx := self.from_env('CXX')): |
| 104 | return cxx |
| 105 | |
| 106 | possible_cxx_compiler = 'clang++' if self.cc_is_clang else 'g++' |
| 107 | |
| 108 | # Use CXX from the 'bin' folder of CC if it exists |
| 109 | if (cxx := Path(self.cc.parent, possible_cxx_compiler)).exists(): |
| 110 | return cxx |