[cfe-commits] Patch: reading clang configuration from yaml

Josh Rickmar jrick at devio.us
Wed Aug 15 08:59:04 PDT 2012


Hi,

Let me start off by saying that this is my first time in the clang
codebase, and also that my c++ is pretty terrible.  Anyways, I was
asked to see if it would be possible to read some sort of clang
configuration (using the llvm yaml parser) to set things like the
linker and assembler binaries, and other include and library paths.
This is a very rough patch (currently it only sets the modifies the
linker and assembler binaries if changed in the conf), but at this
point I'm just wondering if there's any enthusiasm to get something
like this in, and other general suggestions on how to get this coded
together.

Anyways, with this patch it should be possible to create some yaml,
for example:

---
ld: /usr/bin/ld
as: /usr/bin/as

and then either save that in /etc/clang.yaml or point the CLANG_CONF
environmental variable to it.  If after parsing the yaml, either of
those settings were specified, the ToolChain::GetProgramPath()
function will now return what was parsed from the yaml insteading of
getting the full path from the driver.

Again, this is very rough and needs a lot of work still, but any
feedback is welcome.

-- 
Josh Rickmar
http://jrick.devio.us/
-------------- next part --------------
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index ab417bb..ea7f9ef 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -15,6 +15,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/YAMLParser.h"
 #include <string>
 
 namespace clang {
@@ -56,6 +57,20 @@ private:
   /// programs.
   path_list ProgramPaths;
 
+  /// Custom binaries and paths from yaml
+  std::string Linker;
+  std::string Assembler;
+
+  std::string CXXStdLibPath;
+  SmallVector<std::string, 10> CXXStdLibInc;
+  SmallVector<std::string, 10> CXXStdLib;
+
+  void LoadAndParse(const char *env);
+  bool ParseScalar(llvm::yaml::MappingNode::iterator n, std::string& h,
+                   const char *key);
+  bool ParseList(llvm::yaml::MappingNode::iterator n,
+                 SmallVectorImpl<std::string> &v, const char *key);
+
 protected:
   ToolChain(const Driver &D, const llvm::Triple &T);
 
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 48ed044..d46a972 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -17,12 +17,21 @@
 #include "clang/Driver/Options.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/YAMLParser.h"
 #include "clang/Basic/ObjCRuntime.h"
 using namespace clang::driver;
 using namespace clang;
 
 ToolChain::ToolChain(const Driver &D, const llvm::Triple &T)
   : D(D), Triple(T) {
+  const char *env = getenv("CLANG_CONF");
+  if (env == NULL)
+    env = "/etc/clang.conf";
+  if (llvm::sys::fs::exists(env))
+    ToolChain::LoadAndParse(env);
 }
 
 ToolChain::~ToolChain() {
@@ -38,6 +47,10 @@ std::string ToolChain::GetFilePath(const char *Name) const {
 }
 
 std::string ToolChain::GetProgramPath(const char *Name, bool WantFile) const {
+  if (!strcmp(Name, "ld") && Linker != "")
+    return Linker;
+  if (!strcmp(Name, "as") && Assembler != "")
+    return Assembler;
   return D.GetProgramPath(Name, *this, WantFile);
 }
 
@@ -273,3 +286,72 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args,
                                  ArgStringList &CmdArgs) const {
   CmdArgs.push_back("-lcc_kext");
 }
+
+void ToolChain::LoadAndParse(const char *env) {
+  llvm::SourceMgr sm;
+  OwningPtr<llvm::MemoryBuffer> Buf;
+  Buf.get()->getFile(env, Buf);
+  StringRef input = Buf.get()->getBuffer();
+  llvm::yaml::Stream stream(input, sm);
+
+  llvm::yaml::MappingNode *Root = dyn_cast<llvm::yaml::MappingNode>(stream.begin()->getRoot());
+  if (!Root)
+    return;
+
+  for (llvm::yaml::MappingNode::iterator i = Root->begin(), e = Root->end();
+       i != e; ++i) {
+    if (ParseScalar(i, Linker, "ld"))
+      continue;
+    if (ParseScalar(i, Assembler, "as"))
+      continue;
+    if (ParseScalar(i, CXXStdLibPath, "cxxstdlibpath"))
+      continue;
+    if (ParseList(i, CXXStdLib, "cxxstdlib"))
+      continue;
+    if (ParseList(i, CXXStdLibInc, "cxxstdlibinc"))
+      continue;
+  }
+}
+
+bool ToolChain::ParseScalar(llvm::yaml::MappingNode::iterator n,
+                         std::string& handle, const char *key) {
+  llvm::yaml::ScalarNode *Key = dyn_cast<llvm::yaml::ScalarNode>(n->getKey());
+  if (!Key)
+    return false;
+  SmallString<32> Storage;
+  StringRef KeyValue = Key->getValue(Storage);
+  if (KeyValue == key) {
+      llvm::yaml::ScalarNode *sn = dyn_cast<llvm::yaml::ScalarNode>(Key);
+      if (!sn)
+        return true;    // continue to next root node
+      llvm::yaml::ScalarNode *Val
+        = dyn_cast<llvm::yaml::ScalarNode>(n->getValue());
+      StringRef StrVal = llvm::yaml::escape(Val->getValue(Storage));
+      handle = std::string(StrVal.data());
+      return true;
+  }
+  return false;
+}
+
+bool ToolChain::ParseList(llvm::yaml::MappingNode::iterator n,
+                       SmallVectorImpl<std::string> &v, const char *key) {
+  llvm::yaml::ScalarNode *Key = dyn_cast<llvm::yaml::ScalarNode>(n->getKey());
+  if (!Key)
+    return false;
+  SmallString<32> Storage;
+  StringRef KeyValue = Key->getValue(Storage);
+  if (KeyValue == key) {
+    llvm::yaml::SequenceNode *seqn =
+      dyn_cast<llvm::yaml::SequenceNode>(n->getValue());
+    if (seqn == NULL)
+      return false;
+    for (llvm::yaml::SequenceNode::iterator si = seqn->begin(), e = seqn->end();
+         si != e; ++si) {
+      llvm::yaml::ScalarNode *Val = dyn_cast<llvm::yaml::ScalarNode>(&*si);
+      StringRef StrVal = llvm::yaml::escape(Val->getValue(Storage));
+      v.push_back(std::string(StrVal.data()));
+    }
+    return true;
+  }
+  return false;
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 2527 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120815/766372ce/attachment.bin>


More information about the cfe-commits mailing list