Subversion Repositories Programming Utils

Rev

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

Rev Author Line No. Line
45 rm5248 1
#include <fstream>
2
#include <iostream>
3
#include <cstring>
4
#include <cstdlib>
46 rm5248 5
#ifdef        sparc
6
#    include <sys/timeb.h>
7
#endif
8
#include <unistd.h>
9
#include <time.h>
10
#include <vector>
11
#include <sstream>
12
#include <iterator>
13
#include <algorithm>
67 rm5248 14
#include <functional> 
15
#include <cctype>
16
#include <locale>
45 rm5248 17
 
18
#include "MakefileObject.h"
19
#include "dirlist.h"
46 rm5248 20
#include "PlatformSwitcher.h"
45 rm5248 21
 
22
using std::ifstream;
23
using std::cerr;
24
using std::endl;
25
using std::string;
26
using std::set;
27
using std::cout;
49 rm5248 28
using std::pair;
45 rm5248 29
 
30
static string parseList( char* buffer ){
31
        string finalString;
32
        char* equalsLocation = strchr( buffer, '=' );
33
        if( equalsLocation == NULL ){
34
                cerr << "ERROR: Couldn't parse list" << endl;
35
                return finalString;
36
        }
37
 
38
        //pointer arithmetic to get rid of the equals sign
39
        char* file = strtok( buffer + ( equalsLocation - buffer ) + 1, " \t" );
40
        while( file != NULL ){
41
                finalString.append( file );
42
                file = strtok( NULL, " " );
43
        }
44
 
45
        return finalString;
46
}
47
 
48
static void parseFileList( char* buffer, set<string>* putInto ){
49
        char* equalsLocation = strchr( buffer, '=' );
50
        if( equalsLocation == NULL ){
51
                cerr << "ERROR: Couldn't parse files" << endl;
52
                return;
53
        }
54
        //We've found our files
55
        //pointer arithmetic to get rid of the equals sign
56
        char* file = strtok( buffer + ( equalsLocation - buffer ) + 1, " \t" );
57
        while( file != NULL ){
58
                putInto->insert( string( file ) );
59
                file = strtok( NULL, " " );
60
        }
61
 
62
}
63
 
67 rm5248 64
// trim from start
65
static inline std::string &ltrim(std::string &s) {
66
        s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
67
        return s;
68
}
69
 
70
// trim from end
71
static inline std::string &rtrim(std::string &s) {
72
        s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
73
        return s;
74
}
75
 
76
// trim from both ends
77
static inline std::string &trim(std::string &s) {
78
        return ltrim(rtrim(s));
79
}
80
 
