1 /* $Id: proj_tree_builder.cpp 602953 2020-03-04 19:52:40Z gouriano $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Viatcheslav Gorelenkov
27 *
28 */
29
30 #include <ncbi_pch.hpp>
31 #include "proj_tree_builder.hpp"
32 #include "proj_builder_app.hpp"
33 #include "proj_src_resolver.hpp"
34 #include "msvc_prj_defines.hpp"
35
36 #include "proj_projects.hpp"
37 #include <algorithm>
38
39 #include "ptb_err_codes.hpp"
40
41 BEGIN_NCBI_SCOPE
42
43 const char* s_check_separator = " ____ ";
44 static map<string,size_t> s_buildOrder_byname;
45 static size_t s_BuildOrder=0;
46
s_WriteBuildOrder(const string & dir_name,const string & mkname)47 void s_WriteBuildOrder(const string& dir_name, const string& mkname)
48 {
49 string name( CDirEntry::ConcatPath(dir_name,mkname));
50 s_buildOrder_byname[name] = ++s_BuildOrder;
51 }
52
VerifyBuildOrder(const CProjItem & item,list<string> dependencies,const CProjectItemsTree & tree)53 bool CProjectTreeBuilder::VerifyBuildOrder(
54 const CProjItem& item, list<string> dependencies, const CProjectItemsTree& tree)
55 {
56 bool res = true;
57 if (item.m_MkName.empty()) {
58 // error?
59 return res;
60 }
61 ITERATE(list<string>, d, dependencies) {
62 CProjectItemsTree::TProjects::const_iterator n =
63 tree.m_Projects.find(CreateProjKey(*d));
64 if (n != tree.m_Projects.end()) {
65 const CProjItem& dep_item = n->second;
66 if (dep_item.m_MkName.empty()) {
67 //error?
68 } else if (s_buildOrder_byname[dep_item.m_MkName] >
69 s_buildOrder_byname[item.m_MkName]) {
70 PTB_WARNING_EX(item.m_MkName,
71 ePTB_InvalidMakefile,
72 "should be built after: " << dep_item.m_MkName);
73 res = false;
74 }
75 }
76
77 }
78 return res;
79 }
80
81
82 struct PLibExclude
83 {
PLibExcludePLibExclude84 PLibExclude(const string& prj_name, const list<string>& excluded_lib_ids)
85 : m_Prj(prj_name)
86 {
87 copy(excluded_lib_ids.begin(), excluded_lib_ids.end(),
88 inserter(m_ExcludedLib, m_ExcludedLib.end()) );
89 }
90
operator ()PLibExclude91 bool operator() (const string& lib_id) const
92 {
93 if (m_ExcludedLib.find(lib_id) != m_ExcludedLib.end()) {
94 PTB_WARNING_EX(kEmptyStr,ePTB_ProjectExcluded,"Project " << m_Prj << ": library excluded by request: " << lib_id);
95 return true;
96 }
97 return false;
98 }
99
100 private:
101 string m_Prj;
102 set<string> m_ExcludedLib;
103 };
104
105
106 //-----------------------------------------------------------------------------
GetProjType(const string & base_dir,const string & projname,SMakeInInfo::TMakeinType type)107 CProjItem::TProjType SMakeProjectT::GetProjType(const string& base_dir,
108 const string& projname,
109 SMakeInInfo::TMakeinType type)
110 {
111 string fname = "Makefile." + projname;
112
113 string fname_base = CDirEntry::ConcatPath(base_dir, fname);
114 string fname_app = CDirEntry::ConcatPath(base_dir, fname + ".app");
115 string fname_lib = CDirEntry::ConcatPath(base_dir, fname + ".lib");
116 string fname_dll = CDirEntry::ConcatPath(base_dir, fname + ".dll");
117 string fname_msvc= CDirEntry::ConcatPath(base_dir, fname);
118 string fname_msvc2(fname_msvc);
119
120 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eMsvcWin32 ||
121 CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eMsvcX64) {
122 fname_msvc += ".msvcproj";
123 } else {
124 fname_msvc2 += ".in";
125 }
126
127 switch (type) {
128 case SMakeInInfo::eApp:
129 if ( CDirEntry(fname_app).Exists()) {
130 return CProjKey::eApp;
131 }
132 break;
133 case SMakeInInfo::eLib:
134 if ( CDirEntry(fname_lib).Exists()) {
135 return CProjKey::eLib;
136 }
137 break;
138 case SMakeInInfo::eDll:
139 if ( CDirEntry(fname_dll).Exists()) {
140 return CProjKey::eDll;
141 }
142 break;
143 case SMakeInInfo::eMsvc:
144 if ( CDirEntry(fname_msvc).Exists() || CDirEntry(fname_msvc2).Exists()) {
145 return CProjKey::eMsvc;
146 }
147 break;
148
149 default:
150 break;
151 }
152
153 if ( CDirEntry(fname_lib).Exists() )
154 return CProjKey::eLib;
155 else if (CDirEntry(fname_dll).Exists() )
156 return CProjKey::eDll;
157 else if (CDirEntry(fname_app).Exists() )
158 return CProjKey::eApp;
159 else if (CDirEntry(fname_msvc).Exists() || CDirEntry(fname_msvc2).Exists() )
160 return CProjKey::eMsvc;
161 else if (CDirEntry(CDirEntry::ConcatPath(base_dir, fname + ".metal")).Exists() )
162 return CProjKey::eLib;
163
164 switch (type) {
165 case SMakeInInfo::eApp:
166 PTB_WARNING_EX(fname_app, ePTB_MissingMakefile,
167 "Makefile not found");
168 break;
169
170 case SMakeInInfo::eLib:
171 PTB_WARNING_EX(fname_lib, ePTB_MissingMakefile,
172 "Makefile not found");
173 break;
174
175 case SMakeInInfo::eDll:
176 PTB_WARNING_EX(fname_dll, ePTB_MissingMakefile,
177 "Makefile not found");
178 break;
179
180 case SMakeInInfo::eMsvc:
181 PTB_WARNING_EX(fname_msvc, ePTB_MissingMakefile,
182 "Makefile not found");
183 break;
184
185 default:
186 PTB_WARNING_EX(fname_base, ePTB_MissingMakefile,
187 "Makefile not found");
188 break;
189 }
190 return CProjKey::eNoProj;
191 }
192
193
IsMakeInFile(const string & name)194 bool SMakeProjectT::IsMakeInFile(const string& name)
195 {
196 return name == "Makefile.in";
197 }
198
199
IsMakeLibFile(const string & name)200 bool SMakeProjectT::IsMakeLibFile(const string& name)
201 {
202 return NStr::StartsWith(name, "Makefile") &&
203 NStr::EndsWith(name, ".lib");
204 }
205
IsMakeDllFile(const string & name)206 bool SMakeProjectT::IsMakeDllFile(const string& name)
207 {
208 return NStr::StartsWith(name, "Makefile") &&
209 NStr::EndsWith(name, ".dll");
210 }
211
212
IsMakeAppFile(const string & name)213 bool SMakeProjectT::IsMakeAppFile(const string& name)
214 {
215 return NStr::StartsWith(name, "Makefile") &&
216 NStr::EndsWith(name, ".app");
217 }
218
219
220 /*
221 bool SMakeProjectT::IsUserProjFile(const string& name)
222 {
223 return NStr::StartsWith(name, "Makefile") &&
224 NStr::EndsWith(name, ".msvcproj");
225 }
226 */
227
228
DoResolveDefs(CSymResolver & resolver,TFiles & files,const set<string> & keys)229 void SMakeProjectT::DoResolveDefs(CSymResolver& resolver,
230 TFiles& files,
231 const set<string>& keys)
232 {
233 const CMsvcSite& site = GetApp().GetSite();
234 set<string> defs_unresolved;
235 map<string,string> defs_resolved;
236 NON_CONST_ITERATE(CProjectTreeBuilder::TFiles, p, files) {
237
238 CMsvcProjectMakefile msvc_prj(p->first + "." + GetApp().GetRegSettings().m_MakefilesExt);
239 bool msvc_empty = msvc_prj.IsEmpty();
240
241 NON_CONST_ITERATE(CSimpleMakeFileContents::TContents,
242 n,
243 p->second.m_Contents) {
244
245 const string& key = n->first;
246 list<string>& values = n->second;
247 bool cppflags = key == "CPPFLAGS";
248
249 // if (keys.find(key) != keys.end())
250 {
251 bool modified = false;
252 list<string> new_vals;
253 list<string> redef_values;
254 modified = msvc_prj.Redefine(values,redef_values);
255 NON_CONST_ITERATE(list<string>, k, redef_values) {
256 // NON_CONST_ITERATE(list<string>, k, values) {
257 //iterate all values and try to resolve
258 const string& val = *k;
259 if (cppflags && site.IsCppflagDescribed(val)) {
260 if (msvc_empty) {
261 new_vals.push_back(val);
262 } else {
263 msvc_prj.Append(new_vals,val);
264 }
265 } else if( !CSymResolver::HasDefine(val) ) {
266 if (msvc_empty) {
267 new_vals.push_back(val);
268 } else {
269 msvc_prj.Append(new_vals,val);
270 }
271 } else {
272 list<string> resolved_def;
273 string val_define = FilterDefine(val);
274 resolver.Resolve(val, &resolved_def, p->second);
275 if ( resolved_def.empty() ) {
276 defs_unresolved.insert(val);
277 new_vals.push_back(val_define); //not resolved - keep old val
278 } else {
279 defs_resolved[val] = NStr::Join( resolved_def, " ");
280 //was resolved
281 ITERATE(list<string>, l, resolved_def) {
282 const string& define = *l;
283 if ( IsConfigurableDefine(define) ) {
284 string stripped = StripConfigurableDefine(define);
285 string resolved_def_str;
286 list<string> libchoices_includes ;
287 site.GetLibChoiceIncludes(stripped, &libchoices_includes);
288 if (!libchoices_includes.empty()) {
289 resolved_def_str = NStr::Join( libchoices_includes, " ");
290 } else {
291 resolved_def_str = site.GetDefinesEntry(stripped);
292 }
293 if ( !resolved_def_str.empty() ) {
294 defs_resolved[define] = resolved_def_str;
295 list<string> resolved_defs;
296 NStr::Split(resolved_def_str,
297 LIST_SEPARATOR,
298 resolved_defs, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
299 if (msvc_empty) {
300 copy(resolved_defs.begin(),
301 resolved_defs.end(),
302 back_inserter(new_vals));
303 } else {
304 msvc_prj.Append(new_vals,resolved_defs);
305 }
306 } else {
307 // configurable definitions could be described in terms of components
308 list<string> components;
309 site.GetComponents(stripped, &components);
310 if (!components.empty()) {
311 defs_resolved[define] = "Component= " + NStr::Join( components, ", ");
312 } else {
313 defs_unresolved.insert(define);
314 }
315 if (msvc_empty) {
316 new_vals.push_back(define);
317 } else {
318 msvc_prj.Append(new_vals,define);
319 }
320 }
321
322 } else if (HasConfigurableDefine(define)) {
323 string def(define);
324 while (HasConfigurableDefine(def)) {
325 string raw = ExtractConfigurableDefine(def);
326 string stripped = StripConfigurableDefine(raw);
327 string resolved_def_str = site.GetDefinesEntry(stripped);
328 if (resolved_def_str == " ") {
329 resolved_def_str.erase();
330 }
331 NStr::ReplaceInPlace(def, raw, resolved_def_str);
332 }
333 if (msvc_empty) {
334 new_vals.push_back( def);
335 } else {
336 msvc_prj.Append(new_vals,def);
337 }
338 } else {
339 if (msvc_empty) {
340 new_vals.push_back(define);
341 } else {
342 msvc_prj.Append(new_vals,define);
343 }
344 }
345 }
346 modified = true;
347 }
348 }
349 }
350 if (modified) {
351 msvc_prj.Redefine(new_vals,redef_values);
352 values = redef_values; // by ref!
353 }
354 }
355 }
356 }
357
358 if (!defs_resolved.empty()) {
359 string s;
360 for (map<string,string>::const_iterator r = defs_resolved.begin();
361 r != defs_resolved.end(); ++r) {
362 s += ' ';
363 s += r->first;
364 s += " = ";
365 s += r->second;
366 s += ";";
367 }
368 PTB_INFO("Resolved macro definitions: " << s);
369 }
370 if (!defs_unresolved.empty()) {
371 string s;
372 for (set<string>::const_iterator u = defs_unresolved.begin();
373 u != defs_unresolved.end(); ++u) {
374 s += ' ';
375 s += *u;
376 }
377 PTB_WARNING_EX(kEmptyStr, ePTB_MacroUndefined,
378 "Unresolved macro definitions:" << s);
379 }
380 }
381
382
GetOneIncludeDir(const string & flag,const string & token)383 string SMakeProjectT::GetOneIncludeDir(const string& flag, const string& token)
384 {
385 size_t token_pos = flag.find(token);
386 if (token_pos != NPOS &&
387 token_pos + token.length() < flag.length()) {
388 return flag.substr(token_pos + token.length());
389 }
390 return "";
391 }
392
393
CreateIncludeDirs(const list<string> & cpp_flags,const string & source_base_dir,list<string> * include_dirs)394 void SMakeProjectT::CreateIncludeDirs(const list<string>& cpp_flags,
395 const string& source_base_dir,
396 list<string>* include_dirs)
397 {
398 include_dirs->clear();
399 ITERATE(list<string>, p, cpp_flags) {
400 const string& flag = *p;
401 // string token("-I$(includedir)");
402
403 // process -I$(includedir)
404 string token_val;
405 token_val = SMakeProjectT::GetOneIncludeDir(flag, "-I$(includedir)");
406 if ( !token_val.empty() ) {
407 string dir =
408 CDirEntry::ConcatPath(GetApp().GetProjectTreeInfo().m_Include,
409 token_val);
410 dir = CDirEntry::NormalizePath(dir);
411 dir = CDirEntry::AddTrailingPathSeparator(dir);
412
413 include_dirs->push_back(dir);
414 }
415 token_val = SMakeProjectT::GetOneIncludeDir(flag, "-I$(incdir)");
416 if ( !token_val.empty() ) {
417 string dir = CDirEntry::ConcatPath(GetApp().m_IncDir,token_val);
418 dir = CDirEntry::NormalizePath(dir);
419 dir = CDirEntry::AddTrailingPathSeparator(dir);
420
421 include_dirs->push_back(dir);
422 }
423
424 // process -I$(srcdir)
425 token_val = SMakeProjectT::GetOneIncludeDir(flag, "-I$(srcdir)");
426 if ( !token_val.empty() || flag == "-I$(srcdir)" ) {
427 string dir =
428 CDirEntry::ConcatPath(source_base_dir,
429 token_val);
430 dir = CDirEntry::NormalizePath(dir);
431 dir = CDirEntry::AddTrailingPathSeparator(dir);
432
433 include_dirs->push_back(dir);
434 }
435
436 // process -Ipath
437 token_val = SMakeProjectT::GetOneIncludeDir(flag, "-I");
438 if ( !token_val.empty() && token_val[0] != '$' && token_val[0] != '@' && token_val[0] != ':' ) {
439 string dir = CDirEntry::NormalizePath(token_val);
440 dir = CDirEntry::AddTrailingPathSeparator(dir);
441 include_dirs->push_back(dir);
442 }
443
444 // process defines like NCBI_C_INCLUDE
445 if(CSymResolver::IsDefine(flag)) {
446 string dir_all;
447 GetApp().GetSite().ResolveDefine(CSymResolver::StripDefine(flag), dir_all);
448 if ( !dir_all.empty() ) {
449 list<string> dir_list;
450 NStr::Split(dir_all, LIST_SEPARATOR, dir_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate | NStr::fSplit_CanQuote);
451 ITERATE(list<string>, dir_item, dir_list) {
452 const string& dir = *dir_item;
453 if ( CDirEntry(dir).IsDir() ) {
454 include_dirs->push_back(dir);
455 } else if (CDirEntry::IsAbsolutePath(dir)) {
456 PTB_WARNING_EX(kEmptyStr, ePTB_FileNotFound, "In " << source_base_dir << ": "
457 << flag << " = " << dir << ": "
458 << dir << " not found");
459 include_dirs->push_back(dir);
460 } else {
461 string d =
462 CDirEntry::ConcatPath(GetApp().GetProjectTreeInfo().m_Include, dir);
463 d = CDirEntry::NormalizePath(d);
464 d = CDirEntry::AddTrailingPathSeparator(d);
465 if ( CDirEntry(d).IsDir() ) {
466 include_dirs->push_back(d);
467 }
468 /*
469 else {
470 LOG_POST(Warning << flag << " = " << dir << ": "
471 << dir << " not found");
472 }
473 */
474 }
475 }
476 }
477 }
478
479 // process additional include dirs for LibChoices
480 if(CSymResolver::IsDefine(flag)) {
481 string sflag = CSymResolver::StripDefine(flag);
482 list<string> libchoices_abs_includes ;
483 GetApp().GetSite().GetLibChoiceIncludes(sflag,
484 &libchoices_abs_includes);
485 ITERATE(list<string>, n, libchoices_abs_includes) {
486 const string& dir = *n;
487 if ( !dir.empty() ) {
488 include_dirs->push_back(dir);
489 }
490 }
491 }
492 }
493 include_dirs->sort();
494 include_dirs->unique();
495 }
496
497
CreateDefines(const list<string> & cpp_flags,list<string> * defines)498 void SMakeProjectT::CreateDefines(const list<string>& cpp_flags,
499 list<string>* defines)
500 {
501 defines->clear();
502
503 ITERATE(list<string>, p, cpp_flags) {
504 const string& flag = *p;
505 if ( NStr::StartsWith(flag, "-D") ) {
506 defines->push_back(flag.substr(2));
507 }
508 }
509 }
510
511
Create3PartyLibs(const list<string> & libs_flags,const list<string> & expected_flags,list<string> * libs_list,const string * mkname)512 void SMakeProjectT::Create3PartyLibs(
513 const list<string>& libs_flags, const list<string>& expected_flags,
514 list<string>* libs_list, const string* mkname)
515 {
516 bool liborder_found = mkname != NULL && GetApp().m_LibraryOrder.find(*mkname) != GetApp().m_LibraryOrder.end();
517 set<string> done;
518 list<string> unkflags;
519 list<CProjKey> libs3;
520 ITERATE(list<string>, p, libs_flags) {
521 string flag = *p;
522 if (flag == "#") {
523 break;
524 } else if ( IsConfigurableDefine(flag) ) {
525 libs_list->push_back(StripConfigurableDefine(flag));
526 done.insert(flag);
527 } else if (NStr::StartsWith(flag, "-l")) {
528 string suffix;
529 CSymResolver::StripSuffix(flag, &suffix);
530 if (liborder_found && find(
531 GetApp().m_LibraryOrder[*mkname].begin(),
532 GetApp().m_LibraryOrder[*mkname].end(), flag.substr(2)) !=
533 GetApp().m_LibraryOrder[*mkname].end()) {
534 continue;
535 }
536 libs3.push_back( CProjKey(CProjKey::eLib, flag.substr(2), suffix));
537 // user cannot be trusted
538 // GetApp().m_3PartyLibs.insert(flag.substr(2));
539 done.insert(flag.substr(2));
540 } else if ( NStr::CompareCase(flag, "-framework") == 0 ) {
541 if (p != libs_flags.end()) {
542 GetApp().m_3PartyLibs.insert(*(++p));
543 GetApp().m_Frameworks.insert(*p);
544 done.insert(flag);
545 }
546 } else {
547 unkflags.push_back(flag);
548 }
549 }
550 bool added = false;
551 if (GetApp().m_AddMissingDep) {
552 ITERATE(list<string>, p, expected_flags) {
553 const string& flag = *p;
554 if (NStr::StartsWith(flag, "-l")) {
555 if (done.find(flag.substr(2)) == done.end()) {
556 libs3.push_back( CProjKey(CProjKey::eLib, flag.substr(2)));
557 done.insert(flag.substr(2));
558 added = true;
559 }
560 } else if (IsConfigurableDefine(flag)) {
561 if (done.find(flag) == done.end()) {
562 libs3.push_back( CProjKey(CProjKey::eLib, flag));
563 done.insert(flag);
564 added = true;
565 }
566 } else {
567 if (find(unkflags.begin(), unkflags.end(), flag) == unkflags.end()) {
568 unkflags.push_back(flag);
569 added = true;
570 }
571 }
572 }
573 }
574 if (mkname != NULL && !GetApp().IsScanningWholeTree() && !libs3.empty()) {
575 list<string> liborder;
576 if (added) {
577 liborder.push_back("");
578 }
579 VerifyLibDepends(libs3, *mkname, liborder);
580 if (!liborder.empty()) {
581 GetApp().m_3PartyLibraryOrder[*mkname] = unkflags;
582 ITERATE( list<string>, s, liborder) {
583 if (!s->empty()) {
584 GetApp().m_3PartyLibraryOrder[*mkname].push_back(*s);
585 if (libs_list && find(libs_list->begin(), libs_list->end(), *s) == libs_list->end()) {
586 if ( IsConfigurableDefine(*s) ) {
587 libs_list->push_back(StripConfigurableDefine(*s));
588 } else {
589 libs_list->push_back(*s);
590 }
591 }
592 }
593 }
594 }
595 }
596 }
597
598
AnalyzeMakeIn(const CSimpleMakeFileContents & makein_contents,TMakeInInfoList * info)599 void SMakeProjectT::AnalyzeMakeIn
600 (const CSimpleMakeFileContents& makein_contents,
601 TMakeInInfoList* info)
602 {
603 info->clear();
604 CSimpleMakeFileContents::TContents::const_iterator p;
605
606 p = makein_contents.m_Contents.find("LIB_PROJ");
607 if (p != makein_contents.m_Contents.end()) {
608
609 info->push_back(SMakeInInfo(SMakeInInfo::eLib, p->second,
610 makein_contents.GetMakeType()));
611 }
612 p = makein_contents.m_Contents.find("EXPENDABLE_LIB_PROJ");
613 if (p != makein_contents.m_Contents.end()) {
614
615 info->push_back(SMakeInInfo(SMakeInInfo::eLib, p->second,
616 max(makein_contents.GetMakeType(),eMakeType_Expendable)));
617 }
618 p = makein_contents.m_Contents.find("POTENTIAL_LIB_PROJ");
619 if (p != makein_contents.m_Contents.end()) {
620
621 info->push_back(SMakeInInfo(SMakeInInfo::eLib, p->second,
622 max(makein_contents.GetMakeType(),eMakeType_Potential)));
623 }
624
625 p = makein_contents.m_Contents.find("DLL_PROJ");
626 if (p != makein_contents.m_Contents.end()) {
627
628 info->push_back(SMakeInInfo(SMakeInInfo::eDll, p->second,
629 makein_contents.GetMakeType()));
630 }
631 p = makein_contents.m_Contents.find("EXPENDABLE_DLL_PROJ");
632 if (p != makein_contents.m_Contents.end()) {
633
634 info->push_back(SMakeInInfo(SMakeInInfo::eDll, p->second,
635 max(makein_contents.GetMakeType(),eMakeType_Expendable)));
636 }
637 p = makein_contents.m_Contents.find("POTENTIAL_DLL_PROJ");
638 if (p != makein_contents.m_Contents.end()) {
639
640 info->push_back(SMakeInInfo(SMakeInInfo::eDll, p->second,
641 max(makein_contents.GetMakeType(),eMakeType_Potential)));
642 }
643
644 p = makein_contents.m_Contents.find("APP_PROJ");
645 if (p != makein_contents.m_Contents.end()) {
646
647 info->push_back(SMakeInInfo(SMakeInInfo::eApp, p->second,
648 makein_contents.GetMakeType()));
649 }
650 p = makein_contents.m_Contents.find("EXPENDABLE_APP_PROJ");
651 if (p != makein_contents.m_Contents.end()) {
652
653 info->push_back(SMakeInInfo(SMakeInInfo::eApp, p->second,
654 max(makein_contents.GetMakeType(),eMakeType_Expendable)));
655 }
656 p = makein_contents.m_Contents.find("POTENTIAL_APP_PROJ");
657 if (p != makein_contents.m_Contents.end()) {
658
659 info->push_back(SMakeInInfo(SMakeInInfo::eApp, p->second,
660 max(makein_contents.GetMakeType(),eMakeType_Potential)));
661 }
662
663 p = makein_contents.m_Contents.find("ASN_PROJ");
664 if (p != makein_contents.m_Contents.end()) {
665
666 info->push_back(SMakeInInfo(SMakeInInfo::eASN, p->second,
667 makein_contents.GetMakeType()));
668 }
669 p = makein_contents.m_Contents.find("DTD_PROJ");
670 if (p != makein_contents.m_Contents.end()) {
671
672 info->push_back(SMakeInInfo(SMakeInInfo::eDTD, p->second,
673 makein_contents.GetMakeType()));
674 }
675 p = makein_contents.m_Contents.find("XSD_PROJ");
676 if (p != makein_contents.m_Contents.end()) {
677
678 info->push_back(SMakeInInfo(SMakeInInfo::eXSD, p->second,
679 makein_contents.GetMakeType()));
680 }
681 p = makein_contents.m_Contents.find("WSDL_PROJ");
682 if (p != makein_contents.m_Contents.end()) {
683
684 info->push_back(SMakeInInfo(SMakeInInfo::eWSDL, p->second,
685 makein_contents.GetMakeType()));
686 }
687 p = makein_contents.m_Contents.find("JSD_PROJ");
688 if (p != makein_contents.m_Contents.end()) {
689
690 info->push_back(SMakeInInfo(SMakeInInfo::eJSD, p->second,
691 makein_contents.GetMakeType()));
692 }
693 p = makein_contents.m_Contents.find("PROTOBUF_PROJ");
694 if (p != makein_contents.m_Contents.end()) {
695
696 info->push_back(SMakeInInfo(SMakeInInfo::eProtobuf, p->second,
697 makein_contents.GetMakeType()));
698 }
699
700 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
701 p = makein_contents.m_Contents.find("UNIX_PROJ");
702 } else if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode) {
703 p = makein_contents.m_Contents.find("XCODE_PROJ");
704 } else {
705 p = makein_contents.m_Contents.find("MSVC_PROJ");
706 }
707 if (p != makein_contents.m_Contents.end()) {
708
709 info->push_back(SMakeInInfo(SMakeInInfo::eMsvc, p->second,
710 makein_contents.GetMakeType()));
711 }
712
713 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
714 p = makein_contents.m_Contents.find("EXPENDABLE_UNIX_PROJ");
715 if (p != makein_contents.m_Contents.end()) {
716
717 info->push_back(SMakeInInfo(SMakeInInfo::eMsvc, p->second,
718 max(makein_contents.GetMakeType(),eMakeType_Expendable)));
719 }
720 }
721 p = makein_contents.m_Contents.find("METAL_PROJ");
722 if (p != makein_contents.m_Contents.end()) {
723
724 info->push_back(SMakeInInfo(SMakeInInfo::eMetal, p->second,
725 makein_contents.GetMakeType()));
726 }
727 }
728
729
CreateMakeAppLibFileName(const string & base_dir,const string & projname,SMakeInInfo::TMakeinType type)730 string SMakeProjectT::CreateMakeAppLibFileName
731 (const string& base_dir,
732 const string& projname,
733 SMakeInInfo::TMakeinType type)
734 {
735 CProjItem::TProjType proj_type =
736 SMakeProjectT::GetProjType(base_dir, projname, type);
737
738 string fname = "Makefile." + projname;
739 switch (proj_type) {
740 case CProjKey::eLib: fname += type == SMakeInInfo::eMetal ? ".metal" : ".lib"; break;
741 case CProjKey::eDll: fname += ".dll"; break;
742 case CProjKey::eApp: fname += ".app"; break;
743 case CProjKey::eMsvc:
744 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
745 if (!CDirEntry( CDirEntry::ConcatPath(base_dir,fname)).Exists()) {
746 fname += ".in";
747 }
748 } else if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eXCode) {
749 fname += ".msvcproj";
750 }
751 break;
752 default: break;
753 }
754 return CDirEntry::ConcatPath(base_dir, fname);
755 }
756
757
CreateFullPathes(const string & dir,const list<string> files,list<string> * full_pathes)758 void SMakeProjectT::CreateFullPathes(const string& dir,
759 const list<string> files,
760 list<string>* full_pathes)
761 {
762 ITERATE(list<string>, p, files) {
763 string full_path = CDirEntry::ConcatPath(dir, *p);
764 full_pathes->push_back(full_path);
765 }
766 }
767
768 static
s_CollectAllLeaves(const map<string,set<string>> & source_dep,const map<string,set<string>> & source_flags,const string & branch,set<string> & all_dep,set<string> & all_flags)769 void s_CollectAllLeaves(const map<string, set<string> >& source_dep,
770 const map<string, set<string> >& source_flags,
771 const string& branch,
772 set<string>& all_dep,
773 set<string>& all_flags)
774 {
775 if (all_dep.find(branch) != all_dep.end()) {
776 return;
777 }
778 all_dep.insert(branch);
779 if (source_flags.find(branch) != source_flags.end()) {
780 const set<string>& flags(source_flags.find(branch)->second);
781 ITERATE(set<string>, f, flags) {
782 all_flags.insert(*f);
783 }
784 }
785 if (source_dep.find(branch) != source_dep.end()) {
786 const set<string>& branches(source_dep.find(branch)->second);
787 ITERATE(set<string>, b, branches) {
788 s_CollectAllLeaves(source_dep, source_flags, *b, all_dep, all_flags);
789 }
790 }
791 }
792
VerifyLibDepends(list<CProjKey> & depends_ids_arg,const string & mkname,list<string> & liborder,const set<string> * libs_3party,list<string> * expected_3party)793 void SMakeProjectT::VerifyLibDepends(
794 list<CProjKey>& depends_ids_arg, const string& mkname, list<string>& liborder,
795 const set<string>* libs_3party, list<string>* expected_3party)
796 {
797 if (depends_ids_arg.empty()) {
798 return;
799 }
800 if (GetApp().m_GraphDepPrecedes.empty()) {
801 return;
802 }
803 CProjBulderApp& app(GetApp());
804 list<string> warnings;
805 list<string> original;
806 list<string> duplicates;
807 list<string> missing;
808 map<string, string> missing_suffix;
809 set<string> alldepends;
810 set<string> allflags;
811 list<CProjKey> depends_ids( depends_ids_arg);
812
813 for(list<CProjKey>::const_iterator p = depends_ids.begin();
814 p != depends_ids.end(); ++p) {
815 for(list<CProjKey>::const_iterator i = p;
816 ++i != depends_ids.end();) {
817 if (*i == *p) {
818 duplicates.push_back(i->Id());
819 break;
820 }
821 }
822 original.push_back(p->Id());
823 s_CollectAllLeaves( app.m_GraphDepPrecedes, app.m_GraphDepFlags, p->Id(), alldepends, allflags);
824 }
825 if (expected_3party != nullptr) {
826 ITERATE( set<string>, s, allflags) {
827 expected_3party->push_back(*s);
828 }
829 }
830 ITERATE( set<string>, s, alldepends) {
831 string id(*s);
832 string s_suffix;
833 CSymResolver::StripSuffix(id, &s_suffix);
834 list<CProjKey>::const_iterator p = depends_ids.begin();
835 for(; p != depends_ids.end(); ++p) {
836 if (p->Id() == id) {
837 break;
838 }
839 }
840 if (p == depends_ids.end()) {
841 for(p = depends_ids.begin(); p != depends_ids.end(); ++p) {
842 if (app.m_GraphDepIncludes[p->Id()].find(id) != app.m_GraphDepIncludes[p->Id()].end()) {
843 break;
844 }
845 }
846 if (p == depends_ids.end()) {
847 if (libs_3party == nullptr ||
848 libs_3party->find(id) == libs_3party->end()) {
849 if (!SMakeProjectT::IsConfigurableDefine(id) &&
850 !app.GetSite().IsLibWithChoice(id) &&
851 !app.GetSite().Is3PartyLibWithChoice(id)) {
852 missing.push_back(id);
853 missing_suffix[id] = s_suffix;
854 }
855 } else if (expected_3party != nullptr) {
856 if (SMakeProjectT::IsConfigurableDefine(id)) {
857 expected_3party->push_back( id);
858 } else {
859 expected_3party->push_back( "-l" + id);
860 }
861 }
862 }
863 }
864 }
865 if (!missing.empty()) {
866 warnings.push_back("missing dependencies: " + NStr::Join(missing,","));
867 if (app.m_AddMissingDep && libs_3party != nullptr) {
868 ITERATE( list<string>, m, missing) {
869 depends_ids.push_back(CProjKey(CProjKey::eLib, *m, missing_suffix[*m]));
870 }
871 }
872 }
873 if (!duplicates.empty()) {
874 warnings.push_back("duplicate dependencies: " + NStr::Join(duplicates,","));
875 }
876 #if 1
877 set<string> projlibs;
878 bool fix = (!liborder.empty() && liborder.begin()->empty()) ||
879 !duplicates.empty() || depends_ids_arg.size() != depends_ids.size();
880 if (fix) {
881 liborder.clear();
882 }
883 if (!app.m_GraphDepPrecedes.empty()) {
884 set<string> libsofar;
885 for(list<CProjKey>::const_iterator p = depends_ids.begin();
886 p != depends_ids.end(); ++p) {
887 list<string> wrong;
888 bool obsolete = false;
889 ITERATE(set<string>, s, libsofar) {
890 if (app.m_GraphDepPrecedes.find(p->Id()) != app.m_GraphDepPrecedes.end()) {
891 if (app.m_GraphDepPrecedes[p->Id()].find(*s) != app.m_GraphDepPrecedes[p->Id()].end()) {
892 wrong.push_back(*s);
893 }
894 }
895 if (app.m_GraphDepIncludes[p->Id()].find(*s) != app.m_GraphDepIncludes[p->Id()].end()) {
896 fix=true;
897 obsolete = true;
898 projlibs.erase(*s);
899 projlibs.insert(p->Id());
900 warnings.push_back("obsolete library: " + *s + " already included into " + p->Id());
901 }
902 if (app.m_GraphDepIncludes[*s].find(p->Id()) != app.m_GraphDepIncludes[*s].end()) {
903 fix=true;
904 obsolete = true;
905 projlibs.erase(p->Id());
906 projlibs.insert(*s);
907 warnings.push_back("obsolete library: " + p->Id() + " already included into " + *s);
908 }
909 }
910 if (!wrong.empty()) {
911 fix=true;
912 #if 0
913 if (find(missing.begin(), missing.end(), p->Id()) == missing.end()) {
914 warnings.push_back("wrong library order: " + p->Id() + " should precede " + NStr::Join(wrong,","));
915 }
916 #endif
917 }
918 libsofar.insert(p->Id());
919 if (!obsolete) {
920 projlibs.insert(p->Id());
921 }
922 }
923 // all libs should be known
924 {
925 list<string> unknown;
926 ITERATE (set<string>, p, projlibs) {
927 if (app.m_GraphDepPrecedes.find(*p) == app.m_GraphDepPrecedes.end()) {
928 unknown.push_back(*p);
929 }
930 }
931 if (!unknown.empty()) {
932 fix = false;
933 warnings.push_back("unknown libraries: " + NStr::Join(unknown,","));
934 }
935 }
936 }
937 if (fix) {
938 if (app.m_GraphDepRank.empty()) {
939 ITERATE (set<string>, p, projlibs) {
940 liborder.push_back(*p);
941 }
942 } else {
943 vector< list<string> > recommend;
944 for (set<string>::const_iterator p= projlibs.begin(); p != projlibs.end(); ++p) {
945 size_t rank = app.m_GraphDepRank[*p];
946 while (recommend.size() < rank+1) {
947 list<string> t;
948 recommend.push_back(t);
949 }
950 recommend[rank].push_back(*p);
951 }
952 list<string> advice;
953 for (size_t a= recommend.size(); a!= 0; --a) {
954 advice.insert(advice.end(), recommend[a-1].begin(), recommend[a-1].end());
955 }
956 #if 0
957 warnings.push_back("present library order: " + NStr::Join(original,","));
958 warnings.push_back("recommended library order: " + NStr::Join(advice,","));
959 #endif
960 list<string> advice_full;
961 ITERATE( list<string>, a, advice) {
962 for(list<CProjKey>::const_iterator p = depends_ids.begin();
963 p != depends_ids.end(); ++p) {
964 if (*a == p->Id()) {
965 advice_full.push_back( p->FullId());
966 break;
967 }
968 }
969 }
970 liborder = advice_full;
971 }
972 }
973 #if 0
974 if (!warnings.empty() && expected_3party != nullptr) {
975 if (libs_3party == nullptr) {
976 warnings.push_front("====== Library order warnings (3rd party libs) ======");
977 } else {
978 warnings.push_front("====== Library order warnings (toolkit libs) ======");
979 }
980 PTB_WARNING_EX(mkname,ePTB_InvalidMakefile,
981 NStr::Join(warnings,"\n"));
982 }
983 #endif
984 #else
985 /*
986 this compares dependency rank,
987 BUT rank does not mean that one library really needs another one;
988 maybe, they are just in different dependency branches.
989 That is, while, in general, it is good to place higher rank libs first,
990 in reality, it is not necessarily a problem.
991
992 ALSO, this is very slow, most likely because of large number of warning generated
993 */
994 if (!app.m_GraphDepRank.empty()) {
995 set<string> libsofar;
996 for(list<CProjKey>::const_iterator p = depends_ids.begin();
997 p != depends_ids.end(); ++p) {
998 list<string> wrong;
999 ITERATE(set<string>, s, libsofar) {
1000 if (app.m_GraphDepRank[*s] < app.m_GraphDepRank[p->Id()]) {
1001 wrong.push_back(*s);
1002 }
1003 if (app.m_GraphDepIncludes[p->Id()].find(*s) != app.m_GraphDepIncludes[p->Id()].end()) {
1004 PTB_WARNING_EX(mkname,ePTB_InvalidMakefile,
1005 "obsolete library: " << *s << " already included into " << p->Id());
1006 }
1007 if (app.m_GraphDepIncludes[*s].find(p->Id()) != app.m_GraphDepIncludes[*s].end()) {
1008 PTB_WARNING_EX(mkname,ePTB_InvalidMakefile,
1009 "obsolete library: " << p->Id() << " already included into " << *s);
1010 }
1011 }
1012 if (!wrong.empty()) {
1013 PTB_WARNING_EX(mkname,ePTB_InvalidMakefile,
1014 "wrong library order: " << p->Id() << " should precede " << NStr::Join(wrong,","));
1015 }
1016 libsofar.insert(p->Id());
1017 }
1018 }
1019 #endif
1020 if (depends_ids_arg.size() != depends_ids.size()) {
1021 depends_ids_arg = depends_ids;
1022 }
1023 }
1024
ConvertLibDepends(const list<string> & depends,list<CProjKey> * depends_ids,const string * mkname,list<string> * expected_3party)1025 void SMakeProjectT::ConvertLibDepends(const list<string>& depends,
1026 list<CProjKey>* depends_ids,
1027 const string* mkname,
1028 list<string>* expected_3party)
1029 {
1030 list<string> depends_libs;
1031 SMakeProjectT::ConvertLibDependsMacro(depends, depends_libs);
1032
1033 const CMsvcSite& site = GetApp().GetSite();
1034 ITERATE(list<string>, p, depends_libs) {
1035 string id = *p;
1036 string suffix;
1037 CSymResolver::StripSuffix(id, &suffix);
1038 if(CSymResolver::IsDefine(id)) {
1039 string def;
1040 GetApp().GetSite().ResolveDefine(CSymResolver::StripDefine(id), def);
1041 list<string> resolved_def;
1042 NStr::Split(def, LIST_SEPARATOR, resolved_def, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
1043 ITERATE(list<string>, r, resolved_def) {
1044 id = *r;
1045 if (!site.IsLibWithChoice(id) ||
1046 site.GetChoiceForLib(id) == CMsvcSite::eLib) {
1047 depends_ids->push_back(CProjKey(CProjKey::eLib, id, suffix));
1048 }
1049 }
1050 } else if (SMakeProjectT::IsConfigurableDefine(id)) {
1051 } else if (id.empty()) {
1052 } else {
1053 if (!site.IsLibWithChoice(id) ||
1054 site.GetChoiceForLib(id) == CMsvcSite::eLib) {
1055 depends_ids->push_back(CProjKey(CProjKey::eLib, id, suffix));
1056 }
1057 }
1058 }
1059
1060 if (mkname != NULL && !GetApp().IsScanningWholeTree()) {
1061 VerifyLibDepends(*depends_ids, *mkname, GetApp().m_LibraryOrder[ *mkname],
1062 &GetApp().m_3PartyLibs, expected_3party);
1063 }
1064
1065 depends_ids->sort();
1066 depends_ids->unique();
1067 }
1068
ConvertLibDependsMacro(const list<string> & depends,list<string> & depends_libs)1069 void SMakeProjectT::ConvertLibDependsMacro(const list<string>& depends,
1070 list<string>& depends_libs)
1071 {
1072 const CMsvcSite& site = GetApp().GetSite();
1073 ITERATE(list<string>, p, depends) {
1074 const string& id = *p;
1075 if (id[0] == '#') {
1076 break;
1077 }
1078 string lib = site.ProcessMacros(id,false);
1079 if (!lib.empty()) {
1080 depends_libs.push_back(lib);
1081 } else {
1082 if (CSymResolver::IsDefine(id) &&
1083 site.GetMacros().GetValue(CSymResolver::StripDefine(id),lib)) {
1084 list<string> res;
1085 NStr::Split(lib, LIST_SEPARATOR, res, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
1086 ITERATE( list<string>, r, res) {
1087 if (NStr::StartsWith(*r, "-l")) {
1088 depends_libs.push_back(r->substr(2));
1089 } else {
1090 depends_libs.push_back(*r);
1091 }
1092 }
1093 } else {
1094 depends_libs.push_back(id);
1095 }
1096 }
1097 }
1098 }
1099
1100
IsConfigurableDefine(const string & define)1101 bool SMakeProjectT::IsConfigurableDefine(const string& define)
1102 {
1103 if (NStr::StartsWith(define, "@")) {
1104 string::size_type end = define.find("@",1);
1105 return end != string::npos && ( ++end == define.size() || define[end] == '\0');
1106 }
1107 return false;
1108
1109 }
1110
1111
StripConfigurableDefine(const string & define)1112 string SMakeProjectT::StripConfigurableDefine(const string& define)
1113 {
1114 return IsConfigurableDefine(define) ?
1115 define.substr(1, define.length() - 2): "";
1116 }
1117
HasConfigurableDefine(const string & define)1118 bool SMakeProjectT::HasConfigurableDefine(const string& define)
1119 {
1120 return define.find("@") != string::npos;
1121 }
1122
ExtractConfigurableDefine(const string & define)1123 string SMakeProjectT::ExtractConfigurableDefine (const string& define)
1124 {
1125 string::size_type start, end;
1126 start = define.find("@");
1127 end = define.find("@",start+1);
1128 if (end == string::npos) {
1129 PTB_WARNING_EX(kEmptyStr, ePTB_MacroInvalid, "Possibly incorrect MACRO definition in: " + define);
1130 return define;
1131 }
1132 return define.substr(start,end-start+1);
1133 }
1134
1135 //-----------------------------------------------------------------------------
CreateNcbiCToolkitLibs(const CSimpleMakeFileContents & makefile,list<string> * libs_list)1136 void SAppProjectT::CreateNcbiCToolkitLibs(const CSimpleMakeFileContents& makefile,
1137 list<string>* libs_list)
1138 {
1139 CSimpleMakeFileContents::TContents::const_iterator k =
1140 makefile.m_Contents.find("NCBI_C_LIBS");
1141 if (k == makefile.m_Contents.end()) {
1142 return;
1143 }
1144 const list<string>& values = k->second;
1145
1146 ITERATE(list<string>, p, values) {
1147 const string& val = *p;
1148 if ( NStr::StartsWith(val, "-l") ) {
1149 string lib_id = val.substr(2);
1150 libs_list->push_back(lib_id);
1151 } else {
1152 libs_list->push_back(val);
1153 }
1154 }
1155
1156 libs_list->sort();
1157 libs_list->unique();
1158 }
1159
DoCreate(const string & source_base_dir,const string & proj_name,const string & applib_mfilepath,const TFiles & makeapp,CProjectItemsTree * tree,EMakeFileType maketype)1160 CProjKey SAppProjectT::DoCreate(const string& source_base_dir,
1161 const string& proj_name,
1162 const string& applib_mfilepath,
1163 const TFiles& makeapp ,
1164 CProjectItemsTree* tree,
1165 EMakeFileType maketype)
1166 {
1167 CProjectItemsTree::TFiles::const_iterator m = makeapp.find(applib_mfilepath);
1168 if (m == makeapp.end()) {
1169 /// FIXME: items may not be really missing here; they may just be
1170 /// excluded based on user preference
1171 /**
1172 PTB_WARNING_EX(applib_mfilepath, ePTB_MissingMakefile,
1173 "Makefile not found");
1174 **/
1175 return CProjKey();
1176 }
1177
1178 const CSimpleMakeFileContents& makefile = m->second;
1179 string full_makefile_name = CDirEntry(applib_mfilepath).GetName();
1180 string full_makefile_path = applib_mfilepath;
1181
1182 CSimpleMakeFileContents::TContents::const_iterator k;
1183 //project id
1184 k = makefile.m_Contents.find("APP");
1185 if (k == makefile.m_Contents.end() || k->second.empty()) {
1186 if (GetApp().IsScanningWholeTree()) {
1187 PTB_WARNING_EX(full_makefile_path, ePTB_InvalidMakefile,
1188 "APP is not specified: " << full_makefile_name);
1189 } else {
1190 PTB_ERROR_EX(full_makefile_path, ePTB_InvalidMakefile,
1191 "APP is not specified: " << full_makefile_name);
1192 }
1193 return CProjKey();
1194 }
1195 string proj_id = k->second.front();
1196 {{
1197 CProjKey proj_key(CProjKey::eApp, proj_id);
1198 CProjectItemsTree::TProjects::const_iterator z = tree->m_Projects.find(proj_key);
1199 if (z != tree->m_Projects.end()) {
1200 if (z->second.m_MakeType < eMakeType_Excluded) {
1201 PTB_WARNING_EX(full_makefile_path, ePTB_ConfigurationError,
1202 "Application " << proj_id << " already defined at "
1203 << tree->m_Projects[proj_key].m_SourcesBaseDir);
1204 if (maketype == eMakeType_Excluded || GetApp().IsScanningWholeTree()) {
1205 return CProjKey();
1206 } else {
1207 GetApp().RegisterSuspiciousProject(proj_key);
1208 }
1209 } else {
1210 tree->m_Projects.erase(proj_key);
1211 }
1212 }
1213 }}
1214
1215 k = makefile.m_Contents.find("SRC");
1216 if (k == makefile.m_Contents.end()) {
1217 if (GetApp().IsScanningWholeTree()) {
1218 PTB_WARNING_EX(full_makefile_path, ePTB_InvalidMakefile,
1219 "SRC is not specified: " << full_makefile_name);
1220 } else {
1221 PTB_ERROR_EX(full_makefile_path, ePTB_InvalidMakefile,
1222 "SRC is not specified: " << full_makefile_name);
1223 }
1224 return CProjKey();
1225 }
1226
1227 //sources - relative paths from source_base_dir
1228 //We'll create relative pathes from them
1229 CProjSRCResolver src_resolver(applib_mfilepath,
1230 source_base_dir, k->second);
1231 list<string> sources;
1232 src_resolver.ResolveTo(&sources);
1233
1234 if (CMsvc7RegSettings::GetMsvcPlatform() >= CMsvc7RegSettings::eUnix) {
1235 k = makefile.m_Contents.find("UNIX_SRC");
1236 if (k != makefile.m_Contents.end()) {
1237 CProjSRCResolver unix_src_resolver(applib_mfilepath,
1238 source_base_dir, k->second);
1239 list<string> unix_sources;
1240 unix_src_resolver.ResolveTo(&unix_sources);
1241 copy(unix_sources.begin(), unix_sources.end(), back_inserter(sources));
1242 }
1243 }
1244
1245 //depends
1246 list<string> depends;
1247 k = makefile.m_Contents.find("LIB");
1248 if (GetApp().GetBuildType().GetType() == CBuildType::eStatic) {
1249 CSimpleMakeFileContents::TContents::const_iterator tmp_k =
1250 makefile.m_Contents.find("STATIC_LIB");
1251 if (tmp_k != makefile.m_Contents.end()) {
1252 k = tmp_k;
1253 }
1254 }
1255 if (k != makefile.m_Contents.end()) {
1256 // depends = k->second;
1257 ITERATE(list<string>, i, k->second) {
1258 #if 0
1259 depends.push_back(
1260 NStr::Replace(NStr::Replace(*i, "-dll", kEmptyStr),
1261 "-static", kEmptyStr));
1262 #else
1263 depends.push_back( *i);
1264 #endif
1265 }
1266 }
1267 //Adjust depends by information from msvc Makefile
1268 CMsvcProjectMakefile project_makefile( CDirEntry::ConcatPath(
1269 source_base_dir, CreateMsvcProjectMakefileName(proj_name, CProjKey::eApp)));
1270
1271 list<string> added_depends;
1272 project_makefile.GetAdditionalLIB(SConfigInfo(), &added_depends);
1273
1274 list<string> excluded_depends;
1275 project_makefile.GetExcludedLIB(SConfigInfo(), &excluded_depends);
1276
1277 list<string> adj_depends(depends);
1278 copy(added_depends.begin(),
1279 added_depends.end(), back_inserter(adj_depends));
1280
1281 PLibExclude pred(proj_name, excluded_depends);
1282 EraseIf(adj_depends, pred);
1283
1284 list<string> expected_3party;
1285 list<CProjKey> depends_ids;
1286 SMakeProjectT::ConvertLibDepends(adj_depends, &depends_ids,
1287 &applib_mfilepath, &expected_3party);
1288
1289 list<CProjKey> unconditional_depends_ids;
1290 k = m->second.m_Contents.find("USR_DEP");
1291 if (k != m->second.m_Contents.end()) {
1292 const list<string> depends = k->second;
1293 SMakeProjectT::ConvertLibDepends(depends, &unconditional_depends_ids);
1294 copy(unconditional_depends_ids.begin(),
1295 unconditional_depends_ids.end(), back_inserter(depends_ids));
1296 }
1297 k = m->second.m_Contents.find("MSVC_DEP");
1298 if (k != m->second.m_Contents.end()) {
1299 const list<string> deps = k->second;
1300 ITERATE(list<string>, p, deps) {
1301 depends_ids.push_back(CProjKey(CProjKey::eMsvc, *p));
1302 }
1303 }
1304 ///////////////////////////////////
1305
1306 //requires
1307 list<string> requires;
1308 list<string> req_lst;
1309 if (makefile.CollectValues("REQUIRES", req_lst,
1310 CSimpleMakeFileContents::eSortUnique)) {
1311 project_makefile.Redefine(req_lst,requires);
1312 }
1313
1314 //LIBS
1315 list<string> libs_3_party;
1316 k = makefile.m_Contents.find("LIBS");
1317 if (GetApp().GetBuildType().GetType() == CBuildType::eStatic) {
1318 CSimpleMakeFileContents::TContents::const_iterator tmp_k =
1319 makefile.m_Contents.find("STATIC_LIBS");
1320 if (tmp_k != makefile.m_Contents.end()) {
1321 k = tmp_k;
1322 }
1323 }
1324 if (k != makefile.m_Contents.end() || !expected_3party.empty()) {
1325 list<string> libs_flags;
1326 if (k != makefile.m_Contents.end()) {
1327 libs_flags = k->second;
1328 }
1329 SMakeProjectT::Create3PartyLibs(libs_flags, expected_3party, &libs_3_party, &applib_mfilepath);
1330 }
1331
1332 //CPPFLAGS
1333 list<string> include_dirs;
1334 list<string> defines;
1335 k = makefile.m_Contents.find("CPPFLAGS");
1336 if (k != makefile.m_Contents.end()) {
1337 const list<string>& cpp_flags = k->second;
1338 SMakeProjectT::CreateIncludeDirs(cpp_flags,
1339 source_base_dir, &include_dirs);
1340 SMakeProjectT::CreateDefines(cpp_flags, &defines);
1341 }
1342 bool style_objcpp = false;
1343 k = makefile.m_Contents.find("CXXFLAGS");
1344 if (k != makefile.m_Contents.end()) {
1345 const list<string>& cxx_flags = k->second;
1346 style_objcpp = find(cxx_flags.begin(), cxx_flags.end(), "objective-c++") != cxx_flags.end();
1347 }
1348
1349 //NCBI_C_LIBS - Special case for NCBI C Toolkit
1350 k = makefile.m_Contents.find("NCBI_C_LIBS");
1351 list<string> ncbi_clibs;
1352 if (k != makefile.m_Contents.end()) {
1353 libs_3_party.push_back("NCBI_C_LIBS");
1354 CreateNcbiCToolkitLibs(makefile, &ncbi_clibs);
1355 }
1356
1357 CProjItem project(CProjKey::eApp,
1358 proj_name,
1359 proj_id,
1360 source_base_dir,
1361 sources,
1362 depends_ids,
1363 requires,
1364 libs_3_party,
1365 include_dirs,
1366 defines,
1367 maketype,
1368 IdentifySlnGUID(source_base_dir, CProjKey(CProjKey::eApp, proj_id)));
1369 //
1370 project.m_NcbiCLibs = ncbi_clibs;
1371 project.m_StyleObjcpp = style_objcpp;
1372 project.m_MkName = applib_mfilepath;
1373 project.m_DataSource = CSimpleMakeFileContents(applib_mfilepath);;
1374
1375 //DATATOOL_SRC
1376 list<CDataToolGeneratedSrc> datatool_sources;
1377 k = makefile.m_Contents.find("DATATOOL_SRC");
1378 if ( k != makefile.m_Contents.end() ) {
1379 const list<string> datatool_src_list = k->second;
1380 ITERATE(list<string>, i, datatool_src_list) {
1381
1382 const string& src = *i;
1383 //Will process .asn or .dtd files
1384 string source_file_path =
1385 CDirEntry::ConcatPath(source_base_dir, src);
1386 source_file_path = CDirEntry::NormalizePath(source_file_path);
1387 if ( CDirEntry(source_file_path + ".asn").Exists() )
1388 source_file_path += ".asn";
1389 else if ( CDirEntry(source_file_path + ".dtd").Exists() )
1390 source_file_path += ".dtd";
1391 else if ( CDirEntry(source_file_path + ".xsd").Exists() )
1392 source_file_path += ".xsd";
1393
1394 CDataToolGeneratedSrc data_tool_src;
1395 CDataToolGeneratedSrc::LoadFrom(source_file_path, &data_tool_src);
1396 if ( !data_tool_src.IsEmpty() )
1397 datatool_sources.push_back(data_tool_src);
1398 }
1399 }
1400 if ( !datatool_sources.empty() ) {
1401 project.m_DatatoolSources = datatool_sources;
1402 if (GetApp().m_Dtdep && !GetApp().GetDatatoolId().empty()) {
1403 project.m_Depends.push_back(CProjKey(CProjKey::eApp, GetApp().GetDatatoolId()));
1404 }
1405 }
1406
1407 // assemble check info
1408 string check_info;
1409 string check_dir = CDirEntry::CreateRelativePath(
1410 GetApp().GetProjectTreeInfo().m_Src, source_base_dir);
1411 NStr::ReplaceInPlace(check_dir,"\\","/");
1412 if (NStr::EndsWith(check_dir,'/')) {
1413 check_dir.erase(check_dir.size()-1,1);
1414 }
1415 string check_testname(proj_name);
1416 string check_appname(proj_id);
1417
1418 string check_copy;
1419 k = makefile.m_Contents.find("CHECK_COPY");
1420 if ( k != makefile.m_Contents.end() && !k->second.empty() ) {
1421 check_copy = NStr::Join(k->second, " ");
1422 }
1423 string check_timeout("200");
1424 k = makefile.m_Contents.find("CHECK_TIMEOUT");
1425 if ( k != makefile.m_Contents.end() && !k->second.empty() ) {
1426 check_timeout = NStr::Join(k->second, " ");
1427 }
1428 bool check_requires_ok = true;
1429 string check_requires;
1430 k = makefile.m_Contents.find("CHECK_REQUIRES");
1431 if ( k != makefile.m_Contents.end() && !k->second.empty() ) {
1432 ITERATE(list<string>, p, k->second) {
1433 if ( !GetApp().GetSite().IsProvided(*p) ) {
1434 check_requires_ok = false;
1435 break;
1436 }
1437 }
1438 check_requires = NStr::Join(k->second, " ");
1439 }
1440 if (check_requires_ok) {
1441 k = makefile.m_Contents.find("REQUIRES");
1442 if ( k != makefile.m_Contents.end() && !k->second.empty() ) {
1443 if (!check_requires.empty()) {
1444 check_requires += " ";
1445 }
1446 check_requires += NStr::Join(k->second, " ");
1447 }
1448 }
1449
1450 string check_authors;
1451 list<string> lst_authors;
1452 if (makefile.CollectValues("WATCHERS", lst_authors,
1453 CSimpleMakeFileContents::eSortUnique)) {
1454 check_authors = NStr::Join(lst_authors, " ");
1455 project.m_Watchers = check_authors;
1456 } else {
1457 k = makefile.m_Contents.find("CHECK_AUTHORS");
1458 if ( k != makefile.m_Contents.end() && !k->second.empty() ) {
1459 check_authors = NStr::Join(k->second, " ");
1460 }
1461 }
1462
1463 k = makefile.m_Contents.find("CHECK_CMD");
1464 if ( check_requires_ok && k != makefile.m_Contents.end() ) {
1465 const list<string> check_cmd_list = k->second;
1466 string test_name("/CHECK_NAME=");
1467 ITERATE(list<string>, i, check_cmd_list) {
1468 string check_cmd(*i), check_name;
1469 string::size_type n = check_cmd.find(test_name);
1470 if (n != string::npos) {
1471 check_name = check_cmd.substr(n+test_name.size());
1472 check_cmd = check_cmd.substr(0,n);
1473 }
1474 NStr::TruncateSpacesInPlace(check_cmd);
1475 CNcbiOstrstream check;
1476 check << check_dir
1477 << s_check_separator << check_testname
1478 << s_check_separator << check_appname
1479 << s_check_separator << check_cmd
1480 << s_check_separator << check_name
1481 << s_check_separator << check_copy
1482 << s_check_separator << check_timeout
1483 << s_check_separator << check_requires
1484 << s_check_separator << check_authors;
1485 project.m_CheckInfo.push_back( CNcbiOstrstreamToString(check) );
1486 }
1487 }
1488
1489 project.m_ProjTags.push_back("exe");
1490 if (find(requires.begin(), requires.end(), "internal") == requires.end() ) {
1491 project.m_ProjTags.push_back("public");
1492 } else {
1493 project.m_ProjTags.push_back("internal");
1494 }
1495 makefile.CollectValues("PROJ_TAG", project.m_ProjTags,
1496 CSimpleMakeFileContents::eMergePlusMinus);
1497
1498 list<string> pch_lst;
1499 if (makefile.CollectValues("USE_PCH", pch_lst,
1500 CSimpleMakeFileContents::eFirstNonempty)) {
1501 project.m_Pch = pch_lst.front();
1502 }
1503
1504 CProjKey proj_key(CProjKey::eApp, proj_id);
1505 tree->m_Projects[proj_key] = project;
1506
1507 return proj_key;
1508 }
1509
1510
1511 //-----------------------------------------------------------------------------
DoCreate(const string & source_base_dir,const string & proj_name,const string & applib_mfilepath,const TFiles & makelib,CProjectItemsTree * tree,EMakeFileType maketype)1512 CProjKey SLibProjectT::DoCreate(const string& source_base_dir,
1513 const string& proj_name,
1514 const string& applib_mfilepath,
1515 const TFiles& makelib ,
1516 CProjectItemsTree* tree,
1517 EMakeFileType maketype)
1518 {
1519 TFiles::const_iterator m = makelib.find(applib_mfilepath);
1520 if (m == makelib.end()) {
1521 /// FIXME: items may not be really missing here; they may just be
1522 /// excluded based on user preference
1523 /**
1524 PTB_WARNING_EX(applib_mfilepath, ePTB_MissingMakefile,
1525 "Makefile not found");
1526 **/
1527 return CProjKey();
1528 }
1529
1530 // const CSimpleMakeFileContents& makefile = m->second;
1531 string full_makefile_name = CDirEntry(applib_mfilepath).GetName();
1532 string full_makefile_path = applib_mfilepath;
1533
1534 CSimpleMakeFileContents::TContents::const_iterator k;
1535 //project name
1536 k = m->second.m_Contents.find("LIB");
1537 if (GetApp().GetBuildType().GetType() == CBuildType::eStatic) {
1538 CSimpleMakeFileContents::TContents::const_iterator tmp_k =
1539 m->second.m_Contents.find("STATIC_LIB");
1540 if (tmp_k != m->second.m_Contents.end()) {
1541 k = tmp_k;
1542 }
1543 }
1544 if (k == m->second.m_Contents.end() ||
1545 k->second.empty()) {
1546 if (GetApp().IsScanningWholeTree()) {
1547 PTB_WARNING_EX(full_makefile_path, ePTB_InvalidMakefile,
1548 "LIB is not specified: " << full_makefile_name);
1549 } else {
1550 PTB_ERROR_EX(full_makefile_path, ePTB_InvalidMakefile,
1551 "LIB is not specified: " << full_makefile_name);
1552 }
1553 return CProjKey();
1554 }
1555 string proj_id = k->second.front();
1556 {{
1557 CProjKey proj_key(CProjKey::eLib, proj_id);
1558 CProjectItemsTree::TProjects::const_iterator z = tree->m_Projects.find(proj_key);
1559 if (z != tree->m_Projects.end()) {
1560 if (z->second.m_MakeType < eMakeType_Excluded) {
1561 PTB_WARNING_EX(full_makefile_path, ePTB_ConfigurationError,
1562 "Library " << proj_id << " already defined at "
1563 << tree->m_Projects[proj_key].m_SourcesBaseDir);
1564 if (maketype == eMakeType_Excluded || GetApp().IsScanningWholeTree()) {
1565 return CProjKey();
1566 } else {
1567 GetApp().RegisterSuspiciousProject(proj_key);
1568 }
1569 } else {
1570 tree->m_Projects.erase(proj_key);
1571 }
1572
1573 }
1574 }}
1575
1576 k = m->second.m_Contents.find("SRC");
1577 if (k == m->second.m_Contents.end()) {
1578 if (GetApp().IsScanningWholeTree()) {
1579 PTB_WARNING_EX(full_makefile_path, ePTB_InvalidMakefile,
1580 "SRC is not specified: " << full_makefile_name);
1581 } else {
1582 PTB_ERROR_EX(full_makefile_path, ePTB_InvalidMakefile,
1583 "SRC is not specified: " << full_makefile_name);
1584 }
1585 return CProjKey();
1586 }
1587
1588 // sources - relative pathes from source_base_dir
1589 // We'll create relative pathes from them)
1590 CProjSRCResolver src_resolver(applib_mfilepath,
1591 source_base_dir, k->second);
1592 list<string> sources;
1593 src_resolver.ResolveTo(&sources);
1594
1595 if (CMsvc7RegSettings::GetMsvcPlatform() >= CMsvc7RegSettings::eUnix) {
1596 k = m->second.m_Contents.find("UNIX_SRC");
1597 if (k != m->second.m_Contents.end()) {
1598 CProjSRCResolver unix_src_resolver(applib_mfilepath,
1599 source_base_dir, k->second);
1600 list<string> unix_sources;
1601 unix_src_resolver.ResolveTo(&unix_sources);
1602 copy(unix_sources.begin(), unix_sources.end(), back_inserter(sources));
1603 }
1604 }
1605
1606 // depends
1607 list<CProjKey> depends_ids;
1608 list<CProjKey> unconditional_depends_ids;
1609 k = m->second.m_Contents.find("ASN_DEP");
1610 if (k != m->second.m_Contents.end()) {
1611 const list<string> depends = k->second;
1612 SMakeProjectT::ConvertLibDepends(depends, &unconditional_depends_ids);
1613 copy(unconditional_depends_ids.begin(),
1614 unconditional_depends_ids.end(), back_inserter(depends_ids));
1615 }
1616 k = m->second.m_Contents.find("USR_DEP");
1617 if (k != m->second.m_Contents.end()) {
1618 const list<string> depends = k->second;
1619 SMakeProjectT::ConvertLibDepends(depends, &unconditional_depends_ids);
1620 copy(unconditional_depends_ids.begin(),
1621 unconditional_depends_ids.end(), back_inserter(depends_ids));
1622 }
1623 k = m->second.m_Contents.find("MSVC_DEP");
1624 if (k != m->second.m_Contents.end()) {
1625 const list<string> deps = k->second;
1626 ITERATE(list<string>, p, deps) {
1627 depends_ids.push_back(CProjKey(CProjKey::eMsvc, *p));
1628 }
1629 }
1630
1631 string dll_host;
1632 string lib_or_dll;
1633 k = m->second.m_Contents.find("LIB_OR_DLL");
1634 if (k != m->second.m_Contents.end()) {
1635 lib_or_dll = k->second.front();
1636 }
1637 if (NStr::CompareNocase(lib_or_dll,"dll") == 0 ||
1638 NStr::CompareNocase(lib_or_dll,"both") == 0 ||
1639 NStr::CompareNocase(lib_or_dll,"@USUAL_AND_DLL@") == 0) {
1640 dll_host = proj_id;
1641 }
1642 bool need_dll = (!dll_host.empty() &&
1643 GetApp().GetBuildType().GetType() == CBuildType::eDll);
1644
1645 //requires
1646 list<string> requires;
1647 list<string> req_lst;
1648 if (m->second.CollectValues("REQUIRES",req_lst,
1649 CSimpleMakeFileContents::eSortUnique)) {
1650 CMsvcProjectMakefile project_makefile( CDirEntry::ConcatPath(
1651 source_base_dir, CreateMsvcProjectMakefileName(proj_name, CProjKey::eLib)));
1652 project_makefile.Redefine(req_lst,requires);
1653 }
1654
1655 //CPPFLAGS
1656 list<string> include_dirs;
1657 list<string> defines;
1658 k = m->second.m_Contents.find("CPPFLAGS");
1659 if (k != m->second.m_Contents.end()) {
1660 const list<string>& cpp_flags = k->second;
1661 SMakeProjectT::CreateIncludeDirs(cpp_flags,
1662 source_base_dir, &include_dirs);
1663 SMakeProjectT::CreateDefines(cpp_flags, &defines);
1664
1665 }
1666 bool style_objcpp = false;
1667 k = m->second.m_Contents.find("CXXFLAGS");
1668 if (k != m->second.m_Contents.end()) {
1669 const list<string>& cxx_flags = k->second;
1670 style_objcpp = find(cxx_flags.begin(), cxx_flags.end(), "objective-c++") != cxx_flags.end();
1671 }
1672
1673 bool isbundle = false;
1674 k = m->second.m_Contents.find("DLL_TYPE");
1675 if (k != m->second.m_Contents.end() && k->second.front() == "plugin") {
1676 isbundle = true;
1677 }
1678 // if (!lib_or_dll.empty() ||
1679 // CMsvc7RegSettings::GetMsvcPlatform() >= CMsvc7RegSettings::eUnix) {
1680 // if (GetApp().GetBuildType().GetType() == CBuildType::eDll) {
1681 list<string> dll_depends;
1682 k = m->second.m_Contents.find("DLL_LIB");
1683 if (GetApp().m_AllDllBuild) {
1684 CSimpleMakeFileContents::TContents::const_iterator tmp_k =
1685 m->second.m_Contents.find("DLL_DLIB");
1686 if (tmp_k != m->second.m_Contents.end()) {
1687 k = tmp_k;
1688 }
1689 }
1690 if (k != m->second.m_Contents.end()) {
1691 ITERATE(list<string>, i, k->second) {
1692 #if 0
1693 dll_depends.push_back(
1694 NStr::Replace(NStr::Replace(*i, "-dll", kEmptyStr),
1695 "-static", kEmptyStr));
1696 #else
1697 dll_depends.push_back(*i);
1698 #endif
1699 }
1700 }
1701 list<string> expected_3party;
1702 list<CProjKey> dll_depends_ids;
1703 SMakeProjectT::ConvertLibDepends(dll_depends, &dll_depends_ids,
1704 need_dll ? &applib_mfilepath : NULL,
1705 need_dll ? &expected_3party : NULL);
1706 copy(dll_depends_ids.begin(),
1707 dll_depends_ids.end(),
1708 back_inserter(depends_ids));
1709 // }
1710 // }
1711
1712 //LIBS
1713 list<string> libs_3_party;
1714 k = m->second.m_Contents.find("LIBS");
1715 if (GetApp().GetBuildType().GetType() == CBuildType::eStatic) {
1716 CSimpleMakeFileContents::TContents::const_iterator tmp_k =
1717 m->second.m_Contents.find("STATIC_LIBS");
1718 if (tmp_k != m->second.m_Contents.end()) {
1719 k = tmp_k;
1720 }
1721 }
1722 if (k != m->second.m_Contents.end() || !expected_3party.empty()) {
1723 list<string> libs_flags;
1724 if (k != m->second.m_Contents.end()) {
1725 libs_flags = k->second;
1726 }
1727 SMakeProjectT::Create3PartyLibs(libs_flags, expected_3party, &libs_3_party,
1728 need_dll ? &applib_mfilepath : NULL);
1729 }
1730
1731 CProjKey proj_key(CProjKey::eLib, proj_id);
1732 tree->m_Projects[proj_key] = CProjItem(CProjKey::eLib,
1733 proj_name,
1734 proj_id,
1735 source_base_dir,
1736 sources,
1737 depends_ids,
1738 requires,
1739 libs_3_party,
1740 include_dirs,
1741 defines,
1742 maketype,
1743 IdentifySlnGUID(source_base_dir, proj_key));
1744 (tree->m_Projects[proj_key]).m_StyleObjcpp = style_objcpp;
1745 (tree->m_Projects[proj_key]).m_MkName = applib_mfilepath;
1746 (tree->m_Projects[proj_key]).m_DataSource = CSimpleMakeFileContents(applib_mfilepath);
1747 if (CDirEntry(full_makefile_name).GetExt() == ".metal") {
1748 (tree->m_Projects[proj_key]).m_IsMetallib = true;
1749 }
1750
1751 k = m->second.m_Contents.find("HEADER_EXPORT");
1752 if (k != m->second.m_Contents.end()) {
1753 (tree->m_Projects[proj_key]).m_ExportHeaders = k->second;
1754 }
1755 k = m->second.m_Contents.find("PACKAGE_EXPORT");
1756 if (k != m->second.m_Contents.end()) {
1757 (tree->m_Projects[proj_key]).m_ExportHeadersDest = k->second.front();
1758 }
1759 list<string> lst_watchers;
1760 if (m->second.CollectValues("WATCHERS", lst_watchers,
1761 CSimpleMakeFileContents::eSortUnique)) {
1762 tree->m_Projects[proj_key].m_Watchers = NStr::Join(lst_watchers, " ");
1763 }
1764
1765 tree->m_Projects[proj_key].m_ProjTags.push_back("lib");
1766 if (find(requires.begin(), requires.end(), "internal") == requires.end() ) {
1767 tree->m_Projects[proj_key].m_ProjTags.push_back("public");
1768 } else {
1769 tree->m_Projects[proj_key].m_ProjTags.push_back("internal");
1770 }
1771 m->second.CollectValues("PROJ_TAG", tree->m_Projects[proj_key].m_ProjTags,
1772 CSimpleMakeFileContents::eMergePlusMinus);
1773
1774 list<string> pch_lst;
1775 if (m->second.CollectValues("USE_PCH", pch_lst,
1776 CSimpleMakeFileContents::eFirstNonempty)) {
1777 tree->m_Projects[proj_key].m_Pch = pch_lst.front();
1778 }
1779
1780 if (!dll_host.empty() && GetApp().GetBuildType().GetType() == CBuildType::eDll) {
1781 tree->m_Projects[proj_key].m_DllHost = dll_host;
1782 CProjKey proj_dll(CProjKey::eDll, dll_host);
1783 if (tree->m_Projects.find(proj_dll) == tree->m_Projects.end()) {
1784 CProjItem item_dll = tree->m_Projects[proj_dll];
1785 item_dll.m_ProjType = CProjKey::eDll;
1786 #if 0
1787 item_dll.m_Name = dll_host;
1788 item_dll.m_ID = dll_host;
1789 #else
1790 item_dll.m_Name = proj_name;
1791 item_dll.m_ID = proj_id;
1792 #endif
1793 item_dll.m_SourcesBaseDir = source_base_dir;
1794 item_dll.m_MakeType = maketype;
1795 item_dll.m_HostedLibs.push_back(proj_id);
1796 item_dll.m_GUID = IdentifySlnGUID(source_base_dir, proj_dll);
1797 item_dll.m_IsBundle = isbundle;
1798 item_dll.m_External = true;
1799 item_dll.m_StyleObjcpp = style_objcpp;
1800 item_dll.m_MkName = applib_mfilepath;
1801 item_dll.m_DataSource = CSimpleMakeFileContents(applib_mfilepath);
1802 item_dll.m_ProjTags = tree->m_Projects[proj_key].m_ProjTags;
1803 item_dll.m_ProjTags.push_back("dll");
1804 tree->m_Projects[proj_dll] = item_dll;
1805 }
1806 }
1807 ITERATE(list<CProjKey>, u, unconditional_depends_ids) {
1808 (tree->m_Projects[proj_key]).m_UnconditionalDepends.insert( *u);
1809 }
1810 return proj_key;
1811 }
1812
DoCreateDataSpec(const string & source_base_dir,const string & proj_name,const string & proj_id,CProjectItemsTree * tree,EMakeFileType maketype)1813 CProjKey SLibProjectT::DoCreateDataSpec(
1814 const string& source_base_dir,
1815 const string& proj_name,
1816 const string& proj_id,
1817 CProjectItemsTree* tree,
1818 EMakeFileType maketype)
1819 {
1820 string spec_proj_name = proj_name;
1821 string spec_proj_id = proj_id;
1822
1823 list<string> s_empty;
1824 list<CProjKey> d_empty;
1825 CProjKey::TProjType type = CProjKey::eDataSpec;
1826 CProjKey proj_key(type, spec_proj_id);
1827 tree->m_Projects[proj_key] = CProjItem(type,
1828 spec_proj_name,
1829 spec_proj_id,
1830 source_base_dir,
1831 s_empty,
1832 d_empty,
1833 s_empty,
1834 s_empty,
1835 s_empty,
1836 s_empty,
1837 maketype,
1838 IdentifySlnGUID(source_base_dir, proj_key));
1839 return proj_key;
1840 }
1841
CreateUtilityProjectItem(const string & prj_dir,const string & name)1842 CProjItem CreateUtilityProjectItem( const string& prj_dir, const string& name)
1843 {
1844 string spec_proj_name = name;
1845 string spec_proj_id = NStr::Replace(name, "-", "_");
1846
1847 list<string> s_empty;
1848 list<CProjKey> d_empty;
1849 CProjKey::TProjType type = CProjKey::eUtility;
1850 CProjKey proj_key(type, spec_proj_id);
1851 return CProjItem(type,
1852 spec_proj_name,
1853 spec_proj_id,
1854 prj_dir,
1855 s_empty,
1856 d_empty,
1857 s_empty,
1858 s_empty,
1859 s_empty,
1860 s_empty,
1861 eMakeType_Undefined,
1862 IdentifySlnGUID(prj_dir, proj_key));
1863 }
1864
1865 //-----------------------------------------------------------------------------
DoCreate(const string & source_base_dir,const string & proj_name,const string & applib_mfilepath,const TFiles & makedll,CProjectItemsTree * tree,EMakeFileType maketype)1866 CProjKey SDllProjectT::DoCreate(const string& source_base_dir,
1867 const string& proj_name,
1868 const string& applib_mfilepath,
1869 const TFiles& makedll ,
1870 CProjectItemsTree* tree,
1871 EMakeFileType maketype)
1872 {
1873 TFiles::const_iterator m = makedll.find(applib_mfilepath);
1874 if (m == makedll.end()) {
1875
1876 PTB_WARNING_EX(kEmptyStr, ePTB_ProjectNotFound, "Dll Makefile not found: " << applib_mfilepath);
1877 return CProjKey();
1878 }
1879 CSimpleMakeFileContents::TContents::const_iterator k;
1880
1881 //DLL
1882 k = m->second.m_Contents.find("DLL");
1883 if (k == m->second.m_Contents.end() ||
1884 k->second.empty()) {
1885 PTB_WARNING_EX(kEmptyStr, ePTB_ConfigurationError, "No DLL specified in Makefile." << proj_name
1886 << ".dll at " << applib_mfilepath);
1887 return CProjKey();
1888 }
1889 string proj_id = k->second.front();
1890 {{
1891 CProjKey proj_key(CProjKey::eDll, proj_id);
1892 CProjectItemsTree::TProjects::const_iterator z = tree->m_Projects.find(proj_key);
1893 if (z != tree->m_Projects.end()) {
1894 if (z->second.m_MakeType < eMakeType_Excluded) {
1895 const CProjItem& item = tree->m_Projects[proj_key];
1896 if (item.m_HostedLibs.size() != 1 || item.m_HostedLibs.front() != proj_id) {
1897 string full_makefile_path = applib_mfilepath;
1898 PTB_WARNING_EX(full_makefile_path, ePTB_ConfigurationError,
1899 "DLL " << proj_id << " already defined at "
1900 << tree->m_Projects[proj_key].m_SourcesBaseDir);
1901 if (maketype == eMakeType_Excluded || GetApp().IsScanningWholeTree()) {
1902 return CProjKey();
1903 } else {
1904 GetApp().RegisterSuspiciousProject(proj_key);
1905 }
1906 }
1907 } else {
1908 tree->m_Projects.erase(proj_key);
1909 }
1910 }
1911 }}
1912
1913 //CPPFLAGS
1914 list<string> include_dirs;
1915 list<string> defines;
1916 k = m->second.m_Contents.find("CPPFLAGS");
1917 if (k != m->second.m_Contents.end()) {
1918 const list<string>& cpp_flags = k->second;
1919 SMakeProjectT::CreateIncludeDirs(cpp_flags,
1920 source_base_dir, &include_dirs);
1921 SMakeProjectT::CreateDefines(cpp_flags, &defines);
1922
1923 }
1924 bool style_objcpp = false;
1925 k = m->second.m_Contents.find("CXXFLAGS");
1926 if (k != m->second.m_Contents.end()) {
1927 const list<string>& cxx_flags = k->second;
1928 style_objcpp = find(cxx_flags.begin(), cxx_flags.end(), "objective-c++") != cxx_flags.end();
1929 }
1930
1931 list<CProjKey> depends_ids;
1932 k = m->second.m_Contents.find("DEPENDENCIES");
1933 if (k != m->second.m_Contents.end()) {
1934 const list<string> depends = k->second;
1935 SMakeProjectT::ConvertLibDepends(depends, &depends_ids /*, &applib_mfilepath*/);
1936 }
1937
1938 list<string> requires;
1939 requires.push_back("DLL");
1940
1941 list<string> sources;
1942 list<string> libs_3_party;
1943
1944 CProjKey proj_key(CProjKey::eDll, proj_id);
1945 tree->m_Projects[proj_key] = CProjItem(CProjKey::eDll,
1946 proj_name,
1947 proj_id,
1948 source_base_dir,
1949 sources,
1950 depends_ids,
1951 requires,
1952 libs_3_party,
1953 include_dirs,
1954 defines,
1955 maketype,
1956 IdentifySlnGUID(source_base_dir, proj_key));
1957 tree->m_Projects[proj_key].m_External = true;
1958 tree->m_Projects[proj_key].m_StyleObjcpp = style_objcpp;
1959 tree->m_Projects[proj_key].m_MkName = applib_mfilepath;
1960 tree->m_Projects[proj_key].m_DataSource = CSimpleMakeFileContents(applib_mfilepath);;
1961
1962 k = m->second.m_Contents.find("HOSTED_LIBS");
1963 if (k != m->second.m_Contents.end()) {
1964 tree->m_Projects[proj_key].m_HostedLibs = k->second;
1965 }
1966 k = m->second.m_Contents.find("DLL_TYPE");
1967 if (k != m->second.m_Contents.end() && k->second.front() == "plugin") {
1968 tree->m_Projects[proj_key].m_IsBundle = true;
1969 }
1970 list<string> lst_watchers;
1971 if (m->second.CollectValues("WATCHERS", lst_watchers,
1972 CSimpleMakeFileContents::eSortUnique)) {
1973 tree->m_Projects[proj_key].m_Watchers = NStr::Join(lst_watchers, " ");
1974 }
1975 tree->m_Projects[proj_key].m_ProjTags.push_back("dll");
1976 m->second.CollectValues("PROJ_TAG", tree->m_Projects[proj_key].m_ProjTags,
1977 CSimpleMakeFileContents::eMergePlusMinus);
1978 return proj_key;
1979 }
1980
1981 //-----------------------------------------------------------------------------
DoCreate(const string & source_base_dir,const string & proj_name,const string & applib_mfilepath,const TFiles & makeapp,const TFiles & makelib,CProjectItemsTree * tree,const SMakeProjectT::SMakeInInfo & makeinfo)1982 CProjKey SAsnProjectT::DoCreate(const string& source_base_dir,
1983 const string& proj_name,
1984 const string& applib_mfilepath,
1985 const TFiles& makeapp,
1986 const TFiles& makelib,
1987 CProjectItemsTree* tree,
1988 const SMakeProjectT::SMakeInInfo& makeinfo)
1989 {
1990 TAsnType asn_type = GetAsnProjectType(applib_mfilepath, makeapp, makelib);
1991 if (asn_type == eMultiple) {
1992 return SAsnProjectMultipleT::DoCreate(source_base_dir,
1993 proj_name,
1994 applib_mfilepath,
1995 makeapp,
1996 makelib,
1997 tree, makeinfo);
1998 }
1999 if(asn_type == eSingle) {
2000 return SAsnProjectSingleT::DoCreate(source_base_dir,
2001 proj_name,
2002 applib_mfilepath,
2003 makeapp,
2004 makelib,
2005 tree, makeinfo);
2006 }
2007 return CProjKey();
2008 }
2009
2010
GetAsnProjectType(const string & applib_mfilepath,const TFiles & makeapp,const TFiles & makelib)2011 SAsnProjectT::TAsnType SAsnProjectT::GetAsnProjectType(const string& applib_mfilepath,
2012 const TFiles& makeapp,
2013 const TFiles& makelib)
2014 {
2015 TFiles::const_iterator p = makeapp.find(applib_mfilepath);
2016 if ( p != makeapp.end() ) {
2017 const CSimpleMakeFileContents& fc = p->second;
2018 if (fc.m_Contents.find("ASN") != fc.m_Contents.end() )
2019 return eMultiple;
2020 else
2021 return eSingle;
2022 }
2023
2024 p = makelib.find(applib_mfilepath);
2025 if ( p != makelib.end() ) {
2026 const CSimpleMakeFileContents& fc = p->second;
2027 if (fc.m_Contents.find("ASN") != fc.m_Contents.end() )
2028 return eMultiple;
2029 else
2030 return eSingle;
2031 }
2032 return eNoAsn;
2033 }
2034
2035
2036 //-----------------------------------------------------------------------------
DoCreate(const string & source_base_dir,const string & proj_name,const string & applib_mfilepath,const TFiles & makeapp,const TFiles & makelib,CProjectItemsTree * tree,const SMakeProjectT::SMakeInInfo & makeinfo)2037 CProjKey SAsnProjectSingleT::DoCreate(const string& source_base_dir,
2038 const string& proj_name,
2039 const string& applib_mfilepath,
2040 const TFiles& makeapp,
2041 const TFiles& makelib,
2042 CProjectItemsTree* tree,
2043 const SMakeProjectT::SMakeInInfo& makeinfo)
2044 {
2045 EMakeFileType maketype = makeinfo.m_MakeType;
2046 CProjItem::TProjType proj_type =
2047 IsMakeLibFile( CDirEntry(applib_mfilepath).GetName()) ? CProjKey::eLib : CProjKey::eApp;
2048
2049 CProjKey proj_id =
2050 proj_type == CProjKey::eLib?
2051 SLibProjectT::DoCreate(source_base_dir,
2052 proj_name, applib_mfilepath, makelib, tree, maketype) :
2053 SAppProjectT::DoCreate(source_base_dir,
2054 proj_name, applib_mfilepath, makeapp, tree, maketype);
2055 if ( proj_id.Id().empty() )
2056 return CProjKey();
2057
2058 TProjects::iterator p = tree->m_Projects.find(proj_id);
2059 if (p == tree->m_Projects.end()) {
2060 PTB_ERROR_EX(kEmptyStr, ePTB_ProjectNotFound, "ASN project not found: " + proj_id.Id());
2061 return CProjKey();
2062 }
2063 CProjItem& project = p->second;
2064
2065 //Will process .asn or .dtd files
2066 string source_file_path = CDirEntry::ConcatPath(source_base_dir, proj_name);
2067 switch (makeinfo.m_Type) {
2068 case SMakeProjectT::SMakeInInfo::eASN:
2069 if ( CDirEntry(source_file_path + ".asn").Exists() )
2070 source_file_path += ".asn";
2071 break;
2072 case SMakeProjectT::SMakeInInfo::eDTD:
2073 if ( CDirEntry(source_file_path + ".dtd").Exists() )
2074 source_file_path += ".dtd";
2075 break;
2076 case SMakeProjectT::SMakeInInfo::eXSD:
2077 if ( CDirEntry(source_file_path + ".xsd").Exists() )
2078 source_file_path += ".xsd";
2079 break;
2080 case SMakeProjectT::SMakeInInfo::eWSDL:
2081 if ( CDirEntry(source_file_path + ".wsdl").Exists() )
2082 source_file_path += ".wsdl";
2083 break;
2084 case SMakeProjectT::SMakeInInfo::eJSD:
2085 if ( CDirEntry(source_file_path + ".jsd").Exists() )
2086 source_file_path += ".jsd";
2087 break;
2088 case SMakeProjectT::SMakeInInfo::eProtobuf:
2089 if ( CDirEntry(source_file_path + ".proto").Exists() )
2090 source_file_path += ".proto";
2091 break;
2092 default:
2093 break;
2094 }
2095 if ( !CDirEntry(source_file_path).Exists() ) {
2096 ERR_POST(
2097 (GetApp().IsScanningWholeTree() ? Warning : Error)
2098 << MDiagFile(kEmptyStr)
2099 << "Data specification for ASN project not found: " << source_file_path);
2100 return CProjKey();
2101 }
2102
2103 CDataToolGeneratedSrc data_tool_src;
2104 CDataToolGeneratedSrc::LoadFrom(source_file_path, &data_tool_src);
2105 if ( !data_tool_src.IsEmpty()) {
2106 project.m_DatatoolSources.push_back(data_tool_src);
2107 if (GetApp().m_Dtdep && !GetApp().GetDatatoolId().empty() && makeinfo.m_Type != SMakeProjectT::SMakeInInfo::eProtobuf) {
2108 project.m_Depends.push_back(CProjKey(CProjKey::eApp, GetApp().GetDatatoolId()));
2109 }
2110 if (makeinfo.m_Type == SMakeProjectT::SMakeInInfo::eProtobuf) {
2111 string rel_path = CDirEntry::CreateRelativePath(GetApp().GetProjectTreeInfo().m_Src, source_base_dir);
2112 string incl_path = CDirEntry::NormalizePath( CDirEntry::ConcatPath(GetApp().GetProjectTreeInfo().m_Include, rel_path));
2113 project.m_IncludeDirs.push_back(incl_path);
2114 project.m_Pch = "FALSE";
2115 }
2116 }
2117
2118 return proj_id;
2119 }
2120
2121
2122 //-----------------------------------------------------------------------------
DoCreate(const string & source_base_dir,const string & proj_name,const string & applib_mfilepath,const TFiles & makeapp,const TFiles & makelib,CProjectItemsTree * tree,const SMakeProjectT::SMakeInInfo & makeinfo)2123 CProjKey SAsnProjectMultipleT::DoCreate(const string& source_base_dir,
2124 const string& proj_name,
2125 const string& applib_mfilepath,
2126 const TFiles& makeapp,
2127 const TFiles& makelib,
2128 CProjectItemsTree* tree,
2129 const SMakeProjectT::SMakeInInfo& makeinfo)
2130 {
2131 EMakeFileType maketype = makeinfo.m_MakeType;
2132 CProjItem::TProjType proj_type =
2133 IsMakeLibFile( CDirEntry(applib_mfilepath).GetName()) ? CProjKey::eLib : CProjKey::eApp;
2134
2135
2136 const TFiles& makefile = proj_type == CProjKey::eLib? makelib : makeapp;
2137 TFiles::const_iterator m = makefile.find(applib_mfilepath);
2138 if (m == makefile.end()) {
2139
2140 PTB_WARNING_EX(kEmptyStr, ePTB_ProjectNotFound, "AsnProject Makefile not found: " << applib_mfilepath);
2141 return CProjKey();
2142 }
2143 const CSimpleMakeFileContents& fc = m->second;
2144
2145 // ASN
2146 CSimpleMakeFileContents::TContents::const_iterator k =
2147 fc.m_Contents.find("ASN");
2148 if (k == fc.m_Contents.end()) {
2149
2150 PTB_WARNING_EX(kEmptyStr, ePTB_ConfigurationError, "No ASN specified in Makefile: project " << proj_name
2151 << " at " << applib_mfilepath);
2152 return CProjKey();
2153 }
2154 const list<string> asn_names = k->second;
2155
2156 list<CDataToolGeneratedSrc> datatool_sources;
2157 ITERATE(list<string>, p, asn_names) {
2158 const string& asn = *p;
2159
2160 // this dir
2161 string asn_path_abs = CDirEntry::NormalizePath(source_base_dir);
2162 asn_path_abs = CDirEntry::AddTrailingPathSeparator(asn_path_abs);
2163 asn_path_abs = CDirEntry::ConcatPath(asn_path_abs, asn);
2164 if ( CDirEntry(asn_path_abs + ".asn").Exists() )
2165 asn_path_abs += ".asn";
2166 else if ( CDirEntry(asn_path_abs + ".dtd").Exists() )
2167 asn_path_abs += ".dtd";
2168 else if ( CDirEntry(asn_path_abs + ".xsd").Exists() )
2169 asn_path_abs += ".xsd";
2170 else {
2171 // one level up
2172 string parent_dir_abs = ParentDir(source_base_dir);
2173 string asn_dir_abs = CDirEntry::ConcatPath(parent_dir_abs, asn);
2174 asn_dir_abs = CDirEntry::NormalizePath(asn_dir_abs);
2175 asn_dir_abs = CDirEntry::AddTrailingPathSeparator(asn_dir_abs);
2176
2177 asn_path_abs = CDirEntry::ConcatPath(asn_dir_abs, asn);
2178 if ( CDirEntry(asn_path_abs + ".asn").Exists() )
2179 asn_path_abs += ".asn";
2180 else if ( CDirEntry(asn_path_abs + ".dtd").Exists() )
2181 asn_path_abs += ".dtd";
2182 else if ( CDirEntry(asn_path_abs + ".xsd").Exists() )
2183 asn_path_abs += ".xsd";
2184 else {
2185 // one level down
2186 string asn_dir_abs = CDirEntry::ConcatPath(source_base_dir, asn);
2187 asn_dir_abs = CDirEntry::NormalizePath(asn_dir_abs);
2188 asn_dir_abs = CDirEntry::AddTrailingPathSeparator(asn_dir_abs);
2189
2190 asn_path_abs = CDirEntry::ConcatPath(asn_dir_abs, asn);
2191 if ( CDirEntry(asn_path_abs + ".asn").Exists() )
2192 asn_path_abs += ".asn";
2193 else if ( CDirEntry(asn_path_abs + ".dtd").Exists() )
2194 asn_path_abs += ".dtd";
2195 else if ( CDirEntry(asn_path_abs + ".xsd").Exists() )
2196 asn_path_abs += ".xsd";
2197 else {
2198 PTB_ERROR_EX(asn_path_abs, ePTB_FileNotFound,
2199 "ASN spec file not found");
2200 }
2201 }
2202 }
2203
2204 CDataToolGeneratedSrc data_tool_src;
2205 CDataToolGeneratedSrc::LoadFrom(asn_path_abs, &data_tool_src);
2206 if ( !data_tool_src.IsEmpty() )
2207 datatool_sources.push_back(data_tool_src);
2208
2209 }
2210
2211 // SRC
2212 k = fc.m_Contents.find("SRC");
2213 if (k == fc.m_Contents.end()) {
2214
2215 PTB_WARNING_EX(kEmptyStr, ePTB_ConfigurationError, "No SRC specified in Makefile: project " << proj_name
2216 << " at " << applib_mfilepath);
2217 return CProjKey();
2218 }
2219 list<string> src_list = k->second;
2220 if (CMsvc7RegSettings::GetMsvcPlatform() >= CMsvc7RegSettings::eUnix) {
2221 k = fc.m_Contents.find("UNIX_SRC");
2222 if (k != fc.m_Contents.end()) {
2223 copy(k->second.begin(), k->second.end(), back_inserter(src_list));
2224 }
2225 }
2226 list<string> sources;
2227 ITERATE(list<string>, p, src_list) {
2228 const string& src = *p;
2229 if ( !CSymResolver::IsDefine(src) )
2230 sources.push_back(src);
2231 }
2232
2233 CProjKey proj_id =
2234 proj_type == CProjKey::eLib?
2235 SLibProjectT::DoCreate(source_base_dir,
2236 proj_name, applib_mfilepath, makelib, tree, maketype) :
2237 SAppProjectT::DoCreate(source_base_dir,
2238 proj_name, applib_mfilepath, makeapp, tree, maketype);
2239 if ( proj_id.Id().empty() )
2240 return CProjKey();
2241
2242 TProjects::iterator pid = tree->m_Projects.find(proj_id);
2243 if (pid == tree->m_Projects.end()) {
2244 PTB_WARNING_EX(kEmptyStr, ePTB_ProjectNotFound, "ASN project not found: " << proj_id.Id()
2245 << " at " << applib_mfilepath);
2246 return CProjKey();
2247 }
2248 CProjItem& project = pid->second;
2249
2250 // Adjust created proj item
2251 //SRC -
2252 project.m_Sources.clear();
2253 ITERATE(list<string>, p, src_list) {
2254 const string& src = *p;
2255 if ( !CSymResolver::IsDefine(src) )
2256 project.m_Sources.push_front(src);
2257 }
2258 ITERATE( list<CDataToolGeneratedSrc>, dts, datatool_sources) {
2259 const string& asn = dts->m_SourceCPP;
2260 project.m_Sources.remove(asn);
2261 project.m_Sources.remove(asn + "__");
2262 project.m_Sources.remove(asn + "___");
2263 string src = CDirEntry::ConcatPath(CDirEntry::CreateRelativePath( source_base_dir, dts->m_SourceBaseDir), asn);
2264 project.m_Sources.push_back(src + "__");
2265 project.m_Sources.push_back(src + "___");
2266 }
2267
2268 if ( !datatool_sources.empty() ) {
2269 project.m_DatatoolSources = datatool_sources;
2270 if (GetApp().m_Dtdep && !GetApp().GetDatatoolId().empty()) {
2271 project.m_Depends.push_back(CProjKey(CProjKey::eApp, GetApp().GetDatatoolId()));
2272 }
2273 }
2274
2275 return proj_id;
2276 }
2277
2278 //-----------------------------------------------------------------------------
DoCreate(const string & source_base_dir,const string & proj_name,const string & applib_mfilepath,const TFiles & makemsvc,CProjectItemsTree * tree,EMakeFileType maketype)2279 CProjKey SMsvcProjectT::DoCreate(const string& source_base_dir,
2280 const string& proj_name,
2281 const string& applib_mfilepath,
2282 const TFiles& makemsvc,
2283 CProjectItemsTree* tree,
2284 EMakeFileType maketype)
2285 {
2286 TFiles::const_iterator m = makemsvc.find(applib_mfilepath);
2287 if (m == makemsvc.end()) {
2288
2289 PTB_WARNING_EX(kEmptyStr, ePTB_ProjectNotFound, "Native Makefile not found: " << applib_mfilepath);
2290 return CProjKey();
2291 }
2292
2293 CSimpleMakeFileContents::TContents::const_iterator k;
2294 //project id
2295 string proj_id;
2296 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
2297 proj_id = proj_name;
2298 } else {
2299 bool is_xcode = CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode;
2300 k = m->second.m_Contents.find(is_xcode ? "XCODE_PROJ" : "MSVC_PROJ");
2301 if (k == m->second.m_Contents.end() ||
2302 k->second.empty()) {
2303
2304 PTB_WARNING_EX(kEmptyStr, ePTB_ConfigurationError, "No MSVC_PROJ specified in Makefile: project " << proj_name
2305 << " at " << applib_mfilepath);
2306 return CProjKey();
2307 }
2308 proj_id = k->second.front();
2309 }
2310 {{
2311 CProjKey proj_key(CProjKey::eMsvc, proj_id);
2312 CProjectItemsTree::TProjects::const_iterator z = tree->m_Projects.find(proj_key);
2313 if (z != tree->m_Projects.end()) {
2314 if (z->second.m_MakeType < eMakeType_Excluded) {
2315 string full_makefile_path = applib_mfilepath;
2316 PTB_WARNING_EX(full_makefile_path, ePTB_ConfigurationError,
2317 "Native project \'" << proj_id << "\' already defined at "
2318 << tree->m_Projects[proj_key].m_SourcesBaseDir);
2319 if (maketype == eMakeType_Excluded || GetApp().IsScanningWholeTree()) {
2320 return CProjKey();
2321 } else {
2322 GetApp().RegisterSuspiciousProject(proj_key);
2323 }
2324 } else {
2325 tree->m_Projects.erase(proj_key);
2326 }
2327 }
2328 }}
2329
2330 string vcproj_file;
2331 list<string> sources;
2332 if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix &&
2333 CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eXCode) {
2334 // VCPROJ - will map to src
2335 string vcproj_key("VCPROJ");
2336 if (CMsvc7RegSettings::GetMsvcVersion() >= CMsvc7RegSettings::eMsvc1000) {
2337 vcproj_key = "VCXPROJ";
2338 }
2339 k = m->second.m_Contents.find(vcproj_key);
2340 if (k == m->second.m_Contents.end()) {
2341
2342 PTB_WARNING_EX(kEmptyStr, ePTB_ConfigurationError, "No " << vcproj_key <<" specified in Makefile: project " << proj_name
2343 << " at " << applib_mfilepath);
2344 return CProjKey();
2345 }
2346 ITERATE(list<string>, s, k->second) {
2347 string d = GetApp().ProcessLocationMacros( *s );
2348 vcproj_file = d;
2349 if (CDirEntry::IsAbsolutePath(d)) {
2350 d = CDirEntry::CreateRelativePath( source_base_dir, d);
2351 }
2352 sources.push_back( d );
2353 break;
2354 }
2355 }
2356
2357 // depends -
2358 list<CProjKey> depends_ids;
2359 k = m->second.m_Contents.find("LIB_DEP");
2360 if (k != m->second.m_Contents.end()) {
2361 const list<string> deps = k->second;
2362 ITERATE(list<string>, p, deps) {
2363 depends_ids.push_back(CProjKey(CProjKey::eLib, *p));
2364 }
2365 }
2366 k = m->second.m_Contents.find("APP_DEP");
2367 if (k != m->second.m_Contents.end()) {
2368 const list<string> deps = k->second;
2369 ITERATE(list<string>, p, deps) {
2370 depends_ids.push_back(CProjKey(CProjKey::eApp, *p));
2371 }
2372 }
2373 k = m->second.m_Contents.find("DLL_DEP");
2374 if (k != m->second.m_Contents.end()) {
2375 const list<string> deps = k->second;
2376 ITERATE(list<string>, p, deps) {
2377 depends_ids.push_back(CProjKey(CProjKey::eDll, *p));
2378 }
2379 }
2380 k = m->second.m_Contents.find("MSVC_DEP");
2381 if (k != m->second.m_Contents.end()) {
2382 const list<string> deps = k->second;
2383 ITERATE(list<string>, p, deps) {
2384 depends_ids.push_back(CProjKey(CProjKey::eMsvc, *p));
2385 }
2386 }
2387 k = m->second.m_Contents.find("USR_DEP");
2388 if (k != m->second.m_Contents.end()) {
2389 const list<string> deps = k->second;
2390 list<CProjKey> ids;
2391 SMakeProjectT::ConvertLibDepends(deps, &ids);
2392 copy(ids.begin(), ids.end(), back_inserter(depends_ids));
2393 }
2394
2395 //requires
2396 list<string> requires;
2397 list<string> req_lst;
2398 if (m->second.CollectValues("REQUIRES", req_lst,
2399 CSimpleMakeFileContents::eSortUnique)) {
2400 CMsvcProjectMakefile project_makefile( CDirEntry::ConcatPath(
2401 source_base_dir, CreateMsvcProjectMakefileName(proj_name, CProjKey::eMsvc)));
2402 project_makefile.Redefine(req_lst,requires);
2403 }
2404
2405 list<string> libs_3_party;
2406 list<string> include_dirs;
2407 list<string> defines;
2408
2409 CMsvcProjectMakefile project_makefile
2410 ((CDirEntry::ConcatPath( source_base_dir,
2411 CreateMsvcProjectMakefileName(proj_name,
2412 CProjKey::eMsvc))));
2413 CProjKey proj_key(CProjKey::eMsvc, proj_id);
2414 CProjItem project(CProjKey::eMsvc,
2415 proj_name,
2416 proj_id,
2417 source_base_dir,
2418 sources,
2419 depends_ids,
2420 requires,
2421 libs_3_party,
2422 include_dirs,
2423 defines,
2424 maketype,
2425 IdentifySlnGUID(vcproj_file, proj_key));
2426
2427 m->second.CollectValues("PROJ_TAG", project.m_ProjTags,
2428 CSimpleMakeFileContents::eMergePlusMinus);
2429
2430 list<string> watchers;
2431 if (m->second.CollectValues("WATCHERS", watchers,
2432 CSimpleMakeFileContents::eSortUnique)) {
2433 project.m_Watchers = NStr::Join(watchers, " ");
2434 }
2435
2436 project.m_MkName = applib_mfilepath;
2437 tree->m_Projects[proj_key] = project;
2438
2439 return proj_key;
2440 }
2441 //-----------------------------------------------------------------------------
2442
s_AnalyzeLibraryOrder(CSymResolver & resolver,const CProjectItemsTree & tree)2443 void s_AnalyzeLibraryOrder( CSymResolver& resolver, const CProjectItemsTree& tree)
2444 {
2445 CProjBulderApp& app(GetApp());
2446 CProjectItemsTree::TProjects::const_iterator p;
2447 for (p = tree.m_Projects.begin(); p != tree.m_Projects.end(); ++p) {
2448 if (p->first.Type() != CProjKey::eApp) {
2449 continue;
2450 }
2451 const CProjItem& project = p->second;
2452
2453 list<string> list_lib;
2454 if (!project.m_DataSource.GetValue("LIB", list_lib)) {
2455 continue;
2456 }
2457 list<string> lib_list_in, lib_list_in0;
2458 for( const string& lib : list_lib) {
2459 if (lib.at(0) == '#') {
2460 break;
2461 }
2462 else if (!CSymResolver::IsDefine(lib) && CSymResolver::HasDefine(lib)) {
2463 string def = FilterDefine(lib);
2464 string val = CSymResolver::StripDefine(def);
2465 list<string> tmp;
2466 if (project.m_DataSource.GetValue(val, tmp)) {
2467 copy(tmp.begin(), tmp.end(), back_inserter(lib_list_in));
2468 } else {
2469 lib_list_in.push_back(def);
2470 }
2471 } else {
2472 lib_list_in.push_back(lib);
2473 }
2474 }
2475 if (lib_list_in.empty()) {
2476 continue;
2477 }
2478 lib_list_in0 = lib_list_in;
2479
2480 map< string, set<string> > lib_contents;
2481 map< string, set<string> > lib_dependencies;
2482
2483 list<string> lib_list_out[2];
2484 size_t pass=0;
2485 for (pass=0; pass<4; ++pass) {
2486
2487 if (pass > 1) {
2488 lib_list_out[0] = lib_list_out[1];
2489 lib_list_out[1].clear();
2490 }
2491 list<string>& list_in = pass == 0 ? lib_list_in : lib_list_out[0];
2492 list<string>& list_out = pass == 0 ? lib_list_out[0] : lib_list_out[1];
2493
2494 bool failed = false;
2495 for (list<string>::const_iterator l = list_in.begin(); ; ++l) {
2496
2497 // list_in may change (grow) during the cycle
2498 if (l == list_in.end()) {
2499 break;
2500 }
2501 const string& lib = *l;
2502 if (failed) {
2503 list_out.push_back(lib);
2504 continue;
2505 }
2506
2507 // this item contents
2508 list<string> resolved;
2509 if (!CSymResolver::IsDefine(lib) ||
2510 !project.m_DataSource.GetValue(CSymResolver::StripDefine(lib), resolved)) {
2511 resolver.Resolve(lib, &resolved);
2512 }
2513 for_each(resolved.begin(), resolved.end(), [&lib_contents, &lib](const string& ce) {
2514 string e(ce);
2515 CSymResolver::StripSuffix(e);
2516 if (!e.empty() && e.at(0) != '@') {
2517 lib_contents[lib].insert(e);
2518 }});
2519
2520 // this item dependencies
2521 set<string> alldepends;
2522 set<string> allflags;
2523 for( const string& lib_item : lib_contents[lib]) {
2524 s_CollectAllLeaves( app.m_GraphDepPrecedes, app.m_GraphDepFlags, lib_item, alldepends, allflags);
2525 }
2526 for_each(alldepends.begin(), alldepends.end(), [&lib_dependencies, &lib](const string& ce){
2527 string e(ce);
2528 CSymResolver::StripSuffix(e);
2529 if (!e.empty() && e.at(0) != '@') {
2530 lib_dependencies[lib].insert(e);
2531 }});
2532
2533 list<string>::iterator iout = list_out.begin();
2534 bool do_append = true;
2535
2536 // check that this item dependencies do not contain items in 'out' list
2537 for (; iout != list_out.end(); ++iout) {
2538 for( const string& lib_dep : lib_dependencies[lib]) {
2539 if (lib_contents[*iout].find(lib_dep) != lib_contents[*iout].end()) {
2540 do_append = false;
2541 break;
2542 }
2543 }
2544 if (!do_append) {
2545 break;
2546 }
2547 }
2548
2549 // good to append
2550 if (do_append) {
2551 list_out.push_back(lib);
2552 continue;
2553 }
2554
2555 list<string>::const_iterator i = iout;
2556 set<string> already_there;
2557 bool do_replace = false;
2558
2559 // maybe we could drop item at iout, because new one includes it
2560 // compare lib_contents[*iout] with the contents of the new item
2561 already_there.clear();
2562 for( const string& lib_item : lib_contents[*iout]) {
2563 if (lib_contents[lib].find(lib_item) != lib_contents[lib].end()) {
2564 already_there.insert(lib_item);
2565 }
2566 }
2567 if (already_there.size() == lib_contents[*iout].size() &&
2568 already_there.size() != lib_contents[lib].size()) {
2569 // it seems that the new item can replace old one
2570 // make a note to check that it indeed may be inserted here
2571 do_replace = true;
2572 }
2573
2574 // is there a need to add this item?
2575 // compare this item contents with what is already there
2576 already_there.clear();
2577 for (i = iout; i != list_out.end(); ++i) {
2578 for( const string& lib_item : lib_contents[lib]) {
2579 if (lib_contents[*i].find(lib_item) != lib_contents[*i].end()) {
2580 already_there.insert(lib_item);
2581 }
2582 }
2583 }
2584 if (already_there.size() == lib_contents[lib].size()) {
2585 // this is a duplicate which is already included
2586 continue;
2587 }
2588 // if this item adds only few new libraries, maybe we would better
2589 // add them expicitely instead
2590 if (//!do_replace &&
2591 already_there.size() != 0 &&
2592 already_there.size() >= (lib_contents[lib].size() * 3)/4) {
2593 for( const string& lib_item : lib_contents[lib]) {
2594 if (already_there.find(lib_item) == already_there.end()) {
2595 list_in.push_back(lib_item);
2596 }
2597 }
2598 continue;
2599 }
2600
2601 // if we insert it at iout, check that items that follow do not depend on it
2602 do_append = false;
2603 bool do_insert = true;
2604 i = iout;
2605 if (do_replace) {
2606 ++i;
2607 }
2608 for (; i != list_out.end(); ++i) {
2609 for( const string& lib_dep : lib_dependencies[*i]) {
2610 if (lib_contents[lib].find(lib_dep) != lib_contents[lib].end()) {
2611 // maybe both include the same library.
2612 // if so, that is acceptable
2613 if (lib_contents[*i].find(lib_dep) != lib_contents[*i].end()) {
2614 do_append = true;
2615 continue;
2616 }
2617 do_insert = false;
2618 break;
2619 }
2620 }
2621 if (!do_insert) {
2622 break;
2623 }
2624 }
2625
2626 // good to insert
2627 if (do_insert) {
2628 i = iout;
2629 if (do_append && ++i == list_out.end()) {
2630 list_out.push_back(lib);
2631 } else {
2632 if (do_replace) {
2633 iout = list_out.erase(iout);
2634 }
2635 list_out.insert(iout, lib);
2636 }
2637 continue;
2638 }
2639
2640 // once again, try to append, allowing identical libraries in both
2641 do_append = true;
2642 // check that this item dependencies do not contain items in 'out' list
2643 for (i=iout; i != list_out.end(); ++i) {
2644 for( const string& lib_dep : lib_dependencies[lib]) {
2645 if (lib_contents[*i].find(lib_dep) != lib_contents[*i].end()) {
2646 if (lib_contents[lib].find(lib_dep) != lib_contents[lib].end()) {
2647 continue;
2648 }
2649 do_append = false;
2650 break;
2651 }
2652 }
2653 if (!do_append) {
2654 break;
2655 }
2656 }
2657
2658 // not sure about this one
2659 if (do_replace) {
2660 list_out.erase(iout);
2661 for( const string& lib_item : already_there) {
2662 list_out.remove(lib_item);
2663 }
2664 }
2665 // good to append
2666 if (do_append) {
2667 list_out.push_back(lib);
2668 continue;
2669 }
2670 // Do not know what to do
2671 // keep it as is, in a hope that it will work
2672 // failed = true;
2673 list_out.push_back(lib);
2674 }
2675
2676 if (list_in.size() == list_out.size() &&
2677 equal(list_in.begin(), list_in.end(), list_out.begin())) {
2678 break;
2679 }
2680 }
2681 if (pass != 0) {
2682 list<string> warnings;
2683 warnings.push_back("====== Library order warnings (toolkit libs) ======");
2684 warnings.push_back("present library order: " + NStr::Join(lib_list_in0," "));
2685 if (lib_list_out[0].size() == lib_list_out[1].size() &&
2686 equal(lib_list_out[0].begin(), lib_list_out[0].end(), lib_list_out[1].begin())) {
2687 warnings.push_back("recommended library order: " + NStr::Join(lib_list_out[0]," "));
2688
2689 set<string> all_libs, all_deps;
2690 for(const string& lib_item: lib_list_out[0]) {
2691 all_libs.insert( lib_contents[lib_item].begin(),lib_contents[lib_item].end());
2692 all_deps.insert( lib_dependencies[lib_item].begin(),lib_dependencies[lib_item].end());
2693 }
2694 set<string> all_missing;
2695 for(const string& lib_item: all_deps) {
2696 if (all_libs.find(lib_item) == all_libs.end()) {
2697 all_missing.insert(lib_item);
2698 }
2699 }
2700 if (!all_missing.empty()) {
2701 warnings.push_back("missing libraries: " + NStr::Join(all_missing," "));
2702 }
2703 } else {
2704 warnings.push_back("Failed to identify recommended library order");
2705 if (pass >= 2) {
2706 warnings.push_back("candidate1: " + NStr::Join(lib_list_out[0]," "));
2707 warnings.push_back("candidate2: " + NStr::Join(lib_list_out[1]," "));
2708 }
2709 }
2710 PTB_WARNING_EX(project.m_DataSource.GetFileName(),ePTB_InvalidMakefile, NStr::Join(warnings,"\n"));
2711 }
2712 }
2713 }
2714 //-----------------------------------------------------------------------------
2715
2716
2717 void
BuildOneProjectTree(const IProjectFilter * filter,const string & root_src_path,CProjectItemsTree * tree)2718 CProjectTreeBuilder::BuildOneProjectTree(const IProjectFilter* filter,
2719 const string& root_src_path,
2720 CProjectItemsTree* tree)
2721 {
2722 SMakeFiles subtree_makefiles;
2723
2724 ProcessDir(root_src_path,
2725 true,
2726 filter,
2727 &subtree_makefiles, eMakeType_Undefined, NULL);
2728
2729 // Resolve macrodefines
2730 list<string> metadata_files;
2731 GetApp().GetMetaDataFiles(&metadata_files);
2732 CSymResolver resolver;
2733 if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix) {
2734 resolver.Append( GetApp().GetSite().GetMacros());
2735 }
2736 ITERATE(list<string>, p, metadata_files) {
2737 string fileloc;
2738 if (!GetApp().m_BuildRoot.empty()) {
2739 fileloc = CDirEntry::ConcatPath(GetApp().m_BuildRoot,*p);
2740 }
2741 if (fileloc.empty() || !CFile(fileloc).Exists()) {
2742 fileloc = CDirEntry::ConcatPath(root_src_path, CDirEntry::ConvertToOSPath(*p));
2743 }
2744 if (!CDirEntry(fileloc).Exists() && !GetApp().m_ExtSrcRoot.empty()) {
2745 fileloc = CDirEntry::ConcatPath( CDirEntry::ConcatPath(
2746 GetApp().m_ExtSrcRoot,
2747 GetApp().GetConfig().Get("ProjectTree", "src")),
2748 CDirEntry::ConvertToOSPath(*p));
2749 }
2750 if (!CDirEntry(fileloc).Exists()) {
2751 fileloc = CDirEntry::ConcatPath(CDirEntry(GetApp().m_Solution).GetDir(),*p);
2752 }
2753 if (CDirEntry(fileloc).Exists()) {
2754 CSymResolver sym(fileloc);
2755 bool is_good = true;
2756 string requires;
2757 if (sym.GetValue("REQUIRES", requires)) {
2758 list<string> items;
2759 NStr::Split(requires, LIST_SEPARATOR, items, NStr::fSplit_Tokenize);
2760 for(const string& i : items) {
2761 if (!GetApp().GetSite().IsProvided(i)) {
2762 PTB_WARNING_EX(kEmptyStr, ePTB_FileExcluded, "Custom metadata " << fileloc << " rejected because of unmet requirement: " << i);
2763 is_good = false;
2764 break;
2765 }
2766 }
2767 }
2768 if (is_good) {
2769 PTB_INFO("Resolve macros using rules from " << fileloc);
2770 resolver.Append( sym, true);;
2771 }
2772 }
2773 }
2774 ResolveDefs(resolver, subtree_makefiles);
2775 GetApp().UpdateDepGraph( subtree_makefiles.m_Lib);
2776
2777 // Build projects tree
2778 CProjectItemsTree::CreateFrom(root_src_path,
2779 subtree_makefiles.m_In,
2780 subtree_makefiles.m_Lib,
2781 subtree_makefiles.m_Dll,
2782 subtree_makefiles.m_App,
2783 subtree_makefiles.m_User, tree);
2784
2785 if (!GetApp().IsScanningWholeTree()) {
2786 s_AnalyzeLibraryOrder(resolver, *tree);
2787 }
2788 }
2789
2790
2791 void
BuildProjectTree(const IProjectFilter * filter,const string & root_src_path,CProjectItemsTree * tree)2792 CProjectTreeBuilder::BuildProjectTree(const IProjectFilter* filter,
2793 const string& root_src_path,
2794 CProjectItemsTree* tree)
2795 {
2796 // Build subtree
2797 CProjectItemsTree target_tree;
2798
2799 BuildOneProjectTree(filter, root_src_path, &target_tree);
2800
2801 if (GetApp().IsScanningWholeTree()) {
2802 *tree = target_tree;
2803 NON_CONST_ITERATE( CProjectItemsTree::TProjects, t, tree->m_Projects) {
2804 t->second.m_MakeType = eMakeType_Excluded;
2805 t->second.m_External = true;
2806 }
2807 return;
2808 }
2809
2810 GetApp().ExcludeProjectsByTag(target_tree);
2811 if ( GetApp().m_InteractiveCfg &&
2812 !GetApp().Gui_ConfirmProjects(target_tree))
2813 {
2814 GetApp().SetFail();
2815 return;
2816 }
2817 GetApp().ExcludeUnrequestedProjects(target_tree);
2818
2819 for (;;) {
2820 size_t orig_size = target_tree.m_Projects.size();
2821 // Analyze subtree dependencies
2822 list<CProjKey> external_depends;
2823 target_tree.GetExternalDepends(&external_depends);
2824
2825 // We have to add more projects to the target tree
2826 if ( !external_depends.empty()) {
2827 list<CProjKey> depends_to_resolve = external_depends;
2828 while ( !depends_to_resolve.empty() ) {
2829 bool modified = false;
2830 ITERATE(list<CProjKey>, p, depends_to_resolve) {
2831 // id of the project we have to resolve
2832 const CProjKey& prj_id = *p;
2833 CProjectItemsTree::TProjects::const_iterator n =
2834 GetApp().GetWholeTree().m_Projects.find(prj_id);
2835
2836 if (n != GetApp().GetWholeTree().m_Projects.end()) {
2837 //insert this project into the target_tree
2838 target_tree.m_Projects[prj_id] = n->second;
2839 modified = true;
2840 } else {
2841 /// FIXME: is this needed?
2842 _TRACE("Project not found: " + prj_id.Id());
2843 }
2844 }
2845
2846 if (!modified) {
2847 //done - no projects has been added to target_tree
2848 AddDatatoolSourcesDepends(&target_tree);
2849 *tree = target_tree;
2850 return;
2851 } else {
2852 //continue resolving dependencies
2853 target_tree.GetExternalDepends(&depends_to_resolve);
2854 }
2855 }
2856 }
2857
2858 AddDatatoolSourcesDepends(&target_tree);
2859 if (orig_size == target_tree.m_Projects.size()) {
2860 break;
2861 }
2862 }
2863 *tree = target_tree;
2864 }
2865
2866
ProcessDir(const string & dir_name,bool is_root,const IProjectFilter * filter,SMakeFiles * makefiles,EMakeFileType maketype,const CSimpleMakeFileContents * parent)2867 void CProjectTreeBuilder::ProcessDir(const string& dir_name,
2868 bool is_root,
2869 const IProjectFilter* filter,
2870 SMakeFiles* makefiles,
2871 EMakeFileType maketype,
2872 const CSimpleMakeFileContents* parent)
2873 {
2874 // Node - Makefile.in should present
2875 // this is true if and only if there are also Makefile.*.lib or
2876 // Makefile.*.app project makefiles to process
2877 string node_path =
2878 CDirEntry::ConcatPath(dir_name,
2879 GetApp().GetProjectTreeInfo().m_TreeNode);
2880 if ( !is_root && !CDirEntry(node_path).Exists() ) {
2881 CDir::TGetEntriesFlags flags = CDir::fIgnoreRecursive;
2882 CDir::TEntries entries =
2883 CDir(dir_name).GetEntries("Makefile.*.lib", flags);
2884 if (entries.empty()) {
2885 entries = CDir(dir_name).GetEntries("Makefile.*.app", flags);
2886 }
2887 if ( !entries.empty() ) {
2888 PTB_WARNING_EX(node_path, ePTB_MissingMakefile,
2889 "Makefile.in missing");
2890 }
2891
2892 string bld_sys = CDirEntry::DeleteTrailingPathSeparator(
2893 CDirEntry(GetApp().GetConfigPath()).GetDir());
2894 if (NStr::CompareNocase(bld_sys,dir_name) == 0) {
2895 CDir dir(dir_name);
2896 CDir::TEntries contents;
2897 contents = dir.GetEntries(GetApp().GetProjectTreeInfo().m_CustomMetaData);
2898 ITERATE(CDir::TEntries, p, contents) {
2899 GetApp().AddCustomMetaData( (*p)->GetPath());
2900 }
2901 contents = dir.GetEntries(GetApp().GetProjectTreeInfo().m_CustomConfH);
2902 ITERATE(CDir::TEntries, p, contents) {
2903 GetApp().AddCustomConfH( (*p)->GetPath());
2904 }
2905 }
2906 return;
2907 }
2908 if (!is_root &&
2909 CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
2910 // on UNIX the build tree is already configured,
2911 // we check if this particular subtree is enabled (ie, exists) there
2912 string subtree =
2913 CDirEntry::CreateRelativePath(
2914 GetApp().GetProjectTreeInfo().m_Src, dir_name);
2915 subtree = CDirEntry::ConcatPath(CDirEntry(GetApp().m_Solution).GetDir(), subtree);
2916 if (!CDirEntry(subtree).Exists()) {
2917 PTB_INFO_EX(subtree, ePTB_NoError,
2918 "skipped missing subtree");
2919 return;
2920 }
2921 }
2922
2923 bool weak=false;
2924 bool process_projects = !is_root && filter->CheckProject(dir_name,&weak);
2925 if (!process_projects && !weak && !is_root) {
2926 return;
2927 }
2928
2929 // Process Makefile.in
2930 const CSimpleMakeFileContents* mkin = NULL;
2931 map<string, EMakeFileType> subprojects;
2932 map<string, EMakeFileType> appprojects;
2933 map<string, EMakeFileType> libprojects;
2934 map<string, EMakeFileType> dllprojects;
2935 map<string, EMakeFileType> userprojects;
2936 vector<string> ordered_subprojects;
2937 string topbuilddir;
2938 bool has_metal = false;
2939 bool get_order = GetApp().IsScanningWholeTree();
2940 if (is_root && get_order) {
2941 topbuilddir = GetApp().GetRegSettings().GetTopBuilddir();
2942 }
2943
2944 if ( process_projects || weak || !topbuilddir.empty()) {
2945 string node(topbuilddir.empty() ? node_path : topbuilddir);
2946 ProcessMakeInFile(node, makefiles, maketype, parent);
2947 TFiles::const_iterator p = makefiles->m_In.find(node);
2948 if (p != makefiles->m_In.end()) {
2949 const CSimpleMakeFileContents& makefile = p->second;
2950 mkin = &makefile;
2951 CSimpleMakeFileContents::TContents::const_iterator k;
2952 int j;
2953 string subproj[] = {"SUB_PROJ","EXPENDABLE_SUB_PROJ","POTENTIAL_SUB_PROJ",""};
2954 EMakeFileType subtype[] = {eMakeType_Undefined,eMakeType_Expendable,eMakeType_Potential};
2955 if (filter->ExcludePotential()) {
2956 subtype[2] = eMakeType_Excluded;
2957 }
2958 for (j=0; !subproj[j].empty(); ++j) {
2959 k = makefile.m_Contents.find(subproj[j]);
2960 if (k != makefile.m_Contents.end()) {
2961 const list<string>& values = k->second;
2962 for (list<string>::const_iterator i=values.begin(); i!=values.end(); ++i) {
2963 if (i->at(0) == '#') {
2964 break;
2965 }
2966 subprojects[*i] = max(maketype, subtype[j]);
2967 ordered_subprojects.push_back(*i);
2968 }
2969 }
2970 }
2971 if ( process_projects ) {
2972 string userproj[] = {"UNIX_PROJ","EXPENDABLE_UNIX_PROJ", ""};
2973 if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix) {
2974 bool is_xcode = CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode;
2975 userproj[0] = is_xcode ? "XCODE_PROJ" : "MSVC_PROJ";
2976 userproj[1] = "";
2977 }
2978 EMakeFileType usertype[] = {eMakeType_Undefined,eMakeType_Expendable};
2979 for (j=0; !userproj[j].empty(); ++j) {
2980 k = makefile.m_Contents.find(userproj[j]);
2981 if (k != makefile.m_Contents.end()) {
2982 const list<string>& values = k->second;
2983 for (list<string>::const_iterator i=values.begin(); i!=values.end(); ++i) {
2984 if (i->at(0) == '#') {
2985 break;
2986 }
2987 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
2988 userprojects["Makefile." + *i] = max(maketype, usertype[j]);
2989 userprojects["Makefile." + *i + ".in"] = max(maketype, usertype[j]);
2990 if (get_order) {
2991 s_WriteBuildOrder(dir_name,"Makefile." + *i);
2992 s_WriteBuildOrder(dir_name,"Makefile." + *i + ".in");
2993 }
2994 } else {
2995 string mkname("Makefile." + *i);
2996 if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eXCode) {
2997 mkname += ".msvcproj";
2998 }
2999 userprojects[mkname] = max(maketype, usertype[j]);
3000 if (get_order) {
3001 s_WriteBuildOrder(dir_name,mkname);
3002 }
3003 }
3004 }
3005 }
3006 }
3007 string libproj[] = {"ASN_PROJ","DTD_PROJ","XSD_PROJ","WSDL_PROJ","JSD_PROJ", "PROTOBUF_PROJ",
3008 "LIB_PROJ","EXPENDABLE_LIB_PROJ","POTENTIAL_LIB_PROJ",""};
3009 EMakeFileType libtype[] = {
3010 eMakeType_Undefined, eMakeType_Undefined, eMakeType_Undefined, eMakeType_Undefined,
3011 eMakeType_Undefined, eMakeType_Undefined,
3012 eMakeType_Undefined,eMakeType_Expendable, filter->ExcludePotential() ? eMakeType_Excluded : eMakeType_Potential};
3013 for (j=0; !libproj[j].empty(); ++j) {
3014 k = makefile.m_Contents.find(libproj[j]);
3015 if (k != makefile.m_Contents.end()) {
3016 const list<string>& values = k->second;
3017 for (list<string>::const_iterator i=values.begin(); i!=values.end(); ++i) {
3018 if (i->at(0) == '#') {
3019 break;
3020 }
3021 string mkname("Makefile." + *i + ".lib");
3022 libprojects[mkname] = max(maketype, libtype[j]);
3023 if (get_order) {
3024 s_WriteBuildOrder(dir_name,mkname);
3025 }
3026 }
3027 }
3028 }
3029 string dllproj[] = {"DLL_PROJ","EXPENDABLE_DLL_PROJ","POTENTIAL_DLL_PROJ",""};
3030 EMakeFileType dlltype[] = {eMakeType_Undefined,eMakeType_Expendable,
3031 filter->ExcludePotential() ? eMakeType_Excluded : eMakeType_Potential};
3032 for (j=0; !dllproj[j].empty(); ++j) {
3033 k = makefile.m_Contents.find(dllproj[j]);
3034 if (k != makefile.m_Contents.end()) {
3035 const list<string>& values = k->second;
3036 for (list<string>::const_iterator i=values.begin(); i!=values.end(); ++i) {
3037 if (i->at(0) == '#') {
3038 break;
3039 }
3040 string mkname("Makefile." + *i + ".dll");
3041 dllprojects[mkname] = max(maketype, dlltype[j]);
3042 if (get_order) {
3043 s_WriteBuildOrder(dir_name,mkname);
3044 }
3045 }
3046 }
3047 }
3048 string metallib[] = {"METAL_PROJ", ""};
3049 EMakeFileType metaltype[] = { eMakeType_Undefined};
3050 for (j=0; !metallib[j].empty(); ++j) {
3051 k = makefile.m_Contents.find(metallib[j]);
3052 if (k != makefile.m_Contents.end()) {
3053 const list<string>& values = k->second;
3054 for (list<string>::const_iterator i=values.begin(); i!=values.end(); ++i) {
3055 if (i->at(0) == '#') {
3056 break;
3057 }
3058 string mkname("Makefile." + *i + ".metal");
3059 libprojects[mkname] = max(maketype, metaltype[j]);
3060 if (get_order) {
3061 s_WriteBuildOrder(dir_name,mkname);
3062 }
3063 has_metal = true;
3064 }
3065 }
3066 }
3067 string appproj[] = {"APP_PROJ","EXPENDABLE_APP_PROJ","POTENTIAL_APP_PROJ",""};
3068 EMakeFileType apptype[] = {eMakeType_Undefined,eMakeType_Expendable,eMakeType_Potential};
3069 if (filter->ExcludePotential()) {
3070 apptype[2] = eMakeType_Excluded;
3071 }
3072 for (j=0; !appproj[j].empty(); ++j) {
3073 k = makefile.m_Contents.find(appproj[j]);
3074 if (k != makefile.m_Contents.end()) {
3075 const list<string>& values = k->second;
3076 for (list<string>::const_iterator i=values.begin(); i!=values.end(); ++i) {
3077 if (i->at(0) == '#') {
3078 break;
3079 }
3080 string mkname("Makefile." + *i + ".app");
3081 appprojects[mkname] = max(maketype, apptype[j]);
3082 if (get_order) {
3083 s_WriteBuildOrder(dir_name,mkname);
3084 }
3085 }
3086 }
3087 }
3088 }
3089 }
3090 }
3091
3092 // Process Makefile.*.lib
3093 if ( process_projects && !libprojects.empty()) {
3094 CDir dir(dir_name);
3095 CDir::TEntries contents = dir.GetEntries("Makefile.*.lib");
3096 ITERATE(CDir::TEntries, p, contents) {
3097 const AutoPtr<CDirEntry>& dir_entry = *p;
3098 const string name = dir_entry->GetName();
3099 if (libprojects.find(name) != libprojects.end() &&
3100 SMakeProjectT::IsMakeLibFile(name) )
3101 ProcessMakeLibFile(dir_entry->GetPath(), makefiles, libprojects[name], mkin);
3102
3103 }
3104 if (has_metal) {
3105 contents = dir.GetEntries("Makefile.*.metal");
3106 ITERATE(CDir::TEntries, p, contents) {
3107 const AutoPtr<CDirEntry>& dir_entry = *p;
3108 const string name = dir_entry->GetName();
3109 if (libprojects.find(name) != libprojects.end()) {
3110 ProcessMakeLibFile(dir_entry->GetPath(), makefiles, libprojects[name], mkin);
3111 }
3112 }
3113 }
3114 }
3115 // Process Makefile.*.dll
3116 if ( process_projects && !dllprojects.empty()) {
3117 CDir dir(dir_name);
3118 CDir::TEntries contents = dir.GetEntries("Makefile.*.dll");
3119 ITERATE(CDir::TEntries, p, contents) {
3120 const AutoPtr<CDirEntry>& dir_entry = *p;
3121 const string name = dir_entry->GetName();
3122 if (dllprojects.find(name) != dllprojects.end() &&
3123 SMakeProjectT::IsMakeDllFile(name) )
3124 ProcessMakeDllFile(dir_entry->GetPath(), makefiles, dllprojects[name], mkin);
3125
3126 }
3127 }
3128 // Process Makefile.*.app
3129 if ( process_projects && !appprojects.empty() ) {
3130 CDir dir(dir_name);
3131 CDir::TEntries contents = dir.GetEntries("Makefile.*.app");
3132 ITERATE(CDir::TEntries, p, contents) {
3133 const AutoPtr<CDirEntry>& dir_entry = *p;
3134 const string name = dir_entry->GetName();
3135 if (appprojects.find(name) != appprojects.end() &&
3136 SMakeProjectT::IsMakeAppFile(name) )
3137 ProcessMakeAppFile(dir_entry->GetPath(), makefiles, appprojects[name], mkin);
3138
3139 }
3140 }
3141 // Process Makefile.*.msvcproj
3142 if ( process_projects && !userprojects.empty() ) {
3143 CDir dir(dir_name);
3144 // CDir::TEntries contents = dir.GetEntries("Makefile.*.msvcproj");
3145 CDir::TEntries contents = dir.GetEntries("Makefile.*");
3146 ITERATE(CDir::TEntries, p, contents) {
3147 const AutoPtr<CDirEntry>& dir_entry = *p;
3148 const string name = dir_entry->GetName();
3149 if (userprojects.find(name) != userprojects.end() /*&&
3150 SMakeProjectT::IsUserProjFile(name)*/ )
3151 ProcessUserProjFile(dir_entry->GetPath(), makefiles, userprojects[name], mkin);
3152
3153 }
3154 }
3155
3156 if ( process_projects) {
3157 /*if (!GetApp().IsScanningWholeTree())*/ {
3158 CDir dir(dir_name);
3159 CDir::TEntries contents = dir.GetEntries(GetApp().GetProjectTreeInfo().m_CustomMetaData);
3160 ITERATE(CDir::TEntries, p, contents) {
3161 GetApp().AddCustomMetaData( (*p)->GetPath());
3162 }
3163 contents = dir.GetEntries(GetApp().GetProjectTreeInfo().m_CustomConfH);
3164 ITERATE(CDir::TEntries, p, contents) {
3165 GetApp().AddCustomConfH( (*p)->GetPath());
3166 }
3167 }
3168 }
3169
3170 // Convert subprojects to subdirs
3171 map<string, EMakeFileType> subprojects_dirs;
3172 vector<string> ordered_subprojects_dirs;
3173
3174 // begin with explicitely requested subprojects
3175 ITERATE( vector<string>, p, ordered_subprojects) {
3176 string name(*p);
3177 CDirEntry dir_entry( CDirEntry::ConcatPath(dir_name, name));
3178 if ( dir_entry.IsDir() ) {
3179 if (subprojects.find(name) != subprojects.end()) {
3180 subprojects_dirs[dir_entry.GetPath()] = subprojects[name];
3181 } else {
3182 subprojects_dirs[dir_entry.GetPath()] =
3183 is_root ? eMakeType_Undefined : eMakeType_Excluded;
3184 }
3185 if (find(ordered_subprojects_dirs.begin(), ordered_subprojects_dirs.end(), name) ==
3186 ordered_subprojects_dirs.end()) {
3187 ordered_subprojects_dirs.push_back(name);
3188 } else {
3189 PTB_WARNING_EX(node_path, ePTB_InvalidMakefile,
3190 "Duplicate entry: " << name);
3191 }
3192 }
3193 }
3194
3195 // if ( is_root || (!process_projects && weak) ) {
3196 CDir dir(dir_name);
3197 CDir::TEntries contents = dir.GetEntries("*");
3198 ITERATE(CDir::TEntries, p, contents) {
3199 const AutoPtr<CDirEntry>& dir_entry = *p;
3200 if ( !dir_entry->IsDir() ) {
3201 continue;
3202 }
3203 string name = dir_entry->GetName();
3204 // if ( name == "." || name == ".." || name == "CVS" || name == ".svn" ||
3205 if ( name[0] == '.' || name == "CVS" ||
3206 name == string(1,CDir::GetPathSeparator()) ) {
3207 continue;
3208 }
3209 if (find(ordered_subprojects_dirs.begin(), ordered_subprojects_dirs.end(), name) !=
3210 ordered_subprojects_dirs.end()) {
3211 // already processed
3212 continue;
3213 }
3214 if (subprojects.find(name) != subprojects.end()) {
3215 subprojects_dirs[dir_entry->GetPath()] = subprojects[name];
3216 } else {
3217 subprojects_dirs[dir_entry->GetPath()] =
3218 is_root ? eMakeType_Undefined : eMakeType_Excluded;
3219 }
3220 if (find(ordered_subprojects_dirs.begin(), ordered_subprojects_dirs.end(), name) ==
3221 ordered_subprojects_dirs.end()) {
3222 ordered_subprojects_dirs.push_back(name);
3223 }
3224 }
3225 {
3226 map<string, EMakeFileType>::const_iterator s;
3227 for (s = subprojects.begin(); s != subprojects.end(); ++s) {
3228 if (s->first.find('/') != string::npos) {
3229 CDir dir_entry(CDirEntry::NormalizePath(
3230 CDirEntry::ConcatPath(dir_name, s->first)));
3231 if (dir_entry.IsDir()) {
3232 subprojects_dirs[dir_entry.GetPath()] = subprojects[s->first];
3233 }
3234 }
3235 }
3236 }
3237 /*
3238 } else {
3239 // for non-root only subprojects
3240 map<string, EMakeFileType>::const_iterator p;
3241 for (p = subprojects.begin(); p != subprojects.end(); ++p) {
3242 const string& subproject = p->first;
3243 string subproject_dir =
3244 CDirEntry::ConcatPath(dir_name, subproject);
3245 subprojects_dirs[subproject_dir] = p->second;
3246 }
3247 }
3248 */
3249
3250 // Process subproj ( e.t. subdirs )
3251 ITERATE( vector<string>, ps, ordered_subprojects_dirs) {
3252 const string& subproject_dir = CDirEntry::ConcatPath(dir_name, *ps);
3253 ProcessDir(subproject_dir, false, filter, makefiles, subprojects_dirs[subproject_dir], mkin);
3254 }
3255
3256 }
3257
3258
ProcessMakeInFile(const string & file_name,SMakeFiles * makefiles,EMakeFileType type,const CSimpleMakeFileContents * parent)3259 void CProjectTreeBuilder::ProcessMakeInFile(const string& file_name,
3260 SMakeFiles* makefiles,
3261 EMakeFileType type,
3262 const CSimpleMakeFileContents* parent)
3263 {
3264 CSimpleMakeFileContents fc(file_name, type);
3265 fc.SetParent(parent);
3266 if ( !fc.m_Contents.empty() ) {
3267 makefiles->m_In[file_name] = fc;
3268 PTB_TRACE_EX(file_name, 0, MakeFileTypeAsString(type));
3269 } else {
3270 PTB_WARNING(file_name, "ignored; empty");
3271 }
3272 }
3273
3274
ProcessMakeLibFile(const string & file_name,SMakeFiles * makefiles,EMakeFileType type,const CSimpleMakeFileContents * parent)3275 void CProjectTreeBuilder::ProcessMakeLibFile(const string& file_name,
3276 SMakeFiles* makefiles,
3277 EMakeFileType type,
3278 const CSimpleMakeFileContents* parent)
3279 {
3280 CSimpleMakeFileContents fc(file_name, type);
3281 fc.SetParent(parent);
3282 if ( !fc.m_Contents.empty() ) {
3283 makefiles->m_Lib[file_name] = fc;
3284 PTB_TRACE_EX(file_name, 0, MakeFileTypeAsString(type));
3285 } else {
3286 PTB_WARNING(file_name, "ignored; empty");
3287 }
3288 }
3289
ProcessMakeDllFile(const string & file_name,SMakeFiles * makefiles,EMakeFileType type,const CSimpleMakeFileContents * parent)3290 void CProjectTreeBuilder::ProcessMakeDllFile(const string& file_name,
3291 SMakeFiles* makefiles,
3292 EMakeFileType type,
3293 const CSimpleMakeFileContents* parent)
3294 {
3295 string s = "MakeDll : " + file_name + " ";
3296
3297 CSimpleMakeFileContents fc(file_name, type);
3298 fc.SetParent(parent);
3299 if ( !fc.m_Contents.empty() ) {
3300 makefiles->m_Dll[file_name] = fc;
3301 } else {
3302 PTB_INFO(s << "rejected (is empty)");
3303 }
3304 }
3305
3306
ProcessMakeAppFile(const string & file_name,SMakeFiles * makefiles,EMakeFileType type,const CSimpleMakeFileContents * parent)3307 void CProjectTreeBuilder::ProcessMakeAppFile(const string& file_name,
3308 SMakeFiles* makefiles,
3309 EMakeFileType type,
3310 const CSimpleMakeFileContents* parent)
3311 {
3312 CSimpleMakeFileContents fc(file_name, type);
3313 fc.SetParent(parent);
3314 if ( !fc.m_Contents.empty() ) {
3315 makefiles->m_App[file_name] = fc;
3316 PTB_TRACE_EX(file_name, 0, MakeFileTypeAsString(type));
3317 } else {
3318 PTB_WARNING(file_name, "ignored; empty");
3319 }
3320 }
3321
3322
ProcessUserProjFile(const string & file_name,SMakeFiles * makefiles,EMakeFileType type,const CSimpleMakeFileContents * parent)3323 void CProjectTreeBuilder::ProcessUserProjFile(const string& file_name,
3324 SMakeFiles* makefiles,
3325 EMakeFileType type,
3326 const CSimpleMakeFileContents* parent)
3327 {
3328 bool allow_empty = CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix;
3329 CSimpleMakeFileContents fc(file_name, type);
3330 fc.SetParent(parent);
3331 if ( allow_empty || !fc.m_Contents.empty() ) {
3332 makefiles->m_User[file_name] = fc;
3333 PTB_TRACE_EX(file_name, 0, MakeFileTypeAsString(type));
3334 } else {
3335 PTB_WARNING(file_name, "ignored; empty");
3336 }
3337 }
3338
3339 //recursive resolving
ResolveDefs(CSymResolver & resolver,SMakeFiles & makefiles)3340 void CProjectTreeBuilder::ResolveDefs(CSymResolver& resolver,
3341 SMakeFiles& makefiles)
3342 {
3343 {{
3344 _TRACE("*** Resolving macrodefinitions in App projects ***");
3345 //App
3346 set<string> keys;
3347 keys.insert("LIB");
3348 keys.insert("LIBS");
3349 if (GetApp().GetBuildType().GetType() == CBuildType::eStatic) {
3350 keys.insert("STATIC_LIB");
3351 keys.insert("STATIC_LIBS");
3352 }
3353 keys.insert("NCBI_C_LIBS");
3354 SMakeProjectT::DoResolveDefs(resolver, makefiles.m_App, keys);
3355 }}
3356
3357 {{
3358 _TRACE("*** Resolving macrodefinitions in Lib projects ***");
3359 //Lib
3360 set<string> keys;
3361 keys.insert("LIB");
3362 keys.insert("LIBS");
3363 if (GetApp().GetBuildType().GetType() == CBuildType::eStatic) {
3364 keys.insert("STATIC_LIB");
3365 keys.insert("STATIC_LIBS");
3366 }
3367 keys.insert("SRC");
3368 keys.insert("DLL_LIB");
3369 if (GetApp().GetBuildType().GetType() == CBuildType::eDll) {
3370 keys.insert("DLL_DLIB");
3371 }
3372 SMakeProjectT::DoResolveDefs(resolver, makefiles.m_Lib, keys);
3373 }}
3374
3375 {{
3376 _TRACE("*** Resolving macrodefinitions in Msvc projects ***");
3377 set<string> keys;
3378 keys.insert("DLL_DEP");
3379 SMakeProjectT::DoResolveDefs(resolver, makefiles.m_User, keys);
3380 }}
3381 {{
3382 set<string> keys;
3383 SMakeProjectT::DoResolveDefs(resolver, makefiles.m_In, keys);
3384 SMakeProjectT::DoResolveDefs(resolver, makefiles.m_Dll, keys);
3385 }}
3386 }
3387
3388
3389 //analyze modules
s_CollectDatatoolIds(const CProjectItemsTree & tree,map<string,CProjKey> * datatool_ids)3390 void s_CollectDatatoolIds(const CProjectItemsTree& tree,
3391 map<string, CProjKey>* datatool_ids)
3392 {
3393 ITERATE(CProjectItemsTree::TProjects, p, tree.m_Projects) {
3394 const CProjKey& project_id = p->first;
3395 if (project_id.Type() == CProjKey::eDataSpec) {
3396 continue;
3397 }
3398 const CProjItem& project = p->second;
3399 ITERATE(list<CDataToolGeneratedSrc>, n, project.m_DatatoolSources) {
3400 const CDataToolGeneratedSrc& src = *n;
3401 string src_abs_path =
3402 CDirEntry::ConcatPath(src.m_SourceBaseDir, src.m_SourceFile);
3403 string src_rel_path =
3404 CDirEntry::CreateRelativePath
3405 (GetApp().GetProjectTreeInfo().m_Src,
3406 src_abs_path);
3407 (*datatool_ids)[src_rel_path] = project_id;
3408 }
3409 }
3410 }
3411
3412
AddDatatoolSourcesDepends(CProjectItemsTree * tree)3413 void CProjectTreeBuilder::AddDatatoolSourcesDepends(CProjectItemsTree* tree)
3414 {
3415 //datatool src rel path / project ID
3416
3417 // 1. Collect all projects with datatool-generated-sources
3418 map<string, CProjKey> whole_datatool_ids;
3419 bool whole_collected = false;
3420 if (GetApp().IsScanningWholeTree()) {
3421 whole_collected = true;
3422 s_CollectDatatoolIds(GetApp().GetWholeTree(), &whole_datatool_ids);
3423 }
3424
3425 // 2. Extent tree to accomodate more ASN projects if necessary
3426 bool tree_extented = false;
3427 map<string, CProjKey> datatool_ids;
3428
3429 do {
3430
3431 tree_extented = false;
3432 s_CollectDatatoolIds(*tree, &datatool_ids);
3433
3434 CProjectItemsTree::TProjects added;
3435
3436 NON_CONST_ITERATE(CProjectItemsTree::TProjects, p, tree->m_Projects) {
3437 // const CProjKey& project_id = p->first;
3438 CProjItem& project = p->second;
3439 ITERATE(list<CDataToolGeneratedSrc>, n, project.m_DatatoolSources) {
3440 const CDataToolGeneratedSrc& src = *n;
3441 ITERATE(list<string>, i, src.m_ImportModules) {
3442 const string& module = *i;
3443 map<string, CProjKey>::const_iterator j =
3444 datatool_ids.find(module);
3445 if (j == datatool_ids.end()) {
3446 if (!whole_collected) {
3447 whole_collected = true;
3448 s_CollectDatatoolIds(GetApp().GetWholeTree(), &whole_datatool_ids);
3449 }
3450 j = whole_datatool_ids.find(module);
3451 if (j != whole_datatool_ids.end()) {
3452 const CProjKey& depends_id = j->second;
3453 #if 1
3454 datatool_ids[module] = depends_id;
3455 added[depends_id] = GetApp().GetWholeTree().m_Projects.find(depends_id)->second;
3456 #else
3457 tree->m_Projects[depends_id] =
3458 GetApp().GetWholeTree().m_Projects.find(depends_id)->second;
3459 tree_extented = true;
3460 #endif
3461 }
3462 }
3463 }
3464 }
3465 }
3466 #if 1
3467 tree_extented = !added.empty();
3468 ITERATE(CProjectItemsTree::TProjects, p, added) {
3469 tree->m_Projects[p->first] = p->second;
3470 }
3471 #endif
3472 } while( tree_extented );
3473
3474
3475 CProjKey proj_key(CProjKey::eDataSpec, GetApp().GetDataspecProjId());
3476 CProjectItemsTree::TProjects::iterator z = tree->m_Projects.find(proj_key);
3477
3478 // 3. Finally - generate depends
3479 NON_CONST_ITERATE(CProjectItemsTree::TProjects, p, tree->m_Projects) {
3480 const CProjKey& project_id = p->first;
3481 if (project_id.Type() == CProjKey::eDataSpec) {
3482 continue;
3483 }
3484 CProjItem& project = p->second;
3485 ITERATE(list<CDataToolGeneratedSrc>, n, project.m_DatatoolSources) {
3486 const CDataToolGeneratedSrc& src = *n;
3487 if (z != tree->m_Projects.end()) {
3488 z->second.m_DatatoolSources.push_back(src);
3489 }
3490 ITERATE(list<string>, i, src.m_ImportModules) {
3491 const string& module = *i;
3492 map<string, CProjKey>::const_iterator j =
3493 datatool_ids.find(module);
3494 if (j != datatool_ids.end()) {
3495 const CProjKey& depends_id = j->second;
3496 if (depends_id != project_id) {
3497 project.m_Depends.push_back(depends_id);
3498 project.m_Depends.sort();
3499 project.m_Depends.unique();
3500 }
3501 }
3502 }
3503 }
3504 }
3505
3506 }
3507
3508
3509 END_NCBI_SCOPE
3510