/** * $Id: //depot/mkdepend/mkdepend.cpp#2 $ */ #if defined(_MSC_VER) #pragma warning( disable : 4786 ) #endif #include #include #include #include #include #include #define MAKEFILETAGSHORT "# DO NOT DELETE" #define MAKEFILETAGLONG "# DO NOT DELETE THIS LINE -- make depend depends on it." // types typedef std::vector stringvec; typedef struct _FileInfo { bool scanned; stringvec includes; } FileInfo; // globals stringvec gSourceFiles; stringvec gIncludeDirs; std::map gScanList; FILE* gOutputFile; // determine if a file can be found bool FileExists(std::string filename) { FILE* f = fopen(filename.c_str(),"rt"); if ( f ) { fclose(f); return true; } return false; } // reset all data void Clear() { gSourceFiles.clear(); gIncludeDirs.clear(); gScanList.clear(); } // add a directory to out global list void AddIncludeDirectory(std::string dir) { gIncludeDirs.push_back(dir); } // add a source file to our global list void AddSourceFile(std::string source) { gSourceFiles.push_back(source); } // search through all include dirs until we find a file or fail std::string FindIncludeFile(std::string filename,bool check_current=true) { // check filename alone (might be absolute) if ( FileExists( filename ) ) { return filename; } // check current directory if ( check_current ) { if ( FileExists( std::string("./") + filename ) ) { return std::string("./") + filename; } } // now check each include dir for ( unsigned int i=0;i::iterator it; for ( it=gScanList.begin();it!=gScanList.end();it++ ) { if ( !(*it).second.scanned ) { unscanned++; } } return unscanned; } // return true if 'str' begins with 'sub', else false bool StrBegins(const char* str,const char* sub) { int i = 0; while (str[i] && sub[i]) { if (str[i] != sub[i]) { return false; } i++; } // if mathced all the way to the end of sub[i] then success if (!sub[i]) { return true; } return false; } // grab all include directories and source files from the command line void ParseCommandLine(int argc,char** argv) { for (int i=1;i" : "\"" ); if ( !(*c) ) break; *c = '\0'; // we can trim it if it was a <> type if ( quote_type == '<' ) StrTrim(fn_begin); std::string incfile = FindIncludeFile(std::string(fn_begin)); if ( incfile != "" ) { gScanList[filename].includes.push_back(incfile); AddFileToScanList(incfile); } else if ( quote_type == '\"' ) fprintf(stderr,"Warning: Unable to find include file '%s' included from '%s'\n",fn_begin,filename.c_str()); } // close file fclose(f); } // replace .cpp with .o, etc. std::string ExtSubst(const std::string filename) { std::string ret = filename; // find the last '.' ret.resize( ret.find('.') ); // add a ".o" ret += ".o"; return ret; } // this does the actual work void DiscoverDependencies() { // add all the source files to the scan list for (unsigned int i=0;i::iterator it; for ( it=gScanList.begin();it!=gScanList.end();it++ ) { ScanFile((*it).first); } } } void WriteDependencies() { fprintf(gOutputFile,"\n"); // output each source file for ( unsigned int i=0;i dumped; std::set dependencies; // add our includes for this file for ( unsigned int j=0;j::iterator it; for ( it = dependencies.begin(); it != dependencies.end(); it++ ) { if ( dumped.find(*it) == dumped.end() ) { dumped.insert(*it); for ( unsigned int j=0;j::iterator it; fprintf(gOutputFile,"%s: ",objfile.c_str()); for ( it = dependencies.begin(); it != dependencies.end(); it++ ) fprintf(gOutputFile,"\\\n\t%s ",(*it).c_str()); fprintf(gOutputFile,"\n\n"); } } } void OpenOutputFile() { FILE* oldmakefile = fopen("Makefile","r"); if ( !oldmakefile ) { gOutputFile = stdout; return; } gOutputFile = fopen("Makefile.tmp","w"); if ( !gOutputFile ) { // **TODO** should warn user gOutputFile = stdout; fclose(oldmakefile); return; } // look for our tag line while copying to a temp file char instr[4096]; while ( fgets(instr,4096,oldmakefile) ) { fputs(instr,gOutputFile); if ( StrBegins(instr,MAKEFILETAGSHORT) ) { fclose(oldmakefile); return; } } // got to the end without finding it, so let's add the tag fprintf(gOutputFile,"\n" MAKEFILETAGLONG "\n"); fclose(oldmakefile); } void CloseOutputFile() { fflush(gOutputFile); if ( gOutputFile != stdout ) { // close temp file fclose(gOutputFile); // copy to actual Makefile FILE* dest = fopen("Makefile","w"); if ( !dest ) { // **TODO** warn user return; } FILE* src = fopen("Makefile.tmp","r"); if ( !src ) { // **TODO** warn user fclose(dest); return; } // do copy char instr[4096]; while ( fgets(instr,4096,src) ) { fputs(instr,dest); } fclose(src); fclose(dest); } } int main(int argc,char** argv) { Clear(); ParseCommandLine(argc,argv); DiscoverDependencies(); OpenOutputFile(); WriteDependencies(); CloseOutputFile(); return 0; }