81
Makefile::Makefile( const char* makefile, map<string,string>* inConfig ){
45 rm5248 82
        ifstream theFile( makefile );
83
        char* buffer;
67 rm5248 84
        configuration = inConfig;
45 rm5248 85
 
86
        buffer = (char*)malloc( 300 );
87
 
46 rm5248 88
        //Initialize our default configuration
67 rm5248 89
/*      configuration = new map<string, string>();
46 rm5248 90
        map<string, string>& config = (*configuration);
91
        config["c_compiler"] = "cc";
92
        config["cpp_compiler"] = "CC";
93
        config["no_debug"] = "false";
94
        config["header_file"] = "header.mak";
95
        config["program_file"] = "programs.mak";
96
        config["update"] = "false";
97
        config["depends"] = "false";
98
        config["ar"] = "false";
99
        config["so"] = "false";
100
        config["install"] = "false";
101
        config["prefix"] = "/usr/bin";
102
        config["dirs"] = ".";
67 rm5248 103
*/
46 rm5248 104
 
67 rm5248 105
        initializeMakefileVariables();
106
 
45 rm5248 107
        if( theFile.fail() ){
108
                cerr << "ERROR: Couldn't open file " << makefile << endl;
109
        }
110
 
48 rm5248 111
        string* lastUsedVariable = NULL;
112
        set<string>* lastUsedList = NULL;
113
        bool append = false;
49 rm5248 114
        char* equalsLocation;
45 rm5248 115
        while( theFile.good() ){
116
                theFile.getline( buffer, 300 );
48 rm5248 117
 
49 rm5248 118
                if( equalsLocation = strstr( buffer, "=" ) ){
119
                        string beginning( buffer, equalsLocation );
120
                        string end( equalsLocation + 1 );
121
                        if( end[ end.size() ] == '\\' ){
122
                                append = true;
123
                                end.resize( end.size() - 1 );
124
                        }
125
                //      if( regex[ 0 ] == "CPP_FLAGS" || regex[ 0 ] == "H_FLAGS" //...etc, don't put in standard variables
126
                //      }else{
67 rm5248 127
                        beginning = trim( beginning );
128
                        end = trim( end );
129
cout << "inserting |" << beginning << "| => |" << end << "|\n";
49 rm5248 130
                                makefileVariables.insert( pair<string,string>( beginning, end )  );
131
                //      }
132
                }else if( append ){
133
                }
134
 
48 rm5248 135
                //if the append variable is set, we have not reached the end of our line
49 rm5248 136
/*              if( append ){
48 rm5248 137
                        if( lastUsedVariable != NULL ){
138
                                //append to our string variable
139
                                lastUsedVariable->append( parseList( buffer ) );
140
                        }else if( lastUsedList != NULL ){
141
                                //append to our set variable
142
                                parseFileList( buffer, lastUsedList );
143
                        }
144
 
145
                        //if we still haven't reached the end of our line,
146
                        //loop again
147
                        if( theFile.gcount() >= 300 ){
148
                                continue;
149
                        }
150
 
151
                        lastUsedVariable = NULL;
152
                        lastUsedList = NULL;
153
                        append = false;
154
                }
49 rm5248 155
*/
48 rm5248 156
 
49 rm5248 157
                //if we have more than 300 characters, OR the last character on the line is a \,
158
                //we go onto the next line
159
                if( theFile.gcount() >= 300 || buffer[ theFile.gcount() ] == '\\' ){
48 rm5248 160
                        append = true;
47 rm5248 161
                }
162
 
49 rm5248 163
/*              if( memcmp( buffer, "CPP_FILES", 9 ) == 0 ){
45 rm5248 164
                        parseFileList( buffer, &cpp_files );
48 rm5248 165
                        lastUsedList = &cpp_files;
45 rm5248 166
                }
167
 
168
                if( memcmp( buffer, "H_FILES", 7 ) == 0 ){
169
                        parseFileList( buffer, &h_files );
48 rm5248 170
                        lastUsedList = &h_files;
45 rm5248 171
                }
172
 
173
                if( memcmp( buffer, "C_FILES", 7 ) == 0 ){
174
                        parseFileList( buffer, &c_files );
48 rm5248 175
                        lastUsedList = &c_files;
45 rm5248 176
                }
177
 
178
                if( memcmp( buffer, "PS_FILES", 8 ) == 0 ){
179
                        parseFileList( buffer, &ps_files );
48 rm5248 180
                        lastUsedList = &ps_files;
45 rm5248 181
                }
182
 
183
                if( memcmp( buffer, "S_FILES", 7 ) == 0 ){
184
                        parseFileList( buffer, &s_files );
48 rm5248 185
                        lastUsedList = &s_files;
45 rm5248 186
                }
187
 
188
                if( memcmp( buffer, "CPPFLAGS", 8 ) == 0 ){
47 rm5248 189
                        cpp_flags = parseList( buffer );
48 rm5248 190
                        lastUsedVariable = &cpp_flags;
45 rm5248 191
                }
192
 
193
                if( memcmp( buffer, "CFLAGS", 6 ) == 0 ){
194
                        c_flags = parseList( buffer );
48 rm5248 195
                        lastUsedVariable = &c_flags;
45 rm5248 196
                }
197
 
198
                if( memcmp( buffer, "CXXFLAGS", 8 ) == 0 ){
199
                        cxx_flags = parseList( buffer );
48 rm5248 200
                        lastUsedVariable = &cxx_flags;
45 rm5248 201
                }
202
 
203
                if( memcmp( buffer, "CLIBFLAGS", 9 ) == 0 ){
204
                        clib_flags = parseList( buffer );
48 rm5248 205
                        lastUsedVariable = &clib_flags;
45 rm5248 206
                }
207
 
208
                if( memcmp( buffer, "CCLIBFLAGS", 10 ) == 0 ){
209
                        cxxlib_flags = parseList( buffer );
48 rm5248 210
                        lastUsedVariable = &cxxlib_flags;
45 rm5248 211
                }
46 rm5248 212
 
213
                if( memcmp( buffer, "CPPFLAGS", 8 ) == 0 ){
214
                        cpp_flags = parseList( buffer );
48 rm5248 215
                        lastUsedVariable = &cpp_flags;
46 rm5248 216
                }
217
 
218
                if( memcmp( buffer, "CC =", 4 ) == 0 ){
219
                        config["c_compiler"] = parseList( buffer );
220
                }
221
 
222
                if( memcmp( buffer, "CXX =", 5 ) == 0 ){
223
                        config["cpp_compiler"] = parseList( buffer );
224
                }
49 rm5248 225
*/
47 rm5248 226
 
227
 
228
printf("BUFFER IS |%s|\n", buffer );
229
fflush(stdout);
45 rm5248 230
        }
231
 
232
        free( buffer );
46 rm5248 233
 
48 rm5248 234
remove_old_files();
235
 
45 rm5248 236
}
237
 
78 rm5248 238
Makefile::Makefile( std::map<string, string>* conf, DirList* dirList ){
46 rm5248 239
        configuration = conf;
67 rm5248 240
        initializeMakefileVariables();
78 rm5248 241
 
242
        //Copy everything from the DirList to our object
243
        cpp_files = dirList->cpp;
46 rm5248 244
}
245
 
246
Makefile::~Makefile(){
247
}
248
 
45 rm5248 249
void Makefile::writeMakefile(){
49 rm5248 250
        findMainPrograms();
251
        findLibraries();
252
 
46 rm5248 253
        write_header();
49 rm5248 254
        write_variables();
46 rm5248 255
        write_lists();
256
        write_main_targets();
257
        write_dependencies();
48 rm5248 258
        write_trailer( (*configuration)["c_compiler"] == "gcc" );
45 rm5248 259
}
46 rm5248 260
 
