Here is the patch.
It might be useful for the other environments but mine is MinGW so I tried to keep it separate. This fix auto discovers MinGW version and Root folder. I assume root does not have white spaces.
It can cope with new versions like 4.5.1 and specialized ones i.e. 4.5.1-dw2


On 10/28/2010 10:02 PM, NAKAMURA Takumi wrote:
Amer, please make a patch, thank you!

http://llvm.org/docs/DeveloperPolicy.html#patches

...Takumi
Index: lib/Frontend/InitHeaderSearch.cpp
===================================================================
--- lib/Frontend/InitHeaderSearch.cpp   (revision 117652)
+++ lib/Frontend/InitHeaderSearch.cpp   (working copy)
@@ -67,6 +67,14 @@
   void AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
                                      llvm::StringRef Arch,
                                      llvm::StringRef Version);
+  /// Flexible path base recovery - A step closer to removing hardcoded paths
+  std::string FindPathBase(const std::string &body,const std::string &part);
+  /// Returns the base or root folder of MinGW
+  std::string GetMinGWBase();
+  /// Interacts with System using pipes to collect valuable data
+  std::string EvalSystemCommand(std::string cmd,bool trim);
+  /// Returns last two bits of info needed to make mingw paths dynamic
+  std::string GetMinGWVersion(const std::string & base);
 
   /// AddDelimitedPaths - Add a list of paths delimited by the system PATH
   /// separator. The processing follows that of the CPATH variable for gcc.
@@ -414,7 +422,116 @@
   }
   return(false);
 }
+/** Finds full path that contains provided substring within a collection of 
paths.
+* You can supply any Env var that holds path collections and extract paths 
from it
+* that match a partial string. The path return is only up to the part 
substring so even if a path
+* is mentioned that is used for BIN folder you get the actual base path.
+* Search is case insensitive and should work for Win and Unix paths. If Mac 
and other
+* platforms fail then what we consider path and name separators needs to be 
generalized.
+* Finds the first occurance of provided parial string.
+* Path separators used: :;"'
+* Name separators used: forward and backward slash
+* @param body string with collection of paths
+* @param part partial string known to be present in our desired path base
+* @return path base from last path separator until the first path separator 
after part
+*/
+std::string InitHeaderSearch::FindPathBase(const std::string &body,const 
std::string &part){
+       // convert to lower case for case insesitive search
+       std::string lbody=body;
+       std::transform(lbody.begin(), lbody.end(), lbody.begin(),
+             (int(*)(int)) std::tolower);
+       std::string lpart=part;
+       std::transform(lpart.begin(), lpart.end(), lpart.begin(),
+             (int(*)(int)) std::tolower);
 
+       std::string ret="";
+       // locate first occurance
+       int plen=lpart.length();
+       int blen=lbody.length();
+       int state=-1; // when it reaches plen we got a match
+       int index=0;
+       for(;index<blen && state<(plen-1);index++){
+               char cl=lbody[index];
+               char cr=lpart[state+1];
+               if(cl=='\\') cl='/'; //translate name separator
+               if(cr=='\\') cr='/';
+               if(cl==cr){
+                       state++; // advance fsm state
+               }else{
+                       state=-1;// reset fsm state
+               }
+       }
+       if(state!=(plen-1)) return ret; // no luck
+       // index points to first occurance
+       // now we find teh start and end of the path
+       int end=index;
+       int begin=end-plen;
+       // look for end
+       while(end<blen){
+               char c=lbody[end];
+               // we try to sense a path or name delimiter and break there
+               if(c=='/' || c=='\\' || c==':' || c==';' || c=='"' || c=='\'') 
break;
+               end++;
+       }
+       // look for begin
+       while(begin>0){
+               char c=lbody[begin-1];
+               // we try to sense a path separator
+               if((c==':' && lbody[begin]!='\\')  || c==';' || c=='"' || 
c=='\'') break;
+               begin--;
+       }
+       // should have being and end with blen that contains part
+       ret=body.substr(begin,end-begin);
+       return ret;
+}
+
+/** Returns the base or root folder of MinGW.
+ * Uses FindBasePath to recover MinGW root folder. If it fails for some reason
+ * defaults to c:/MinGW. With this method the only hardcoded part of MinGW 
header search is in
+ * the version.
+ */
+std::string InitHeaderSearch::GetMinGWBase(){
+               const char * path=getenv("PATH");
+               if(path==NULL) path=getenv("CPATH");
+               std::string fallback="c:/mingw";
+               if(path==NULL) return fallback;
+               std::string ret=FindPathBase(path,"/mingw");
+               if(ret.empty()) return fallback;
+               return ret;
+}
+
+/** Tries to execute an external command and collects the result via a pipe.
+*
+*/
+std::string InitHeaderSearch::EvalSystemCommand(std::string cmd,bool trim){
+       const char * exe=cmd.c_str();
+       const int N=4096;
+       char line[N];
+       FILE *pipe=popen(exe,"r");
+       if(pipe==NULL) return std::string(); // issue with pipe opening
+       std::string ret="";
+       while(fgets(line,N,pipe)!=NULL){
+               ret.append(line);
+       }
+       fclose(pipe);
+       if(trim){
+               unsigned int len=ret.length();
+               for(int i=len-1;i>=0;i--){
+                       if(ret[i]=='\n') len--;
+                       else if(ret[i]=='\f') len--;
+                       else if(ret[i]=='\r') len--;
+                       else break;
+               }
+               if(len<ret.length()) ret=ret.substr(0,len);
+       }
+       return ret;
+}
+/// Returns version info needed to make mingw paths dynamic - ie. 4.5.1-dw2
+std::string InitHeaderSearch::GetMinGWVersion(const std::string &base){
+       std::string mingwexe=base+"/bin/gcc";
+       return EvalSystemCommand(mingwexe+" -dumpversion",true);
+}
+
 void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
                                             const HeaderSearchOptions &HSOpts) 
{
   // FIXME: temporary hack: hard-coded paths.
@@ -524,7 +641,10 @@
     break;
   case llvm::Triple::MinGW64:
   case llvm::Triple::MinGW32:
-    AddPath("c:/mingw/include", System, true, false, false);
+  {
+         std::string base=GetMinGWBase();
+         AddPath(base+"/include", System, true, false, false);
+  }
     break;
   default:
     break;
@@ -560,20 +680,36 @@
     AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "3.4.4");
     break;
   case llvm::Triple::MinGW64:
