Subversion Repositories Programming Utils

Rev

Rev 67 | Rev 79 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <fstream>
#include <iostream>
#include <cstring>
#include <cstdlib>
#ifdef        sparc
#    include <sys/timeb.h>
#endif
#include <unistd.h>
#include <time.h>
#include <vector>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>

#include "MakefileObject.h"
#include "dirlist.h"
#include "PlatformSwitcher.h"

using std::ifstream;
using std::cerr;
using std::endl;
using std::string;
using std::set;
using std::cout;
using std::pair;

static string parseList( char* buffer ){
        string finalString;
        char* equalsLocation = strchr( buffer, '=' );
        if( equalsLocation == NULL ){
                cerr << "ERROR: Couldn't parse list" << endl;
                return finalString;
        }

        //pointer arithmetic to get rid of the equals sign
        char* file = strtok( buffer + ( equalsLocation - buffer ) + 1, " \t" );
        while( file != NULL ){
                finalString.append( file );
                file = strtok( NULL, " " );
        }

        return finalString;
}

static void parseFileList( char* buffer, set<string>* putInto ){
        char* equalsLocation = strchr( buffer, '=' );
        if( equalsLocation == NULL ){
                cerr << "ERROR: Couldn't parse files" << endl;
                return;
        }
        //We've found our files
        //pointer arithmetic to get rid of the equals sign
        char* file = strtok( buffer + ( equalsLocation - buffer ) + 1, " \t" );
        while( file != NULL ){
                putInto->insert( string( file ) );
                file = strtok( NULL, " " );
        }

}

// trim from start
static inline std::string &ltrim(std::string &s) {
        s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
        return s;
}

// trim from end
static inline std::string &rtrim(std::string &s) {
        s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
        return s;
}

// trim from both ends
static inline std::string &trim(std::string &s) {
        return ltrim(rtrim(s));
}