261
/*Write::Write( DirList &dirlist, map<string, string> * conf ){
262
  if( dirlist.h_m4.size() > 0 || dirlist.cpp_m4.size() > 0 ){
263
    (*configuration)["m4"] = "true";
264
  }
265
 
266
  configuration = conf;
267
  write_header();
268
  write_lists( dirlist );
269
  write_main_targets( dirlist );
270
  write_dependencies( dirlist );
271
 
272
  write_install_targets( dirlist );
273
 
274
  bool useGCC = (*configuration)["c_compiler"] == "gcc";
275
  write_trailer( dirlist, useGCC );
276
}
277
*/
278
 
279
void Makefile::write_header() {
280
  time_t now( time( 0 ) );
281
 
282
  //
283
  // Write the header
284
  //
285
  cout << "#\n";
286
  /*if(useGCC) {
287
    cout << "# Created by gmakemake (";
288
  } else {
289
    cout << "# Created by makemake (" ;
290
  }*/
291
  cout << "# Created by " << (*configuration)["executable"];
292
  cout << " " << PLATFORM << " (" <<  __DATE__ ") on " << ctime( &now );
293
  cout << "#\n";
294
  cout << "\n";
295
  cout << "#\n";
296
  cout << "# Definitions\n";
297
  cout << "#\n";
298
  cout << "\n";
299
  cout << ".SUFFIXES:\n";
300
  cout << ".SUFFIXES:\t.a .o .c .C .cpp .s .S\n";
301
  cout << ".c.o:\n";
302
  cout << "\t\t$(COMPILE.c) $< -o $@\n";
303
  cout << ".C.o:\n";
304
  cout << "\t\t$(COMPILE.cc) $< -o $@\n";
305
  cout << ".cpp.o:\n";
306
  cout << "\t\t$(COMPILE.cc) $< -o $@\n";
307
  cout << ".S.s:\n";
308
  cout << "\t\t$(CPP) -o $*.s $<\n";
309
  cout << ".s.o:\n";
310
  cout << "\t\t$(COMPILE.cc) $< -o $@\n";
311
  cout << ".c.a:\n";
312
  cout << "\t\t$(COMPILE.c) -o $% $<\n";
313
  cout << "\t\t$(AR) $(ARFLAGS) $@ $%\n";
314
  cout << ".C.a:\n";
315
  cout << "\t\t$(COMPILE.cc) -o $% $<\n";
316
  cout << "\t\t$(AR) $(ARFLAGS) $@ $%\n";
317
  cout << ".cpp.a:\n";
318
  cout << "\t\t$(COMPILE.cc) -o $% $<\n";
319
  cout << "\t\t$(AR) $(ARFLAGS) $@ $%\n";
320
 
321
  if(  (*configuration)["m4"] == "true" ){
322
    cout << "%.h: %.h.m4\n";
323
    cout << "\t\tm4 $< > $@\n";
324
    cout << "%.cpp: %.cpp.m4\n";
325
    cout << "\t\tm4 $< > $@\n";
326
  }
327
 
328
  cout << "\n";
329
  /*if(useGCC) {
330
    cout << "CC =\t\tgcc\n";
331
    cout << "CXX =\t\tg++\n";
332
  } else {
333
    cout << "CC =\t\tcc\n";
334
    cout << "CXX =\t\tCC\n";
335
  }*/
49 rm5248 336
}
337
 
338
 