+  {
+       std::string base=GetMinGWBase();
+       std::string version=GetMinGWVersion(base);
+       // Try to guess the actual version
+       if(!version.empty()){
+           AddMinGWCPlusPlusIncludePaths(base+"/lib/gcc", "mingw64", version);
+       }
     // Try gcc 4.5.0
-    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.5.0");
+    AddMinGWCPlusPlusIncludePaths(base+"/lib/gcc", "mingw64", "4.5.0");
     // Try gcc 4.4.0
-    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
+    AddMinGWCPlusPlusIncludePaths(base+"/lib/gcc", "mingw64", "4.4.0");
     // Try gcc 4.3.0
-    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
+    AddMinGWCPlusPlusIncludePaths(base+"/lib/gcc", "mingw64", "4.3.0");
     // Fall through.
+  }
   case llvm::Triple::MinGW32:
-   // Try gcc 4.5.0
-    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0"); 
+  {
+       std::string base=GetMinGWBase();
+       std::string version=GetMinGWVersion(base);
+       // Try to guess the actual version
+       if(!version.empty()){
+           AddMinGWCPlusPlusIncludePaths(base+"/lib/gcc", "mingw32", version);
+       }
+    // Try gcc 4.5.0
+    AddMinGWCPlusPlusIncludePaths(base+"/lib/gcc", "mingw32", "4.5.0");
     // Try gcc 4.4.0
-    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
+    AddMinGWCPlusPlusIncludePaths(base+"/lib/gcc", "mingw32", "4.4.0");
     // Try gcc 4.3.0
-    AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
+    AddMinGWCPlusPlusIncludePaths(base+"/lib/gcc", "mingw32", "4.3.0");
+  }
     break;
   case llvm::Triple::Darwin:
     switch (triple.getArch()) {

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to