Makefile::Makefile( const char* makefile, map<string,string>* inConfig ){
        ifstream theFile( makefile );
        char* buffer;
        configuration = inConfig;

        buffer = (char*)malloc( 300 );

        //Initialize our default configuration
/*      configuration = new map<string, string>();
        map<string, string>& config = (*configuration);
        config["c_compiler"] = "cc";
        config["cpp_compiler"] = "CC";
        config["no_debug"] = "false";
        config["header_file"] = "header.mak";
        config["program_file"] = "programs.mak";
        config["update"] = "false";
        config["depends"] = "false";
        config["ar"] = "false";
        config["so"] = "false";
        config["install"] = "false";
        config["prefix"] = "/usr/bin";
        config["dirs"] = ".";
*/


        initializeMakefileVariables();

        if( theFile.fail() ){
                cerr << "ERROR: Couldn't open file " << makefile << endl;
        }

        string* lastUsedVariable = NULL;
        set<string>* lastUsedList = NULL;
        bool append = false;
        char* equalsLocation;
        while( theFile.good() ){
                theFile.getline( buffer, 300 );

                if( equalsLocation = strstr( buffer, "=" ) ){
                        string beginning( buffer, equalsLocation );
                        string end( equalsLocation + 1 );
                        if( end[ end.size() ] == '\\' ){
                                append = true;
                                end.resize( end.size() - 1 );
                        }
                //      if( regex[ 0 ] == "CPP_FLAGS" || regex[ 0 ] == "H_FLAGS" //...etc, don't put in standard variables
                //      }else{
                        beginning = trim( beginning );
                        end = trim( end );
cout << "inserting |" << beginning << "| => |" << end << "|\n";
                                makefileVariables.insert( pair<string,string>( beginning, end )  );
                //      }
                }else if( append ){
                }

                //if the append variable is set, we have not reached the end of our line
/*              if( append ){
                        if( lastUsedVariable != NULL ){
                                //append to our string variable
                                lastUsedVariable->append( parseList( buffer ) );
                        }else if( lastUsedList != NULL ){
                                //append to our set variable
                                parseFileList( buffer, lastUsedList );
                        }

                        //if we still haven't reached the end of our line,
                        //loop again
                        if( theFile.gcount() >= 300 ){
                                continue;
                        }

                        lastUsedVariable = NULL;
                        lastUsedList = NULL;
                        append = false;
                }
*/


                //if we have more than 300 characters, OR the last character on the line is a \,
                //we go onto the next line
                if( theFile.gcount() >= 300 || buffer[ theFile.gcount() ] == '\\' ){
                        append = true;
                }

/*              if( memcmp( buffer, "CPP_FILES", 9 ) == 0 ){
                        parseFileList( buffer, &cpp_files );
                        lastUsedList = &cpp_files;
                }

                if( memcmp( buffer, "H_FILES", 7 ) == 0 ){
                        parseFileList( buffer, &h_files );
                        lastUsedList = &h_files;
                }

                if( memcmp( buffer, "C_FILES", 7 ) == 0 ){
                        parseFileList( buffer, &c_files );
                        lastUsedList = &c_files;
                }

                if( memcmp( buffer, "PS_FILES", 8 ) == 0 ){
                        parseFileList( buffer, &ps_files );
                        lastUsedList = &ps_files;
                }

                if( memcmp( buffer, "S_FILES", 7 ) == 0 ){
                        parseFileList( buffer, &s_files );
                        lastUsedList = &s_files;
                }

                if( memcmp( buffer, "CPPFLAGS", 8 ) == 0 ){
                        cpp_flags = parseList( buffer );
                        lastUsedVariable = &cpp_flags;
                }

                if( memcmp( buffer, "CFLAGS", 6 ) == 0 ){
                        c_flags = parseList( buffer );
                        lastUsedVariable = &c_flags;
                }

                if( memcmp( buffer, "CXXFLAGS", 8 ) == 0 ){
                        cxx_flags = parseList( buffer );
                        lastUsedVariable = &cxx_flags;
                }

                if( memcmp( buffer, "CLIBFLAGS", 9 ) == 0 ){
                        clib_flags = parseList( buffer );
                        lastUsedVariable = &clib_flags;
                }
       
                if( memcmp( buffer, "CCLIBFLAGS", 10 ) == 0 ){
                        cxxlib_flags = parseList( buffer );
                        lastUsedVariable = &cxxlib_flags;
                }

                if( memcmp( buffer, "CPPFLAGS", 8 ) == 0 ){
                        cpp_flags = parseList( buffer );
                        lastUsedVariable = &cpp_flags;
                }
               
                if( memcmp( buffer, "CC =", 4 ) == 0 ){
                        config["c_compiler"] = parseList( buffer );
                }

                if( memcmp( buffer, "CXX =", 5 ) == 0 ){
                        config["cpp_compiler"] = parseList( buffer );
                }
*/


               
printf("BUFFER IS |%s|\n", buffer );
fflush(stdout);
        }

        free( buffer );

remove_old_files();

}

Makefile::Makefile( std::map<string, string>* conf, DirList* dirList ){
        configuration = conf;
        initializeMakefileVariables();

        //Copy everything from the DirList to our object
        cpp_files = dirList->cpp;
}

Makefile::~Makefile(){
}

void Makefile::writeMakefile(){
        findMainPrograms();
        findLibraries();

        write_header();
        write_variables();
        write_lists();
        write_main_targets();
        write_dependencies();
        write_trailer( (*configuration)["c_compiler"] == "gcc" );
}

/*Write::Write( DirList &dirlist, map<string, string> * conf ){
  if( dirlist.h_m4.size() > 0 || dirlist.cpp_m4.size() > 0 ){
    (*configuration)["m4"] = "true";
  }

  configuration = conf;
  write_header();
  write_lists( dirlist );
  write_main_targets( dirlist );
  write_dependencies( dirlist );
 
  write_install_targets( dirlist );
 
  bool useGCC = (*configuration)["c_compiler"] == "gcc";
  write_trailer( dirlist, useGCC );
}
*/


