Here is it again.
Take a look and if acceptable please integrate. Please let me know.
Why did I bother:
1.) I have MinGW under c:\projects\bin which is not default
2.) I use TDM Dwarf compilation which changes lib paths to append
-dw2 at the end
This addition basically adds code to parse env variables like PATH and
extract the root.
It also queries GCC for certain things. Similar code can be added for
other supported compilers.
It makes CLANG work better with MINGW environments.
On 11/11/2010 12:59 PM, Eric Christopher wrote:
On Nov 11, 2010, at 6:45 AM, Amer Agovic wrote:
I submitted a patch a while back. It was a change to
InitiHeaderSearch.cpp.
Has it been accepted, has it been rejected? What is the status?
Probably got missed, can you please resend and I'll take a look at it?
Thanks!
-eric
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