Subversion Repositories Programming Utils

Rev

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

/* makemake.cpp
 *
 * $Id: makemake.cpp,v 1.2 2009/12/26 01:41:46 sidney Exp $
 *
 * $Log: makemake.cpp,v $
 * Revision 1.2  2009/12/26 01:41:46  sidney
 * changed while(c = *exename++) to while((c = *exename++)) for style
 *
 * Revision 1.1  2006/06/08 02:14:38  swm
 * Initial revision
 *
 */


#include <iostream>
#include <cstdlib>
#include <cstring>

#include <fstream>

#include <popt.h>

#include "dirlist.h"
#include "write.h"
#include "MakefileObject.h"

bool debug( false );

//Method prototype
void printHelp( const char*);

const char* UPDATE_OPTION_DESC =
    "Let makemake update the list of files that it compiles.  "
    "Any new files will be added to the makefile.  "
    "This will also remove files if makemake cannot find them.  "
    "All custom targets and flags from the old makefile are kept.  "
    "Implies --depends";

const char* DEPENDS_OPTION_DESC =
    "Update only the dependencies that the makefile keeps track of.  "
    "All targets and flags from the old makefile are kept";

const char* HEADER_OPTION_DESC =
    "Use the specified file instead of header.mak.  "
    "See the manual for more information.";

const char* NO_HEADER_OPTION_DESC =
    "Do not open header.mak even if it exists";

const char* PROGRAM_OPTION_DESC =
    "Use the specified file instead of programs.mak.  "
    "See the manual for more information on the programs.mak file";

const char* NO_PROGRAM_MAK_OPTION_DESC =
     "Do not open programs.mak even if it exists";
   
const char* NO_DEBUG_OPTION_DESC =
     "Do not output compiler debugging flags";

const char* AR_OPTION_DESC =
     "Explicitly make a static archive.  "
     "Made automatically if a source file starts with 'ar'";

const char* SO_OPTION_DESC =
      "Explicitly make a shared library file.  "
      "Made automatically if a source file starts with 'lib'";

const char* INSTALL_OPTION_DESC =
      "Generate a 'install' target to install this program.  "
      "By default, this will install to /usr/local/bin";

const char* PREFIX_OPTION_DESC =
      "Generate an install target, but install to PREFIX instead "
      "of /usr/local/bin.  Implies --install";

const char* DIRS_OPTION_DESC =
      "Look through the specified colon-separated directories for files to compile";

const char* RECURSIVE_OPTION_DESC =
      "Recursively search through all directories for files to compile.";

const char* FILES_OPTION_DESC =
      "The files to create the makefile from.  If no files are specified, "
      "makemake will look through the current directory.";

const char* MAKEFILE_OPTION_DESC =
      "The makefile to open in order to parse.  If no arg given, will attempt to open file 'Makefile'";

void printHelp( const char* progName){
    //This line is 80 characters long
    //------------------------------------------------------------------------------
    const char* HELP_TEXT =  
    "                   instead of /usr/bin.  -install is implied\n"
    " --dirs=DIR        Look through the specified colon-separated directores\n"
    "                   for files to compile\n"
    " -r                Recursively search through all directories for files\n"
    " files             The files to create the makefile from.  If no files are\n"
    "                   specified, makemake will look through the current\n"
    "                   directory\n"
        "\n"
    "SuperMakemake v1.0\n"
    "Based off of code by Prof. Sidney Marshall,\n"
    "Rochester Institute of Technology Department of Computer Science\n"
    "Original source code may be found at http://cs.rit.edu/~swm/makemake\n"
    "Currently maintained by rm5248 @ www.programming.rm5248.com\n";

    cout << "Usage: " << progName << " [-update] [-depends] [-header headerfile | -no-header] [-programs programsfile | -no-programs] ";
    cout << "[-no-debug] [-ar name] [-so name] [-install] [--prefix=PREFIX] [--dirs=DIRS | -r] [files] " << endl;
    cout << endl;

    cout << "Note that " << progName << " outputs the makefile to STDOUT; it is typically invoked as " << progName << " > Makefile" << endl;
 
    cout << endl;

    cout << HELP_TEXT << endl;
       
}