void Makefile::write_header() {
  time_t now( time( 0 ) );

  //
  // Write the header
  //
  cout << "#\n";
  /*if(useGCC) {
    cout << "# Created by gmakemake (";
  } else {
    cout << "# Created by makemake (" ;
  }*/

  cout << "# Created by " << (*configuration)["executable"];
  cout << " " << PLATFORM << " (" <<  __DATE__ ") on " << ctime( &now );
  cout << "#\n";
  cout << "\n";
  cout << "#\n";
  cout << "# Definitions\n";
  cout << "#\n";
  cout << "\n";
  cout << ".SUFFIXES:\n";
  cout << ".SUFFIXES:\t.a .o .c .C .cpp .s .S\n";
  cout << ".c.o:\n";
  cout << "\t\t$(COMPILE.c) $< -o $@\n";
  cout << ".C.o:\n";
  cout << "\t\t$(COMPILE.cc) $< -o $@\n";
  cout << ".cpp.o:\n";
  cout << "\t\t$(COMPILE.cc) $< -o $@\n";
  cout << ".S.s:\n";
  cout << "\t\t$(CPP) -o $*.s $<\n";
  cout << ".s.o:\n";
  cout << "\t\t$(COMPILE.cc) $< -o $@\n";
  cout << ".c.a:\n";
  cout << "\t\t$(COMPILE.c) -o $% $<\n";
  cout << "\t\t$(AR) $(ARFLAGS) $@ $%\n";
  cout << ".C.a:\n";
  cout << "\t\t$(COMPILE.cc) -o $% $<\n";
  cout << "\t\t$(AR) $(ARFLAGS) $@ $%\n";
  cout << ".cpp.a:\n";
  cout << "\t\t$(COMPILE.cc) -o $% $<\n";
  cout << "\t\t$(AR) $(ARFLAGS) $@ $%\n";

  if(  (*configuration)["m4"] == "true" ){
    cout << "%.h: %.h.m4\n";
    cout << "\t\tm4 $< > $@\n";
    cout << "%.cpp: %.cpp.m4\n";
    cout << "\t\tm4 $< > $@\n";
  }

  cout << "\n";
  /*if(useGCC) {
    cout << "CC =\t\tgcc\n";
    cout << "CXX =\t\tg++\n";
  } else {
    cout << "CC =\t\tcc\n";
    cout << "CXX =\t\tCC\n";
  }*/

}


