pw_toolchain: Allow user-provided clang toolchain

Allows a user to specify the root directory of the llvm tools to use
when compiling with clang. This makes it easier to debug
compiler-related issues.

Bug: 321
Change-Id: I74552f128d80553279896ebd2d9cb25c9f7bff32
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/42932
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Armando Montanez <amontanez@google.com>
diff --git a/pw_toolchain/arm_clang/toolchains.gni b/pw_toolchain/arm_clang/toolchains.gni
index 91aea25..5b61bf3 100644
--- a/pw_toolchain/arm_clang/toolchains.gni
+++ b/pw_toolchain/arm_clang/toolchains.gni
@@ -14,13 +14,11 @@
 
 import("//build_overrides/pigweed.gni")
 
+import("$dir_pw_toolchain/clang_tools.gni")
+
 # Specifies the tools used by host Clang toolchains.
 _arm_clang_toolchain = {
-  # Note: On macOS, there is no "llvm-ar", only "ar", which happens to be LLVM
-  # ar. This should get updated for linux systems.
-  ar = "ar"
-  cc = "clang"
-  cxx = "clang++"
+  forward_variables_from(pw_toolchain_clang_tools, "*")
 
   link_whole_archive = true
 }
diff --git a/pw_toolchain/clang_tools.gni b/pw_toolchain/clang_tools.gni
new file mode 100644
index 0000000..6ecd3b7
--- /dev/null
+++ b/pw_toolchain/clang_tools.gni
@@ -0,0 +1,37 @@
+# Copyright 2021 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+declare_args() {
+  # This flag allows you to specify the root directory of the clang, clang++,
+  # and llvm-ar binaries to use when compiling with a clang-based toolchain.
+  # This is useful for debugging toolchain-related issues by building with an
+  # externally-provided toolchain.
+  pw_toolchain_CLANG_PREFIX = ""
+}
+
+pw_toolchain_clang_tools = {
+  if (pw_toolchain_CLANG_PREFIX != "") {
+    ar = pw_toolchain_CLANG_PREFIX + "/"
+    cc = pw_toolchain_CLANG_PREFIX + "/"
+    cxx = pw_toolchain_CLANG_PREFIX + "/"
+  } else {
+    ar = ""
+    cc = ""
+    cxx = ""
+  }
+
+  ar += "llvm-ar"
+  cc += "clang"
+  cxx += "clang++"
+}
diff --git a/pw_toolchain/docs.rst b/pw_toolchain/docs.rst
index 919eb88..1e8d6efd 100644
--- a/pw_toolchain/docs.rst
+++ b/pw_toolchain/docs.rst
@@ -48,3 +48,11 @@
 installation and Pylint in toolchains created with ``pw_non_c_toolchain``. This
 allows all toolchains to cleanly share the same protobuf and Python declarations
 without any duplicated work.
+
+Testing other compiler versions
+===============================
+The clang-based toolchain provided by Pigweed can be substituted with another
+version by modifying the ``pw_toolchain_CLANG_PREFIX`` GN build argument to
+point to the directory that contains the desired clang, clang++, and llvm-ar
+binaries. This should only be used for debugging purposes. Pigweed does not
+officially support any compilers other than those provided by Pigweed.
diff --git a/pw_toolchain/host_clang/toolchains.gni b/pw_toolchain/host_clang/toolchains.gni
index b04c86a..1d13a77 100644
--- a/pw_toolchain/host_clang/toolchains.gni
+++ b/pw_toolchain/host_clang/toolchains.gni
@@ -14,6 +14,8 @@
 
 import("//build_overrides/pigweed.gni")
 
+import("$dir_pw_toolchain/clang_tools.gni")
+
 declare_args() {
   # Sets the sanitizer to pass to clang. Valid values are those for "-fsanitize"
   # listed in https://clang.llvm.org/docs/UsersManual.html#id9.
@@ -27,14 +29,13 @@
 
 # Specifies the tools used by host Clang toolchains.
 _host_clang_toolchain = {
-  ar = "llvm-ar"
-
   if (pw_toolchain_OSS_FUZZ_ENABLED) {
+    # Just use the "llvm-ar" on the system path.
+    ar = "llvm-ar"
     cc = getenv("CC")
     cxx = getenv("CXX")
   } else {
-    cc = "clang"
-    cxx = "clang++"
+    forward_variables_from(pw_toolchain_clang_tools, "*")
   }
 
   is_host_toolchain = true