339
void Makefile::write_variables(){
340
  ifstream in;
67 rm5248 341
  map<string,string>::iterator iter;
49 rm5248 342
 
343
  //
344
  // Open the header file
345
  //
346
  if( (*configuration)["header_file"] == "//" ){
347
    //
348
    // They specifically said not to use one.
349
    //
350
    in.clear( ios::badbit | ios::failbit );
351
  } else {
352
    //
353
    // Open the one they said to use.
354
    //
355
    in.open( ((*configuration)["header_file"]).c_str() );
356
  }
357
 
67 rm5248 358
  //Write out our compiler variables
359
  //C compiler
78 rm5248 360
/*
67 rm5248 361
  iter = makefileVariables.find( "CC" );
362
  cout << "CC = \t\t" << makefileVariables[ "CC" ] << "\n";
363
  makefileVariables.erase( iter );
364
 
365
  //C++ compiler
366
  iter = makefileVariables.find( "CXX" );
367
  cout << "CXX = \t\t" << makefileVariables[ "CXX" ] << "\n";
368
  makefileVariables.erase( iter );
46 rm5248 369
  cout << "\n";
67 rm5248 370
 
371
  //Write out our remove variable
372
  iter = makefileVariables.find( "RM" );
373
  cout << "RM = " << makefileVariables[ "RM" ] << "\n";
374
  makefileVariables.erase( iter );
375
 
376
  //Write out our archive variable
377
  iter = makefileVariables.find( "AR" );
378
  cout << "AR = " << makefileVariables[ "AR" ] << "\n";
379
  makefileVariables.erase( iter );
380
 
381
  //Write out the link and compile variables
382
  iter = makefileVariables.find( "LINK.c" );
383
  cout << "LINK.c = " << makefileVariables[ "LINK.c" ] << "\n";
384
  makefileVariables.erase( iter );
385
 
386
  iter = makefileVariables.find( "LINK.cc" );
387
  cout << "LINK.cc = " << makefileVariables[ "LINK.cc" ] << "\n";
388
  makefileVariables.erase( iter );
389
 
390
  iter = makefileVariables.find( "COMPILE.c" );
391
  cout << "COMPILE.c = " << makefileVariables[ "COMPILE.c" ] << "\n";
392
  makefileVariables.erase( iter );
393
 
394
  iter = makefileVariables.find( "COMPILE.cc" );
395
  cout << "COMPILE.cc = " << makefileVariables[ "COMPILE.cc" ] << "\n";
396
  makefileVariables.erase( iter );
78 rm5248 397
*/
67 rm5248 398
 
46 rm5248 399
  cout << '\n';
400
 
49 rm5248 401
  if( makefileVariables.size() > 0 ){
67 rm5248 402
    cout << "########## Custom Variables\n";
403
    for( iter = makefileVariables.begin();
49 rm5248 404
         iter != makefileVariables.end();
405
         iter++ ){
67 rm5248 406
      if( (*iter).first.compare( "CPPFLAGS" ) == 0 ||
407
          (*iter).first.compare( "CFLAGS" ) == 0 ||
408
          (*iter).first.compare( "CXXFLAGS" ) == 0 ||
409
          (*iter).first.compare( "CLIBFLAGS" ) == 0 ||
410
          (*iter).first.compare( "CCLIBFLAGS" ) == 0 ){
411
//        continue;
412
      }
413
      cout << (*iter).first << " =\t" << (*iter).second << "\n";
49 rm5248 414
    }
415
  }
416
 
67 rm5248 417
  cout << '\n';
418
 
46 rm5248 419
  if( in ){
420
    cout << "########## Flags from " << (*configuration)["header_file"] << "\n\n";
421
    copy(istreambuf_iterator<char>(in),
422
         istreambuf_iterator<char>(),
423
         ostreambuf_iterator<char>(cout));
424
    cout << '\n'; // in case no end-of-line at end of file
425
    cout << "########## End of flags from " << (*configuration)["header_file"] << "\n\n";
426
  } else {
427
    cout << "########## Default flags (redefine these with a header.mak file if desired)\n";
67 rm5248 428
    cout << "CPPFLAGS = \t" << makefileVariables[ "CPPFLAGS" ] << "\n";
429
    cout << "CFLAGS = \t" << makefileVariables[ "CFLAGS" ] << "\n";
430
    cout << "CXXFLAGS = \t" << makefileVariables[ "CXXFLAGS" ] << "\n";
431
    cout << "CLIBFLAGS = \t" << makefileVariables[ "CLIBFLAGS" ] << "\n";
432
    cout << "CCLIBFLAGS = \t" << makefileVariables[ "CCLIBFLAGS" ] << "\n";
46 rm5248 433
    cout << "########## End of default flags\n";
49 rm5248 434
  //if( !lib_files.empty() ){
435
   // CFLAGS += -fPIC 
46 rm5248 436
    cout << '\n';
437
  }
438
  cout << '\n';
439
}
440
 
441
void Makefile::write_lists( ){
442
  cout << "CPP_FILES =\t" << FileListInserter( cpp_files ) << '\n';
443
  cout << "C_FILES =\t" << FileListInserter( c_files ) << '\n';
444
  //cout << "PS_FILES = \t \n";
49 rm5248 445
  //cout << "S_FILES =\t" << FileListInserter( s_files ) << '\n';
46 rm5248 446
  cout << "H_FILES =\t" << FileListInserter( h_files ) << '\n';
447
  if(  (*configuration)["m4"] == "true" ){
448
    //cout << "M4_FILES = \t" << FileListInserter(dirlist.h_m4) << FileListInserter(dirlist.cpp_m4);
449
  }
450
  cout << "SOURCEFILES =\t$(H_FILES) $(CPP_FILES) $(C_FILES) $(S_FILES)";
451
  if(  (*configuration)["m4"] == "true" ){
452
    cout << "$(M4_FILES)";
453
  }
454
  cout << "\n";
455
  cout << ".PRECIOUS:\t$(SOURCEFILES)\n";
456
 
457
  cout << "OBJFILES =\t";
458
  cout << FileListInserter( cpp_other, ".o" );
459
  if( !cpp_other.empty() ) {
460
    cout << " ";
461
  }
462
  cout << FileListInserter( c_other, ".o" );
463
  if( !c_other.empty() ) {
464
    cout << " ";
465
  }
466
  cout << FileListInserter( s_other, ".o" );
467
  cout << '\n';
468
 
469
//  if( !dirlist.archive.empty() ){
470
//    cout << "LOCAL_LIBS =\t" << FileListInserter( dirlist.archive ) << '\n';
471
//  }
472
  cout << '\n';
473
}
474
 
