Subversion Repositories Programming Utils

Rev

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