void Makefile::write_variables(){
  ifstream in;
  map<string,string>::iterator iter;

  //
  // Open the header file
  //
  if( (*configuration)["header_file"] == "//" ){
    //
    // They specifically said not to use one.
    //
    in.clear( ios::badbit | ios::failbit );
  } else {
    //
    // Open the one they said to use.
    //
    in.open( ((*configuration)["header_file"]).c_str() );
  }

  //Write out our compiler variables
  //C compiler
/*
  iter = makefileVariables.find( "CC" );
  cout << "CC = \t\t" << makefileVariables[ "CC" ] << "\n";
  makefileVariables.erase( iter );

  //C++ compiler
  iter = makefileVariables.find( "CXX" );
  cout << "CXX = \t\t" << makefileVariables[ "CXX" ] << "\n";
  makefileVariables.erase( iter );
  cout << "\n";

  //Write out our remove variable
  iter = makefileVariables.find( "RM" );
  cout << "RM = " << makefileVariables[ "RM" ] << "\n";
  makefileVariables.erase( iter );

  //Write out our archive variable
  iter = makefileVariables.find( "AR" );
  cout << "AR = " << makefileVariables[ "AR" ] << "\n";
  makefileVariables.erase( iter );

  //Write out the link and compile variables
  iter = makefileVariables.find( "LINK.c" );
  cout << "LINK.c = " << makefileVariables[ "LINK.c" ] << "\n";
  makefileVariables.erase( iter );

  iter = makefileVariables.find( "LINK.cc" );
  cout << "LINK.cc = " << makefileVariables[ "LINK.cc" ] << "\n";
  makefileVariables.erase( iter );

  iter = makefileVariables.find( "COMPILE.c" );
  cout << "COMPILE.c = " << makefileVariables[ "COMPILE.c" ] << "\n";
  makefileVariables.erase( iter );

  iter = makefileVariables.find( "COMPILE.cc" );
  cout << "COMPILE.cc = " << makefileVariables[ "COMPILE.cc" ] << "\n";
  makefileVariables.erase( iter );
*/


  cout << '\n';

  if( makefileVariables.size() > 0 ){
    cout << "########## Custom Variables\n";
    for( iter = makefileVariables.begin();
         iter != makefileVariables.end();
         iter++ ){
      if( (*iter).first.compare( "CPPFLAGS" ) == 0 ||
          (*iter).first.compare( "CFLAGS" ) == 0 ||
          (*iter).first.compare( "CXXFLAGS" ) == 0 ||
          (*iter).first.compare( "CLIBFLAGS" ) == 0 ||
          (*iter).first.compare( "CCLIBFLAGS" ) == 0 ){
//        continue;
      }
      cout << (*iter).first << " =\t" << (*iter).second << "\n";
    }
  }

  cout << '\n';

  if( in ){
    cout << "########## Flags from " << (*configuration)["header_file"] << "\n\n";
    copy(istreambuf_iterator<char>(in),
         istreambuf_iterator<char>(),
         ostreambuf_iterator<char>(cout));
    cout << '\n'; // in case no end-of-line at end of file
    cout << "########## End of flags from " << (*configuration)["header_file"] << "\n\n";
  } else {
    cout << "########## Default flags (redefine these with a header.mak file if desired)\n";
    cout << "CPPFLAGS = \t" << makefileVariables[ "CPPFLAGS" ] << "\n";
    cout << "CFLAGS = \t" << makefileVariables[ "CFLAGS" ] << "\n";
    cout << "CXXFLAGS = \t" << makefileVariables[ "CXXFLAGS" ] << "\n";
    cout << "CLIBFLAGS = \t" << makefileVariables[ "CLIBFLAGS" ] << "\n";
    cout << "CCLIBFLAGS = \t" << makefileVariables[ "CCLIBFLAGS" ] << "\n";
    cout << "########## End of default flags\n";
  //if( !lib_files.empty() ){
   // CFLAGS += -fPIC
    cout << '\n';
  }
  cout << '\n';
}

void Makefile::write_lists( ){
  cout << "CPP_FILES =\t" << FileListInserter( cpp_files ) << '\n';
  cout << "C_FILES =\t" << FileListInserter( c_files ) << '\n';
  //cout << "PS_FILES = \t \n";
  //cout << "S_FILES =\t" << FileListInserter( s_files ) << '\n';
  cout << "H_FILES =\t" << FileListInserter( h_files ) << '\n';
  if(  (*configuration)["m4"] == "true" ){
    //cout << "M4_FILES = \t" << FileListInserter(dirlist.h_m4) << FileListInserter(dirlist.cpp_m4);
  }
  cout << "SOURCEFILES =\t$(H_FILES) $(CPP_FILES) $(C_FILES) $(S_FILES)";
  if(  (*configuration)["m4"] == "true" ){
    cout << "$(M4_FILES)";
  }
  cout << "\n";
  cout << ".PRECIOUS:\t$(SOURCEFILES)\n";

  cout << "OBJFILES =\t";
  cout << FileListInserter( cpp_other, ".o" );
  if( !cpp_other.empty() ) {
    cout << " ";
  }
  cout << FileListInserter( c_other, ".o" );
  if( !c_other.empty() ) {
    cout << " ";
  }
  cout << FileListInserter( s_other, ".o" );
  cout << '\n';

//  if( !dirlist.archive.empty() ){
//    cout << "LOCAL_LIBS =\t" << FileListInserter( dirlist.archive ) << '\n';
//  }
  cout << '\n';
}