475
void Makefile::write_main_targets( ){
476
  string local_libs( !archive.empty()
477
                          ? " $(LOCAL_LIBS)"
478
                          : "" );
479
  ifstream in;
480
 
481
//  if( dirlist.cpp_main.empty() && dirlist.c_main.empty()
482
//      && dirlist.ass_main.empty() ) {
483
  if( c_main.empty() && cpp_main.empty() && ps_main.empty() && s_main.empty() ){
484
    cerr << "Warning: no main program(s) found\n";
485
  }
486
  //
487
  // Open the programs file
488
  //
489
  if( (*configuration)["programs_file"] == "//" ){
490
    //
491
    // They specifically said not to use one.
492
    //
493
    in.clear( ios::badbit | ios::failbit );
494
  } else {
495
    //
496
    // Open the one they said to use.
497
    //
498
    in.open( ((*configuration)["programs_file"]).c_str() );
499
  }
500
  vector<string> lines;
501
  istreambuf_iterator<char> init(in), eof;
502
 
503
  if(in) { // read lines of "programs.mak"
504
    while(in && init != eof) {
505
      ostringstream ss;
506
      ostreambuf_iterator<char> ssit(ss);
507
      while(in && init != eof && *init != '\n' && *init != '\r') {
508
        *ssit++ = *init++;
509
      }
510
      while(in && init != eof && (*init == '\n' || *init == '\r')) {
511
        init++; // skip eol
512
      }
513
      string line = ss.str();
514
      string::iterator colon = find(line.begin(), line.end(), ':');
515
      if(colon == line.end()
516
         || find(line.begin(), colon, ' ') != colon
517
         || find(colon + 1, line.end(), ':') != line.end()) {
518
        cerr << "error in format of file : " << (*configuration)["programs_file"] << '\n';
519
        cerr << line << '\n';
520
      } else {
521
#ifdef WINDOWS
522
        lines.push_back(string(line.begin(), colon) + ".exe"
523
                        + string(colon, line.end()));
524
        products.insert(string(line.begin(), colon) + ".exe");
525
#else
526
        lines.push_back(line);
527
        products.insert(string(line.begin(), colon));
528
#endif
529
      }
530
    }
531
 
532
    //
533
    // Executable targets
534
    //
535
    cout << "#\n"
536
         << "# Main targets\n"
537
         << "#\n\n"
538
         << "all:";
539
    for(vector<string>::iterator lit = lines.begin();
540
        lit != lines.end();
541
        ++lit) {
542
      string line = *lit;
543
      string::iterator colon = find(line.begin(), line.end(), ':');
544
      if(colon != line.end()) {
545
        cout << ' ' << string(line.begin(), colon);
546
      }
547
    }
548
 
549
    cout << "\n\n";
550
 
551
    for(vector<string>::iterator lit = lines.begin();
552
        lit != lines.end();
553
        ++lit) {
554
      string line = *lit;
555
      string::iterator colon = find(line.begin(), line.end(), ':');
556
      bool cpplink = false;
557
      istringstream iss(string(colon + 1, line.end()));
558
      string name;
559
      while(iss >> name) {
560
        string bname = DirList::basename(name);
561
        for(set<string>::iterator nit = cpp_files.begin();
562
            nit != cpp_files.end();
563
            ++nit) {
564
          if(DirList::basename(*nit) == bname) {
565
            cpplink = true;
566
            goto cpplinkdone;
567
          }
568
        }
569
      }
570
    cpplinkdone:
571
      cout << line << '\n';
572
      if(cpplink) {
573
        cout << '\t' << "$(CXX) $(CXXFLAGS) -o "
574
             << string(line.begin(), colon) << ' '
575
             << string(colon+1, line.end()) << local_libs << " $(CCLIBFLAGS)"
576
             << "\n\n";
577
      } else {
578
        cout << '\t' << "$(CC) $(CFLAGS) -o "
579
             << string(line.begin(), colon) << ' '
580
             << string(colon+1, line.end()) << local_libs << " $(CLIBFLAGS)"
581
             << "\n\n";
582
      }
583
    }
584
  } else {
585
    //
586
    // Executable targets
587
    //
588
        const char* extension = "";
589
#ifdef WINDOWS
590
        extension = ".exe";
591
#endif
592
 
593
    cout << "#\n"
594
         << "# Main targets\n"
595
         << "#\n\n"
596
         << "all:\t";
597
    cout << FileListInserter( cpp_main, extension );
598
    if( !cpp_main.empty() ) {
599
      cout << " ";
600
    }
601
    cout << FileListInserter( c_main, extension );
602
    if( !c_main.empty() ) {
603
      cout << " ";
604
    }
605
    cout << FileListInserter( s_main, extension );
606
    cout << "\n\n";
607
    write_main_target_list( cpp_main,
608
                            "$(CXX) $(CXXFLAGS)",
609
                            local_libs + " $(CCLIBFLAGS)" );
610
    write_main_target_list( c_main,
611
                            "$(CC) $(CFLAGS)" ,
612
                            local_libs + " $(CLIBFLAGS)");
613
    write_main_target_list( s_main,
614
                            "$(CC) $(CFLAGS)" ,
615
                            local_libs + " $(CLIBFLAGS)");
616
  }
49 rm5248 617
 
618
  //
619
  //Write out shared libraries
620
  //
621
  if( !lib_files.empty() ){
622
    cout << "#\n"
623
         << "# SO targets\n"
624
         << "#\n\n";
625
 
626
    for( set<string>::const_iterator it = lib_files.begin();
627
         it != lib_files.end();
628
         ++it ) {
629
      string basename( DirList::basename( *it) );
630
 
631
      cout << basename << ":\t";
632
      cout << basename << ".o $(OBJFILES)\n";
633
      cout << "$(CC) -shared -Wl,-soname," << basename << ".so -o $(OBJFILES)\n";
634
    }
635
  }
636
 
46 rm5248 637
}
638
 
