source: CMT/v1r19/source/cmt_generator.cxx@ 303

Last change on this file since 303 was 185, checked in by garonne, 19 years ago

commit changes to cmt_generator.cxx thanks to Markus

  • Property svn:eol-style set to native
File size: 19.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
20//------------------------------------------------------------------------
21void SourceFile::set (const cmt_string name, Language& language, const cmt_string output)
22{
23 m_name = name;
24 m_language = &language;
25 m_output = output;
26
27 CmtSystem::reduce_file_separators (m_name);
28}
29
30cmt_string SourceFile::name () const
31{
32 return (m_name);
33}
34
35Language& SourceFile::language () const
36{
37 return (*m_language);
38}
39
40cmt_string SourceFile::output () const
41{
42 return (m_output);
43}
44//------------------------------------------------------------------------
45
46//--------------------------------------------------
47CmtGenerator::CmtGenerator ()
48{
49 m_CONSTITUENT.set ("CONSTITUENT");
50 m_LINKMACRO.set ("LINKMACRO");
51 m_DOCPATH.set ("DOCPATH");
52 m_PACKAGEPATH.set ("PACKAGEPATH");
53 m_PACKAGEPREFIX.set ("PACKAGEPREFIX");
54 m_PACKAGE.set ("PACKAGE");
55 m_VERSION.set ("VERSION");
56 m_MGRSTYLE.set ("MGRSTYLE");
57 m_TITLE.set ("TITLE");
58 m_GROUP.set ("GROUP");
59 m_CONSTITUENT.set ("CONSTITUENT");
60 m_CONSTITUENTSUFFIX.set ("CONSTITUENTSUFFIX");
61 m_LIBRARYSUFFIX.set ("LIBRARYSUFFIX");
62 m_USER.set ("USER");
63 m_DATE.set ("DATE");
64 m_PROTOTARGET.set ("PROTOTARGET");
65 m_OBJS.set ("OBJS");
66 m_CLASSES.set ("CLASSES");
67 m_PROTOSTAMPS.set ("PROTOSTAMPS");
68 m_NAME.set ("NAME");
69 m_FILEPATH.set ("FILEPATH");
70 m_FILESUFFIX.set ("FILESUFFIX");
71 m_SUFFIX.set ("SUFFIX");
72 m_FILENAME.set ("FILENAME");
73 m_LINKMACRO.set ("LINKMACRO");
74 m_LINE.set ("LINE");
75 m_ADDINCLUDE.set ("ADDINCLUDE");
76 m_FULLNAME.set ("FULLNAME");
77 m_DIRNAME.set ("DIRNAME");
78 m_OUTPUTNAME.set ("OUTPUTNAME");
79 m_ALLOS9SOURCES.set ("ALLOS9SOURCES");
80 m_NODEBUGUSELINKOPTS.set ("NODEBUGUSELINKOPTS");
81 m_DEBUGUSELINKOPTS.set ("DEBUGUSELINKOPTS");
82 m_USEINCLUDES.set ("USEINCLUDES");
83 m_HASTARGETTAG.set ("HASTARGETTAG");
84}
85
86//--------------------------------------------------
87void CmtGenerator::reset ()
88{
89 m_CONSTITUENT = "";
90 m_LINKMACRO = "";
91 m_DOCPATH = "";
92 m_PACKAGEPATH = "";
93 m_PACKAGEPREFIX = "";
94 m_PACKAGE = "";
95 m_VERSION = "";
96 m_MGRSTYLE = "";
97 m_TITLE = "";
98 m_GROUP = "";
99 m_CONSTITUENTSUFFIX = "";
100 m_LIBRARYSUFFIX = "";
101 m_USER = "";
102 m_DATE = "";
103 m_PROTOTARGET = "";
104 m_OBJS = "";
105 m_CLASSES = "";
106 m_PROTOSTAMPS = "";
107 m_NAME = "";
108 m_FILEPATH = "";
109 m_FILESUFFIX = "";
110 m_SUFFIX = "";
111 m_FILENAME = "";
112 m_LINE = "";
113 m_ADDINCLUDE = "";
114 m_FULLNAME = "";
115 m_OUTPUTNAME = "";
116 m_ALLOS9SOURCES = "";
117 m_NODEBUGUSELINKOPTS = "";
118 m_DEBUGUSELINKOPTS = "";
119 m_USEINCLUDES = "";
120 m_HASTARGETTAG = "";
121 m_PACKINCLUDES = "";
122 m_PACKOS9 = false;
123 m_GENERATOR = "";
124
125 is_library = false;
126 is_application = false;
127 srcdir = "";
128 docdir = "";
129 cmtdir = "";
130 incdir = "";
131 src = "$(src)";
132 doc = "$(doc)";
133 inc = "$(inc)";
134 mgr = "$(mgr)";
135 cmt = "$(cmt)";
136 protos = "";
137 protonames = "";
138 os9sources = "";
139
140 m_source_files.clear ();
141
142 Language::setup_all_fragments ();
143
144 CmtSystem::cd (Cmt::get_current_dir ());
145
146 cmt_string branch = CmtSystem::current_branch ();
147
148 if ((branch == "mgr") || (branch == "cmt"))
149 {
150 if (CmtSystem::test_directory ("../src"))
151 {
152 srcdir = "..";
153 srcdir += CmtSystem::file_separator ();
154 srcdir += "src";
155 srcdir += CmtSystem::file_separator ();
156 }
157 else
158 {
159 srcdir = "";
160 }
161
162 if (CmtSystem::test_directory ("../doc"))
163 {
164 docdir = "..";
165 docdir += CmtSystem::file_separator ();
166 docdir += "doc";
167 docdir += CmtSystem::file_separator ();
168 }
169 else
170 {
171 docdir = "";
172 }
173
174 if (CmtSystem::test_directory ("../cmt"))
175 {
176 cmtdir = "..";
177 cmtdir += CmtSystem::file_separator ();
178 cmtdir += "cmt";
179 cmtdir += CmtSystem::file_separator ();
180 }
181 else if (CmtSystem::test_directory ("../mgr"))
182 {
183 cmtdir = "..";
184 cmtdir += CmtSystem::file_separator ();
185 cmtdir += "mgr";
186 cmtdir += CmtSystem::file_separator ();
187 }
188 else
189 {
190 cmtdir = CmtSystem::pwd ();
191 cmtdir += CmtSystem::file_separator ();
192 }
193
194 if (CmtSystem::test_directory ("../src"))
195 {
196 incdir = "..";
197 incdir += CmtSystem::file_separator ();
198 incdir += "src";
199 incdir += CmtSystem::file_separator ();
200 }
201 else
202 {
203 incdir = "";
204 }
205 }
206 else
207 {
208 srcdir = ".";
209 srcdir += CmtSystem::file_separator ();
210 docdir = ".";
211 docdir += CmtSystem::file_separator ();
212 cmtdir = CmtSystem::pwd ();
213 cmtdir += CmtSystem::file_separator ();
214 incdir = ".";
215 incdir += CmtSystem::file_separator ();
216 }
217}
218
219//--------------------------------------------------
220bool CmtGenerator::prepare_output (const cmt_string& package,
221 const Constituent& constituent)
222{
223 m_PACKAGE = package;
224 m_CONSTITUENT = constituent.name;
225 m_CONSTITUENTSUFFIX = constituent.suffix;
226
227 m_PACKOS9 = constituent.need_OS9;
228
229 m_output_file_name = cmtdir + m_CONSTITUENT + ".";
230
231 if (Cmt::build_nmake ())
232 {
233 m_output_file_name += "nmake";
234 }
235 else
236 {
237 m_output_file_name += "make";
238 }
239
240 m_output_file_name += "new";
241
242
243 m_output_file = fopen (m_output_file_name.c_str (), "wb");
244 if (m_output_file != NULL)
245 {
246 return (true);
247 }
248 else
249 {
250 return (false);
251 }
252}
253
254//--------------------------------------------------
255void CmtGenerator::check (const cmt_string& name)
256{
257 static cmt_string old;
258 static cmt_string backup;
259
260 old = name;
261
262 int pos = old.find_last_of ("new");
263 old.erase (pos);
264
265 if (!CmtSystem::compare_files (old, name))
266 {
267 backup = old;
268 backup += "sav";
269
270 unlink (backup.c_str ());
271 rename (old.c_str (), backup.c_str ());
272 rename (name.c_str (), old.c_str ());
273 }
274 else
275 {
276 unlink (name);
277 }
278}
279
280//--------------------------------------------------
281void CmtGenerator::commit (const cmt_string& name)
282{
283 static cmt_string old;
284 static cmt_string backup;
285
286 old = name;
287
288 int pos = old.find_last_of ("new");
289 old.erase (pos);
290
291 if (CmtSystem::test_file (old))
292 {
293 backup = old;
294 backup += "sav";
295
296 unlink (backup.c_str ());
297 rename (old.c_str (), backup.c_str ());
298 }
299
300 rename (name.c_str (), old.c_str ());
301}
302
303//--------------------------------------------------
304void CmtGenerator::terminate ()
305{
306 fclose (m_output_file);
307
308 //--- Complete the operation --------------
309
310 commit (m_output_file_name);
311}
312
313//--------------------------------------------------
314void CmtGenerator::fill_outputs ()
315{
316 bool first = true;
317
318 m_OBJS = "";
319
320 for (int i = 0; i < m_source_files.size (); i++)
321 {
322 const SourceFile& file = m_source_files[i];
323 const cmt_string output = file.output ();
324
325 if (output != "")
326 {
327 if (first)
328 {
329 first = false;
330 }
331 else
332 {
333 m_OBJS += " ";
334 }
335
336 m_OBJS += output;
337 }
338
339 if (Cmt::get_debug ())
340 {
341 cout << "CmtGenerator::fill_outputs> output=" << output << " OBJS=" << m_OBJS << endl;
342 }
343
344 }
345
346 if (Cmt::get_debug ())
347 {
348 cout << "CmtGenerator::fill_outputs> OBJS=" << m_OBJS << endl;
349 }
350
351}
352
353//--------------------------------------------------
354void CmtGenerator::prepare_use_context ()
355{
356 cmt_string path;
357 cmt_string substitution;
358
359 Use* use = &Use::current ();
360
361 m_deps_builder.clear ();
362
363 if (use->include_path != "none")
364 {
365 if (use->include_path == "")
366 {
367 m_deps_builder.add (incdir, "$(src)");
368 }
369 else
370 {
371 substitution = use->include_path;
372
373 path = substitution;
374 Symbol::expand (path);
375
376 CmtSystem::reduce_file_separators (path);
377
378 m_deps_builder.add (path, substitution);
379 }
380 }
381
382 m_deps_builder.add_includes (*use);
383
384 Use::UsePtrVector& uses = Use::get_ordered_uses ();
385
386 if (uses.size () > 0)
387 {
388 int number;
389
390 for (number = 0; number < uses.size (); number++)
391 {
392 use = uses[number];
393 if (use->discarded) continue;
394
395 if (use->real_path != "")
396 {
397 if (use->include_path != "none")
398 {
399 if (use->include_path == "")
400 {
401 use->get_full_path (path);
402 path += CmtSystem::file_separator ();
403 path += "src";
404
405 substitution = "$(";
406 substitution += use->prefix;
407 substitution += "ROOT)";
408 substitution += CmtSystem::file_separator ();
409 substitution += "src";
410 substitution += CmtSystem::file_separator ();
411 }
412 else
413 {
414 substitution = use->include_path;
415
416 path = substitution;
417 Symbol::expand (path);
418
419 CmtSystem::reduce_file_separators (path);
420 }
421
422 m_deps_builder.add (path, substitution);
423 }
424
425 m_deps_builder.add_includes (*use);
426 }
427 }
428 }
429}
430
431//--------------------------------------------------
432void CmtGenerator::filter_path (cmt_string& text)
433{
434 CmtSystem::compress_path (text);
435
436 text.replace_all ("./../src/../", "../");
437 text.replace_all ("./../src/", "$(src)");
438
439 text.replace_all (".\\..\\src\\..\\", "..\\");
440 text.replace_all (".\\..\\src\\", "$(src)");
441
442 text.replace_all ("../src/../", "../");
443 text.replace_all ("../src/", "$(src)");
444
445 text.replace_all ("..\\src\\..\\", "..\\");
446 text.replace_all ("..\\src\\", "$(src)");
447
448 text.replace_all ("../doc/../", "../");
449 text.replace_all ("../doc/", "$(doc)");
450
451 text.replace_all ("..\\doc\\..\\", "..\\");
452 text.replace_all ("..\\doc\\", "$(doc)");
453
454 text.replace_all ("$(src)$(src)", "$(src)");
455}
456
457/**
458 Scan a complete file spec (with possibly wild cards and directory)
459 given in full_name ad fill in a vector of found file names.
460
461 Result of the scan is filtered against matching suffixes
462
463 Returns the count of non empty file names really found.
464
465*/
466int CmtGenerator::get_all_files (const cmt_string& full_name,
467 const cmt_vector<cmt_regexp>& exclude_exprs,
468 const cmt_vector<cmt_regexp>& select_exprs,
469 CmtSystem::cmt_string_vector& files)
470{
471 static cmt_string suffix;
472 static cmt_string name;
473
474 bool has_excludes = false;
475 bool has_selects = false;
476
477 suffix = "";
478 name = "";
479
480 files.clear ();
481
482 has_excludes = (exclude_exprs.size () > 0);
483 has_selects = (select_exprs.size () > 0);
484
485 CmtSystem::get_dot_suffix (full_name, suffix);
486
487 bool wilcarded_suffix = false;
488
489 if (suffix == ".*") wilcarded_suffix = true;
490
491 int count = 0;
492
493 if (full_name.find ('*') != cmt_string::npos)
494 {
495 CmtSystem::scan_dir (full_name, files);
496
497 if (Cmt::get_debug ())
498 {
499 cout << "CMT::get_all_files> full_name=" << full_name <<
500 " pwd=" << CmtSystem::pwd () << endl;
501 cout << "CMT::get_all_files> files.size=" << files.size () << endl;
502 }
503
504 /**
505
506 We have to treat patterns of the form *.xxx (ie with a
507 suffix) thus we filter out everything that could have been
508 collected with a different suffix because the
509 CmtSystem::scan_dir function only handles patterns of the
510 form xxx* (ie with trailing *)
511
512 [If the original suffix was empty (ie files specified using
513 xx*) this means getting files without any dot-suffix. This
514 may be incorrect??]
515
516 */
517
518 for (int j = 0; j < files.size (); j++)
519 {
520 cmt_string& n = files[j];
521
522 bool rejected = false;
523
524 if (n == "")
525 {
526 rejected = true;
527 }
528
529 if (!rejected && has_selects)
530 {
531 rejected = true;
532
533 for (int k = 0; k < select_exprs.size (); k++)
534 {
535 const cmt_regexp& exp = select_exprs[k];
536 if (exp.match (n))
537 {
538 rejected = false;
539 break;
540 }
541 }
542 }
543
544 if (!rejected && has_excludes)
545 {
546 for (int k = 0; k < exclude_exprs.size (); k++)
547 {
548 const cmt_regexp& exp = exclude_exprs[k];
549 if (exp.match (n))
550 {
551 rejected = true;
552 break;
553 }
554 }
555 }
556
557 if (!rejected)
558 {
559 static cmt_string s;
560
561 CmtSystem::get_dot_suffix (n, s);
562 if (!wilcarded_suffix && (s != suffix))
563 {
564 rejected = true;
565 }
566 else
567 {
568 count++;
569 }
570 }
571
572 if (Cmt::get_debug ())
573 {
574 if (rejected)
575 {
576 cout << "CMT::get_all_files> reject " << n << endl;
577 }
578 else
579 {
580 cout << "CMT::get_all_files> keep " << n << endl;
581 }
582 }
583
584 if (rejected)
585 {
586 n = "";
587 }
588 }
589 }
590 else
591 {
592 if (full_name != "")
593 {
594 bool rejected = false;
595
596 if (has_excludes)
597 {
598 for (int k = 0; k < exclude_exprs.size (); k++)
599 {
600 const cmt_regexp& exp = exclude_exprs[k];
601 if (exp.match (full_name))
602 {
603 rejected = true;
604 break;
605 }
606 }
607 }
608
609 if (!rejected)
610 {
611 cmt_string& n = files.add ();
612
613 n = full_name;
614
615 count++;
616 }
617 }
618 }
619
620 return (count);
621}
622
623//--------------------------------------------------
624void CmtGenerator::set_full_name (cmt_string& full_name, cmt_string& file)
625{
626 full_name = "";
627
628 Symbol::expand (file);
629
630 if (file == "") return;
631
632 if (!CmtSystem::absolute_path (file))
633 {
634 full_name = srcdir;
635 if (full_name != "") full_name += CmtSystem::file_separator ();
636 }
637
638 full_name += file;
639
640 CmtSystem::reduce_file_separators (full_name);
641}
642
643//------------------------------------------------------------------------
644static ApplicationGenerator ApplicationContext;
645static LibraryGenerator LibraryContext;
646static DocumentGenerator DocumentContext;
647static ReadmeGenerator ReadmeContext;
648static PrototypeGenerator PrototypeContext;
649static DefaultMakefileGenerator DefaultMakefileContext;
650static MSDEVGenerator MSDEVContext;
651static VSNETGenerator VSNETContext;
652static MakeSetupGenerator MakeSetupContext;
653static ConstituentsMakefileGenerator ConstituentsMakefileContext;
654static DependencyGenerator DependencyContext;
655
656//--------------------------------------------------
657int Generator::build_msdev_workspace (const Constituent::ConstituentVector& constituents)
658{
659 return (MSDEVContext.build_workspace (constituents));
660}
661
662//--------------------------------------------------
663int Generator::build_msdev (const Constituent& constituent)
664{
665 return (MSDEVContext.build_project (constituent));
666}
667
668//--------------------------------------------------
669int Generator::build_vsnet_workspace (const Constituent::ConstituentVector& constituents)
670{
671 return (VSNETContext.build_workspace (constituents));
672}
673
674//--------------------------------------------------
675int Generator::build_vsnet (const Constituent& constituent)
676{
677 return (VSNETContext.build_project (constituent));
678}
679
680//--------------------------------------------------
681void Generator::build_make_setup (const cmt_string& package)
682{
683 MakeSetupContext.build (package);
684}
685
686//--------------------------------------------------
687void Generator::build_constituents_makefile (const cmt_string& package,
688 const CmtSystem::cmt_string_vector& arguments)
689{
690 ConstituentsMakefileContext.build (package, arguments);
691}
692
693//--------------------------------------------------
694int Generator::build_constituent_makefile (const Constituent& constituent)
695{
696 const cmt_string& package = Cmt::get_current_package ();
697
698 switch (constituent.type)
699 {
700 case Application:
701 ApplicationContext.build (package, constituent);
702 break;
703 case Library:
704 LibraryContext.build (package, constituent);
705 break;
706 case Document:
707 DocumentContext.build (package, constituent);
708 break;
709 }
710
711 return (0);
712}
713
714//--------------------------------------------------
715void Generator::build_constituent_makefile (const cmt_string& name)
716{
717 const Constituent* constituent = Constituent::find (name);
718 if (constituent != 0) build_constituent_makefile (*constituent);
719}
720
721//--------------------------------------------------
722void Generator::build_default_makefile ()
723{
724 DefaultMakefileContext.build ();
725}
726
727//--------------------------------------------------
728void Generator::build_dependencies (const CmtSystem::cmt_string_vector& arguments)
729{
730 DependencyContext.build (arguments);
731}
732
733//--------------------------------------------------
734void Generator::build_prototype (const cmt_string& file_name)
735{
736 PrototypeContext.build (file_name);
737}
738
739//--------------------------------------------------
740void Generator::build_readme (const CmtSystem::cmt_string_vector& arguments)
741{
742 ReadmeContext.build (arguments);
743}
744
745class WinDefAwk : public PAwk
746{
747public :
748 WinDefAwk (const cmt_string& library_name)
749 {
750 m_name = library_name;
751 }
752
753 void begin ()
754 {
755 cout << "LIBRARY " << m_name << endl;
756 cout << "EXPORTS" << endl;
757 }
758
759 void filter (const cmt_string& line)
760 {
761 if (line.find ("External") == cmt_string::npos) return;
762 if (line.find ("??_") != cmt_string::npos)
763 {
764 if (line.find ("operator/=") == cmt_string::npos) return;
765 // Keep operator /= .
766 }
767
768 CmtSystem::cmt_string_vector words;
769 CmtSystem::split (line, " \t", words);
770 if (words.size () >= 7)
771 {
772 int pos = 7;
773
774 cmt_string& fifth_word = words[4];
775 if (fifth_word == "()") pos = 7;
776 else if (fifth_word == "External") pos = 6;
777 else return;
778
779 cmt_string& symbol = words[pos];
780 if (symbol[0] == '_') symbol.erase (0, 1);
781 symbol.replace_all ("\r", "");
782 symbol.replace_all ("\n", "");
783
784 if ((pos == 6) &&
785 ((line.find(": static") != cmt_string::npos) ||
786 (line.find("(class") != cmt_string::npos)) )
787 {
788 // static data members are not DATA :
789 // extern objects are not DATA :
790 cout << " " << symbol << " " << endl;
791 }
792 else if (pos == 6)
793 {
794 // DATA :
795 cout << " " << symbol << "\tDATA" << endl;
796 }
797 else
798 {
799 // code :
800 cout << " " << symbol << " " << endl;
801 }
802 }
803 }
804
805 void end ()
806 {
807 }
808
809private:
810 cmt_string m_name;
811};
812
813//--------------------------------------------------
814void Generator::build_windefs (const cmt_string& library_name)
815{
816 cmt_string bin;
817 cmt_string name;
818 cmt_string suffix;
819
820 CmtSystem::dirname (library_name, bin);
821 CmtSystem::get_dot_suffix (library_name, suffix);
822 CmtSystem::basename (library_name, suffix, name);
823
824 if (!CmtSystem::cd (bin)) return;
825
826 cmt_string text;
827 cmt_string command;
828
829 command = "dumpbin /symbols ";
830 command += library_name;
831
832 WinDefAwk filter (name);
833
834 filter.run (command, "SECT");
835}
836
837//--------------------------------------------------
838void Packager::begin ()
839{
840 m_package_name = "";
841}
842
843void Packager::filter (const cmt_string& line)
844{
845 CmtSystem::cmt_string_vector words;
846
847 CmtSystem::split (line, " ", words);
848 if (words.size () > 1)
849 {
850 cmt_string& w = words[0];
851
852 if (w == "package")
853 {
854 m_package_name = words[1];
855
856 int pos = m_package_name.find (";");
857 if (pos != cmt_string::npos) m_package_name.erase (pos);
858 m_package_name.replace_all (".", CmtSystem::file_separator ());
859 }
860 }
861}
862
863cmt_string& Packager::package_name ()
864{
865 return (m_package_name);
866}
867
Note: See TracBrowser for help on using the repository browser.