void Makefile::write_main_targets( ){
  string local_libs( !archive.empty()
                          ? " $(LOCAL_LIBS)"
                          : "" );
  ifstream in;

//  if( dirlist.cpp_main.empty() && dirlist.c_main.empty()
//      && dirlist.ass_main.empty() ) {
  if( c_main.empty() && cpp_main.empty() && ps_main.empty() && s_main.empty() ){
    cerr << "Warning: no main program(s) found\n";
  }
  //
  // Open the programs file
  //
  if( (*configuration)["programs_file"] == "//" ){
    //
    // They specifically said not to use one.
    //
    in.clear( ios::badbit | ios::failbit );
  } else {
    //
    // Open the one they said to use.
    //
    in.open( ((*configuration)["programs_file"]).c_str() );
  }
  vector<string> lines;
  istreambuf_iterator<char> init(in), eof;

  if(in) { // read lines of "programs.mak"
    while(in && init != eof) {
      ostringstream ss;
      ostreambuf_iterator<char> ssit(ss);
      while(in && init != eof && *init != '\n' && *init != '\r') {
        *ssit++ = *init++;
      }
      while(in && init != eof && (*init == '\n' || *init == '\r')) {
        init++; // skip eol
      }
      string line = ss.str();
      string::iterator colon = find(line.begin(), line.end(), ':');
      if(colon == line.end()
         || find(line.begin(), colon, ' ') != colon
         || find(colon + 1, line.end(), ':') != line.end()) {
        cerr << "error in format of file : " << (*configuration)["programs_file"] << '\n';
        cerr << line << '\n';
      } else {
#ifdef WINDOWS
        lines.push_back(string(line.begin(), colon) + ".exe"
                        + string(colon, line.end()));
        products.insert(string(line.begin(), colon) + ".exe");
#else
        lines.push_back(line);
        products.insert(string(line.begin(), colon));
#endif
      }
    }
   
    //
    // Executable targets
    //
    cout << "#\n"
         << "# Main targets\n"
         << "#\n\n"
         << "all:";
    for(vector<string>::iterator lit = lines.begin();
        lit != lines.end();
        ++lit) {
      string line = *lit;
      string::iterator colon = find(line.begin(), line.end(), ':');
      if(colon != line.end()) {
        cout << ' ' << string(line.begin(), colon);
      }
    }

    cout << "\n\n";
   
    for(vector<string>::iterator lit = lines.begin();
        lit != lines.end();
        ++lit) {
      string line = *lit;
      string::iterator colon = find(line.begin(), line.end(), ':');
      bool cpplink = false;
      istringstream iss(string(colon + 1, line.end()));
      string name;
      while(iss >> name) {
        string bname = DirList::basename(name);
        for(set<string>::iterator nit = cpp_files.begin();
            nit != cpp_files.end();
            ++nit) {
          if(DirList::basename(*nit) == bname) {
            cpplink = true;
            goto cpplinkdone;
          }
        }
      }
    cpplinkdone:
      cout << line << '\n';
      if(cpplink) {
        cout << '\t' << "$(CXX) $(CXXFLAGS) -o "
             << string(line.begin(), colon) << ' '
             << string(colon+1, line.end()) << local_libs << " $(CCLIBFLAGS)"
             << "\n\n";
      } else {
        cout << '\t' << "$(CC) $(CFLAGS) -o "
             << string(line.begin(), colon) << ' '
             << string(colon+1, line.end()) << local_libs << " $(CLIBFLAGS)"
             << "\n\n";
      }
    }
  } else {
    //
    // Executable targets
    //
        const char* extension = "";
#ifdef WINDOWS
        extension = ".exe";
#endif

    cout << "#\n"
         << "# Main targets\n"
         << "#\n\n"
         << "all:\t";
    cout << FileListInserter( cpp_main, extension );
    if( !cpp_main.empty() ) {
      cout << " ";
    }
    cout << FileListInserter( c_main, extension );
    if( !c_main.empty() ) {
      cout << " ";
    }
    cout << FileListInserter( s_main, extension );
    cout << "\n\n";
    write_main_target_list( cpp_main,
                            "$(CXX) $(CXXFLAGS)",
                            local_libs + " $(CCLIBFLAGS)" );
    write_main_target_list( c_main,
                            "$(CC) $(CFLAGS)" ,
                            local_libs + " $(CLIBFLAGS)");
    write_main_target_list( s_main,
                            "$(CC) $(CFLAGS)" ,
                            local_libs + " $(CLIBFLAGS)");
  }

  //
  //Write out shared libraries
  //
  if( !lib_files.empty() ){
    cout << "#\n"
         << "# SO targets\n"
         << "#\n\n";

    for( set<string>::const_iterator it = lib_files.begin();
         it != lib_files.end();
         ++it ) {
      string basename( DirList::basename( *it) );

      cout << basename << ":\t";
      cout << basename << ".o $(OBJFILES)\n";
      cout << "$(CC) -shared -Wl,-soname," << basename << ".so -o $(OBJFILES)\n";
    }
  }

}