639
 
640
void Makefile::write_main_target_list( const set<string> &list,
641
                                    string compile,
642
                                    string local_libs ) {
643
  for( set<string>::const_iterator it = list.begin();
644
       it != list.end();
645
       ++it ) {
646
    string basename( DirList::basename( *it ) );
647
 
648
#ifdef WINDOWS
649
    cout << (basename + ".exe") << ":\t"
650
#else
651
    cout << basename << ":\t"
652
#endif
653
         << basename << ".o $(OBJFILES)" << '\n';
654
 
655
#ifdef WINDOWS
656
    cout << '\t' << compile << " -o " << (basename + ".exe") << ' '
657
#else
658
    cout << '\t' << compile << " -o " << basename << ' '
659
#endif
660
         << basename << ".o $(OBJFILES)" << local_libs
661
         << "\n\n";
662
  }
663
}
664
 
665
 
666
void Makefile::doFork(int fileds){
667
        //Child process
668
        dup2( fileds, STDOUT_FILENO ); //make output go to pipe instead of STDOUT
669
 
670
        set<string> allDefines;
671
 
672
        char* cstrCppFlags = (char*)malloc( cpp_flags.size() );
673
        memcpy( cstrCppFlags, cpp_flags.c_str(), cpp_flags.size() + 1 );
674
        char* define = strtok( cstrCppFlags, " " );
675
        while( define != NULL && define < ( cstrCppFlags + cpp_flags.size() ) ){
676
                if( define[ 0 ] == '-' && define[ 1 ] == 'D' ){
677
                        //this is a define
678
                        allDefines.insert( string( define ) );
679
                }
680
                define = strtok( NULL, " " );
681
        }
682
 
683
        int totalElements = cpp_files.size() + c_files.size() + allDefines.size() + 3; //all c/cpp files, plus three for "gcc" "-MM" [defines] [args] NULL
684
        char** argArray = (char**)malloc( sizeof(char*) * totalElements );
685
        int currentArgSpot = 0;
686
 
687
        // put in the first parameters for the GCC exec call
688
        char* gcc = (char*)malloc(4);
689
        memcpy(gcc, "gcc", 4);
690
        char* mm = (char*)malloc(4);
691
        memcpy( mm, "-MM", 4);
692
 
693
        argArray[currentArgSpot++] = gcc;
694
        argArray[currentArgSpot++] = mm;
695
 
696
        //Now, let's add in each define statement
697
        for( set<string>::iterator it = allDefines.begin(); it != allDefines.end(); it++  ){
698
                char* thedefine = (char*)malloc( (*it).size() + 1 );
699
                memcpy( thedefine, (*it).c_str(), (*it).size() + 1 );
700
                argArray[currentArgSpot++] = thedefine;
701
        }
702
 
703
        //Add in all the CPP files
704
        for( set<string>::iterator it = cpp_files.begin(); it != cpp_files.end(); it++ ){
705
                char* toAdd = (char*)malloc( (*it).size() + 1 );
706
                memcpy( toAdd, (*it).c_str(), (*it).size() + 1 );
707
                argArray[currentArgSpot++] = toAdd;
708
        }
709
 
710
        //add in all the C files
711
        for( set<string>::iterator it = c_files.begin(); it != c_files.end(); it++ ){
712
                char* toAdd = (char*)malloc( (*it).size() + 1 );
713
                memcpy( toAdd, (*it).c_str(), (*it).size() + 1 );
714
                argArray[currentArgSpot++] = toAdd;
715
        }
716
        argArray[currentArgSpot] = NULL;
717
 
718
        execvp( "gcc", argArray );
719
 
720
        //should not get here
721
        perror("execvp");
722
        exit( 2 );
723
 
724
}
725
 
726
 
727
void Makefile::write_dependencies(){
728
  cout << "#\n"
729
       << "# Dependencies\n"
730
       << "#\n\n";
731
 
732
  int fileds[2];
733
  if( pipe( fileds ) < 0 ) perror("pipe");
734
 
735
//  if( (*configuration)["c_compiler"].compare("gcc")  ){
736
  if( 1 ){
737
    //Fork and read in the data from gcc
738
    //command: gcc -MM *.cpp *.c $(CPPFLAGS)
739
    switch( fork() ){
740
      case 0:
741
        //Child process
742
        //close( fileds[0] );
743
        doFork( fileds[1] );
744
     case -1:
745
       //bad error.  
746
       exit( 3 );
747
     default:
748
       //parent process
749
       close( fileds[1] );
750
    }
751
    char read_buffer[100];
752
    int val;
753
    while( val = read( fileds[0], read_buffer, 100 ), val > 0 ){
754
      read_buffer[val] = '\0';
755
      cout << read_buffer;
756
    }
757
  }
758
 
759
  cout << '\n';
760
}
761
 
