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