void Makefile::write_main_target_list( const set<string> &list,
                                    string compile,
                                    string local_libs ) {
  for( set<string>::const_iterator it = list.begin();
       it != list.end();
       ++it ) {
    string basename( DirList::basename( *it ) );

#ifdef WINDOWS
    cout << (basename + ".exe") << ":\t"
#else
    cout << basename << ":\t"
#endif
         << basename << ".o $(OBJFILES)" << '\n';

#ifdef WINDOWS
    cout << '\t' << compile << " -o " << (basename + ".exe") << ' '
#else
    cout << '\t' << compile << " -o " << basename << ' '
#endif
         << basename << ".o $(OBJFILES)" << local_libs
         << "\n\n";
  }
}


void Makefile::doFork(int fileds){
        //Child process
        dup2( fileds, STDOUT_FILENO ); //make output go to pipe instead of STDOUT

        set<string> allDefines;

        char* cstrCppFlags = (char*)malloc( cpp_flags.size() );
        memcpy( cstrCppFlags, cpp_flags.c_str(), cpp_flags.size() + 1 );
        char* define = strtok( cstrCppFlags, " " );
        while( define != NULL && define < ( cstrCppFlags + cpp_flags.size() ) ){
                if( define[ 0 ] == '-' && define[ 1 ] == 'D' ){
                        //this is a define
                        allDefines.insert( string( define ) );
                }
                define = strtok( NULL, " " );
        }

        int totalElements = cpp_files.size() + c_files.size() + allDefines.size() + 3; //all c/cpp files, plus three for "gcc" "-MM" [defines] [args] NULL
        char** argArray = (char**)malloc( sizeof(char*) * totalElements );
        int currentArgSpot = 0;

        // put in the first parameters for the GCC exec call
        char* gcc = (char*)malloc(4);
        memcpy(gcc, "gcc", 4);
        char* mm = (char*)malloc(4);
        memcpy( mm, "-MM", 4);

        argArray[currentArgSpot++] = gcc;
        argArray[currentArgSpot++] = mm;
       
        //Now, let's add in each define statement
        for( set<string>::iterator it = allDefines.begin(); it != allDefines.end(); it++  ){
                char* thedefine = (char*)malloc( (*it).size() + 1 );
                memcpy( thedefine, (*it).c_str(), (*it).size() + 1 );
                argArray[currentArgSpot++] = thedefine;
        }

        //Add in all the CPP files
        for( set<string>::iterator it = cpp_files.begin(); it != cpp_files.end(); it++ ){
                char* toAdd = (char*)malloc( (*it).size() + 1 );
                memcpy( toAdd, (*it).c_str(), (*it).size() + 1 );
                argArray[currentArgSpot++] = toAdd;
        }

        //add in all the C files
        for( set<string>::iterator it = c_files.begin(); it != c_files.end(); it++ ){
                char* toAdd = (char*)malloc( (*it).size() + 1 );
                memcpy( toAdd, (*it).c_str(), (*it).size() + 1 );
                argArray[currentArgSpot++] = toAdd;
        }
        argArray[currentArgSpot] = NULL;

        execvp( "gcc", argArray );

        //should not get here
        perror("execvp");
        exit( 2 );

}