int main( int argc, const char **argv ){
  bool search_dirs = false;
  bool recursive_search = false;
  const char* progName;
  const char *exename = argv[0];
  char c;
  Makefile* makefile;
  poptContext pc;
  int poptVal;

  //update variables
  bool update = false;
  bool depends = false;

  //header option variables
  char* header_mak = NULL;
  bool ignore_header_mak = false;
 
  //programs option variables
  char* programs_mak = NULL;
  bool ignore_programs_mak = false;

  //debug option variable
  bool no_debug = false;

  //file option variable
  char* open_makefile = NULL;

  //update help table
  struct poptOption update_options[] = {
    { "update", 0, POPT_ARG_NONE, &update, 0, UPDATE_OPTION_DESC, NULL },
    { "depends", 0, POPT_ARG_NONE, &depends, 0, DEPENDS_OPTION_DESC, NULL },
    { "file", 'f', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &open_makefile, 'f', MAKEFILE_OPTION_DESC, NULL },
    POPT_TABLEEND
  };

  struct poptOption generation_options[] = {
    { "header", 0, POPT_ARG_STRING, &header_mak, 'h', HEADER_OPTION_DESC, NULL },
    { "no-header", 0, POPT_ARG_NONE, &ignore_header_mak, 'h', NO_HEADER_OPTION_DESC, NULL },
    { "programs", 0, POPT_ARG_STRING, &programs_mak, 'p', PROGRAM_OPTION_DESC, NULL },
    { "no-programs", 0, POPT_ARG_NONE, &ignore_programs_mak, 'p', NO_PROGRAM_MAK_OPTION_DESC, NULL },
    { "no-debug", 0, POPT_ARG_NONE, &no_debug, 0, NO_DEBUG_OPTION_DESC, NULL },
    POPT_TABLEEND
  };

  struct poptOption main_options[] = {
    { NULL, 0, POPT_ARG_INCLUDE_TABLE, &update_options, 0, "Makefile update options(makefile must already exist): ", NULL },
    { NULL, 0, POPT_ARG_INCLUDE_TABLE, &generation_options, 0, "Makefile generation options(any existing makefile will be overwritten): ", NULL },
    POPT_AUTOHELP
    POPT_TABLEEND
  };

  pc = poptGetContext( NULL, argc, argv, main_options, 0 );

  while( ( poptVal = poptGetNextOpt( pc ) ) >= 0 ){
    switch( poptVal ){
      case 'h':
         if( header_mak != NULL && ignore_header_mak == true ){
           std::cerr << "ERROR: Unable to have both --no-header and --header, mutually exclusive!" << std::endl;
           return 1;
         }
         break;
      case 'p':
         if( programs_mak != NULL && ignore_programs_mak == true ){
           std::cerr << "ERROR: Unable to have both --no-programs and --programs, mutually exclusive!" << std::endl;
           return 1;
         }
         break;
      default: ;
    }
  }

std::cout << open_makefile << std::endl;
return 1;

  if( poptVal != -1 ){
    std::cerr << "Unable to parse options: " << poptStrerror( poptVal )  << std::endl;
    return 1;
  }

  map<string, string> config;  
  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"] = ".";

  // check gnu compiler make or sun compiler make
  // if first letter of executable is 'g' then gnu otherwise sun
  while((c = *exename++)) {
    if(c == '/') {
      argv[0] = exename;
    }
  }
  if(argv[0][0] == 'g') {
    //useGCC = true;
    config["c_compiler"] = "gcc";
    config["cpp_compiler"] = "g++";
  }
  progName = argv[0];
  config["executable"] = string( progName );

  //
  // Process command line options
  //
  while( argc--, *++argv != NULL && **argv == '-' ){
    if( strcmp( *argv, "-header" ) == 0 && argv[ 1 ] != NULL ){
        config["header_file"] = *++argv;
      argc--;
    } else if( strcmp( *argv, "-no-header" ) == 0 ){
        config["header_file"] = "//";
    } else if( strcmp( *argv, "-programs" ) == 0 && argv[ 1 ] != NULL ){
        config["programs_file"] = *++argv;
      argc--;
    } else if( strcmp( *argv, "-no-programs" ) == 0 ){
        config["header_file"] = "//";
    } else if(strcmp("-no-debug",*argv) == 0){
        config["no-debug"] = "true";
    } else if( strcmp("--help", *argv) == 0 || strcmp("-help", *argv) == 0 ){
        printHelp( progName );
        return 0;
    } else if( strcmp("-update", *argv) == 0 ){
        cout << "Update makefile NOT YET IMPLEMENTED" << endl;
    } else if( strcmp("-depends", *argv) == 0 ){
        cout << "Update depends NOT YET IMPLEMENTED" << endl;
    } else if( strcmp("-ar", *argv) == 0 ){
        cout << "make archive file NOT YET IMPLEMENTED" << endl;
    } else if( strcmp("-so", *argv) == 0 ){
        cout << "make shared object file NOT YET IMPLEMENTED" << endl;
    } else if( strcmp("-install", *argv) == 0 ){
        config["install"] = "true";
    } else if( strcmp("--prefix", *argv) == 0 ){
       if( argc != 0 ){
         config["install"] = "true";
         config["prefix"] = *++argv;
         argc--;
        }
    } else if( strstr(*argv, "--dirs=") != NULL ){
        if( !search_dirs ){
          search_dirs = true;
          config["dirs"] = string( &((*argv)[6]) );
        }
    } else if( strcmp("-r", *argv) == 0 ){
        search_dirs = false;
        recursive_search = true;
    //} else if( strcmp("-update", *argv) == 0 ){
    }else {
      switch( *++*argv ){
      case 'd':
        debug = true;
        break;

      default:
        cerr << "Invalid option: -" << **argv << endl;
        exit( 1 );
      }
    }
  }

  //
  // Read the current directory (and cmd line arguments) to find
  // file names.
  //
  DirList* dirlist;
  if( recursive_search ){
    dirlist = new DirList();
  }else if( poptPeekArg( pc ) != NULL ){
    dirlist = new DirList( poptGetArgs( pc ) );
  }else{
    dirlist = new DirList( config );
  }

  //
  // Now write the makefile
  //
  //Write write( *dirlist, &config );

//makefile = new Makefile( "Makefile", &config );
  makefile = new Makefile( &config, dirlist );
//  makefile->addFiles( dirlist );
  makefile->writeMakefile();

  return 0;
}