762
/*
763
void Write::write_archive_targets( ){
764
  cout << "#\n";
765
  cout << "# Archive Targets\n";
766
  cout << "#\n";
767
}
768
 
769
void Write::write_shared_obj_targets(  ){
770
  cout << "#\n";
771
  cout << "# Shared Object Targets\n";
772
  cout << "#\n";
773
}
47 rm5248 774
*/
46 rm5248 775
 
47 rm5248 776
void Makefile::write_install_targets( ){
46 rm5248 777
  cout << "#\n";
778
  cout << "# Installation Targets\n";
779
  cout << "#\n";
47 rm5248 780
 
781
  const char* extension = "";
782
#ifdef WINDOWS
783
  extension = ".exe";
784
#endif
785
 
786
  //First, write out our dependencies
46 rm5248 787
  cout << "\n";
788
  cout << "install: ";
47 rm5248 789
  cout << FileListInserter( cpp_main, extension );
790
  if( !cpp_main.empty() ) {
791
    cout << " ";
792
  }
793
 
794
  cout << FileListInserter( c_main, extension );
795
  if( !c_main.empty() ) {
796
    cout << " ";
797
  }
798
 
799
  cout << FileListInserter( s_main, extension );
800
  cout << "\n";
801
 
802
  //Now, write out the actual install command
803
  cout << "\t/usr/bin/install ";
46 rm5248 804
 
47 rm5248 805
  cout << FileListInserter( cpp_main, extension );
806
  if( !cpp_main.empty() ) {
807
    cout << " ";
808
  }
46 rm5248 809
 
47 rm5248 810
  cout << FileListInserter( c_main, extension );
811
  if( !c_main.empty() ) {
812
    cout << " ";
813
  }
814
 
815
  cout << FileListInserter( s_main, extension );
816
 
817
  cout << (*configuration)["prefix"];
818
  cout << "\n\n" ;
46 rm5248 819
}
820
 
48 rm5248 821
 
822
void Makefile::write_trailer( bool useGCC ){
46 rm5248 823
  cout << "#\n";
824
  cout << "# Housekeeping\n";
825
  cout << "#\n";
826
  cout << "\n";
827
  cout << "Archive:\tarchive.tgz\n";
828
  cout << "\n";
829
  cout << "archive.tgz:\t$(SOURCEFILES) Makefile\n";
830
  cout << "\ttar cf - $(SOURCEFILES) Makefile | gzip > archive.tgz\n";
831
  cout << '\n';
832
 
833
  cout << "clean:\n"
834
       << "\t-/bin/rm $(OBJFILES)";
48 rm5248 835
  if( !cpp_main.empty() ){
836
    cout << " " << FileListInserter( cpp_main, ".o" );
46 rm5248 837
  }
48 rm5248 838
  if( !c_main.empty() ){
839
    cout << " " << FileListInserter( c_main, ".o" );
46 rm5248 840
  }
48 rm5248 841
  if( !s_main.empty() ){
842
    cout << " " << FileListInserter( s_main, ".o" );
46 rm5248 843
  }
844
  if(useGCC) {
845
    cout << " core 2> /dev/null\n";
846
  } else {
847
    cout << " ptrepository SunWS_cache .sb ii_files core 2> /dev/null\n";
848
  }
849
  cout << '\n';
850
  cout << "realclean:        clean\n";
851
  cout << "\t-/bin/rm -rf ";
852
  if(products.empty()) {
853
#ifdef WINDOWS
48 rm5248 854
    cout << FileListInserter( cpp_main, ".exe" );
46 rm5248 855
#else
48 rm5248 856
    cout << FileListInserter( cpp_main, "" );
46 rm5248 857
#endif
48 rm5248 858
    if( !cpp_main.empty() ) {
46 rm5248 859
      cout << " ";
860
    }
861
#ifdef WINDOWS
48 rm5248 862
    cout << FileListInserter( c_main, ".exe" );
46 rm5248 863
#else
48 rm5248 864
    cout << FileListInserter( c_main, "" );
46 rm5248 865
#endif
48 rm5248 866
    if( !c_main.empty() ) {
46 rm5248 867
      cout << " ";
868
    }
869
#ifdef WINDOWS
48 rm5248 870
    cout << FileListInserter( s_main, ".exe" );
46 rm5248 871
#else
48 rm5248 872
    cout << FileListInserter( s_main, "" );
46 rm5248 873
#endif
48 rm5248 874
    if( !s_main.empty() ) {
46 rm5248 875
      cout << " ";
876
    }
877
  } else {
878
    for(set<string>::iterator it = products.begin();
879
        it != products.end();
880
        ++it) {
881
      cout << *it << ' ';
882
    }
883
  }
884
  cout << endl; // to flush buffer
885
}
47 rm5248 886
 