void Makefile::write_dependencies(){
  cout << "#\n"
       << "# Dependencies\n"
       << "#\n\n";

  int fileds[2];
  if( pipe( fileds ) < 0 ) perror("pipe");

//  if( (*configuration)["c_compiler"].compare("gcc")  ){
  if( 1 ){
    //Fork and read in the data from gcc
    //command: gcc -MM *.cpp *.c $(CPPFLAGS)
    switch( fork() ){
      case 0:
        //Child process
        //close( fileds[0] );
        doFork( fileds[1] );
     case -1:
       //bad error.  
       exit( 3 );
     default:
       //parent process
       close( fileds[1] );
    }
    char read_buffer[100];
    int val;
    while( val = read( fileds[0], read_buffer, 100 ), val > 0 ){
      read_buffer[val] = '\0';
      cout << read_buffer;
    }
  }

  cout << '\n';
}

/*
void Write::write_archive_targets( ){
  cout << "#\n";
  cout << "# Archive Targets\n";
  cout << "#\n";
}

void Write::write_shared_obj_targets(  ){
  cout << "#\n";
  cout << "# Shared Object Targets\n";
  cout << "#\n";
}
*/


void Makefile::write_install_targets( ){
  cout << "#\n";
  cout << "# Installation Targets\n";
  cout << "#\n";

  const char* extension = "";
#ifdef WINDOWS
  extension = ".exe";
#endif

  //First, write out our dependencies
  cout << "\n";
  cout << "install: ";
  cout << FileListInserter( cpp_main, extension );
  if( !cpp_main.empty() ) {
    cout << " ";
  }

  cout << FileListInserter( c_main, extension );
  if( !c_main.empty() ) {
    cout << " ";
  }

  cout << FileListInserter( s_main, extension );
  cout << "\n";

  //Now, write out the actual install command
  cout << "\t/usr/bin/install ";
   
  cout << FileListInserter( cpp_main, extension );
  if( !cpp_main.empty() ) {
    cout << " ";
  }

  cout << FileListInserter( c_main, extension );
  if( !c_main.empty() ) {
    cout << " ";
  }

  cout << FileListInserter( s_main, extension );

  cout << (*configuration)["prefix"];
  cout << "\n\n" ;
}


void Makefile::write_trailer( bool useGCC ){
  cout << "#\n";
  cout << "# Housekeeping\n";
  cout << "#\n";
  cout << "\n";
  cout << "Archive:\tarchive.tgz\n";
  cout << "\n";
  cout << "archive.tgz:\t$(SOURCEFILES) Makefile\n";
  cout << "\ttar cf - $(SOURCEFILES) Makefile | gzip > archive.tgz\n";
  cout << '\n';

  cout << "clean:\n"
       << "\t-/bin/rm $(OBJFILES)";
  if( !cpp_main.empty() ){
    cout << " " << FileListInserter( cpp_main, ".o" );
  }
  if( !c_main.empty() ){
    cout << " " << FileListInserter( c_main, ".o" );
  }
  if( !s_main.empty() ){
    cout << " " << FileListInserter( s_main, ".o" );
  }
  if(useGCC) {
    cout << " core 2> /dev/null\n";
  } else {
    cout << " ptrepository SunWS_cache .sb ii_files core 2> /dev/null\n";
  }
  cout << '\n';
  cout << "realclean:        clean\n";
  cout << "\t-/bin/rm -rf ";
  if(products.empty()) {
#ifdef WINDOWS
    cout << FileListInserter( cpp_main, ".exe" );
#else
    cout << FileListInserter( cpp_main, "" );
#endif
    if( !cpp_main.empty() ) {
      cout << " ";
    }
#ifdef WINDOWS
    cout << FileListInserter( c_main, ".exe" );
#else
    cout << FileListInserter( c_main, "" );
#endif
    if( !c_main.empty() ) {
      cout << " ";
    }
#ifdef WINDOWS
    cout << FileListInserter( s_main, ".exe" );
#else
    cout << FileListInserter( s_main, "" );
#endif
    if( !s_main.empty() ) {
      cout << " ";
    }
  } else {
    for(set<string>::iterator it = products.begin();
        it != products.end();
        ++it) {
      cout << *it << ' ';
    }
  }
  cout << endl; // to flush buffer
}


