source: CMT/HEAD/source/cmt_generator.cxx @ 588

Last change on this file since 588 was 588, checked in by rybkin, 13 years ago

See C.L. 465

  • Property svn:eol-style set to native
File size: 40.5 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// See the complete license in cmt_license.txt "http://www.cecill.info".
5//-----------------------------------------------------------
6
7#include <errno.h>
8#include <stdio.h>
9
10#ifndef WIN32
11#include <unistd.h>
12#endif
13
14#include "cmt_generator.h"
15#include "cmt_use.h"
16#include "cmt_symbol.h"
17
18#include "cmt_generators.h"
19#include "cmt_log.h"
20#include "cmt_error.h"
21
22#include "cmt_install_area.h"
23
24//------------------------------------------------------------------------
25void SourceFile::set (const cmt_string name, Language& language, const cmt_string output)
26{
27  m_name = name;
28  m_language = &language;
29  m_output = output;
30 
31  CmtSystem::reduce_file_separators (m_name);
32}
33
34cmt_string SourceFile::name () const
35{
36  return (m_name);
37}
38
39Language& SourceFile::language () const
40{
41  return (*m_language);
42}
43
44cmt_string SourceFile::output () const
45{
46  return (m_output);
47}
48//------------------------------------------------------------------------
49
50//--------------------------------------------------
51CmtGenerator::CmtGenerator ()
52{
53  m_CONSTITUENT.set ("CONSTITUENT");
54  m_LINKMACRO.set ("LINKMACRO");
55  m_DEPENDENCIESOPTS.set ("DEPENDENCIESOPTS");
56  m_DOCPATH.set ("DOCPATH");
57  m_PACKAGEPATH.set ("PACKAGEPATH");
58  m_PACKAGEPREFIX.set ("PACKAGEPREFIX");
59  m_PACKAGE.set ("PACKAGE");
60  m_VERSION.set ("VERSION");
61  m_MGRSTYLE.set ("MGRSTYLE");
62  m_TITLE.set ("TITLE");
63  m_GROUP.set ("GROUP");
64  m_CONSTITUENTSUFFIX.set ("CONSTITUENTSUFFIX");
65  m_LIBRARYSUFFIX.set ("LIBRARYSUFFIX");
66  m_USER.set ("USER");
67  m_DATE.set ("DATE");
68  m_PROTOTARGET.set ("PROTOTARGET");
69  m_OBJS.set ("OBJS");
70  m_CLASSES.set ("CLASSES");
71  m_PROTOSTAMPS.set ("PROTOSTAMPS");
72  m_NAME.set ("NAME");
73  m_FILEPATH.set ("FILEPATH");
74  m_FILESUFFIX.set ("FILESUFFIX");
75  m_SUFFIX.set ("SUFFIX");
76  m_FILENAME.set ("FILENAME");
77  m_LINE.set ("LINE");
78  m_ADDINCLUDE.set ("ADDINCLUDE");
79  m_FULLNAME.set ("FULLNAME");
80  m_DIRNAME.set ("DIRNAME");
81  m_OUTPUTNAME.set ("OUTPUTNAME");
82  m_ALLOS9SOURCES.set ("ALLOS9SOURCES");
83  m_NODEBUGUSELINKOPTS.set ("NODEBUGUSELINKOPTS");
84  m_DEBUGUSELINKOPTS.set ("DEBUGUSELINKOPTS");
85  m_USEINCLUDES.set ("USEINCLUDES");
86  m_HASTARGETTAG.set ("HASTARGETTAG");
87  m_HASDEPENDENCIES.set ("HASDEPENDENCIES");
88}
89
90//--------------------------------------------------
91void CmtGenerator::reset ()
92{
93  m_CONSTITUENT = "";
94  m_LINKMACRO = "";
95  m_DEPENDENCIESOPTS = "";
96  m_DOCPATH = "";
97  m_PACKAGEPATH = "";
98  m_PACKAGEPREFIX = "";
99  m_PACKAGE = "";
100  m_VERSION = "";
101  m_MGRSTYLE = "";
102  m_TITLE = "";
103  m_GROUP = "";
104  m_CONSTITUENTSUFFIX = "";
105  m_LIBRARYSUFFIX = "";
106  m_USER = "";
107  m_DATE = "";
108  m_PROTOTARGET = "";
109  m_OBJS = "";
110  m_CLASSES = "";
111  m_PROTOSTAMPS = "";
112  m_NAME = "";
113  m_FILEPATH = "";
114  m_FILESUFFIX = "";
115  m_SUFFIX = "";
116  m_FILENAME = "";
117  m_LINE = "";
118  m_ADDINCLUDE = "";
119  m_FULLNAME = "";
120  m_OUTPUTNAME = "";
121  m_ALLOS9SOURCES = "";
122  m_NODEBUGUSELINKOPTS = "";
123  m_DEBUGUSELINKOPTS = "";
124  m_USEINCLUDES = "";
125  m_HASTARGETTAG = "";
126  m_HASDEPENDENCIES = "";
127  m_PACKINCLUDES = "";
128  m_PACKOS9      = false;
129  m_GENERATOR    = "";
130
131  is_library     = false;
132  is_application = false;
133  srcdir       = "";
134  docdir       = "";
135  cmtdir       = "";
136  incdir       = "";
137  src          = "$(src)";
138  doc          = "$(doc)";
139  inc          = "$(inc)";
140  mgr          = "$(mgr)";
141  cmt          = "$(cmt)";
142  protos       = "";
143  protonames   = "";
144  os9sources   = "";
145
146  m_source_files.clear ();
147  m_bin = "";
148  m_output_file_name = "";
149  m_output_file = 0;
150  m_constituent = 0;
151
152  Language::setup_all_fragments ();
153
154  CmtSystem::cd (Cmt::get_current_dir ());
155
156  cmt_string branch = CmtSystem::current_branch ();
157
158  if ((branch == "mgr") || (branch == "cmt"))
159    {
160      if (CmtSystem::test_directory ("../src"))
161        {
162          srcdir = "..";
163          srcdir += CmtSystem::file_separator ();
164          srcdir += "src";
165          srcdir += CmtSystem::file_separator ();
166        }
167      else
168        {
169          srcdir = "";
170        }
171
172      if (CmtSystem::test_directory ("../doc"))
173        {
174          docdir = "..";
175          docdir += CmtSystem::file_separator ();
176          docdir += "doc";
177          docdir += CmtSystem::file_separator ();
178        }
179      else
180        {
181          docdir = "";
182        }
183
184      if (CmtSystem::test_directory ("../cmt"))
185        {
186          cmtdir = "..";
187          cmtdir += CmtSystem::file_separator ();
188          cmtdir += "cmt";
189          cmtdir += CmtSystem::file_separator ();
190        }
191      else if (CmtSystem::test_directory ("../mgr"))
192        {
193          cmtdir = "..";
194          cmtdir += CmtSystem::file_separator ();
195          cmtdir += "mgr";
196          cmtdir += CmtSystem::file_separator ();
197        }
198      else
199        {
200          cmtdir = CmtSystem::pwd ();
201          cmtdir += CmtSystem::file_separator ();
202        }
203
204      if (CmtSystem::test_directory ("../src"))
205        {
206          incdir = "..";
207          incdir += CmtSystem::file_separator ();
208          incdir += "src";
209          incdir += CmtSystem::file_separator ();
210        }
211      else
212        {
213          incdir = "";
214        }
215    }
216  else
217    {
218      srcdir = ".";
219      srcdir += CmtSystem::file_separator ();
220      docdir = ".";
221      docdir += CmtSystem::file_separator ();
222      cmtdir = CmtSystem::pwd ();
223      cmtdir += CmtSystem::file_separator ();
224      incdir = ".";
225      incdir += CmtSystem::file_separator ();
226    }
227}
228
229//--------------------------------------------------
230bool CmtGenerator::prepare_output (const cmt_string& package,
231                                   const Constituent& constituent,
232                                   const cmt_string& file)
233{
234  m_PACKAGE = package;
235  m_CONSTITUENT = constituent.name;
236  m_CONSTITUENTSUFFIX = constituent.suffix;
237
238  m_PACKOS9 = constituent.need_OS9;
239
240  m_output_file_name = cmtdir + m_CONSTITUENT + ".";
241
242  if (Cmt::build_nmake ())
243    {
244      m_output_file_name += "nmake";
245    }
246  else
247    {
248      m_output_file_name += "make";
249    }
250 
251  if (file != "") m_output_file_name = file;
252
253  m_output_file_name += "new";
254
255
256  m_output_file = fopen (m_output_file_name.c_str (), "wb");
257  if (m_output_file != NULL)
258    {
259      return (true);
260    }
261  else
262    {
263      return (false);
264    }
265}
266
267//--------------------------------------------------
268void CmtGenerator::check (const cmt_string& name)
269{
270  static cmt_string old;
271  static cmt_string backup;
272
273  old = name;
274
275  int pos = old.find_last_of ("new");
276  old.erase (pos);
277
278  if (!CmtSystem::compare_files (old, name))
279    {
280      backup = old;
281      backup += "sav";
282
283      unlink (backup.c_str ());
284      rename (old.c_str (), backup.c_str ());
285      rename (name.c_str (), old.c_str ());
286    }
287  else
288    {
289      unlink (name);
290    }
291}
292
293//--------------------------------------------------
294void CmtGenerator::commit (const cmt_string& name)
295{
296  static cmt_string old;
297  static cmt_string backup;
298
299  old = name;
300
301  int pos = old.find_last_of ("new");
302  old.erase (pos);
303
304  if (CmtSystem::test_file (old))
305    {
306      backup = old;
307      backup += "sav";
308
309      unlink (backup.c_str ());
310      rename (old.c_str (), backup.c_str ());
311    }
312
313  rename (name.c_str (), old.c_str ());
314}
315
316//--------------------------------------------------
317void CmtGenerator::terminate ()
318{
319  CmtSystem::close_ostream (m_output_file, m_output_file_name);
320  //  fclose (m_output_file);
321
322  //--- Complete the operation --------------
323
324  commit (m_output_file_name);
325}
326
327//--------------------------------------------------
328void CmtGenerator::fill_names_outputs ()
329{
330  bool first = true;
331
332  m_LINE = "";
333  m_OBJS = "";
334
335  for (int i = 0; i < m_source_files.size (); i++)
336    {
337      const SourceFile& file = m_source_files[i];
338      const cmt_string name = file.name ();
339      const cmt_string output = file.output ();
340
341      if (output != "")
342        {
343          if (first)
344            {
345              first = false;
346            }
347          else
348            {
349              m_LINE += " ";
350              m_OBJS += " ";
351            }
352          m_LINE += name;
353          m_OBJS += output;
354        }
355
356      if (Cmt::get_debug ())
357        {
358          cout << "CmtGenerator::fill_names_outputs>" << endl;
359          cout << "name=" << name << " LINE=" << m_LINE << endl;
360          cout << "output=" << output << " OBJS=" << m_OBJS << endl;
361        }
362    }
363
364  filter_path (m_LINE.value);
365}
366
367//--------------------------------------------------
368void CmtGenerator::fill_outputs ()
369{
370  bool first = true;
371
372  m_OBJS = "";
373
374  for (int i = 0; i < m_source_files.size (); i++)
375    {
376      const SourceFile& file = m_source_files[i];
377      const cmt_string output = file.output ();
378
379      if (output != "")
380        {
381          if (first)
382            {
383              first = false;
384            }
385          else
386            {
387              m_OBJS += " ";
388            }
389
390          m_OBJS += output;
391        }
392
393      if (Cmt::get_debug ())
394        {
395          cout << "CmtGenerator::fill_outputs> output=" << output << " OBJS=" << m_OBJS << endl;
396        }
397
398    }
399
400  if (Cmt::get_debug ())
401    {
402      cout << "CmtGenerator::fill_outputs> OBJS=" << m_OBJS << endl;
403    }
404
405}
406
407/*
408//--------------------------------------------------
409void CmtGenerator::prepare_use_context ()
410{
411  cmt_string path;
412  cmt_string substitution;
413
414  Use* use = &Use::current ();
415
416  m_deps_builder.clear ();
417
418  if (use->include_path != "none")
419    {
420      if (use->include_path == "")
421        {
422          m_deps_builder.add (incdir, "$(src)");
423        }
424      else
425        {
426          substitution = use->include_path;
427         
428          path = substitution;
429          Symbol::expand (path);
430         
431          CmtSystem::reduce_file_separators (path);
432
433          m_deps_builder.add (path, substitution);
434        }
435    }
436
437  m_deps_builder.add_includes (*use);
438
439  Use::UsePtrVector& uses = Use::get_ordered_uses ();
440
441  if (uses.size () > 0)
442    {
443      int number;
444
445      for (number = 0; number < uses.size (); number++)
446        {
447          use = uses[number];
448          if (use->discarded) continue;
449
450          if (use->real_path != "")
451            {
452              if (use->include_path != "none")
453                {
454                  if (use->include_path == "")
455                    {
456                      use->get_full_path (path);
457                      path += CmtSystem::file_separator ();
458                      path += "src";
459
460                      substitution = "$(";
461                      substitution += use->prefix;
462                      substitution += "ROOT)";
463                      substitution += CmtSystem::file_separator ();
464                      substitution += "src";
465                      substitution += CmtSystem::file_separator ();
466                    }
467                  else
468                    {
469                      substitution = use->include_path;
470
471                      path = substitution;
472                      Symbol::expand (path);
473
474                      CmtSystem::reduce_file_separators (path);
475                    }
476
477                  m_deps_builder.add (path, substitution);
478                }
479
480              m_deps_builder.add_includes (*use);
481            }
482        }
483    }
484}
485*/
486//--------------------------------------------------
487void CmtGenerator::filter_path (cmt_string& text)
488{
489  CmtSystem::compress_path (text);
490
491  text.replace_all ("./../src/../", "../");
492  text.replace_all ("./../src/", "$(src)");
493
494  text.replace_all (".\\..\\src\\..\\", "..\\");
495  text.replace_all (".\\..\\src\\", "$(src)");
496
497  text.replace_all ("../src/../", "../");
498  text.replace_all ("../src/", "$(src)");
499
500  text.replace_all ("..\\src\\..\\", "..\\");
501  text.replace_all ("..\\src\\", "$(src)");
502
503  text.replace_all ("../doc/../", "../");
504  text.replace_all ("../doc/", "$(doc)");
505
506  text.replace_all ("..\\doc\\..\\", "..\\");
507  text.replace_all ("..\\doc\\", "$(doc)");
508
509  text.replace_all ("$(src)$(src)", "$(src)");
510}
511
512/**
513   Scan a complete file spec (with possibly wild cards and directory)
514   given in full_name ad fill in a vector of found file names.
515
516   Result of the scan is filtered against matching suffixes
517
518   Returns the count of non empty file names really found.
519
520*/
521int CmtGenerator::get_all_files (const cmt_string& full_name,
522                                 const cmt_vector<cmt_regexp>& exclude_exprs,
523                                 const cmt_vector<cmt_regexp>& select_exprs,
524                                 CmtSystem::cmt_string_vector& files)
525{
526  static cmt_string suffix;
527  static cmt_string name;
528
529  bool has_excludes = false;
530  bool has_selects = false;
531
532  suffix = "";
533  name = "";
534
535  files.clear ();
536
537  has_excludes = (exclude_exprs.size () > 0);
538  has_selects = (select_exprs.size () > 0);
539
540  CmtSystem::get_dot_suffix (full_name, suffix);
541
542  bool wilcarded_suffix = false;
543
544  if (suffix == ".*") wilcarded_suffix = true;
545
546  int count = 0;
547
548  if (full_name.find ('*') != cmt_string::npos)
549    {
550      CmtSystem::scan_dir (full_name, files);
551
552      if (Cmt::get_debug ())
553        {
554          cout << "CMT::get_all_files> full_name=" << full_name <<
555            " pwd=" << CmtSystem::pwd () << endl;
556          cout << "CMT::get_all_files> files.size=" <<  files.size () << endl;
557        }
558
559      /**
560
561      We have to treat patterns of the form *.xxx (ie with a
562      suffix) thus we filter out everything that could have been
563      collected with a different suffix because the
564      CmtSystem::scan_dir function only handles patterns of the
565      form xxx* (ie with trailing *)
566
567      [If the original suffix was empty (ie files specified using
568      xx*) this means getting files without any dot-suffix. This
569      may be incorrect??]
570
571      */
572
573      for (int j = 0; j < files.size (); j++)
574        {
575          cmt_string& n = files[j];
576
577          bool rejected = false;
578
579          if (n == "")
580            {
581              rejected = true;
582            }
583
584          if (!rejected && has_selects)
585            {
586              rejected = true;
587
588              for (int k = 0; k < select_exprs.size (); k++)
589                {
590                  const cmt_regexp& exp = select_exprs[k];
591                  if (exp.match (n))
592                    {
593                      rejected = false;
594                      break;
595                    }
596                }
597            }
598
599          if (!rejected && has_excludes)
600            {
601              for (int k = 0; k < exclude_exprs.size (); k++)
602                {
603                  const cmt_regexp& exp = exclude_exprs[k];
604                  if (exp.match (n))
605                    {
606                      rejected = true;
607                      break;
608                    }
609                }
610            }
611
612          if (!rejected)
613            {
614              static cmt_string s;
615
616              CmtSystem::get_dot_suffix (n, s);
617              if (!wilcarded_suffix && (s != suffix)) 
618                {
619                  rejected = true;
620                }
621              else
622                {
623                  count++;
624                }
625            }
626
627          if (Cmt::get_debug ())
628            {
629              if (rejected)
630                {
631                  cout << "CMT::get_all_files> reject " <<  n << endl;
632                }
633              else
634                {
635                  cout << "CMT::get_all_files> keep " <<  n << endl;
636                }
637            }
638
639          if (rejected)
640            {
641              n = "";
642            }
643        }
644    }
645  else
646    {
647      if (full_name != "")
648        {
649          bool rejected = false;
650
651          if (has_excludes)
652            {
653              for (int k = 0; k < exclude_exprs.size (); k++)
654                {
655                  const cmt_regexp& exp = exclude_exprs[k];
656                  if (exp.match (full_name))
657                    {
658                      rejected = true;
659                      break;
660                    }
661                }
662            }
663
664          if (!rejected)
665            {
666              cmt_string& n = files.add ();
667
668              n = full_name;
669
670              count++;
671            }
672        }
673    }
674
675  return (count);
676}
677
678//--------------------------------------------------
679void CmtGenerator::set_full_name (cmt_string& full_name, cmt_string& file)
680{
681  full_name = "";
682
683  Symbol::expand (file);
684
685  if (file == "") return;
686 
687  if (!CmtSystem::absolute_path (file))
688    {
689      full_name = srcdir;
690      if (full_name != "") full_name += CmtSystem::file_separator ();
691    }
692 
693  full_name += file;
694
695  CmtSystem::reduce_file_separators (full_name);
696}
697
698//------------------------------------------------------------------------
699//static ApplicationGenerator ApplicationContext;
700static LibraryGenerator LibraryContext;
701static DocumentGenerator DocumentContext;
702static ReadmeGenerator ReadmeContext;
703static PrototypeGenerator PrototypeContext;
704static DefaultMakefileGenerator DefaultMakefileContext;
705static MSDEVGenerator MSDEVContext;
706static VSNETGenerator VSNETContext;
707static MakeSetupGenerator MakeSetupContext;
708static ConstituentsMakefileGenerator ConstituentsMakefileContext;
709static PackagesMakefileGenerator PackagesMakefileContext;
710static DependencyGenerator DependencyContext;
711
712//--------------------------------------------------
713int Generator::build_msdev_workspace (const Constituent::ConstituentVector& constituents)
714{
715  return (MSDEVContext.build_workspace (constituents));
716}
717
718//--------------------------------------------------
719int Generator::build_msdev (const Constituent& constituent)
720{
721  return (MSDEVContext.build_project (constituent));
722}
723
724//--------------------------------------------------
725int Generator::build_vsnet_workspace (const Constituent::ConstituentVector& constituents)
726{
727  return (VSNETContext.build_workspace (constituents));
728}
729
730//--------------------------------------------------   
731int Generator::build_vsnet (const Constituent& constituent)
732{
733  return (VSNETContext.build_project (constituent));
734}
735
736//--------------------------------------------------
737void Generator::build_make_setup (const cmt_string& package)
738{
739  MakeSetupContext.build (package);
740}
741
742//--------------------------------------------------
743void Generator::build_constituents_makefile (const cmt_string& package,
744                                             const cmt_string& file)
745//                                           const CmtSystem::cmt_string_vector& arguments)
746{
747  ConstituentsMakefileContext.build (package, file);
748  //  ConstituentsMakefileContext.build (package, arguments);
749}
750
751//--------------------------------------------------
752int Generator::build_constituent_infile (const Constituent& constituent,
753                                         const cmt_string& outdir,
754                                         bool usecmt)
755{
756  cmt_string file (constituent.name + ".in");
757  if (outdir != "")
758    {
759      if (outdir [outdir.size () - 1] != CmtSystem::file_separator ())
760        file = outdir + CmtSystem::file_separator () + file;
761      else
762        file = outdir + file;
763    }
764
765  static InGenerator InGen (usecmt);
766
767  bool gen (true);
768  ostringstream os;
769  ofstream s;
770  //  s.open (file);
771  s.open (file, ios::in);
772  if (s) // file already exists
773    {
774      InGen.build (constituent, os);
775      ostringstream osn;
776      osn << s.rdbuf ();
777      if (os.str () == osn.str ())
778        {
779          //      cerr << file << " up-to-date" << endl;
780          gen = false;
781        }
782    }
783  s.clear ();
784  s.close ();
785  s.clear ();
786  if (gen)
787    {
788      s.open (file);
789      if (!s)
790        {
791          CmtError::set (CmtError::file_access_error, file);
792          return -1;
793        }
794      s.exceptions (ios::failbit | ios::badbit);
795      try
796        {
797          if (os.str ().size () != 0)
798            {
799              //  cerr << file << " contents already generated" << endl;
800              s << os.str ();
801            }
802          else
803            {
804              InGen.build (constituent, s);
805            }
806          s.close (); // ios_base::failbit
807        }
808      catch (const ios::failure& e)
809        {
810          CmtSystem::close_ostream (NULL, file + ": " + cmt_string (e.what ()));
811          return -1;
812        }
813    }
814
815      //  InGen.build (constituent, s);
816
817  //  s.close (); // ios_base::failbit
818
819  return 0;
820}
821
822//--------------------------------------------------
823int Generator::build_library_links_infile (const cmt_string& outdir)
824{
825#ifndef WIN32
826  cmt_string file ("library_links.in");
827  if (outdir != "")
828    {
829      if (outdir [outdir.size () - 1] != CmtSystem::file_separator ())
830        file = outdir + CmtSystem::file_separator () + file;
831      else
832        file = outdir + file;
833    }
834
835  bool wrote (false);
836  ostringstream ls;
837
838  Use::UsePtrVector& Uses = Use::get_ordered_uses ();
839  Use& current_use = Use::current ();
840  Use::UsePtrVector uses (Uses);
841  uses.push_back (&Use::current ());
842
843  cmt_string shlibsuffix;
844  {
845    Symbol* macro = Symbol::find ("shlibsuffix");
846    if (macro == 0)
847      {
848        CmtError::set(CmtError::configuration_error, "shlibsuffix undefined");
849        return -1;
850      }
851    shlibsuffix = macro->build_macro_value ();
852    Symbol::expand (shlibsuffix);
853  }
854
855  for (int i = 0; i < uses.size (); i++)
856    {
857      Use* use = uses[i];
858
859      if (use == 0) continue;
860      if (use->discarded) continue;
861      if (use->m_hidden) continue;
862
863      if (use->get_package_name () == "CMT") continue;
864      if (!use->located ()) continue;
865      //use->remove_library_links (cmtinstallarea, tag, shlibsuffix, symunlinkcmd);
866      cmt_string s (use->get_package_name ());
867      s += "_libraries";
868      const Symbol* libraries_macro = Symbol::find (s);
869      if (libraries_macro == 0) continue;
870      cmt_string libraries = libraries_macro->build_macro_value ();
871      Symbol::expand (libraries);
872      static CmtSystem::cmt_string_vector values;
873     
874      CmtSystem::split (libraries, " \t", values);
875     
876      for (int j = 0; j < values.size (); j++)
877        {
878          const cmt_string& library = values[j];
879         
880          static cmt_string libname;
881          static cmt_string name;
882         
883          // Is it a simple name or a complete path?
884         
885          libname = library;
886          Symbol::expand (libname);
887          if (0 == libname.size ()) continue;
888         
889          CmtSystem::cmt_string_vector paths;
890          use->absolute_library_path (libname,
891                                      shlibsuffix, 
892                                      paths);
893          for (int k = 0; k < paths.size (); k++)
894            {
895              cmt_string path (paths[k]);
896              Symbol::expand (path);
897              if (0 == path.size ()) continue;
898              if (wrote) ls << " ";
899              else wrote = true;
900              ls << CmtSystem::quote (path, " \t");
901            }
902        }
903    }
904  ostringstream os;
905  if (wrote)
906    {
907      os << "macro ";
908      os << current_use.get_package_name () + "_libraries ";
909      os << CmtSystem::quote (ls.str ().c_str (), " \t");
910      os << "\n";
911
912      os << "macro shlibsuffix ";
913      os << CmtSystem::quote (shlibsuffix, " \t");
914      os << "\n";
915
916      cmt_string symlinkcmd;
917      {
918        Symbol* macro = Symbol::find ("library_install_command");
919        if (macro != 0)
920          {
921            symlinkcmd = macro->build_macro_value ();
922            Symbol::expand (symlinkcmd);
923          }
924      }
925      os << "macro library_install_command ";
926      os << CmtSystem::quote (symlinkcmd, " \t");
927      os << "\n";
928
929      cmt_string symunlinkcmd;
930      {
931        Symbol* macro = Symbol::find ("symunlink");
932        if (macro != 0)
933          {
934            symunlinkcmd = macro->build_macro_value ();
935            Symbol::expand (symunlinkcmd);
936          }
937      }
938      os << "macro symunlink ";
939      os << CmtSystem::quote (symunlinkcmd, " \t");
940      os << "\n";
941
942      if (current_use.get_strategy ("InstallArea"))
943        {
944          os << "build_strategy with_installarea\n";
945
946          const CmtInstallAreaMgr& ia_mgr = CmtInstallAreaMgr::instance ();
947         
948          cmt_string cmtinstallarea = ia_mgr.get_installarea ();
949          {
950            Symbol* symbol = Symbol::find ("CMTINSTALLAREA");
951            if (symbol != 0)
952              {
953                cmtinstallarea = symbol->build_macro_value ();
954                Symbol::expand (cmtinstallarea);
955              }
956          }
957          os << "macro CMTINSTALLAREA ";
958          os << CmtSystem::quote (cmtinstallarea, " \t");
959          os << "\n";
960
961          cmt_string tag;
962          {
963            Symbol* macro = Symbol::find ("tag");
964            if (macro != 0)
965              {
966                tag = macro->build_macro_value ();
967                Symbol::expand (tag);
968              }
969          }
970          os << "macro tag ";
971          os << CmtSystem::quote (tag, " \t");
972          os << "\n";
973        }
974      //      cerr << os.str ();
975    }
976
977  // Write input requirements file
978
979  //  static InGenerator InGen (usecmt);
980
981  bool gen (true);
982  //  ostringstream os;
983  ofstream s;
984  //  s.open (file);
985  s.open (file, ios::in);
986  if (s) // file already exists
987    {
988      //      InGen.build (constituent, os);
989      ostringstream osn;
990      osn << s.rdbuf ();
991      if (os.str () == osn.str ())
992        {
993          //      cerr << file << " up-to-date" << endl;
994          gen = false;
995        }
996    }
997  s.clear ();
998  s.close ();
999  s.clear ();
1000  if (gen)
1001    {
1002      s.open (file);
1003      if (!s)
1004        {
1005          CmtError::set (CmtError::file_access_error, file);
1006          return -1;
1007        }
1008      s.exceptions (ios::failbit | ios::badbit);
1009      try
1010        {
1011          //      if (os.str ().size () != 0)
1012          //        {
1013              //  cerr << file << " contents already generated" << endl;
1014              s << os.str ();
1015              //            }
1016              //          else
1017              //            {
1018              //              InGen.build (constituent, s);
1019              //            }
1020          s.close (); // ios_base::failbit
1021        }
1022      catch (const ios::failure& e)
1023        {
1024          CmtSystem::close_ostream (NULL, file + ": " + cmt_string (e.what ()));
1025          return -1;
1026        }
1027    }
1028
1029#endif
1030  return 0;
1031}
1032
1033//--------------------------------------------------
1034int Generator::build_dependencies_infile (const Constituent* pconstituent,
1035                                          const cmt_string& outdir,
1036                                          bool usecmt)
1037{
1038  cmt_string file ("dependencies");
1039  if (0 != pconstituent)
1040    file += "_" + pconstituent->name;
1041  file += ".in";
1042
1043  if (outdir != "")
1044    {
1045      if (outdir [outdir.size () - 1] != CmtSystem::file_separator ())
1046        file = outdir + CmtSystem::file_separator () + file;
1047      else
1048        file = outdir + file;
1049    }
1050
1051  ostringstream os;
1052 
1053  cmt_string preprocessor;
1054  Symbol* macro = Symbol::find ("preprocessor_command");
1055  if (macro != 0)
1056    {
1057      preprocessor = macro->resolve_macro_value ();
1058    }
1059
1060  if (preprocessor == "")
1061    {
1062      const Use* current_use = &Use::current ();
1063      Use::UsePtrVector uses (Use::get_ordered_uses ());
1064      uses.push_back (&Use::current ());
1065     
1066      if (current_use->include_path == "none")
1067        os << "include_path none\n";
1068
1069      for (int i = uses.size () - 1; i >= 0; i--)
1070        {
1071          const Use* use = uses[i];
1072          if (use->discarded) continue;
1073          if (use->m_hidden) continue;
1074          if (!use->located ()) continue;
1075         
1076          cmt_string package_name = use->get_package_name ();
1077          if (package_name == "CMT") continue;
1078         
1079          const Symbol* filter_macro = Symbol::find (package_name + "_header_file_filter");
1080          if (filter_macro == 0) continue;
1081         
1082          const Symbol* stamp_macro = Symbol::find (package_name + "_header_file_stamp");
1083          cmt_string stamp;
1084          if (stamp_macro != 0)
1085            {
1086              stamp = stamp_macro->resolve_macro_value ();
1087            }
1088          else
1089            {
1090              use->get_full_path (stamp);
1091              switch (use->style)
1092                {
1093                case cmt_style:
1094                  stamp += CmtSystem::file_separator ();
1095                  stamp += "cmt";
1096                  break;
1097                case mgr_style:
1098                  stamp += CmtSystem::file_separator ();
1099                  stamp += "mgr";
1100                  break;
1101                }
1102              stamp += CmtSystem::file_separator ();
1103              stamp += "cmt_header_file.stamp";
1104            }
1105          if (!CmtSystem::test_file (stamp)) continue;
1106
1107          os << "macro " + package_name + "_header_file_filter ";
1108          os << CmtSystem::quote (filter_macro->resolve_macro_value (), " \t");
1109          os << "\n";
1110          os << "macro " + package_name + "_header_file_stamp ";
1111          os << CmtSystem::quote (stamp, " \t");
1112          os << "\n";
1113        }
1114    }
1115  else
1116    {
1117      os << "macro preprocessor_command ";
1118      os << CmtSystem::quote (preprocessor, " \t");
1119      os << "\n";
1120      macro = Symbol::find ("includes");
1121      if (0 != macro)
1122        {
1123          os << "macro includes ";
1124          os << CmtSystem::quote (macro->resolve_macro_value (), " \t");
1125          os << "\n";
1126        }
1127      if (0 == pconstituent)
1128        {
1129          const Constituent::ConstituentVector& constituents =
1130            Constituent::constituents ();
1131          for (int n = 0; n < constituents.size (); n++)
1132            {
1133              const Constituent& constituent = constituents[n];
1134              if (constituent.has_target_tag) continue;
1135              if (constituent.type == Document) continue;
1136              cmt_string prefix;
1137              switch (constituent.type)
1138                {
1139                case Application:
1140                  prefix = "app_";
1141                  break;
1142                case Library:
1143                  prefix = "lib_";
1144                  break;
1145                }
1146              cmt_string macro_name (prefix + constituent.name + "_cppflags");
1147              macro = Symbol::find (macro_name);
1148              if (0 != macro)
1149                {
1150                  os << "macro_append " + macro_name + " ";
1151                  os << CmtSystem::quote (macro->resolve_macro_value (), " \t");
1152                  os << "\n";
1153                }
1154            }
1155        }
1156      else if (pconstituent->type != Document)
1157        {
1158          const Constituent& constituent = *pconstituent;
1159          cmt_string prefix;
1160          switch (constituent.type)
1161            {
1162            case Application:
1163              prefix = "app_";
1164              break;
1165            case Library:
1166              prefix = "lib_";
1167              break;
1168            }
1169          cmt_string macro_name (prefix + constituent.name + "_cppflags");
1170          macro = Symbol::find (macro_name);
1171          if (0 != macro)
1172            {
1173              os << "macro_append " + macro_name + " ";
1174              os << CmtSystem::quote (macro->resolve_macro_value (), " \t");
1175              os << "\n";
1176            }
1177        }
1178    }
1179
1180  // Write input requirements file
1181
1182  bool gen (true);
1183  //  ostringstream os;
1184  ofstream s;
1185  //  s.open (file);
1186  s.open (file, ios::in);
1187  if (s) // file already exists
1188    {
1189      //      InGen.build (constituent, os);
1190      ostringstream osn;
1191      osn << s.rdbuf ();
1192      if (os.str () == osn.str ())
1193        {
1194          //      cerr << file << " up-to-date" << endl;
1195          gen = false;
1196        }
1197    }
1198  s.clear ();
1199  s.close ();
1200  s.clear ();
1201  if (gen)
1202    {
1203      s.open (file);
1204      if (!s)
1205        {
1206          CmtError::set (CmtError::file_access_error, file);
1207          return -1;
1208        }
1209      s.exceptions (ios::failbit | ios::badbit);
1210      try
1211        {
1212          //      if (os.str ().size () != 0)
1213          //        {
1214              //  cerr << file << " contents already generated" << endl;
1215              s << os.str ();
1216              //            }
1217              //          else
1218              //            {
1219              //              InGen.build (constituent, s);
1220              //            }
1221          s.close (); // ios_base::failbit
1222        }
1223      catch (const ios::failure& e)
1224        {
1225          CmtSystem::close_ostream (NULL, file + ": " + cmt_string (e.what ()));
1226          return -1;
1227        }
1228    }
1229
1230  return 0;
1231}
1232
1233//--------------------------------------------------
1234int Generator::build_constituent_makefile (const Constituent& constituent,
1235                                           bool& dependencies,
1236                                           const cmt_string& file)
1237{
1238  const cmt_string& package = Cmt::get_current_package ();
1239
1240  switch (constituent.type)
1241    {
1242    case Application:
1243      //ApplicationContext.build (package, constituent, file);
1244      //break;
1245    case Library:
1246      LibraryContext.build (package, constituent, dependencies, file);
1247      break;
1248    case Document:
1249      DocumentContext.build (package, constituent, dependencies, file);
1250      break;
1251    }
1252
1253  return (0);
1254}
1255
1256//--------------------------------------------------
1257void Generator::build_constituent_makefile (const CmtSystem::cmt_string_vector& arguments)
1258{
1259  cmt_string name;
1260  cmt_string file;
1261
1262  if (arguments.size () == 1)
1263    {
1264      file = "";
1265      name = arguments[0];
1266    }
1267  else if (arguments.size () == 2) // arguments[0].substr (0, 5) == "-out="
1268    {
1269      cmt_string arg = arguments[0];
1270      arg.erase (0, 5);
1271      file = arg;
1272      name = arguments[1];
1273    }
1274  else
1275    {
1276      CmtMessage::error ("build constituent_makefile : wrong arguments");
1277      //      cerr << "#CMT> build constituent_makefile : wrong arguments" << endl;
1278      return;
1279    }
1280
1281  const Constituent* constituent = Constituent::find (name);
1282  if (constituent != 0)
1283    {
1284      bool dependencies (false);
1285      build_constituent_makefile (*constituent, dependencies, file);
1286    }
1287}
1288
1289//--------------------------------------------------
1290void Generator::build_default_makefile ()
1291{
1292  DefaultMakefileContext.build ();
1293}
1294
1295//--------------------------------------------------
1296void Generator::build_packages_makefile (const cmt_string& package,
1297                                         const cmt_string& file)
1298{
1299  PackagesMakefileContext.build (package, file);
1300  //  UsesMakefileContext.build (package, file);
1301}
1302
1303//--------------------------------------------------
1304void Generator::build_dependencies (const CmtSystem::cmt_string_vector& arguments)
1305{
1306  DependencyContext.build (arguments);
1307}
1308
1309//--------------------------------------------------
1310void Generator::build_prototype (const cmt_string& file_name)
1311{
1312  PrototypeContext.build (file_name);
1313}
1314
1315//--------------------------------------------------
1316void Generator::build_readme (const CmtSystem::cmt_string_vector& arguments)
1317{
1318  ReadmeContext.build (arguments);
1319}
1320
1321class WinDefAwk : public PAwk
1322{
1323public :
1324  WinDefAwk (const cmt_string& library_name)
1325  {
1326    m_name = library_name;
1327  }
1328
1329  void begin ()
1330  {
1331    cout << "LIBRARY " << m_name << endl;
1332    cout << "EXPORTS" << endl;
1333  }
1334
1335  void filter (const cmt_string& line)
1336  {
1337    if (line.find ("External") == cmt_string::npos) return;
1338    if (line.find ("??_") != cmt_string::npos)
1339      {
1340        if (line.find ("operator/=") == cmt_string::npos) return;
1341        // Keep operator /= .
1342      }
1343
1344    CmtSystem::cmt_string_vector words;
1345    CmtSystem::split (line, " \t", words);
1346    if (words.size () >= 7)
1347      {
1348        int pos = 7;
1349
1350        cmt_string& fifth_word = words[4];
1351        if (fifth_word == "()") pos = 7;
1352        else if (fifth_word == "External") pos = 6;
1353        else return;
1354
1355        cmt_string& symbol = words[pos];
1356        if (symbol[0] == '_') symbol.erase (0, 1);
1357        symbol.replace_all ("\r", "");
1358        symbol.replace_all ("\n", "");
1359
1360        if ((pos == 6) && 
1361            ((line.find(": static") != cmt_string::npos) ||
1362             (line.find("(class") != cmt_string::npos)) )
1363          {
1364            // static data members are not DATA :
1365            // extern objects are not DATA :
1366            cout << " " << symbol << " " << endl;
1367          } 
1368        else if (pos == 6)
1369          {
1370            // DATA :
1371            cout << " " << symbol << "\tDATA" << endl;
1372          } 
1373        else
1374          {
1375            // code :
1376            cout << " " << symbol << " " << endl;
1377          } 
1378      }
1379  }
1380
1381  void end ()
1382  {
1383  }
1384
1385private:
1386  cmt_string m_name;
1387};
1388
1389//--------------------------------------------------
1390//void Generator::build_windefs (const cmt_string& library_name)
1391void Generator::build_windefs (const CmtSystem::cmt_string_vector& arguments)
1392{
1393  cmt_string name;
1394  //  CmtSystem::cmt_string_vector files;
1395  cmt_string files;
1396
1397  for (int i = 0; i < arguments.size (); i++)
1398    {
1399      const cmt_string& w = arguments[i];
1400      if (w.substr (0, 6) == "-name=" || w.substr (0, 6) == "-name:" ||
1401          w.substr (0, 6) == "/name:" || w.substr (0, 6) == "/name=")
1402        w.substr (6, name);
1403      else if (w.substr (0, 1) == "@" && w.size () > 1)
1404        {
1405          cmt_string commandfile;
1406          w.substr (1, commandfile);
1407          if (!CmtSystem::test_file (commandfile))
1408            {
1409              CmtMessage::warning ("No such file `" + commandfile + "'.");
1410              continue;
1411            }
1412          cmt_string text;
1413          if (!text.read (commandfile))
1414            {
1415              CmtMessage::warning ("Could not read `" + commandfile + "'.");
1416              continue;
1417            }
1418          text.replace_all ("\r", " ");
1419          text.replace_all ("\n", " ");
1420          files += " " + text;
1421          /*
1422          CmtSystem::cmt_string_vector words;
1423          CmtSystem::split (text, " \t", words);
1424          for (int i = 0; i < words.size (); i++)
1425            {
1426              files.push_back (words[i]);
1427            }
1428          */
1429        }
1430      else
1431        files += " " + w;
1432      //        files.push_back (w);
1433    }
1434
1435  if (files.size () == 0)
1436    {
1437      CmtMessage::error ("build_windefs: no files specified");
1438      return;
1439    }
1440  if (name == "")
1441    {
1442      CmtSystem::cmt_string_vector words;
1443      CmtSystem::split (files, " \t", words);
1444      if (words.size () == 0)
1445        {
1446          CmtMessage::error ("build_windefs: no files specified");
1447          return;
1448        }
1449      cmt_string suffix;
1450      CmtSystem::get_dot_suffix (words[0], suffix);
1451      CmtSystem::basename (words[0], suffix, name);
1452    }
1453  if (name == "")
1454    {
1455      CmtMessage::error ("build_windefs: cannot determine library name");
1456      return;
1457    }
1458
1459  //  cmt_string bin;
1460
1461  //  CmtSystem::dirname (library_name, bin);
1462  //  CmtSystem::get_dot_suffix (library_name, suffix);
1463  //  CmtSystem::basename (library_name, suffix, name);
1464 
1465  //  if (!CmtSystem::cd (bin)) return;
1466 
1467  //  cmt_string command;
1468 
1469  cmt_string command ("dumpbin /symbols");
1470  //  command += library_name;
1471  /*
1472  for (int i = 0; i < files.size (); i++)
1473    {
1474      command += " " + files[i];
1475    }
1476  */
1477  command += " " + files;
1478       
1479  WinDefAwk filter (name);
1480 
1481  filter.run (command, "SECT");
1482}
1483
1484//--------------------------------------------------
1485void Packager::begin ()
1486{
1487  m_package_name = "";
1488}
1489
1490void Packager::filter (const cmt_string& line)
1491{
1492  CmtSystem::cmt_string_vector words;
1493
1494  CmtSystem::split (line, " ", words);
1495  if (words.size () > 1)
1496    {
1497      cmt_string& w = words[0];
1498
1499      if (w == "package")
1500        {
1501          m_package_name = words[1];
1502
1503          int pos = m_package_name.find (";");
1504          if (pos != cmt_string::npos) m_package_name.erase (pos);
1505          m_package_name.replace_all (".", CmtSystem::file_separator ());
1506        }
1507    }
1508}
1509
1510cmt_string& Packager::package_name ()
1511{
1512  return (m_package_name);
1513}
1514
1515//------------------------------------------------------------------------
1516InGenerator::Buffer::Buffer ()
1517  : m_initialized (false), m_usecmt (true)
1518{ }
1519
1520//------------------------------------------------------------------------
1521void InGenerator::Buffer::set_names (const CmtSystem::cmt_string_vector& names)
1522{
1523  m_names = names;
1524}
1525
1526//------------------------------------------------------------------------
1527int InGenerator::Buffer::print (ostream& s)
1528{
1529  initialize ();
1530  s << m_buffer.str ();
1531  return 0;
1532}
1533
1534//------------------------------------------------------------------------
1535void InGenerator::Buffer::set_uses (bool usecmt)
1536{
1537  m_usecmt = usecmt;
1538}
1539
1540//------------------------------------------------------------------------
1541int InGenerator::Languages::initialize ()
1542{
1543  int errors (0);
1544  if (m_initialized) return - errors;
1545  m_initialized = true;
1546  for (int i = 0; i < m_names.size (); i++)
1547    {
1548      const cmt_string& name = m_names[i];
1549      Language& p (Language::find (name));
1550      if (Language::null () == p) { errors += 1; continue; }
1551      p.show (Requirements, m_buffer);
1552      /*
1553      if (!p->use->get_package ()->is_cmt ())
1554        p->print (Requirements, m_buffer);
1555      */
1556    }
1557  //  cerr << "Languages::initialize: " << m_buffer.str ();
1558  return - errors;
1559}
1560
1561//------------------------------------------------------------------------
1562int InGenerator::Fragments::initialize ()
1563{
1564  int errors (0);
1565  if (m_initialized) return - errors;
1566  m_initialized = true;
1567  for (int i = 0; i < m_names.size (); i++)
1568    {
1569      const cmt_string& name = m_names[i];
1570      Fragment* fragment (Fragment::find (name));
1571      if (0 == fragment) { errors += 1; continue; }
1572      if (m_usecmt || !fragment->use->get_package ()->is_cmt ())
1573        fragment->print (Requirements, m_buffer);
1574    }
1575  //  cerr << "initialize: " << m_buffer.str ();
1576  return - errors;
1577}
1578
1579//------------------------------------------------------------------------
1580InGenerator::InGenerator (bool usecmt)
1581  : m_usecmt (usecmt)
1582{
1583  CmtSystem::cmt_string_vector common;
1584  common.push_back ("make_header");
1585  common.push_back ("dependencies");
1586  common.push_back ("cleanup_header");
1587  m_common.set_names (common);
1588  m_common.set_uses (usecmt);
1589
1590  CmtSystem::cmt_string_vector application;
1591  application.push_back ("java_header");
1592  application.push_back ("application_header");
1593  application.push_back ("application");
1594  application.push_back ("check_java");
1595  application.push_back ("cleanup_application");
1596  application.push_back ("cleanup_objects");
1597  application.push_back ("check_application");
1598
1599  CmtSystem::cmt_string_vector application_library;
1600  application_library.push_back ("protos_header");
1601  application_library.push_back ("buildproto");
1602  application_library.push_back ("dependencies_and_triggers");
1603  application_library.push_back ("java");
1604  application_library.push_back ("java_copy");
1605  application_library.push_back ("cleanup");
1606  application_library.push_back ("cleanup_java");
1607  m_application_library.set_names (application_library);
1608  m_application_library.set_uses (usecmt);
1609
1610  CmtSystem::cmt_string_vector library;
1611  library.push_back ("jar_header");
1612  library.push_back ("library_header");
1613  library.push_back ("jar");
1614  library.push_back ("library_no_share");
1615  library.push_back ("library_no_static");
1616  library.push_back ("library");
1617  library.push_back ("cleanup_library");
1618
1619  CmtSystem::cmt_string_vector languages;
1620  Language::LanguageVector& Languages = Language::languages ();
1621  for (int n = 0; n < Languages.size (); n++)
1622    {
1623      Language& language = Languages[n];
1624      //language.setup_fragments ();
1625      application.push_back (language.fragment_name); //application.name ();
1626      library.push_back (language.fragment_name + "_library"); //library.name ();
1627      if (m_usecmt || !language.m_use->get_package ()->is_cmt ())
1628//       if (!language.m_use->get_package ()->is_cmt ())
1629        {
1630          languages.push_back (language.m_name);
1631        }
1632      else if (language.dependencies_options () !=
1633          language.dependencies_options_expanded ())
1634        {
1635          languages.push_back (language.m_name);
1636        }
1637    }
1638  m_languages.set_names (languages);
1639  m_languages.set_uses (usecmt);
1640  m_application.set_names (application);
1641  m_application.set_uses (usecmt);
1642  m_library.set_names (library);
1643  m_library.set_uses (usecmt);
1644 
1645  CmtSystem::cmt_string_vector document;
1646  document.push_back ("document_header");
1647  document.push_back ("dependency");
1648  m_document.set_names (document);
1649  m_document.set_uses (usecmt);
1650}
1651
1652//------------------------------------------------------------------------
1653int InGenerator::build (const Constituent& constituent, ostream& s)
1654{
1655  constituent.show (s);
1656  m_common.print (s);
1657
1658  switch (constituent.type)
1659    {
1660    case Application:
1661      m_application.print (s);
1662      m_application_library.print (s);
1663      m_languages.print (s);
1664      break;
1665    case Library:
1666      m_application_library.print (s);
1667      m_library.print (s);
1668      m_languages.print (s);
1669      break;
1670    case Document:
1671      Fragment* fragment (Fragment::find (constituent.generator));
1672      if (0 == fragment) return -1;
1673      if (m_usecmt || !fragment->use->get_package ()->is_cmt ())
1674        fragment->print (Requirements, s);
1675      if ("" != fragment->header)
1676        {
1677          Fragment* header (Fragment::find (fragment->header));
1678          if (0 == header) return -1;
1679          //      if (header->use != fragment->use &&
1680          if (m_usecmt || !header->use->get_package ()->is_cmt ())
1681            header->print (Requirements, s);
1682        }
1683      if ("" != fragment->trailer)
1684        {
1685          Fragment* trailer (Fragment::find (fragment->trailer));
1686          if (0 == trailer) return -1;
1687          //      if (trailer->use != fragment->use &&
1688          if (m_usecmt || !trailer->use->get_package ()->is_cmt ())
1689            trailer->print (Requirements, s);
1690        }
1691      m_document.print (s);
1692      break;
1693    }
1694
1695  return 0;
1696}
1697//------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.