48 rm5248 887
 
47 rm5248 888
void Makefile::findMainPrograms(){
889
 
890
        //First, let's check all of our C files
891
        for( set<string>::iterator it = c_files.begin(); it != c_files.end(); it++ ){
892
                if( DirList::hasMainFunction( (*it) ) ){
893
                        c_main.insert( *it );
894
                }else{
895
                        c_other.insert( *it );
896
                }
897
        }
898
 
899
        //Now, all of our CPP files
900
        for( set<string>::iterator it = cpp_files.begin(); it != cpp_files.end(); it++ ){
901
                if( DirList::hasMainFunction( (*it) ) ){
902
                        cpp_main.insert( *it );
903
                }else{
904
                        cpp_other.insert( *it );
905
                }
906
        }
907
 
908
        //Finally, all of our assembly files
909
        for( set<string>::iterator it = s_files.begin(); it != s_files.end(); it++ ){
910
                if( DirList::hasMainLabel( (*it) ) ){
911
                        s_main.insert( *it );
912
                }else{
913
                        s_other.insert( *it );
914
                }
915
        }
916
 
917
}
48 rm5248 918
 
49 rm5248 919
void Makefile::findLibraries(){
920
        //First, let's check all of our C files
921
        for( set<string>::iterator it = c_files.begin(); it != c_files.end(); it++ ){
922
                if( (*it).find( "lib" ) == string::npos ){
923
                        lib_files.insert( *it );
924
                }
925
        }
926
 
927
        //Now, all of our CPP files
928
        for( set<string>::iterator it = cpp_files.begin(); it != cpp_files.end(); it++ ){
929
        }
930
 
931
        //Finally, all of our assembly files
932
        for( set<string>::iterator it = s_files.begin(); it != s_files.end(); it++ ){
933
        }
934
 
935
}
936
 
48 rm5248 937
void Makefile::remove_old_files(){
938
        FILE* theFile;
939
 
940
        for( set<string>::iterator it = c_files.begin(); it != c_files.end(); it++ ){
941
                theFile = fopen( (*it).c_str(), "r" );
942
                if( theFile == NULL ){
943
                        c_files.erase( it );
944
                }else{
945
                        fclose( theFile );
946
                }
947
        }
948
 
949
        for( set<string>::iterator it = cpp_files.begin(); it != cpp_files.end(); it++ ){
950
                theFile = fopen( (*it).c_str(), "r" );
951
                if( theFile == NULL ){
952
                        cpp_files.erase( it );
953
                }else{
954
                        fclose( theFile );
955
                }
956
        }
957
 
958
        for( set<string>::iterator it = h_files.begin(); it != h_files.end(); it++ ){
959
                theFile = fopen( (*it).c_str(), "r" );
960
                if( theFile == NULL ){
961
                        h_files.erase( it );
962
                }else{
963
                        fclose( theFile );
964
                }
965
        }
966
}
49 rm5248 967
 
968
void Makefile::addFiles( DirList* dirlist ){
969
        cpp_files.insert( dirlist->cpp.begin(), dirlist->cpp.end() );
970
        c_files.insert( dirlist->c.begin(), dirlist->c.end() );
971
        h_files.insert( dirlist->h.begin(), dirlist->h.end() );
972
}
67 rm5248 973
 
974
void Makefile::initializeMakefileVariables(){
975
        makefileVariables[ "RM" ] = "rm -f";
976
        makefileVariables[ "AR" ] = "ar";
977
        makefileVariables[ "LINK.c" ] = "$(CC) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)";
978
        makefileVariables[ "LINK.cc" ] = "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)";
979
        makefileVariables[ "COMPILE.c" ] = "$(CC) $(CFLAGS) $(CPPFLAGS) -c";
980
        makefileVariables[ "COMPILE.cc" ] = "$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c";
981
        makefileVariables[ "CPPFLAGS" ] = "";
982
        if( (*configuration)["no_debug"] == "false" ){
983
                if((*configuration)["c_compiler"] == "gcc" ) {
984
                        makefileVariables[ "CFLAGS" ] = "-ggdb";
985
                        makefileVariables[ "CXXFLAGS" ] = "-ggdb";
986
                } else {
987
                        makefileVariables[ "CFLAGS" ] = "-g";
988
                        makefileVariables[ "CXXFLAGS" ]  = "-g -xildoff -xsb";
989
                }
990
        }else{
991
                if((*configuration)["c_compiler"] == "gcc" ) {
992
                        makefileVariables[ "CFLAGS" ] = "";
993
                        makefileVariables[ "CXXFLAGS" ] = "";
994
                } else {
995
                        makefileVariables[ "CFLAGS" ] = "";
996
                        makefileVariables[ "CXXFLAGS" ]  = "-xildoff -xsb";
997
                }
998
        }
999
        makefileVariables[ "CLIBFLAGS" ] = "-lm";
1000
        makefileVariables[ "CCLIBFLAGS" ] = "";
1001
}