void Makefile::findMainPrograms(){

        //First, let's check all of our C files
        for( set<string>::iterator it = c_files.begin(); it != c_files.end(); it++ ){
                if( DirList::hasMainFunction( (*it) ) ){
                        c_main.insert( *it );
                }else{
                        c_other.insert( *it );
                }
        }

        //Now, all of our CPP files
        for( set<string>::iterator it = cpp_files.begin(); it != cpp_files.end(); it++ ){
                if( DirList::hasMainFunction( (*it) ) ){
                        cpp_main.insert( *it );
                }else{
                        cpp_other.insert( *it );
                }
        }

        //Finally, all of our assembly files
        for( set<string>::iterator it = s_files.begin(); it != s_files.end(); it++ ){
                if( DirList::hasMainLabel( (*it) ) ){
                        s_main.insert( *it );
                }else{
                        s_other.insert( *it );
                }
        }

}

void Makefile::findLibraries(){
        //First, let's check all of our C files
        for( set<string>::iterator it = c_files.begin(); it != c_files.end(); it++ ){
                if( (*it).find( "lib" ) == string::npos ){
                        lib_files.insert( *it );
                }
        }

        //Now, all of our CPP files
        for( set<string>::iterator it = cpp_files.begin(); it != cpp_files.end(); it++ ){
        }

        //Finally, all of our assembly files
        for( set<string>::iterator it = s_files.begin(); it != s_files.end(); it++ ){
        }

}

void Makefile::remove_old_files(){
        FILE* theFile;

        for( set<string>::iterator it = c_files.begin(); it != c_files.end(); it++ ){
                theFile = fopen( (*it).c_str(), "r" );
                if( theFile == NULL ){
                        c_files.erase( it );
                }else{
                        fclose( theFile );
                }
        }

        for( set<string>::iterator it = cpp_files.begin(); it != cpp_files.end(); it++ ){
                theFile = fopen( (*it).c_str(), "r" );
                if( theFile == NULL ){
                        cpp_files.erase( it );
                }else{
                        fclose( theFile );
                }
        }

        for( set<string>::iterator it = h_files.begin(); it != h_files.end(); it++ ){
                theFile = fopen( (*it).c_str(), "r" );
                if( theFile == NULL ){
                        h_files.erase( it );
                }else{
                        fclose( theFile );
                }
        }
}

void Makefile::addFiles( DirList* dirlist ){
        cpp_files.insert( dirlist->cpp.begin(), dirlist->cpp.end() );
        c_files.insert( dirlist->c.begin(), dirlist->c.end() );
        h_files.insert( dirlist->h.begin(), dirlist->h.end() );
}

void Makefile::initializeMakefileVariables(){
        makefileVariables[ "RM" ] = "rm -f";
        makefileVariables[ "AR" ] = "ar";
        makefileVariables[ "LINK.c" ] = "$(CC) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)";
        makefileVariables[ "LINK.cc" ] = "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)";
        makefileVariables[ "COMPILE.c" ] = "$(CC) $(CFLAGS) $(CPPFLAGS) -c";
        makefileVariables[ "COMPILE.cc" ] = "$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c";
        makefileVariables[ "CPPFLAGS" ] = "";
        if( (*configuration)["no_debug"] == "false" ){
                if((*configuration)["c_compiler"] == "gcc" ) {
                        makefileVariables[ "CFLAGS" ] = "-ggdb";
                        makefileVariables[ "CXXFLAGS" ] = "-ggdb";
                } else {
                        makefileVariables[ "CFLAGS" ] = "-g";
                        makefileVariables[ "CXXFLAGS" ]  = "-g -xildoff -xsb";
                }
        }else{
                if((*configuration)["c_compiler"] == "gcc" ) {
                        makefileVariables[ "CFLAGS" ] = "";
                        makefileVariables[ "CXXFLAGS" ] = "";
                } else {
                        makefileVariables[ "CFLAGS" ] = "";
                        makefileVariables[ "CXXFLAGS" ]  = "-xildoff -xsb";
                }
        }
        makefileVariables[ "CLIBFLAGS" ] = "-lm";
        makefileVariables[ "CCLIBFLAGS" ] = "";
}