1 /* $Id: proj_builder_app.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_builder_app.hpp"
32 #include "proj_item.hpp"
33 #include "proj_tree_builder.hpp"
34 #include "msvc_prj_utils.hpp"
35 #include "msvc_prj_generator.hpp"
36 #include "mac_prj_generator.hpp"
37 #include "msvc_sln_generator.hpp"
38 #include "msvc_masterproject_generator.hpp"
39 #include "proj_utils.hpp"
40 #include "msvc_configure.hpp"
41 #include "msvc_prj_defines.hpp"
42 #include "msvc_configure_prj_generator.hpp"
43 #include "proj_projects.hpp"
44 #include "configurable_file.hpp"
45 #include "ptb_err_codes.hpp"
46 #include <corelib/ncbitime.hpp>
47 #include <corelib/expr.hpp>
48
49 #include <common/test_assert.h> /* This header must go last */
50
51
52 // special task
53 #define DO_PATCHTREEMAKEFILES 0
54
55 BEGIN_NCBI_SCOPE
56
57
58 /////////////////////////////////////////////////////////////////////////////
59 ///
60 /// Windows-specific command-line logger
61 /// This is used to format error output in such a way that the Windows error
62 /// logger can pick this up
63
64 class CWindowsCmdErrorHandler : public CDiagHandler
65 {
66 public:
67
CWindowsCmdErrorHandler()68 CWindowsCmdErrorHandler()
69 {
70 m_OrigHandler.reset(GetDiagHandler(true));
71 CNcbiApplication* app = CNcbiApplication::Instance();
72 if (app) {
73 m_AppName = app->GetProgramDisplayName();
74 } else {
75 m_AppName = "unknown_app";
76 }
77 }
78
~CWindowsCmdErrorHandler()79 ~CWindowsCmdErrorHandler()
80 {
81 }
82
83 /// post a message
Post(const SDiagMessage & msg)84 void Post(const SDiagMessage& msg)
85 {
86 if (m_OrigHandler.get()) {
87 m_OrigHandler->Post(msg);
88 }
89
90 CTempString str(msg.m_Buffer, msg.m_BufferLen);
91 if (!msg.m_Buffer) {
92 str.assign(kEmptyStr.c_str(),0);
93 }
94
95 /// screen for error message level data only
96 /// MSVC doesn't handle the other parts
97 switch (msg.m_Severity) {
98 case eDiag_Error:
99 case eDiag_Critical:
100 case eDiag_Fatal:
101 case eDiag_Warning:
102 break;
103
104 case eDiag_Info:
105 case eDiag_Trace:
106 if (msg.m_ErrCode == ePTB_NoError) {
107 /// simple pass-through to stderr
108 if (strlen(msg.m_File) != 0) {
109 cerr << msg.m_File << ": ";
110 }
111 cerr << str << endl;
112 return;
113 }
114 break;
115 }
116
117 /// REQUIRED: origin
118 if (strlen(msg.m_File) == 0) {
119 cerr << m_AppName;
120 } else {
121 cerr << msg.m_File;
122 }
123 if (msg.m_Line) {
124 cerr << "(" << msg.m_Line << ")";
125 }
126 cerr << ": ";
127
128 /// OPTIONAL: subcategory
129 //cerr << m_AppName << " ";
130
131 /// REQUIRED: category
132 /// the MSVC system understands only 'error' and 'warning'
133 switch (msg.m_Severity) {
134 case eDiag_Error:
135 case eDiag_Critical:
136 case eDiag_Fatal:
137 cerr << "error ";
138 break;
139
140 case eDiag_Warning:
141 cerr << "warning ";
142 break;
143
144 case eDiag_Info:
145 case eDiag_Trace:
146 /// FIXME: find out how to get this in the messages tab
147 cerr << "info ";
148 break;
149 }
150
151 /// REQUIRED: error code
152 cerr << msg.m_ErrCode << ": ";
153
154 /// OPTIONAL: text
155 cerr << str << endl;
156 }
157
158 private:
159 unique_ptr<CDiagHandler> m_OrigHandler;
160
161 /// the original diagnostics handler
162 string m_AppName;
163
164 };
165
166 /////////////////////////////////////////////////////////////////////////////
167
168
169 // When defined, this environment variable
170 // instructs PTB to exclude CONFIGURE, INDEX, and HIERARCHICAL VIEW
171 // projects
172 const char* s_ptb_skipconfig = "__PTB__SKIP__CONFIG__";
173
174 #ifdef COMBINED_EXCLUDE
175 struct PIsExcludedByProjectMakefile
176 {
177 typedef CProjectItemsTree::TProjects::value_type TValueType;
operator ()PIsExcludedByProjectMakefile178 bool operator() (const TValueType& item) const
179 {
180 const CProjItem& project = item.second;
181 CMsvcPrjProjectContext prj_context(project);
182 const list<string> implicit_exclude_dirs =
183 GetApp().GetProjectTreeInfo().m_ImplicitExcludedAbsDirs;
184 ITERATE(list<string>, p, implicit_exclude_dirs) {
185 const string& dir = *p;
186 if ( IsSubdir(dir, project.m_SourcesBaseDir) ) {
187 // implicitly excluded from build
188 return prj_context.GetMsvcProjectMakefile().IsExcludeProject
189 (true);
190 }
191 }
192 // implicitly included to build
193 return prj_context.GetMsvcProjectMakefile().IsExcludeProject(false);
194 }
195 };
196
197
198 struct PIsExcludedMakefileIn
199 {
200 typedef CProjectItemsTree::TProjects::value_type TValueType;
201
PIsExcludedMakefileInPIsExcludedMakefileIn202 PIsExcludedMakefileIn(const string& root_src_dir)
203 :m_RootSrcDir(CDirEntry::NormalizePath(root_src_dir))
204 {
205 ProcessDir(root_src_dir);
206 }
207
operator ()PIsExcludedMakefileIn208 bool operator() (const TValueType& item) const
209 {
210 const CProjItem& project = item.second;
211
212 const list<string> implicit_exclude_dirs =
213 GetApp().GetProjectTreeInfo().m_ImplicitExcludedAbsDirs;
214 ITERATE(list<string>, p, implicit_exclude_dirs) {
215 const string& dir = *p;
216 if ( IsSubdir(dir, project.m_SourcesBaseDir) ) {
217 // implicitly excluded from build
218 return !IsExcplicitlyIncluded(project.m_SourcesBaseDir);
219 }
220 }
221 return false;
222 }
223
224 private:
225 string m_RootSrcDir;
226
227 typedef map<string, AutoPtr<CPtbRegistry> > TMakefiles;
228 TMakefiles m_Makefiles;
229
ProcessDirPIsExcludedMakefileIn230 void ProcessDir(const string& dir_name)
231 {
232 CDir dir(dir_name);
233 CDir::TEntries contents = dir.GetEntries("*");
234 ITERATE(CDir::TEntries, i, contents) {
235 string name = (*i)->GetName();
236 if ( name == "." || name == ".." ||
237 name == string(1,CDir::GetPathSeparator()) ) {
238 continue;
239 }
240 string path = (*i)->GetPath();
241
242 if ( (*i)->IsFile() &&
243 name == "Makefile.in.msvc" ) {
244 m_Makefiles[path] =
245 AutoPtr<CPtbRegistry>
246 (new CPtbRegistry(CNcbiIfstream(path.c_str(),
247 IOS_BASE::in | IOS_BASE::binary)));
248 }
249 else if ( (*i)->IsDir() ) {
250
251 ProcessDir(path);
252 }
253 }
254 }
255
IsExcplicitlyIncludedPIsExcludedMakefileIn256 bool IsExcplicitlyIncluded(const string& project_base_dir) const
257 {
258 string dir = project_base_dir;
259 for(;;) {
260
261 if (dir == m_RootSrcDir)
262 return false;
263 string path = CDirEntry::ConcatPath(dir, "Makefile.in.msvc");
264 TMakefiles::const_iterator p =
265 m_Makefiles.find(path);
266 if ( p != m_Makefiles.end() ) {
267 string val =
268 (p->second)->GetString("Common", "ExcludeProject");
269 if (val == "FALSE")
270 return true;
271 }
272
273 dir = CDirEntry::ConcatPath(dir, "..");
274 dir = CDirEntry::NormalizePath(dir);
275 }
276
277 return false;
278 }
279 };
280
281
282 template <class T1, class T2, class V> class CCombine
283 {
284 public:
CCombine(const T1 & t1,const T2 & t2)285 CCombine(const T1& t1, const T2& t2)
286 :m_T1(t1), m_T2(t2)
287 {
288 }
operator ()(const V & v) const289 bool operator() (const V& v) const
290 {
291 return m_T1(v) && m_T2(v);
292 }
293 private:
294 const T1 m_T1;
295 const T2 m_T2;
296 };
297 #else
298 // not def COMBINED_EXCLUDE
299 struct PIsExcludedByProjectMakefile
300 {
301 typedef CProjectItemsTree::TProjects::value_type TValueType;
operator ()PIsExcludedByProjectMakefile302 bool operator() (const TValueType& item) const
303 {
304 const CProjItem& project = item.second;
305 CMsvcPrjProjectContext prj_context(project);
306 const list<string> implicit_exclude_dirs =
307 GetApp().GetProjectTreeInfo().m_ImplicitExcludedAbsDirs;
308 ITERATE(list<string>, p, implicit_exclude_dirs) {
309 const string& dir = *p;
310 if ( IsSubdir(dir, project.m_SourcesBaseDir) ) {
311 // implicitly excluded from build
312 if (prj_context.GetMsvcProjectMakefile().IsExcludeProject(true)) {
313 PTB_WARNING_EX(kEmptyStr, ePTB_ProjectExcluded,
314 "Excluded: project " << project.m_Name
315 << " by ProjectTree/ImplicitExclude");
316 return true;
317 }
318 return false;
319 }
320 }
321 // implicitly included into build
322 if (prj_context.GetMsvcProjectMakefile().IsExcludeProject(false)) {
323 PTB_WARNING_EX(kEmptyStr, ePTB_ProjectExcluded,
324 "Excluded: project " << project.m_Name
325 << " by Makefile." << project.m_Name << ".*."
326 << GetApp().GetRegSettings().m_MakefilesExt);
327 return true;
328 }
329 return false;
330 }
331 };
332
333 #endif
334
335 struct PIsExcludedByTag
336 {
337 typedef CProjectItemsTree::TProjects::value_type TValueType;
operator ()PIsExcludedByTag338 bool operator() (const TValueType& item) const
339 {
340 const CProjItem& project = item.second;
341 string unmet;
342 if ( project.m_ProjType != CProjKey::eDataSpec &&
343 !GetApp().IsAllowedProjectTag(project) ) {
344 string unmet( NStr::Join(project.m_ProjTags,","));
345 PTB_WARNING_EX(project.GetPath(), ePTB_ProjectExcluded,
346 "Excluded due to proj_tag; this project tags: " << unmet);
347 return true;
348 }
349 return false;
350 }
351 };
352
353 struct PIsExcludedByUser
354 {
355 typedef CProjectItemsTree::TProjects::value_type TValueType;
operator ()PIsExcludedByUser356 bool operator() (const TValueType& item) const
357 {
358 const CProjItem& project = item.second;
359 if (project.m_ProjType != CProjKey::eDll &&
360 project.m_ProjType != CProjKey::eDataSpec &&
361 !GetApp().m_CustomConfiguration.DoesValueContain(
362 "__AllowedProjects",
363 CreateProjectName(CProjKey(project.m_ProjType, project.m_ID)), true)) {
364 PTB_WARNING_EX(project.GetPath(), ePTB_ProjectExcluded,
365 "Excluded by user request");
366 return true;
367 }
368 return false;
369
370 }
371 };
372
373 struct PIsExcludedByRequires
374 {
375 typedef CProjectItemsTree::TProjects::value_type TValueType;
operator ()PIsExcludedByRequires376 bool operator() (const TValueType& item) const
377 {
378 string unmet;
379 const CProjItem& project = item.second;
380 if ( !CMsvcPrjProjectContext::IsRequiresOk(project, &unmet) ) {
381 PTB_WARNING_EX(project.GetPath(), ePTB_ProjectExcluded,
382 "Excluded due to unmet requirement: "
383 << unmet);
384 return true;
385 }
386 return false;
387
388 }
389 };
390
391 struct PIsExcludedByDisuse
392 {
393 typedef CProjectItemsTree::TProjects::value_type TValueType;
operator ()PIsExcludedByDisuse394 bool operator() (const TValueType& item) const
395 {
396 const CProjItem& project = item.second;
397 if (project.m_External) {
398 PTB_WARNING_EX(project.GetPath(), ePTB_ProjectExcluded,
399 "Excluded unused external");
400 return true;
401 }
402 return false;
403 }
404 };
405
406
407 //-----------------------------------------------------------------------------
CProjBulderApp(void)408 CProjBulderApp::CProjBulderApp(void)
409 {
410 SetVersion( CVersionInfo(4,8,2) );
411 m_ScanningWholeTree = false;
412 m_Dll = false;
413 m_AddMissingLibs = false;
414 m_ScanWholeTree = true;
415 m_TweakVTuneR = false;
416 m_TweakVTuneD = false;
417 m_AddUnicode = false;
418 m_CurrentBuildTree = 0;
419 m_IncompleteBuildTree = 0;
420 m_ProjTagCmnd = false;
421 m_ConfirmCfg = false;
422 m_AllDllBuild = false;
423 m_InteractiveCfg = false;
424 m_Dtdep = false;
425 m_AddMissingDep = false;
426 m_LibDep = false;
427 m_Ide = 0;
428 m_ExitCode = 0;
429 }
430
431
Init(void)432 void CProjBulderApp::Init(void)
433 {
434 string logfile = GetLogFile();
435 if (CDirEntry(logfile).Exists()) {
436 RegisterGeneratedFile(CDirEntry::NormalizePath(logfile));
437 }
438 if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
439 if (logfile != "STDERR") {
440 SetDiagHandler(new CWindowsCmdErrorHandler);
441 }
442 }
443 // Create command-line argument descriptions class
444 unique_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
445
446 // Specify USAGE context
447 string context;
448 if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
449 context = "MSVC ";
450 /*
451 context += CMsvc7RegSettings::GetProjectFileFormatVersion() +
452 " (" + CMsvc7RegSettings::GetMsvcPlatformName() + ")";
453 */
454 } else if (CMsvc7RegSettings::GetMsvcPlatform() > CMsvc7RegSettings::eUnix) {
455 context = "XCODE ";
456 /*
457 context += CMsvc7RegSettings::GetMsvcVersionName() +
458 " (" + CMsvc7RegSettings::GetMsvcPlatformName() + ")";
459 */
460 } else {
461 context = CMsvc7RegSettings::GetMsvcPlatformName();
462 }
463 context += " projects tree builder application";
464 arg_desc->SetUsageContext(GetArguments().GetProgramBasename(),context);
465
466 // Programm arguments:
467
468 arg_desc->AddPositional("root",
469 "Root directory of the build tree. "\
470 "This directory ends with \"c++\".",
471 CArgDescriptions::eString);
472
473 arg_desc->AddPositional("subtree",
474 "Subtree, or a file with a list of subtrees to build."\
475 " Examples: src/corelib/ scripts/projects/ncbi_cpp.lst",
476 CArgDescriptions::eString);
477
478 arg_desc->AddPositional("solution",
479 "MSVC Solution to build.",
480 CArgDescriptions::eString);
481
482 arg_desc->AddFlag ("dll",
483 "Dll(s) will be built instead of static libraries.",
484 true);
485
486 arg_desc->AddFlag ("nobuildptb",
487 "Exclude \"build PTB\" step from CONFIGURE project.");
488
489 arg_desc->AddFlag ("ext",
490 "Use external libraries instead of missing in-tree ones.");
491 arg_desc->AddFlag ("nws",
492 "Do not scan the whole source tree for missing projects.");
493 arg_desc->AddOptionalKey("extroot", "external_build_root",
494 "Subtree in which to look for external libraries.",
495 CArgDescriptions::eString);
496
497 arg_desc->AddOptionalKey("projtag", "project_tag",
498 "Expression. Include only projects that match."\
499 " Example: \"core && (test || !demo)\"",
500 CArgDescriptions::eString);
501
502 #if defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
503 arg_desc->AddOptionalKey("ide", "xcode_version",
504 "Target version of Xcode, for example: 30",
505 CArgDescriptions::eInteger);
506 arg_desc->AddOptionalKey("arch", "architecture",
507 "Target architecture, for example: ppc, i386",
508 CArgDescriptions::eString);
509 #elif defined(NCBI_COMPILER_MSVC)
510 arg_desc->AddOptionalKey("ide", "msvc_version",
511 "Target version of MS Visual Studio, for example: 1200, 1400, 1500",
512 CArgDescriptions::eInteger);
513 arg_desc->AddOptionalKey("arch", "platform",
514 "Target platform, for example: Win32, x64",
515 CArgDescriptions::eString);
516 #endif
517
518 arg_desc->AddFlag ("cfg",
519 "Show GUI to confirm configuration parameters (MS Windows only).");
520 arg_desc->AddFlag ("i",
521 "Run interactively. Can only be used by PTB GUI shell!");
522 arg_desc->AddFlag ("dtdep",
523 "Add dependency on datatool where needed.");
524 arg_desc->AddFlag ("noadddep",
525 "Do not add missing dependencies.");
526 arg_desc->AddDefaultKey("libdep", "LibraryDependencies",
527 "Analyze dependencies and generate library info for linker on Unix",
528 CArgDescriptions::eBoolean, "true");
529
530 arg_desc->AddOptionalKey("args", "args_file",
531 "Read arguments from a file",
532 CArgDescriptions::eString);
533
534 // Setup arg.descriptions for this application
535 SetupArgDescriptions(arg_desc.release());
536 }
537
538
539 static
s_ReportDependenciesStatus(const CCyclicDepends::TDependsCycles & cycles,CProjectItemsTree::TProjects & tree)540 void s_ReportDependenciesStatus(const CCyclicDepends::TDependsCycles& cycles,
541 CProjectItemsTree::TProjects& tree)
542 {
543 bool reported = false;
544 ITERATE(CCyclicDepends::TDependsCycles, p, cycles) {
545 const CCyclicDepends::TDependsChain& cycle = *p;
546 bool real_cycle = false;
547 string host0, host;
548 ITERATE(CCyclicDepends::TDependsChain, m, cycle) {
549 host = tree[*m].m_DllHost;
550 if (m == cycle.begin()) {
551 host0 = host;
552 } else {
553 real_cycle = (host0 != host) || (host0.empty() && host.empty());
554 if (real_cycle) {
555 break;
556 }
557 }
558 }
559 if (!real_cycle) {
560 continue;
561 }
562 string str_chain("Dependency cycle found: ");
563 ITERATE(CCyclicDepends::TDependsChain, n, cycle) {
564 const CProjKey& proj_id = *n;
565 if (n != cycle.begin()) {
566 str_chain += " - ";
567 }
568 str_chain += proj_id.Id();
569 }
570 PTB_WARNING_EX(kEmptyStr, ePTB_ConfigurationError, str_chain);
571 reported = true;
572 CCyclicDepends::TDependsChain::const_iterator i = cycle.end();
573 const CProjKey& last = *(--i);
574 const CProjKey& prev = *(--i);
575 if (last.Type() == CProjKey::eLib && prev.Type() == CProjKey::eLib) {
576 CProjectItemsTree::TProjects::const_iterator t = tree.find(prev);
577 if (t != tree.end()) {
578 CProjItem item = t->second;
579 item.m_Depends.remove(last);
580 tree[prev] = item;
581 PTB_WARNING_EX(kEmptyStr, ePTB_FileModified,
582 "Removing LIB dependency: " << prev.Id() << " - " << last.Id());
583 }
584 }
585 }
586 if (!reported) {
587 PTB_INFO("No dependency cycles found.");
588 }
589 }
590
Run(void)591 int CProjBulderApp::Run(void)
592 {
593 // Set error posting and tracing on maximum.
594 // SetDiagTrace(eDT_Enable);
595 SetDiagPostAllFlags(eDPF_All & ~eDPF_DateTime);
596 SetDiagPostLevel(eDiag_Info);
597 PTB_INFO("Started at " + CTime(CTime::eCurrent).AsString());
598 PTB_INFO("Project tree builder version " + GetVersion().Print());
599
600 CStopWatch sw;
601 sw.Start();
602
603 // Get and check arguments
604 ParseArguments();
605 PTB_INFO("Project tags filter: " + m_ProjTags);
606 if (m_InteractiveCfg && !Gui_ConfirmConfiguration())
607 {
608 PTB_INFO("Cancelled by request.");
609 return 1;
610 }
611 else if (m_ConfirmCfg && !ConfirmConfiguration())
612 {
613 PTB_INFO("Cancelled by request.");
614 return 1;
615 }
616 VerifyArguments();
617 m_CustomConfiguration.Save(m_CustomConfFile);
618
619 // Configure
620 CMsvcConfigure configure;
621 configure.Configure(const_cast<CMsvcSite&>(GetSite()),
622 GetRegSettings().m_ConfigInfo,
623 m_IncDir);
624 m_AllDllBuild = GetSite().IsProvided("DLL_BUILD");
625
626 #if DO_PATCHTREEMAKEFILES
627 // this is just a task; it is to be run very rarely
628 {
629 bool b = m_ScanWholeTree;
630 m_ScanWholeTree = true;
631 CMakefilePatch::PatchTreeMakefiles(GetWholeTree());
632 m_ScanWholeTree = b;
633 return 0;
634 }
635 #endif
636 // Build projects tree
637 //#ifndef _DEBUG
638 // I need this to collect library relations data and metadata
639 {
640 bool b = m_ScanWholeTree;
641 m_ScanWholeTree = true;
642 GetWholeTree();
643 m_ScanWholeTree = b;
644 }
645 //#endif
646
647 CProjectItemsTree projects_tree(GetProjectTreeInfo().m_Src);
648 CProjectTreeBuilder::BuildProjectTree(GetProjectTreeInfo().m_IProjectFilter.get(),
649 GetProjectTreeInfo().m_Src,
650 &projects_tree);
651 if (m_ExitCode != 0) {
652 PTB_INFO("Cancelled by request.");
653 return m_ExitCode;
654 }
655 configure.CreateConfH(const_cast<CMsvcSite&>(GetSite()),
656 GetRegSettings().m_ConfigInfo,
657 m_IncDir);
658
659 // MSVC specific part:
660 PTB_INFO("Checking project requirements...");
661 // Exclude some projects from build:
662 #ifdef COMBINED_EXCLUDE
663 {{
664 // Implicit/Exclicit exclude by msvc Makefiles.in.msvc
665 // and project .msvc makefiles.
666 PIsExcludedMakefileIn p_make_in(GetProjectTreeInfo().m_Src);
667 PIsExcludedByProjectMakefile p_project_makefile;
668 CCombine<PIsExcludedMakefileIn,
669 PIsExcludedByProjectMakefile,
670 CProjectItemsTree::TProjects::value_type>
671 logical_combine(p_make_in, p_project_makefile);
672 EraseIf(projects_tree.m_Projects, logical_combine);
673 }}
674 #else
675 {{
676 // Implicit/Exclicit exclude by msvc Makefiles.in.msvc
677 PIsExcludedByProjectMakefile p_project_makefile;
678 EraseIf(projects_tree.m_Projects, p_project_makefile);
679 }}
680
681 #endif
682 {{
683 // Project requires are not provided
684 EraseIf(projects_tree.m_Projects, PIsExcludedByRequires());
685 }}
686
687 CProjectItemsTree dll_projects_tree;
688 bool dll = (GetBuildType().GetType() == CBuildType::eDll);
689 if (dll) {
690 PTB_INFO("Assembling DLLs...");
691 // AnalyzeDllData(projects_tree);
692 CreateDllBuildTree(projects_tree, &dll_projects_tree);
693 }
694 CProjectItemsTree& prj_tree = dll ? dll_projects_tree : projects_tree;
695 prj_tree.VerifyExternalDepends();
696 {{
697 // Erase obsolete external projects
698 EraseIf(prj_tree.m_Projects, PIsExcludedByDisuse());
699 }}
700 prj_tree.VerifyDataspecProj();
701
702 PTB_INFO("Checking project inter-dependencies...");
703 CCyclicDepends::TDependsCycles cycles;
704 CCyclicDepends::FindCyclesNew(prj_tree.m_Projects, &cycles);
705 s_ReportDependenciesStatus(cycles,projects_tree.m_Projects);
706
707 if (!m_SuspiciousProj.empty()) {
708 ITERATE( set<CProjKey>, key, m_SuspiciousProj) {
709 if (prj_tree.m_Projects.find(*key) != prj_tree.m_Projects.end()) {
710 PTB_ERROR(prj_tree.m_Projects.find(*key)->second.GetPath(),
711 "More than one target with this name");
712 m_ExitCode = 1;
713 }
714 }
715 }
716 if (m_ExitCode != 0) {
717 string subtree = CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, m_Subtree);
718 if (CDirEntry(subtree).IsFile()) {
719 return m_ExitCode;
720 }
721 m_ExitCode = 0;
722 }
723 PTB_INFO("Creating projects...");
724 if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
725 GenerateMsvcProjects(prj_tree);
726 }
727 else if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
728 GenerateUnixProjects(prj_tree);
729 }
730 else {
731 GenerateMacProjects(prj_tree);
732 }
733 ReportGeneratedFiles();
734 ReportProjectWatchers();
735 //
736 PTB_INFO("Done. Elapsed time = " << sw.Elapsed() << " seconds");
737 return m_ExitCode;
738 }
739
GenerateMsvcProjects(CProjectItemsTree & projects_tree)740 void CProjBulderApp::GenerateMsvcProjects(CProjectItemsTree& projects_tree)
741 {
742 #if NCBI_COMPILER_MSVC
743 PTB_INFO("Generating MSBuild projects...");
744
745 bool dll = (GetBuildType().GetType() == CBuildType::eDll);
746 list<SConfigInfo> dll_configs;
747 const list<SConfigInfo>* configurations = 0;
748 bool skip_config = !GetEnvironment().Get(s_ptb_skipconfig).empty();
749 string str_config;
750
751 if (dll) {
752 _TRACE("DLL build");
753 GetBuildConfigs(&dll_configs);
754 configurations = &dll_configs;
755 } else {
756 _TRACE("Static build");
757 configurations = &GetRegSettings().m_ConfigInfo;
758 }
759 {{
760 ITERATE(list<SConfigInfo>, p , *configurations) {
761 str_config += p->GetConfigFullName() + " ";
762 }
763 PTB_INFO("Building configurations: " << str_config);
764 }}
765
766 m_CurrentBuildTree = &projects_tree;
767 if ( m_AddMissingLibs ) {
768 m_IncompleteBuildTree = &projects_tree;
769 }
770 // Projects
771 CMsvcProjectGenerator prj_gen(*configurations);
772 CMsvcProjectGenerator::GeneratePropertySheets();
773 NON_CONST_ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
774 prj_gen.Generate(p->second);
775 }
776
777 //Utility projects dir
778 string utility_projects_dir = GetApp().GetUtilityProjectsDir();
779
780 // MasterProject
781 CMsvcMasterProjectGenerator master_prj_gen(projects_tree,
782 *configurations,
783 utility_projects_dir);
784 if (!skip_config) {
785 master_prj_gen.SaveProject();
786 }
787
788 // ConfigureProject
789 string output_dir = GetProjectTreeInfo().m_Compilers;
790 output_dir = CDirEntry::ConcatPath(output_dir,
791 GetRegSettings().m_CompilersSubdir);
792 output_dir = CDirEntry::ConcatPath(output_dir,
793 (m_BuildPtb && dll) ? "static" : GetBuildType().GetTypeStr());
794 output_dir = CDirEntry::ConcatPath(output_dir, "bin");
795 output_dir = CDirEntry::AddTrailingPathSeparator(output_dir);
796 CMsvcConfigureProjectGenerator configure_generator(
797 output_dir,
798 *configurations,
799 dll,
800 utility_projects_dir,
801 GetProjectTreeInfo().m_Root,
802 m_Subtree,
803 m_Solution,
804 m_BuildPtb);
805 if (!skip_config) {
806 configure_generator.SaveProject(false, &prj_gen);
807 configure_generator.SaveProject(true, &prj_gen);
808 }
809
810 // INDEX dummy project
811 string index_prj_path = CDirEntry::ConcatPath(utility_projects_dir, "_INDEX_");
812 index_prj_path += CMsvc7RegSettings::GetVcprojExt();
813 string index_prj_guid, index_prj_name;
814 if (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000) {
815 CVisualStudioProject xmlprj;
816 CreateUtilityProject(" INDEX, see here: ", *configurations, &xmlprj);
817 if (!skip_config) {
818 SaveIfNewer(index_prj_path, xmlprj);
819 index_prj_guid = xmlprj.GetAttlist().GetProjectGUID();
820 index_prj_name = xmlprj.GetAttlist().GetName();
821 }
822 }
823
824 string utils[] = {"_DATASPEC_ALL_", "-DATASPEC-ALL-",
825 "_LIBS_ALL_", "-LIBS-ALL-",
826 "_BUILD_ALL_","-BUILD-ALL-"};
827 vector<string> utils_id;
828 int i = 0, num_util = 3;
829
830 for (i = 0; i < num_util; ++i) {
831 string prj_file(utils[i*2]);
832 string prj_name(utils[i*2+1]);
833 if (CMsvc7RegSettings::GetMsvcVersion() >= CMsvc7RegSettings::eMsvc1100) {
834 NStr::ReplaceInPlace(prj_name,"-", "_");
835 }
836 string prj_path = CDirEntry::ConcatPath(utility_projects_dir, prj_file);
837 prj_path += CMsvc7RegSettings::GetVcprojExt();
838 utils_id.push_back(prj_path);
839 if (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000) {
840 CVisualStudioProject xmlprj;
841 CreateUtilityProject(prj_name, *configurations, &xmlprj);
842 SaveIfNewer(prj_path, xmlprj);
843 utils_id.push_back(xmlprj.GetAttlist().GetProjectGUID());
844 utils_id.push_back(xmlprj.GetAttlist().GetName());
845 } else {
846 string prj_dir = GetApp().GetUtilityProjectsSrcDir();
847 CProjItem prj_item( CreateUtilityProjectItem(prj_dir, prj_name));
848 prj_gen.Generate(prj_item);
849 utils_id.push_back(prj_item.m_GUID);
850 utils_id.push_back(prj_item.m_Name);
851 }
852 }
853 if (m_ProjTags == "*") {
854 for (map<string,string>::const_iterator composite = m_CompositeProjectTags.begin();
855 composite != m_CompositeProjectTags.end(); ++composite) {
856 string composite_name = "_TAG_" + composite->first;
857 string composite_filter = composite->second;
858
859
860 string prj_path = CDirEntry::ConcatPath(utility_projects_dir, composite_name);
861 prj_path += CMsvc7RegSettings::GetVcprojExt();
862 utils_id.push_back(prj_path);
863 if (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000) {
864 CVisualStudioProject xmlprj;
865 CreateUtilityProject(composite_name, *configurations, &xmlprj);
866 SaveIfNewer(prj_path, xmlprj);
867 utils_id.push_back(xmlprj.GetAttlist().GetProjectGUID());
868 utils_id.push_back(xmlprj.GetAttlist().GetName());
869 } else {
870 string prj_dir = GetApp().GetUtilityProjectsSrcDir();
871 CProjItem prj_item( CreateUtilityProjectItem(prj_dir, composite_name));
872 prj_gen.Generate(prj_item);
873 utils_id.push_back(prj_item.m_GUID);
874 utils_id.push_back(prj_item.m_Name);
875 }
876 utils_id.push_back(composite_filter);
877 ++num_util;
878 }
879 }
880
881 // Solution
882 CMsvcSolutionGenerator sln_gen(*configurations);
883 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
884 sln_gen.AddProject(p->second);
885 }
886 if (!skip_config) {
887
888 if (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000) {
889 sln_gen.AddUtilityProject( master_prj_gen.GetPath(),
890 master_prj_gen.GetVisualStudioProject().GetAttlist().GetProjectGUID(),
891 master_prj_gen.GetVisualStudioProject().GetAttlist().GetName());
892
893 sln_gen.AddUtilityProject( index_prj_path, index_prj_guid, index_prj_name);
894 }
895
896 string cfg_path, cfg_guid, cfg_name;
897 configure_generator.GetVisualStudioProject(cfg_path, cfg_guid, cfg_name, false);
898 sln_gen.AddConfigureProject( cfg_path, cfg_guid, cfg_name);
899
900 configure_generator.GetVisualStudioProject(cfg_path, cfg_guid, cfg_name, true);
901 sln_gen.AddConfigureProject( cfg_path, cfg_guid, cfg_name);
902 }
903
904 int u = 0;
905 for (i = 0; i < num_util; ++i) {
906 switch (i) {
907 case 0:
908 sln_gen.AddAsnAllProject( utils_id[u], utils_id[u+1], utils_id[u+2]);
909 u += 3;
910 break;
911 case 1:
912 sln_gen.AddLibsAllProject( utils_id[u], utils_id[u+1], utils_id[u+2]);
913 u += 3;
914 break;
915 case 2:
916 sln_gen.AddBuildAllProject( utils_id[u], utils_id[u+1], utils_id[u+2]);
917 u += 3;
918 break;
919 default:
920 sln_gen.AddTagProject( utils_id[u], utils_id[u+1], utils_id[u+2], utils_id[u+3]);
921 u += 4;
922 break;
923 }
924 }
925
926 sln_gen.SaveSolution(m_Solution);
927
928 CreateCheckList(configurations, projects_tree);
929 list<string> enabled, disabled;
930 CreateFeaturesAndPackagesFiles(configurations, enabled, disabled);
931 GenerateSummary(*configurations, enabled, disabled);
932 #endif //NCBI_COMPILER_MSVC
933 }
934
GenerateMacProjects(CProjectItemsTree & projects_tree)935 void CProjBulderApp::GenerateMacProjects(CProjectItemsTree& projects_tree)
936 {
937 #if defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
938 PTB_INFO("Generating XCode projects...");
939
940 bool dll = (GetBuildType().GetType() == CBuildType::eDll);
941 list<SConfigInfo> dll_configs;
942 const list<SConfigInfo>* configurations = 0;
943 // bool skip_config = !GetEnvironment().Get(s_ptb_skipconfig).empty();
944 string str_config;
945
946 if (dll) {
947 _TRACE("DLL build");
948 GetBuildConfigs(&dll_configs);
949 configurations = &dll_configs;
950 } else {
951 _TRACE("Static build");
952 configurations = &GetRegSettings().m_ConfigInfo;
953 }
954 {{
955 ITERATE(list<SConfigInfo>, p , *configurations) {
956 str_config += p->GetConfigFullName() + " ";
957 }
958 PTB_INFO("Building configurations: " << str_config);
959 }}
960
961 m_CurrentBuildTree = &projects_tree;
962 if ( m_AddMissingLibs ) {
963 m_IncompleteBuildTree = &projects_tree;
964 }
965 // Projects
966 CMacProjectGenerator prj_gen(*configurations, projects_tree);
967 prj_gen.Generate(m_Solution);
968
969 CreateCheckList(configurations, projects_tree);
970 list<string> enabled, disabled;
971 CreateFeaturesAndPackagesFiles(configurations, enabled, disabled);
972 GenerateSummary(*configurations, enabled, disabled);
973 #endif
974 }
CollectLibToLibDependencies(CProjectItemsTree & projects_tree,set<string> & dep,set<string> & visited,CProjectItemsTree::TProjects::const_iterator & lib,CProjectItemsTree::TProjects::const_iterator & lib_dep)975 void CProjBulderApp::CollectLibToLibDependencies(
976 CProjectItemsTree& projects_tree,
977 set<string>& dep, set<string>& visited,
978 CProjectItemsTree::TProjects::const_iterator& lib,
979 CProjectItemsTree::TProjects::const_iterator& lib_dep)
980 {
981 string lib_name(CreateProjectName(lib->first));
982 string lib_dep_name(CreateProjectName(lib_dep->first));
983 if (m_AllDllBuild) {
984 dep.insert(lib_dep_name);
985 // return;
986 }
987 if (visited.find(lib_dep_name) != visited.end() ||
988 lib_dep_name == lib_name) {
989 return;
990 }
991 visited.insert(lib_dep_name);
992 if (!lib_dep->second.m_DatatoolSources.empty() ||
993 !lib_dep->second.m_ExportHeaders.empty() ||
994 lib->second.m_UnconditionalDepends.find(lib_dep->first) !=
995 lib->second.m_UnconditionalDepends.end()) {
996 dep.insert(lib_dep_name);
997 }
998 ITERATE(list<CProjKey>, p, lib_dep->second.m_Depends) {
999 if (p->Type() == CProjKey::eLib) {
1000 CProjectItemsTree::TProjects::const_iterator n =
1001 projects_tree.m_Projects.find(*p);
1002 if (n != projects_tree.m_Projects.end()) {
1003 CollectLibToLibDependencies(projects_tree, dep, visited, lib, n);
1004 }
1005 }
1006 }
1007 }
1008
GenerateUnixProjects(CProjectItemsTree & projects_tree)1009 void CProjBulderApp::GenerateUnixProjects(CProjectItemsTree& projects_tree)
1010 {
1011 map< string, list< string > > path_to_target;
1012 string solution_dir(CDirEntry(m_Solution).GetDir());
1013 CNcbiOfstream ofs(m_Solution.c_str(), IOS_BASE::out | IOS_BASE::trunc);
1014 if (!ofs.is_open()) {
1015 NCBI_THROW(CProjBulderAppException, eFileOpen, m_Solution);
1016 return;
1017 }
1018 GetApp().RegisterGeneratedFile( m_Solution );
1019 ofs << "# This file was generated by PROJECT_TREE_BUILDER v"
1020 << GetVersion().Print() << endl;
1021 ofs << "# on " << CTime(CTime::eCurrent).AsString() << endl << endl;
1022
1023 // see CXX-950
1024 #if 0
1025 ofs << "# This is tricky part; it might work incorrectly on some platforms" << endl;
1026 // ofs << "MARK=$(shell date +%Y%m%d%H%M%S)" << endl;
1027 ofs << "MARK=$(if $(MARK2),,$(eval MARK2=$(shell date +%Y%m%d%H%M%S)))$(MARK2)" << endl;
1028 ofs << "MARK:sh =date +%Y%m%d%H%M%S" << endl;
1029 ofs << endl;
1030 ofs << "prefix=.ncbi.signal." << endl;
1031 ofs << "s=$(prefix)$(MARK)" << endl;
1032 ofs << "sign=rm -f $(prefix)*.$@; touch $(s).$@" << endl;
1033 ofs << endl;
1034 #endif
1035
1036 ofs << "MINPUT=" << CDirEntry(m_Solution).GetName() << endl << endl;
1037 ofs << "# Use empty MTARGET to build a project;" << endl;
1038 ofs << "# MTARGET=clean - to clean, or MTARGET=purge - to purge" << endl;
1039 ofs << "MTARGET =" << endl << endl;
1040
1041 if (m_ExtSrcRoot.empty()) {
1042 ofs << "top_srcdir=" << m_Root << endl;
1043 } else {
1044 ofs << "top_srcdir=" << m_ExtSrcRoot << endl;
1045 }
1046 ofs << "# Non-redundant flags (will be overridden for GNU Make to avoid" << endl;
1047 ofs << "# --jobserver-fds=* proliferation)" << endl;
1048 ofs << "MFLAGS_NR = $(MFLAGS)" << endl;
1049 ofs << "SKIP_PRELIMINARIES= sources= configurables=configurables.null" << endl;
1050
1051 // all dirs -----------------------------------------------------------------
1052 list<string> all_dirs;
1053 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1054 if (p->first.Type() == CProjKey::eDataSpec) {
1055 continue;
1056 }
1057 all_dirs.push_back(
1058 CDirEntry::DeleteTrailingPathSeparator( CDirEntry::CreateRelativePath(
1059 GetProjectTreeInfo().m_Src,p->second.m_SourcesBaseDir)));
1060 }
1061 all_dirs.sort();
1062 all_dirs.unique();
1063 ofs << "all_dirs =";
1064 ITERATE(list<string>, p, all_dirs) {
1065 ofs << " \\" <<endl << " " << *p;
1066 }
1067 ofs << endl << endl;
1068
1069 ofs << "include $(top_srcdir)/src/build-system/Makefile.is_gmake" << endl;
1070 ofs << "include $(top_srcdir)/src/build-system/Makefile.meta.$(is_gmake)" << endl;
1071 ofs << endl;
1072
1073 string dotreal(".real");
1074 string dotfiles(".files");
1075
1076 // all projects -------------------------------------------------------------
1077 ofs << "all_projects =";
1078 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1079 if (p->second.m_MakeType == eMakeType_Excluded ||
1080 p->second.m_MakeType == eMakeType_ExcludedByReq) {
1081 PTB_INFO("For reference only: " << CreateProjectName(p->first));
1082 continue;
1083 }
1084 if (p->first.Type() == CProjKey::eDataSpec) {
1085 continue;
1086 }
1087 ofs << " \\" <<endl << " " << CreateProjectName(p->first);
1088 }
1089 ofs << endl << endl;
1090
1091 ofs << "ptb_all :" << endl
1092 << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) ptb_all" << dotreal
1093 << " MTARGET=$(MTARGET)";
1094 ofs << endl << endl;
1095 ofs << "ptb_all" << dotreal << " :" << " $(all_projects:%=%" << dotreal << ")";
1096 ofs << endl << endl;
1097
1098 // all libs -----------------------------------------------------------------
1099 ofs << "all_libraries =";
1100 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1101 if (p->second.m_MakeType == eMakeType_Excluded ||
1102 p->second.m_MakeType == eMakeType_ExcludedByReq) {
1103 continue;
1104 }
1105 if (p->first.Type() == CProjKey::eLib ||
1106 p->first.Type() == CProjKey::eDll) {
1107 ofs << " \\" <<endl << " " << CreateProjectName(p->first);
1108 }
1109 }
1110 ofs << endl << endl;
1111
1112 ofs << "all_libs :" << endl
1113 << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) all_libs" << dotreal
1114 << " MTARGET=$(MTARGET)";
1115 ofs << endl << endl;
1116 ofs << "all_libs" << dotreal << " :" << " $(all_libraries:%=%" << dotreal << ")";
1117 ofs << endl << endl;
1118
1119 // all sources --------------------------------------------------------------
1120 ofs << "all_dataspec =";
1121 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1122 if (p->second.m_MakeType == eMakeType_Excluded ||
1123 p->second.m_MakeType == eMakeType_ExcludedByReq) {
1124 continue;
1125 }
1126 if (p->first.Type() == CProjKey::eDataSpec) {
1127 continue;
1128 }
1129 if (p->second.m_DatatoolSources.empty()) {
1130 continue;
1131 }
1132 ofs << " \\" <<endl << " " << CreateProjectName(p->first) << dotfiles;
1133 }
1134 ofs << endl << endl;
1135
1136 ofs << "all_files :" << endl
1137 << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) all_files" << dotreal;
1138 ofs << endl << endl;
1139 ofs << "all_files" << dotreal << " :" << " $(all_dataspec:%=%" << dotreal << ")";
1140 ofs << endl << endl;
1141
1142 // all apps -----------------------------------------------------------------
1143 ofs << "all_apps =";
1144 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1145 if (p->second.m_MakeType == eMakeType_Excluded ||
1146 p->second.m_MakeType == eMakeType_ExcludedByReq) {
1147 continue;
1148 }
1149 if (p->first.Type() == CProjKey::eApp) {
1150 ofs << " \\" <<endl << " " << CreateProjectName(p->first);
1151 }
1152 }
1153 ofs << endl << endl;
1154
1155 // all Unix -------------------------------------------------------------
1156 ofs << "all_unix =";
1157 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1158 if (p->second.m_MakeType == eMakeType_Excluded ||
1159 p->second.m_MakeType == eMakeType_ExcludedByReq) {
1160 continue;
1161 }
1162 if (p->first.Type() == CProjKey::eMsvc) {
1163 ofs << " \\" <<endl << " " << CreateProjectName(p->first);
1164 }
1165 }
1166 ofs << endl << endl;
1167
1168 // all excluded -------------------------------------------------------------
1169 ofs << "all_excluded =";
1170 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1171 if (p->first.Type() == CProjKey::eDataSpec) {
1172 continue;
1173 }
1174 if (p->second.m_MakeType == eMakeType_Excluded ||
1175 p->second.m_MakeType == eMakeType_ExcludedByReq) {
1176 ofs << " \\" <<endl << " " << CreateProjectName(p->first);
1177 }
1178 }
1179 ofs << endl << endl;
1180
1181 // CompositeProjectTags -----------------------------------------------------
1182 // (add always)
1183 vector<string> existing_composite_names;
1184 ITERATE(set<string>, r, m_RegisteredProjectTags) {
1185 m_CompositeProjectTags[*r] = *r;
1186 }
1187 /*if (m_ProjTags == "*")*/ {
1188 for (map<string,string>::const_iterator composite = m_CompositeProjectTags.begin();
1189 composite != m_CompositeProjectTags.end(); ++composite) {
1190 string composite_name = "TAG_" + composite->first;
1191 string composite_filter = composite->second;
1192 vector<string> matching;
1193
1194 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1195 if (p->second.m_MakeType == eMakeType_Excluded ||
1196 p->second.m_MakeType == eMakeType_ExcludedByReq) {
1197 continue;
1198 }
1199 if (p->first.Type() == CProjKey::eDataSpec) {
1200 continue;
1201 }
1202 if (IsAllowedProjectTag(p->second, &composite_filter)) {
1203 matching.push_back( CreateProjectName(p->first));
1204 }
1205 }
1206 if (!matching.empty()) {
1207 existing_composite_names.push_back(composite_name);
1208 ofs << composite_name << "_projects =";
1209 ITERATE(vector<string>, c, matching) {
1210 ofs << " \\" <<endl << " " << *c;
1211 }
1212 ofs << endl << endl;
1213
1214 ofs << composite_name << " :" << endl
1215 << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) " << composite_name << dotreal
1216 << " MTARGET=$(MTARGET)";
1217 ofs << endl << endl;
1218 ofs << composite_name << dotreal << " :" << " $("
1219 << composite_name << "_projects" << ":%=%" << dotreal << ")";
1220 ofs << endl << endl;
1221
1222 }
1223 }
1224 }
1225
1226
1227 // help and list targets ----------------------------------------------------
1228 ofs << "help :"
1229 << endl << "\t@echo Build all projects"
1230 << endl << "\t@echo \" make -f $(MINPUT) -j 12 ptb_all\""
1231 << endl << "\t@echo Build a project, for example, xncbi.lib"
1232 << endl << "\t@echo \" make -f $(MINPUT) -j 12 xncbi.lib\""
1233 << endl << "\t@echo Clean project intermediate files"
1234 << endl << "\t@echo \" make -f $(MINPUT) -j 12 xncbi.lib MTARGET=clean\""
1235 << endl << "\t@echo Clean project intermediate and output files"
1236 << endl << "\t@echo \" make -f $(MINPUT) -j 12 xncbi.lib MTARGET=purge\""
1237 << endl << "\t@echo Target lists: "
1238 << endl << "\t@echo \" list-all - list all targets\""
1239 << endl << "\t@echo \" list-apps - list all applications\""
1240 << endl << "\t@echo \" list-libs - list all libraries\""
1241 << endl << "\t@echo \" list-unix - list all native Unix projects\""
1242 << endl << "\t@echo \" list-excluded - list 'excluded' targets\""
1243 << endl << "\t@echo \" list-tags - list composite targets\""
1244 << endl << "\t@echo \" list-tag-TagName - list all targets in a composite target TagName\"";
1245 ofs << endl << endl;
1246
1247 ofs << "list-all :"
1248 << endl << "\t@echo"
1249 << endl << "\t@echo"
1250 << endl << "\t@echo --------------------------------------"
1251 << endl << "\t@echo APPLICATIONS"
1252 << endl << "\t@echo"
1253 << endl << "\t@for i in $(all_apps); do echo $$i; done"
1254 << endl << "\t@echo"
1255 << endl << "\t@echo"
1256 << endl << "\t@echo --------------------------------------"
1257 << endl << "\t@echo LIBRARIES"
1258 << endl << "\t@echo"
1259 << endl << "\t@for i in $(all_libraries); do echo $$i; done"
1260 << endl << "\t@echo"
1261 << endl << "\t@echo"
1262 << endl << "\t@echo --------------------------------------"
1263 << endl << "\t@echo UNIX PROJECTS"
1264 << endl << "\t@echo"
1265 << endl << "\t@for i in $(all_unix); do echo $$i; done";
1266
1267 if (!existing_composite_names.empty()) {
1268 ofs
1269 << endl << "\t@echo"
1270 << endl << "\t@echo"
1271 << endl << "\t@echo --------------------------------------"
1272 << endl << "\t@echo COMPOSITE TARGETS"
1273 << endl << "\t@echo";
1274 ITERATE(vector<string>, c, existing_composite_names) {
1275 ofs << endl << "\t@echo " << *c;
1276 }
1277 }
1278 ofs
1279 << endl << "\t@echo"
1280 << endl << "\t@echo"
1281 << endl << "\t@echo --------------------------------------"
1282 << endl << "\t@echo DIRECTORIES"
1283 << endl << "\t@echo"
1284 << endl << "\t@for i in $(all_dirs); do echo $$i/; done";
1285 ofs << endl << endl;
1286 ofs << "list-apps :"
1287 << endl << "\t@for i in $(all_apps); do echo $$i; done";
1288 ofs << endl << endl;
1289 ofs << "list-libs :"
1290 << endl << "\t@for i in $(all_libraries); do echo $$i; done";
1291 ofs << endl << endl;
1292 ofs << "list-unix :"
1293 << endl << "\t@for i in $(all_unix); do echo $$i; done";
1294 ofs << endl << endl;
1295 ofs << "list-excluded :"
1296 << endl << "\t@for i in $(all_excluded); do echo $$i; done";
1297 ofs << endl << endl;
1298
1299 ofs << "list-tags :";
1300 if (!existing_composite_names.empty()) {
1301 ITERATE(vector<string>, c, existing_composite_names) {
1302 ofs << endl << "\t@echo " << *c;
1303 }
1304 }
1305 ofs << endl << endl;
1306 ITERATE(vector<string>, c, existing_composite_names) {
1307 ofs << "list-tag-" << *c << " :"
1308 << endl << "\t@for i in $(" << *c << "_projects); do echo $$i; done";
1309 ofs << endl << endl;
1310 }
1311
1312 // --------------------------------------------------------------------------
1313 string datatool_key;
1314 string datatool( GetDatatoolId() );
1315 set<string> dataspec_dirs;
1316 if (!datatool.empty()) {
1317 CProjKey t(CProjKey::eApp, datatool);
1318 if (projects_tree.m_Projects.find(t) != projects_tree.m_Projects.end()) {
1319 datatool_key = CreateProjectName(t);
1320 }
1321 }
1322
1323 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1324
1325 if (p->first.Type() == CProjKey::eDataSpec) {
1326 continue;
1327 }
1328
1329 bool isLibrary = p->first.Type() == CProjKey::eLib;
1330 bool hasDataspec = !p->second.m_DatatoolSources.empty();
1331 string target, target_app, target_lib, target_user;
1332 list<string> dependencies;
1333 CProjectItemsTree::TProjects::const_iterator n;
1334
1335 target = CreateProjectName(p->first);
1336 target_app = target_lib = target_user = "\"\"";
1337 if (p->first.Type() == CProjKey::eApp) {
1338 target_app = p->second.m_Name;
1339 } else if (p->first.Type() == CProjKey::eMsvc) {
1340 target_user = p->second.m_Name;
1341 } else if (p->first.Type() == CProjKey::eLib) {
1342 target_lib = p->second.m_Name;
1343 } else {
1344 target_lib = p->second.m_Name;
1345 }
1346 string rel_path = CDirEntry::CreateRelativePath(
1347 GetProjectTreeInfo().m_Src,p->second.m_SourcesBaseDir);
1348
1349 // check for missing dependencies -------------------------------------------
1350 string error;
1351 if (p->second.m_MakeType != eMakeType_Expendable && m_BuildRoot.empty()) {
1352 ITERATE(set<CProjKey>, u, p->second.m_UnconditionalDepends) {
1353 CProjKey proj_key = *u;
1354 if (projects_tree.m_Projects.find(proj_key) ==
1355 projects_tree.m_Projects.end()) {
1356 bool depfound = false;
1357 string dll(GetDllHost(projects_tree, proj_key.Id()));
1358 if (!dll.empty()) {
1359 CProjKey id_alt(CProjKey::eDll,dll);
1360 depfound = (projects_tree.m_Projects.find(id_alt) !=
1361 projects_tree.m_Projects.end());
1362 }
1363 if (!depfound &&
1364 !SMakeProjectT::IsConfigurableDefine(proj_key.Id())) {
1365 error = "@echo ERROR: this project depends on missing " +
1366 CreateProjectName(proj_key);
1367 }
1368 }
1369 }
1370 }
1371
1372 // collect dependencies -----------------------------------------------------
1373 set<string> lib_guid, visited;
1374 ITERATE(list<CProjKey>, i, p->second.m_Depends) {
1375
1376 const CProjKey& id = *i;
1377 // exclude 3rd party libs
1378 if ( GetSite().IsLibWithChoice(id.Id()) ) {
1379 if ( GetSite().GetChoiceForLib(id.Id()) == CMsvcSite::e3PartyLib ) {
1380 continue;
1381 }
1382 }
1383 // exclude missing projects
1384 n = projects_tree.m_Projects.find(id);
1385 if (n == projects_tree.m_Projects.end()) {
1386 /*
1387 CProjKey id_alt(CProjKey::eDll,GetDllsInfo().GetDllHost(id.Id()));
1388 n = projects_tree.m_Projects.find(id_alt);
1389 if (n == projects_tree.m_Projects.end())
1390 */
1391 {
1392 if (!SMakeProjectT::IsConfigurableDefine(id.Id())) {
1393 PTB_WARNING_EX(kEmptyStr, ePTB_ProjectNotFound,
1394 "Project " + p->first.Id() + " depends on missing project " + id.Id());
1395 }
1396 continue;
1397 }
1398 }
1399 if (isLibrary) {
1400 CollectLibToLibDependencies(projects_tree, lib_guid, visited, p, n);
1401 continue;
1402 }
1403 dependencies.push_back(CreateProjectName(n->first));
1404 }
1405 copy(lib_guid.begin(), lib_guid.end(), back_inserter(dependencies));
1406 dependencies.sort();
1407 dependencies.unique();
1408 CProjectTreeBuilder::VerifyBuildOrder( p->second, dependencies, projects_tree);
1409
1410 if (isLibrary && !m_AllDllBuild) {
1411 list<string> new_dependencies;
1412 // new_dependencies.push_back( target + dotfiles);
1413 ITERATE(list<string>, d, dependencies) {
1414 if (*d == datatool_key) {
1415 continue;
1416 }
1417 n = projects_tree.m_Projects.find(CreateProjKey(*d));
1418 if (n != projects_tree.m_Projects.end() &&
1419 !n->second.m_DatatoolSources.empty()) {
1420 new_dependencies.push_back(*d + dotfiles);
1421 continue;
1422 }
1423 new_dependencies.push_back(*d);
1424 }
1425 dependencies = new_dependencies;
1426 }
1427
1428 // collect paths ------------------------------------------------------------
1429 if (p->first.Type() != CProjKey::eDataSpec) {
1430
1431 path_to_target[rel_path].push_back(target);
1432 if (p->second.m_MakeType != eMakeType_Excluded &&
1433 p->second.m_MakeType != eMakeType_ExcludedByReq) {
1434 string stop_path(CDirEntry::AddTrailingPathSeparator("."));
1435 string parent_path, prev_parent(rel_path);
1436 for (;;) {
1437 parent_path = ParentDir(prev_parent);
1438 // see CXX-950
1439 #if 0
1440 path_to_target[parent_path].push_back(prev_parent + ".real");
1441 #else
1442 path_to_target[parent_path].push_back(prev_parent);
1443 #endif
1444 if (parent_path == stop_path) {
1445 break;
1446 }
1447 prev_parent = parent_path;
1448 }
1449 }
1450 }
1451
1452 #if NCBI_COMPILER_MSVC
1453 rel_path = NStr::Replace(rel_path,"\\","/");
1454 #endif //NCBI_COMPILER_MSVC
1455
1456 // see CXX-950
1457 #if 0
1458 ofs << target << " : " << rel_path << "$(s)." << target << ".real";
1459 ofs << endl << endl;
1460 ofs << rel_path << "$(s)." << target << ".real" << " :" << endl
1461 << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) " << target << ".real"
1462 << " MTARGET=$(MTARGET) MARK=$(MARK)";
1463 ofs << endl << endl;
1464 ofs << target << ".real" << " :";
1465 ITERATE(list<string>, d, dependencies) {
1466 ofs << " " << *d;
1467 }
1468 ofs << endl << "\t";
1469 if (!error.empty()) {
1470 ofs << error << endl << "\t@exit 1" << endl << "\t";
1471 }
1472 ofs << "+";
1473 if (p->second.m_MakeType == eMakeType_Expendable) {
1474 ofs << "-";
1475 }
1476 ofs << "cd " << rel_path << "; $(MAKE) $(MFLAGS_NR)"
1477 << " APP_PROJ=" << target_app
1478 << " LIB_PROJ=" << target_lib
1479 << " $(MTARGET)" << endl
1480 << "\t@" << "cd " << rel_path << "; $(sign)";
1481 ofs << endl << endl;
1482 #else
1483 ofs << target << " :" << endl
1484 << "\t$(MAKE) $(MFLAGS) -f $(MINPUT) " << target << dotreal
1485 << " MTARGET=$(MTARGET)";
1486 ofs << endl << endl;
1487 ofs << target << dotreal << " :";
1488
1489 if (hasDataspec) {
1490 dataspec_dirs.insert(rel_path);
1491 }
1492 ITERATE(list<string>, d, dependencies) {
1493 if (*d == datatool_key) {
1494 dataspec_dirs.insert(rel_path);
1495 } else {
1496 ofs << " " << *d << dotreal;
1497 }
1498 }
1499 ofs << " " << rel_path << dotfiles << dotreal;
1500
1501
1502 ofs << endl << "\t";
1503 if (!error.empty()) {
1504 ofs << error << endl << "\t@exit 1" << endl << "\t";
1505 }
1506 ofs << "+";
1507 if (p->second.m_MakeType >= eMakeType_Expendable) {
1508 ofs << "-";
1509 }
1510 ofs << "cd " << rel_path << " && ";
1511 if (p->second.m_MakeType == eMakeType_Expendable) {
1512 ofs << " NCBI_BUT_EXPENDABLE=' (but expendable)'";
1513 }
1514 ofs << " $(MAKE) $(MFLAGS)"
1515 << " APP_PROJ=" << target_app
1516 << (p->second.m_IsMetallib ? " LIB_PROJ=\"\" METAL_PROJ=" : " LIB_PROJ=") << target_lib
1517 << " UNIX_PROJ=" << target_user
1518 << " $(MTARGET)";
1519 if (p->first.Type() != CProjKey::eMsvc) {
1520 ofs << " $(SKIP_PRELIMINARIES)";
1521 }
1522 ofs << endl << endl;
1523 #endif
1524 if (hasDataspec) {
1525 ofs << target << dotfiles << " :" << endl
1526 << "\t$(MAKE) $(MFLAGS) -f $(MINPUT) $(SKIP_PRELIMINARIES) "
1527 << target << dotfiles << dotreal;
1528 ofs << endl << endl;
1529 ofs << target << dotfiles << dotreal << " :";
1530 ofs << " " << rel_path << dotfiles << dotreal;
1531 ofs << endl << endl;
1532 }
1533
1534 // recommended library order
1535 if (p->first.Type() == CProjKey::eApp || p->first.Type() == CProjKey::eDll) {
1536 const list<string>& liborder = m_LibraryOrder[ p->second.m_MkName];
1537 const list<string>& lib3order = m_3PartyLibraryOrder[ p->second.m_MkName];
1538 string filename(
1539 CDirEntry::ConcatPath(solution_dir,
1540 CDirEntry::CreateRelativePath( GetProjectTreeInfo().m_Src, p->second.GetPath() + ".libdep")));
1541 if (m_LibDep && (!liborder.empty() || !lib3order.empty())) {
1542 CNcbiOfstream ofs(filename.c_str(), IOS_BASE::out | IOS_BASE::trunc);
1543 if (ofs.is_open()) {
1544 if (!liborder.empty()) {
1545 ofs << "GENERATED_LIB_ORDER = -l" << NStr::Join(liborder," -l") << endl;
1546 }
1547 if (!lib3order.empty()) {
1548 ofs << "GENERATED_LIB3PARTY_ORDER =";
1549 ITERATE( list<string>, l3, lib3order) {
1550 if (l3->empty()) {
1551 continue;
1552 }
1553 ofs << " ";
1554 if (m_Frameworks.find(*l3) != m_Frameworks.end()) {
1555 ofs << "-framework ";
1556 } else if (m_3PartyLibs.find(*l3) != m_3PartyLibs.end()) {
1557 ofs << "-l";
1558 } else if (l3->at(0) != '-' &&
1559 l3->find_first_of("$/.") == string::npos) {
1560 ofs << "-l";
1561 }
1562 ofs << *l3;
1563 }
1564 ofs << endl;
1565 }
1566 }
1567 }
1568 else {
1569 CFile(filename).Remove();
1570 }
1571 }
1572 }
1573
1574 // folder targets -----------------------------------------------------------
1575 map< string, list< string > >::const_iterator pt;
1576 for ( pt = path_to_target.begin(); pt != path_to_target.end(); ++pt) {
1577 string target(pt->first);
1578 ofs << ".PHONY : " << target << endl << endl;
1579 ofs << target << " :" << endl
1580 << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) " << target << dotreal
1581 << " MTARGET=$(MTARGET)";
1582 ofs << endl << endl;
1583 ofs << target << dotreal << " :";
1584 if (!pt->second.empty()) {
1585 list< string > tt(pt->second);
1586 tt.sort();
1587 tt.unique();
1588 // see CXX-950
1589 #if 0
1590 ofs << " " << NStr::Join( tt, " ");
1591 #else
1592 ofs << " " << NStr::Join( tt, dotreal + " ") << dotreal;
1593 #endif
1594 ofs << endl << endl;
1595 }
1596
1597 ofs << target << dotfiles << " :" << endl
1598 << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) " << target << dotfiles << dotreal
1599 << " MTARGET=$(MTARGET)";
1600 ofs << endl << endl;
1601 ofs << target << dotfiles << dotreal << " :";
1602 if (m_Dtdep && !datatool_key.empty() &&
1603 dataspec_dirs.find(target) != dataspec_dirs.end()) {
1604 ofs << " " << datatool_key << dotreal;
1605 }
1606 ofs << endl << "\t";
1607 ofs << "-";
1608 ofs << "cd " << target << " && $(MAKE) $(MFLAGS) sources";
1609 ofs << endl << endl;
1610 }
1611 }
1612
1613
CreateFeaturesAndPackagesFiles(const list<SConfigInfo> * configs,list<string> & list_enabled,list<string> & list_disabled)1614 void CProjBulderApp::CreateFeaturesAndPackagesFiles(
1615 const list<SConfigInfo>* configs,
1616 list<string>& list_enabled, list<string>& list_disabled)
1617 {
1618 PTB_INFO("Generating Features_And_Packages files...");
1619 // Create makefile path
1620 string base_path = GetProjectTreeInfo().m_Compilers;
1621 base_path = CDirEntry::ConcatPath(base_path,
1622 GetRegSettings().m_CompilersSubdir);
1623
1624 base_path = CDirEntry::ConcatPath(base_path, GetBuildType().GetTypeStr());
1625 ITERATE(list<SConfigInfo>, c , *configs) {
1626 string file_path = CDirEntry::ConcatPath(base_path, c->GetConfigFullName());
1627 CDir(file_path).CreatePath();
1628 string enabled = CDirEntry::ConcatPath(file_path,
1629 "features_and_packages.txt");
1630 string disabled = CDirEntry::ConcatPath(file_path,
1631 "features_and_packages_disabled.txt");
1632 file_path = CDirEntry::ConcatPath(file_path,
1633 "features_and_packages.txt");
1634 CNcbiOfstream ofs(enabled.c_str(), IOS_BASE::out | IOS_BASE::trunc );
1635 if ( !ofs )
1636 NCBI_THROW(CProjBulderAppException, eFileCreation, enabled);
1637 GetApp().RegisterGeneratedFile( enabled );
1638
1639 CNcbiOfstream ofsd(disabled.c_str(), IOS_BASE::out | IOS_BASE::trunc );
1640 if ( !ofsd )
1641 NCBI_THROW(CProjBulderAppException, eFileCreation, disabled);
1642 GetApp().RegisterGeneratedFile( disabled );
1643
1644 if (c->m_rtType == SConfigInfo::rtMultiThreaded) {
1645 ofs << "MT" << endl;
1646 } else if (c->m_rtType == SConfigInfo::rtMultiThreadedDebug) {
1647 ofs << "MT" << endl << "Debug" << endl;
1648 } else if (c->m_rtType == SConfigInfo::rtMultiThreadedDLL) {
1649 ofs << "MT" << endl;
1650 } else if (c->m_rtType == SConfigInfo::rtMultiThreadedDebugDLL) {
1651 ofs << "MT" << endl << "Debug" << endl;
1652 } else if (c->m_rtType == SConfigInfo::rtSingleThreaded) {
1653 } else if (c->m_rtType == SConfigInfo::rtSingleThreadedDebug) {
1654 ofs << "Debug" << endl;
1655 }
1656 if (GetBuildType().GetType() == CBuildType::eDll) {
1657 ofs << "DLL" << endl;
1658 }
1659 const set<string>& epackages =
1660 CMsvcPrjProjectContext::GetEnabledPackages(c->GetConfigFullName());
1661 ITERATE(set<string>, e, epackages) {
1662 ofs << *e << endl;
1663 list_enabled.push_back(*e);
1664 }
1665
1666 list<string> std_features;
1667 GetSite().GetStandardFeatures(std_features);
1668 ITERATE(list<string>, s, std_features) {
1669 ofs << *s << endl;
1670 list_enabled.push_back(*s);
1671 }
1672
1673 const set<string>& dpackages =
1674 CMsvcPrjProjectContext::GetDisabledPackages(c->GetConfigFullName());
1675 ITERATE(set<string>, d, dpackages) {
1676 ofsd << *d << endl;
1677 list_disabled.push_back(*d);
1678 }
1679 }
1680 list_enabled.sort();
1681 list_enabled.unique();
1682 list_disabled.sort();
1683 list_disabled.unique();
1684 }
1685
GenerateSummary(const list<SConfigInfo> configs,const list<string> & enabled,const list<string> & disabled)1686 void CProjBulderApp::GenerateSummary(const list<SConfigInfo> configs,
1687 const list<string>& enabled, const list<string>& disabled)
1688 {
1689 if (!m_ConfSrc.empty() && !m_ConfDest.empty()) {
1690 string orig_ext = CDirEntry( CDirEntry(m_ConfSrc).GetBase() ).GetExt();
1691 ITERATE(list<SConfigInfo>, p , configs) {
1692 const SConfigInfo& cfg_info = *p;
1693 string file_dst_path;
1694 file_dst_path = m_ConfDest + "." +
1695 ConfigurableFileSuffix(cfg_info.GetConfigFullName())+
1696 orig_ext;
1697 CreateConfigurableFile(m_ConfSrc, file_dst_path,
1698 cfg_info.GetConfigFullName());
1699 }
1700 }
1701
1702 string str_config;
1703 // summary
1704 SetDiagPostAllFlags(eDPF_Log);
1705 PTB_INFO("===========================================================");
1706 PTB_INFO("SOLUTION: " << m_Solution);
1707 PTB_INFO("PROJECTS: " << CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, m_Subtree));
1708 PTB_INFO("CONFIGURATIONS: " << str_config);
1709 PTB_INFO("FEATURES AND PACKAGES: ");
1710 string str_pkg = " enabled: ";
1711 ITERATE( list<string>, p, enabled) {
1712 if (str_pkg.length() > 70) {
1713 PTB_INFO(str_pkg);
1714 str_pkg = " ";
1715 }
1716 str_pkg += " ";
1717 str_pkg += *p;
1718 }
1719 if (!str_pkg.empty()) {
1720 PTB_INFO(str_pkg);
1721 }
1722 str_pkg = " disabled: ";
1723 ITERATE( list<string>, p, disabled) {
1724 if (str_pkg.length() > 70) {
1725 PTB_INFO(str_pkg);
1726 str_pkg = " ";
1727 }
1728 str_pkg += " ";
1729 str_pkg += *p;
1730 }
1731 if (!str_pkg.empty()) {
1732 PTB_INFO(str_pkg);
1733 }
1734 string str_path = GetProjectTreeInfo().m_Compilers;
1735 str_path = CDirEntry::ConcatPath(str_path,
1736 GetRegSettings().m_CompilersSubdir);
1737 str_path = CDirEntry::ConcatPath(str_path, GetBuildType().GetTypeStr());
1738
1739 PTB_INFO(" ");
1740 PTB_INFO(" If a package is present in both lists,");
1741 PTB_INFO(" it is disabled in SOME configurations only");
1742 PTB_INFO(" For details see 'features_and_packages' files in");
1743 PTB_INFO(" " << str_path << "/%ConfigurationName%");
1744 PTB_INFO("===========================================================");
1745 }
1746
CreateCheckList(const list<SConfigInfo> * configs,CProjectItemsTree & projects_tree)1747 void CProjBulderApp::CreateCheckList(const list<SConfigInfo>* configs,
1748 CProjectItemsTree& projects_tree)
1749 {
1750 PTB_INFO("Generating check.sh.list files...");
1751 string output_dir(m_Solution);
1752 if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
1753 string::size_type n = output_dir.find_last_of('.');
1754 if (n != string::npos) {
1755 output_dir = output_dir.substr(0,n);
1756 }
1757 }
1758 output_dir += ".check";
1759 ITERATE(list<SConfigInfo>, c , *configs) {
1760 string cfg(c->GetConfigFullName());
1761 string file_path = CDirEntry::ConcatPath(output_dir, cfg);
1762 CDir dir(file_path);
1763 if (!dir.Exists()) {
1764 dir.CreatePath();
1765 }
1766 file_path = CDirEntry::ConcatPath(file_path, "check.sh.list");
1767 CNcbiOfstream ofs(file_path.c_str(), IOS_BASE::out | IOS_BASE::trunc );
1768 if ( !ofs )
1769 NCBI_THROW(CProjBulderAppException, eFileCreation, file_path);
1770 GetApp().RegisterGeneratedFile( file_path );
1771 list<string> all_cmd;
1772 ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
1773 const CProjItem& project = p->second;
1774 if (project.m_MakeType == eMakeType_Excluded ||
1775 project.m_MakeType == eMakeType_ExcludedByReq) {
1776 continue;
1777 }
1778 if (project.m_CheckConfigs.find(cfg) != project.m_CheckConfigs.end()) {
1779 ITERATE( list<string>, cmd, project.m_CheckInfo) {
1780 all_cmd.push_back(*cmd);
1781 }
1782 } else if (!project.m_CheckInfo.empty()) {
1783 PTB_INFO("Project: " << p->first.Id() << ": CHECK_CMD disabled in " << cfg);
1784 }
1785 }
1786 all_cmd.sort();
1787 all_cmd.unique();
1788 ITERATE(list<string>, cmd, all_cmd) {
1789 ofs << *cmd << endl;
1790 }
1791 }
1792 }
1793
ReportGeneratedFiles(void)1794 void CProjBulderApp::ReportGeneratedFiles(void)
1795 {
1796 m_GeneratedFiles.sort();
1797 string file_path( m_Solution + "_generated_files.txt");
1798 string sep;
1799 sep += CDirEntry::GetPathSeparator();
1800 string root(m_Root);
1801 if (!CDirEntry::IsAbsolutePath(root)) {
1802 root = CDirEntry::ConcatPath(CDir::GetCwd(), root);
1803 }
1804 CNcbiOfstream ofs(file_path.c_str(), IOS_BASE::out | IOS_BASE::trunc );
1805 if (ofs.is_open()) {
1806 ITERATE( list<string>, f, m_GeneratedFiles) {
1807 string path(*f);
1808 if (!CDirEntry::IsAbsolutePath(path)) {
1809 path = CDirEntry::ConcatPath(CDir::GetCwd(), path);
1810 }
1811 path = CDirEntry::CreateRelativePath(root, path);
1812 ofs << NStr::ReplaceInPlace( path, sep, "/") << endl;
1813 }
1814 }
1815 }
1816
ReportProjectWatchers(void)1817 void CProjBulderApp::ReportProjectWatchers(void)
1818 {
1819 m_ProjWatchers.sort();
1820 string file_path( m_Solution + "_watchers.txt");
1821 CNcbiOfstream ofs(file_path.c_str(), IOS_BASE::out | IOS_BASE::trunc );
1822 if (ofs.is_open()) {
1823 ITERATE( list<string>, f, m_ProjWatchers) {
1824 ofs << *f << endl;
1825 }
1826 }
1827 }
1828
Exit(void)1829 void CProjBulderApp::Exit(void)
1830 {
1831 }
1832
1833
ParseArguments(void)1834 void CProjBulderApp::ParseArguments(void)
1835 {
1836 const CArgs& args = GetArgs();
1837 string root;
1838 bool extroot = false;
1839 bool argfile = false;
1840 string argsfile;
1841
1842 if ( args["args"] ) {
1843 argsfile = args["args"].AsString();
1844 if (CDirEntry(argsfile).Exists()) {
1845 argfile = true;
1846 m_CustomConfiguration.LoadFrom(argsfile,&m_CustomConfiguration);
1847 } else {
1848 NCBI_THROW(CProjBulderAppException, eFileOpen,
1849 argsfile + " not found");
1850 }
1851 }
1852
1853 root = args["root"].AsString();
1854 if (root == "\"\"") {
1855 root = "";
1856 }
1857 if (argfile && root.empty()) {
1858 m_CustomConfiguration.GetPathValue("__arg_root", root);
1859 }
1860 m_Root = CDirEntry::IsAbsolutePath(root) ?
1861 root : CDirEntry::ConcatPath( CDir::GetCwd(), root);
1862 m_Root = CDirEntry::AddTrailingPathSeparator(m_Root);
1863 m_Root = CDirEntry::NormalizePath(m_Root);
1864 m_Root = CDirEntry::AddTrailingPathSeparator(m_Root);
1865
1866 m_Subtree = args["subtree"].AsString();
1867 if (m_Subtree == "\"\"") {
1868 m_Subtree = "";
1869 }
1870 if (CDirEntry::IsAbsolutePath(m_Subtree)) {
1871 m_Subtree = CDirEntry::NormalizePath(
1872 CDirEntry::CreateRelativePath(m_Root, m_Subtree));
1873 }
1874 m_Solution = CDirEntry::NormalizePath(args["solution"].AsString());
1875 if (m_Solution == "\"\"") {
1876 m_Solution = "";
1877 }
1878 if (!m_Solution.empty() && !CDirEntry::IsAbsolutePath(m_Solution)) {
1879 m_Solution = CDirEntry::ConcatPath( CDir::GetCwd(), m_Solution);
1880 }
1881
1882 if (argfile) {
1883 string v;
1884 if (GetConfigPath().empty() &&
1885 m_CustomConfiguration.GetPathValue("__arg_conffile", v)) {
1886 if (!CDirEntry::IsAbsolutePath(v)) {
1887 v = CDirEntry::ConcatPath(m_Root,v);
1888 }
1889 LoadConfig(GetRWConfig(),&v);
1890 }
1891 string subtree;
1892 m_CustomConfiguration.GetPathValue("__arg_subtree", subtree);
1893 if (m_Subtree.empty()) {
1894 m_Subtree = subtree;
1895 } else if (m_Subtree != subtree) {
1896 m_CustomConfiguration.RemoveDefinition("__AllowedProjects");
1897 }
1898 if (m_Solution.empty()) {
1899 m_CustomConfiguration.GetPathValue("__arg_solution", m_Solution);
1900 if (!CDirEntry::IsAbsolutePath(m_Solution)) {
1901 m_Solution = CDirEntry::ConcatPath(m_Root,m_Solution);
1902 }
1903 }
1904
1905 if (m_CustomConfiguration.GetValue("__arg_dll", v)) {
1906 m_Dll = NStr::StringToBool(v);
1907 }
1908 if (m_CustomConfiguration.GetValue("__arg_nobuildptb", v)) {
1909 m_BuildPtb = !NStr::StringToBool(v);
1910 }
1911
1912 if (m_CustomConfiguration.GetValue("__arg_ext", v)) {
1913 m_AddMissingLibs = NStr::StringToBool(v);
1914 }
1915 if (m_CustomConfiguration.GetValue("__arg_nws", v)) {
1916 m_ScanWholeTree = !NStr::StringToBool(v);
1917 }
1918 extroot = m_CustomConfiguration.GetPathValue("__arg_extroot", m_BuildRoot);
1919 m_CustomConfiguration.GetValue("__arg_projtag", m_ProjTags);
1920
1921 #if defined(NCBI_COMPILER_MSVC) || defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
1922 if (m_CustomConfiguration.GetValue("__arg_ide", v)) {
1923 m_Ide = NStr::StringToInt(v);
1924 }
1925 m_CustomConfiguration.GetValue("__arg_arch", m_Arch);
1926 #endif
1927
1928 if (m_CustomConfiguration.GetValue("__arg_dtdep", v)) {
1929 m_Dtdep = NStr::StringToBool(v);
1930 }
1931 if (m_CustomConfiguration.GetValue("__arg_noadddep", v)) {
1932 m_AddMissingDep = !NStr::StringToBool(v);
1933 }
1934 if (m_CustomConfiguration.GetValue("__arg_libdep", v)) {
1935 m_LibDep = NStr::StringToBool(v);
1936 }
1937 } else {
1938 m_Dll = (bool)args["dll"];
1939 m_BuildPtb = !((bool)args["nobuildptb"]);
1940 m_AddMissingLibs = (bool)args["ext"];
1941 m_ScanWholeTree = !((bool)args["nws"]);
1942 extroot = (bool)args["extroot"];
1943 if (extroot) {
1944 m_BuildRoot = args["extroot"].AsString();
1945 }
1946 if ( const CArgValue& t = args["projtag"] ) {
1947 m_ProjTags = t.AsString();
1948 m_ProjTagCmnd = true;
1949 } else {
1950 m_ProjTags = CProjectsLstFileFilter::GetAllowedTagsInfo(
1951 CDirEntry::ConcatPath(m_Root, m_Subtree));
1952 m_ProjTagCmnd = false;
1953 }
1954 #if defined(NCBI_COMPILER_MSVC) || defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
1955 const CArgValue& ide = args["ide"];
1956 if ((bool)ide) {
1957 m_Ide = ide.AsInteger();
1958 }
1959 const CArgValue& arch = args["arch"];
1960 if ((bool)arch) {
1961 m_Arch = arch.AsString();
1962 }
1963 #endif
1964 }
1965
1966 CMsvc7RegSettings::IdentifyPlatform();
1967
1968 string entry[] = {"","",""};
1969 if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
1970 entry[0] = "ThirdPartyBasePath";
1971 entry[1] = "ThirdParty_C_ncbi";
1972 }
1973 else if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode) {
1974 entry[0] = "XCode_ThirdPartyBasePath";
1975 entry[1] = "XCode_ThirdParty_C_ncbi";
1976 }
1977 if (argfile) {
1978 // this replaces path separators in entry[j] with a native one
1979 string v;
1980 for (int j=0; !entry[j].empty(); ++j) {
1981 if (m_CustomConfiguration.GetPathValue(entry[j], v)) {
1982 m_CustomConfiguration.AddDefinition(entry[j], v);
1983 }
1984 }
1985 }
1986
1987 m_ConfirmCfg = false;
1988 #if defined(NCBI_COMPILER_MSVC)
1989 m_ConfirmCfg = (bool)args["cfg"];
1990 #endif
1991 m_InteractiveCfg = (bool)args["i"];
1992 m_Dtdep = (bool)args["dtdep"];
1993 m_AddMissingDep = !((bool)args["noadddep"]);
1994 m_LibDep = args["libdep"].AsBoolean();
1995
1996 // Solution
1997 PTB_INFO("Solution: " << m_Solution);
1998 m_StatusDir =
1999 CDirEntry::NormalizePath( CDirEntry::ConcatPath( CDirEntry::ConcatPath(
2000 CDirEntry(m_Solution).GetDir(),".."),"status"));
2001 // m_BuildPtb = m_BuildPtb &&
2002 // CMsvc7RegSettings::GetMsvcVersion() == CMsvc7RegSettings::eMsvc710;
2003
2004 if ( extroot ) {
2005 if (CDirEntry(m_BuildRoot).Exists()) {
2006 // verify status dir
2007 if (!CDirEntry(m_StatusDir).Exists() && !m_BuildRoot.empty()) {
2008 m_StatusDir = CDirEntry::NormalizePath(
2009 CDirEntry::ConcatPath( CDirEntry::ConcatPath(
2010 m_BuildRoot,".."),"status"));
2011 }
2012
2013 string t, try_dir;
2014 string src = GetConfig().Get("ProjectTree", "src");
2015 for ( t = try_dir = m_BuildRoot; ; try_dir = t) {
2016 if (CDirEntry(
2017 CDirEntry::ConcatPath(try_dir, src)).Exists()) {
2018 m_ExtSrcRoot = try_dir;
2019 break;
2020 }
2021 t = CDirEntry(try_dir).GetDir();
2022 if (t == try_dir) {
2023 break;
2024 }
2025 }
2026 }
2027 }
2028 if (m_ProjTags.empty() || m_ProjTags == "\"\"" || m_ProjTags == "#") {
2029 m_ProjTags = "*";
2030 }
2031
2032 string tmp(GetConfig().Get("ProjectTree", "CustomConfiguration"));
2033 if (!tmp.empty()) {
2034 m_CustomConfFile = CDirEntry::ConcatPath( CDirEntry(m_Solution).GetDir(), tmp);
2035 }
2036 CDir sln_dir(CDirEntry(m_Solution).GetDir());
2037 if ( !sln_dir.Exists() ) {
2038 sln_dir.CreatePath();
2039 }
2040 if (!argfile) {
2041 if (CFile(m_CustomConfFile).Exists()) {
2042 m_CustomConfiguration.LoadFrom(m_CustomConfFile,&m_CustomConfiguration);
2043
2044 string subtree;
2045 m_CustomConfiguration.GetPathValue("__arg_subtree", subtree);
2046 if (m_Subtree.empty()) {
2047 m_Subtree = subtree;
2048 } else if (m_Subtree != subtree) {
2049 m_CustomConfiguration.RemoveDefinition("__AllowedProjects");
2050 }
2051 } else {
2052 if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix) {
2053 for (int j=0; !entry[j].empty(); ++j) {
2054 m_CustomConfiguration.AddDefinition(entry[j], GetSite().GetConfigureEntry(entry[j]));
2055 }
2056 }
2057 if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
2058 string vt = GetSite().IsProvided("TweakVTune", false) ? "yes" : "no";
2059 m_CustomConfiguration.AddDefinition("__TweakVTuneR", vt);
2060 m_CustomConfiguration.AddDefinition("__TweakVTuneD", vt);
2061 }
2062 }
2063
2064 string v;
2065 v = GetConfigPath();
2066 if (CDirEntry::IsAbsolutePath(v)) {
2067 try {
2068 v = CDirEntry::CreateRelativePath(m_Root, v);
2069 } catch (CFileException&) {
2070 }
2071 }
2072 m_CustomConfiguration.AddDefinition("__arg_conffile", v);
2073
2074 m_CustomConfiguration.AddDefinition("__arg_root", root);
2075 m_CustomConfiguration.AddDefinition("__arg_subtree", m_Subtree);
2076 v = m_Solution;
2077 if (CDirEntry::IsAbsolutePath(v)) {
2078 try {
2079 v = CDirEntry::CreateRelativePath(m_Root, v);
2080 } catch (CFileException&) {
2081 }
2082 }
2083 m_CustomConfiguration.AddDefinition("__arg_solution", v);
2084
2085 m_CustomConfiguration.AddDefinition("__arg_dll", m_Dll ? "yes" : "no");
2086 m_CustomConfiguration.AddDefinition("__arg_nobuildptb", m_BuildPtb ? "no" : "yes");
2087 m_CustomConfiguration.AddDefinition("__arg_ext", m_AddMissingLibs ? "yes" : "no");
2088 m_CustomConfiguration.AddDefinition("__arg_nws", m_ScanWholeTree ? "no" : "yes");
2089 m_CustomConfiguration.AddDefinition("__arg_extroot", m_BuildRoot);
2090 m_CustomConfiguration.AddDefinition("__arg_projtag", m_ProjTags);
2091
2092 #if defined(NCBI_COMPILER_MSVC) || defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
2093 m_CustomConfiguration.AddDefinition("__arg_ide", NStr::IntToString(m_Ide));
2094 m_CustomConfiguration.AddDefinition("__arg_arch", m_Arch);
2095 #endif
2096
2097 m_CustomConfiguration.AddDefinition("__arg_dtdep", m_Dtdep ? "yes" : "no");
2098 m_CustomConfiguration.AddDefinition("__arg_noadddep", m_AddMissingDep ? "no" : "yes");
2099 m_CustomConfiguration.AddDefinition("__arg_libdep", m_LibDep ? "yes" : "no");
2100
2101 // this replaces path separators in entry[j] with a native one
2102 for (int j=0; !entry[j].empty(); ++j) {
2103 if (m_CustomConfiguration.GetPathValue(entry[j], v)) {
2104 m_CustomConfiguration.AddDefinition(entry[j], v);
2105 }
2106 }
2107 }
2108 if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
2109 string v;
2110 if (m_CustomConfiguration.GetValue("__TweakVTuneR", v)) {
2111 m_TweakVTuneR = NStr::StringToBool(v);
2112 }
2113 if (m_CustomConfiguration.GetValue("__TweakVTuneD", v)) {
2114 m_TweakVTuneD = NStr::StringToBool(v);
2115 }
2116 m_AddUnicode = GetSite().IsProvided("Ncbi_Unicode", false) ||
2117 GetSite().IsProvided("Ncbi-Unicode", false);
2118 if (m_AddUnicode && !(
2119 GetSite().IsProvided("Ncbi_Unicode", false) &&
2120 GetSite().IsProvided("Ncbi-Unicode", false))) {
2121 //workaround to handle both
2122 string add;
2123 if (GetSite().IsProvided("Ncbi_Unicode", false)) {
2124 add = "Ncbi-Unicode";
2125 } else {
2126 add = "Ncbi_Unicode";
2127 }
2128 string section("__EnabledUserRequests");
2129 string value;
2130 m_CustomConfiguration.GetValue(section, value);
2131 if (!value.empty()) {
2132 value += " ";
2133 }
2134 value += add;
2135 GetApp().m_CustomConfiguration.AddDefinition(section, value);
2136 }
2137 }
2138 tmp = GetConfig().Get("Configure", "UserRequests");
2139 if (!tmp.empty()) {
2140 m_CustomConfiguration.AddDefinition("__UserRequests", tmp);
2141 } else {
2142 m_CustomConfiguration.RemoveDefinition("__UserRequests");
2143 }
2144 if ( m_MsvcRegSettings.get() ) {
2145 GetBuildConfigs(&m_MsvcRegSettings->m_ConfigInfo);
2146 }
2147 m_AbsDirs.clear();
2148 for (int j=0; !entry[j].empty(); ++j) {
2149 string v;
2150 if (m_CustomConfiguration.GetPathValue(entry[j], v)) {
2151 m_AbsDirs.push_back(v);
2152 }
2153 }
2154 }
2155
VerifyArguments(void)2156 void CProjBulderApp::VerifyArguments(void)
2157 {
2158 m_Root = CDirEntry::AddTrailingPathSeparator(m_Root);
2159 if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
2160 NStr::ToLower(m_Root);
2161 }
2162
2163 m_IncDir = GetProjectTreeInfo().m_Compilers;
2164 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
2165 m_IncDir = CDirEntry(m_Solution).GetDir();
2166 m_IncDir = CDirEntry::ConcatPath(m_IncDir,"..");
2167 } else {
2168 m_IncDir = CDirEntry::ConcatPath(m_IncDir,GetRegSettings().m_CompilersSubdir);
2169 m_IncDir = CDirEntry::ConcatPath(m_IncDir, GetBuildType().GetTypeStr());
2170 }
2171 m_IncDir = CDirEntry::ConcatPath(m_IncDir, "inc");
2172 m_IncDir = CDirEntry::ConcatPath(m_IncDir, CMsvc7RegSettings::GetConfigNameKeyword());
2173 }
2174
2175
EnumOpt(const string & enum_name,const string & enum_val) const2176 int CProjBulderApp::EnumOpt(const string& enum_name,
2177 const string& enum_val) const
2178 {
2179 int opt = GetConfig().GetInt(enum_name, enum_val, -1);
2180 if (opt == -1) {
2181 NCBI_THROW(CProjBulderAppException, eEnumValue,
2182 enum_name + "::" + enum_val);
2183 }
2184 return opt;
2185 }
2186
2187
DumpFiles(const TFiles & files,const string & filename) const2188 void CProjBulderApp::DumpFiles(const TFiles& files,
2189 const string& filename) const
2190 {
2191 CNcbiOfstream ofs(filename.c_str(), IOS_BASE::out | IOS_BASE::trunc);
2192 if ( !ofs ) {
2193 NCBI_THROW(CProjBulderAppException, eFileCreation, filename);
2194 }
2195
2196 ITERATE(TFiles, p, files) {
2197 ofs << "+++++++++++++++++++++++++\n";
2198 ofs << p->first << endl;
2199 p->second.Dump(ofs);
2200 ofs << "-------------------------\n";
2201 }
2202 }
2203
UseAbsolutePath(const string & path) const2204 bool CProjBulderApp::UseAbsolutePath(const string& path) const
2205 {
2206 ITERATE(list<string>, p, m_AbsDirs) {
2207 if (NStr::strncasecmp(path.c_str(), p->c_str(), p->length()) == 0) {
2208 return true;
2209 }
2210 }
2211 return false;
2212 }
2213
AddCustomMetaData(const string & file)2214 void CProjBulderApp::AddCustomMetaData(const string& file)
2215 {
2216 string s( CDirEntry::CreateRelativePath(GetProjectTreeInfo().m_Src, file));
2217 if ( find(m_CustomMetaData.begin(), m_CustomMetaData.end(), s) ==
2218 m_CustomMetaData.end()) {
2219 m_CustomMetaData.push_back( s );
2220 }
2221 }
2222
GetMetaDataFiles(list<string> * files) const2223 void CProjBulderApp::GetMetaDataFiles(list<string>* files) const
2224 {
2225 *files = m_CustomMetaData;
2226 if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix) {
2227 NStr::Split(GetConfig().Get("ProjectTree", "MetaData"), LIST_SEPARATOR,
2228 *files, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2229 } else {
2230 string name(GetApp().GetSite().GetConfigureEntry("MetaData"));
2231 if (!name.empty()) {
2232 files->push_back( name);
2233 }
2234 }
2235 }
2236
AddCustomConfH(const string & file)2237 void CProjBulderApp::AddCustomConfH(const string& file)
2238 {
2239 m_CustomConfH.push_back(file);
2240 }
2241
GetCustomConfH(list<string> * files) const2242 void CProjBulderApp::GetCustomConfH(list<string>* files) const
2243 {
2244 *files = m_CustomConfH;
2245 }
2246
2247
GetBuildConfigs(list<SConfigInfo> * configs)2248 void CProjBulderApp::GetBuildConfigs(list<SConfigInfo>* configs)
2249 {
2250 configs->clear();
2251 string name = m_Dll ? "DllConfigurations" : "Configurations";
2252 const string& config_str
2253 = GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), name);
2254 list<string> configs_list;
2255 NStr::Split(config_str, LIST_SEPARATOR, configs_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2256 LoadConfigInfoByNames(GetConfig(), configs_list, configs);
2257 }
2258
2259
GetRegSettings(void)2260 const CMsvc7RegSettings& CProjBulderApp::GetRegSettings(void)
2261 {
2262 if ( !m_MsvcRegSettings.get() ) {
2263 m_MsvcRegSettings.reset(new CMsvc7RegSettings());
2264
2265 string section(CMsvc7RegSettings::GetMsvcRegSection());
2266
2267 m_MsvcRegSettings->m_MakefilesExt =
2268 GetConfig().GetString(section, "MakefilesExt", "msvc");
2269
2270 m_MsvcRegSettings->m_ProjectsSubdir =
2271 GetConfig().GetString(section, "Projects", "build");
2272
2273 m_MsvcRegSettings->m_MetaMakefile = CDirEntry::ConvertToOSPath(
2274 GetConfig().Get(section, "MetaMakefile"));
2275
2276 m_MsvcRegSettings->m_DllInfo =
2277 GetConfig().Get(section, "DllInfo");
2278
2279 m_MsvcRegSettings->m_Version = NStr::Replace(
2280 GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), "Version"),
2281 "\\n", "\n");
2282
2283 m_MsvcRegSettings->m_CompilersSubdir =
2284 GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), "msvc_prj");
2285
2286 GetBuildConfigs(&m_MsvcRegSettings->m_ConfigInfo);
2287 }
2288 return *m_MsvcRegSettings;
2289 }
2290
2291
GetSite(void)2292 const CMsvcSite& CProjBulderApp::GetSite(void)
2293 {
2294 if ( !m_MsvcSite.get() ) {
2295 m_MsvcSite.reset(new CMsvcSite(GetConfigPath()));
2296 }
2297
2298 return *m_MsvcSite;
2299 }
2300
2301
GetMetaMakefile(void)2302 const CMsvcMetaMakefile& CProjBulderApp::GetMetaMakefile(void)
2303 {
2304 if ( !m_MsvcMetaMakefile.get() ) {
2305 //Metamakefile must be in RootSrc directory
2306 m_MsvcMetaMakefile.reset(new CMsvcMetaMakefile
2307 (CDirEntry::ConcatPath(GetProjectTreeInfo().m_Src,
2308 GetRegSettings().m_MetaMakefile)));
2309
2310 //Metamakefile must present and must not be empty
2311 if ( m_MsvcMetaMakefile->IsEmpty() )
2312 NCBI_THROW(CProjBulderAppException,
2313 eMetaMakefile, GetRegSettings().m_MetaMakefile);
2314 }
2315
2316 return *m_MsvcMetaMakefile;
2317 }
2318
2319
GetProjectTreeInfo(void)2320 const SProjectTreeInfo& CProjBulderApp::GetProjectTreeInfo(void)
2321 {
2322 if ( m_ProjectTreeInfo.get() )
2323 return *m_ProjectTreeInfo;
2324
2325 m_ProjectTreeInfo.reset(new SProjectTreeInfo);
2326
2327 // Root, etc.
2328 m_ProjectTreeInfo->m_Root = m_Root;
2329 PTB_INFO("Project tree root: " << m_Root);
2330
2331 // all possible project tags
2332 string tagsfile = CDirEntry::ConvertToOSPath(
2333 GetConfig().Get("ProjectTree", "ProjectTags"));
2334 if (!tagsfile.empty()) {
2335 string fileloc(CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, tagsfile));
2336 if (!CDirEntry(fileloc).Exists() && !m_ExtSrcRoot.empty()) {
2337 fileloc = CDirEntry::ConcatPath(m_ExtSrcRoot,tagsfile);
2338 }
2339 LoadProjectTags(fileloc);
2340 }
2341
2342 //dependencies
2343 list<string> depsfile;
2344 if (!FindDepGraph(m_ProjectTreeInfo->m_Root, depsfile) && !m_ExtSrcRoot.empty()) {
2345 FindDepGraph(m_ExtSrcRoot, depsfile);
2346 }
2347 if (!depsfile.empty()) {
2348 ITERATE(list<string>, d, depsfile) {
2349 PTB_INFO("Library dependencies graph: " << *d);
2350 LoadDepGraph(*d);
2351 }
2352 }
2353
2354 /// <include> branch of tree
2355 string include = GetConfig().Get("ProjectTree", "include");
2356 m_ProjectTreeInfo->m_Include =
2357 CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root,
2358 include);
2359 m_ProjectTreeInfo->m_Include =
2360 CDirEntry::AddTrailingPathSeparator(m_ProjectTreeInfo->m_Include);
2361
2362
2363 /// <src> branch of tree
2364 string src = GetConfig().Get("ProjectTree", "src");
2365 m_ProjectTreeInfo->m_Src =
2366 CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root,
2367 src);
2368 m_ProjectTreeInfo->m_Src =
2369 CDirEntry::AddTrailingPathSeparator(m_ProjectTreeInfo->m_Src);
2370
2371 // Subtree to build - projects filter
2372 string subtree = CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, m_Subtree);
2373 PTB_INFO("Project list or subtree: " << subtree);
2374 if (!CDirEntry(subtree).Exists()) {
2375 PTB_WARNING_EX(kEmptyStr, ePTB_PathNotFound, "subtree does not exist: "<< subtree);
2376 }
2377 m_ProjectTreeInfo->m_IProjectFilter.reset(
2378 new CProjectsLstFileFilter(m_ProjectTreeInfo->m_Src, subtree));
2379
2380 /// <compilers> branch of tree
2381 string compilers = GetConfig().Get("ProjectTree", "compilers");
2382 m_ProjectTreeInfo->m_Compilers =
2383 CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root,
2384 compilers);
2385 m_ProjectTreeInfo->m_Compilers =
2386 CDirEntry::AddTrailingPathSeparator
2387 (m_ProjectTreeInfo->m_Compilers);
2388
2389 /// ImplicitExcludedBranches - all subdirs will be excluded by default
2390 string implicit_exclude_str
2391 = GetConfig().Get("ProjectTree", "ImplicitExclude");
2392 list<string> implicit_exclude_list;
2393 NStr::Split(implicit_exclude_str,
2394 LIST_SEPARATOR,
2395 implicit_exclude_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2396 ITERATE(list<string>, p, implicit_exclude_list) {
2397 const string& subdir = *p;
2398 string dir = CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Src,
2399 subdir);
2400 dir = CDirEntry::AddTrailingPathSeparator(dir);
2401 m_ProjectTreeInfo->m_ImplicitExcludedAbsDirs.push_back(dir);
2402 }
2403
2404 /// <projects> branch of tree (scripts\projects)
2405 string projects = CDirEntry::ConvertToOSPath(
2406 GetConfig().Get("ProjectTree", "projects"));
2407 m_ProjectTreeInfo->m_Projects =
2408 CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root,
2409 projects);
2410 m_ProjectTreeInfo->m_Projects =
2411 CDirEntry::AddTrailingPathSeparator
2412 (m_ProjectTreeInfo->m_Compilers);
2413
2414 /// impl part if include project node
2415 m_ProjectTreeInfo->m_Impl =
2416 GetConfig().Get("ProjectTree", "impl");
2417
2418 /// Makefile in tree node
2419 m_ProjectTreeInfo->m_TreeNode =
2420 GetConfig().Get("ProjectTree", "TreeNode");
2421
2422 m_ProjectTreeInfo->m_CustomMetaData =
2423 GetConfig().Get("ProjectTree", "CustomMetaData");
2424 m_ProjectTreeInfo->m_CustomConfH =
2425 GetConfig().Get("ProjectTree", "CustomConfH");
2426
2427 return *m_ProjectTreeInfo;
2428 }
2429
2430
GetBuildType(void)2431 const CBuildType& CProjBulderApp::GetBuildType(void)
2432 {
2433 if ( !m_BuildType.get() ) {
2434 m_BuildType.reset(new CBuildType(m_Dll));
2435 }
2436 return *m_BuildType;
2437 }
2438
GetWholeTree(void)2439 const CProjectItemsTree& CProjBulderApp::GetWholeTree(void)
2440 {
2441 if ( !m_WholeTree.get() ) {
2442 m_WholeTree.reset(new CProjectItemsTree);
2443 if (m_ScanWholeTree) {
2444 m_ScanningWholeTree = true;
2445 CProjectsLstFileFilter pass_all_filter(m_ProjectTreeInfo->m_Src, m_ProjectTreeInfo->m_Src);
2446 // pass_all_filter.SetExcludePotential(false);
2447 CProjectTreeBuilder::BuildProjectTree(&pass_all_filter,
2448 GetProjectTreeInfo().m_Src,
2449 m_WholeTree.get());
2450 m_ScanningWholeTree = false;
2451 }
2452 }
2453 return *m_WholeTree;
2454 }
2455
2456
GetDllFilesDistr(void)2457 CDllSrcFilesDistr& CProjBulderApp::GetDllFilesDistr(void)
2458 {
2459 if (m_DllSrcFilesDistr.get())
2460 return *m_DllSrcFilesDistr;
2461
2462 m_DllSrcFilesDistr.reset ( new CDllSrcFilesDistr() );
2463 return *m_DllSrcFilesDistr;
2464 }
2465
GetDataspecProjId(void) const2466 string CProjBulderApp::GetDataspecProjId(void) const
2467 {
2468 return "_generate_all_objects";
2469 }
2470
GetDatatoolId(void) const2471 string CProjBulderApp::GetDatatoolId(void) const
2472 {
2473 return GetConfig().GetString("Datatool", "datatool",
2474 CMsvc7RegSettings::GetMsvcPlatform() >= CMsvc7RegSettings::eUnix ? "datatool" : "");
2475 }
2476
2477
GetDatatoolPathForApp(void) const2478 string CProjBulderApp::GetDatatoolPathForApp(void) const
2479 {
2480 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode) {
2481 return GetConfig().GetString("Datatool", "Location.xcode", "datatool");
2482 }
2483 return GetConfig().GetString("Datatool", "Location.App", "datatool.exe");
2484 }
2485
2486
GetDatatoolPathForLib(void) const2487 string CProjBulderApp::GetDatatoolPathForLib(void) const
2488 {
2489 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode) {
2490 return GetConfig().GetString("Datatool", "Location.xcode", "datatool");
2491 }
2492 return GetConfig().GetString("Datatool", "Location.Lib", "datatool.exe");
2493 }
2494
2495
GetDatatoolCommandLine(void) const2496 string CProjBulderApp::GetDatatoolCommandLine(void) const
2497 {
2498 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode) {
2499 return GetConfig().GetString("Datatool", "CommandLine.xcode", "");
2500 }
2501 return GetConfig().Get("Datatool", "CommandLine");
2502 }
2503
GetProjectTreeRoot(void) const2504 string CProjBulderApp::GetProjectTreeRoot(void) const
2505 {
2506 string path = CDirEntry::ConcatPath(
2507 m_ProjectTreeInfo->m_Compilers,
2508 m_MsvcRegSettings->m_CompilersSubdir);
2509 return CDirEntry::AddTrailingPathSeparator(path);
2510 }
2511
IsAllowedProjectTag(const CProjItem & project,const string * filter) const2512 bool CProjBulderApp::IsAllowedProjectTag(
2513 const CProjItem& project, const string* filter /*= NULL*/) const
2514 {
2515 // verify that all project tags are registered
2516 list<string>::const_iterator i;
2517 for (i = project.m_ProjTags.begin(); i != project.m_ProjTags.end(); ++i) {
2518 if (m_RegisteredProjectTags.find(*i) == m_RegisteredProjectTags.end()) {
2519 NCBI_THROW(CProjBulderAppException, eUnknownProjectTag,
2520 project.GetPath() + ": Unregistered project tag: " + *i);
2521 return false;
2522 }
2523 }
2524
2525 if (filter == NULL) {
2526 filter = &m_ProjTags;
2527 }
2528 // no filter - everything is allowed
2529 if (filter->empty() || *filter == "*") {
2530 return true;
2531 }
2532
2533 CExprParser parser;
2534 ITERATE( set<string>, p, m_RegisteredProjectTags) {
2535 parser.AddSymbol(p->c_str(),
2536 find( project.m_ProjTags.begin(), project.m_ProjTags.end(), *p) != project.m_ProjTags.end());
2537 }
2538 parser.Parse(filter->c_str());
2539 return parser.GetResult().GetBool();
2540 }
2541
LoadProjectTags(const string & filename)2542 void CProjBulderApp::LoadProjectTags(const string& filename)
2543 {
2544 CNcbiIfstream ifs(filename.c_str(), IOS_BASE::in | IOS_BASE::binary);
2545 if ( ifs.is_open() ) {
2546 string line;
2547 while ( NcbiGetlineEOL(ifs, line) ) {
2548 if (line.empty() || line[0] == '#') {
2549 continue;
2550 }
2551 list<string> values;
2552 if (line.find('=') != string::npos) {
2553 NStr::Split(line, "=", values, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2554 if (values.size() > 1) {
2555 string first = NStr::TruncateSpaces(values.front());
2556 string second = NStr::TruncateSpaces(values.back());
2557 m_CompositeProjectTags[first] = second;
2558
2559 }
2560 continue;
2561 }
2562 NStr::Split(line, LIST_SEPARATOR, values, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2563 ITERATE(list<string>,v,values) {
2564 m_RegisteredProjectTags.insert(*v);
2565 }
2566 }
2567 }
2568 m_RegisteredProjectTags.insert("exe");
2569 m_RegisteredProjectTags.insert("lib");
2570 m_RegisteredProjectTags.insert("dll");
2571 m_RegisteredProjectTags.insert("public");
2572 m_RegisteredProjectTags.insert("internal");
2573 }
2574
FindDepGraph(const string & root,list<string> & found) const2575 bool CProjBulderApp::FindDepGraph(const string& root, list<string>& found) const
2576 {
2577 found.clear();
2578 list<string> locations;
2579 string locstr(GetConfig().Get("ProjectTree", "DepGraph"));
2580 NStr::Split(locstr, LIST_SEPARATOR, locations, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2581 for (list<string>::const_iterator l = locations.begin(); l != locations.end(); ++l) {
2582 CDirEntry fileloc(CDirEntry::ConcatPath(root,CDirEntry::ConvertToOSPath(*l)));
2583 if (fileloc.Exists() && fileloc.IsFile()) {
2584 found.push_back(fileloc.GetPath());
2585 }
2586 }
2587 return !found.empty();
2588 }
2589
LoadDepGraph(const string & filename)2590 void CProjBulderApp::LoadDepGraph(const string& filename)
2591 {
2592 const CMsvcSite& site = GetSite();
2593 CNcbiIfstream ifs(filename.c_str(), IOS_BASE::in);
2594 if ( ifs.is_open() ) {
2595 string line;
2596 while ( NcbiGetlineEOL(ifs, line) ) {
2597 if (line.empty() || line[0] == '#') {
2598 continue;
2599 }
2600 list<string> values;
2601 NStr::Split(line, " ", values, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2602 if (values.size() < 2) {
2603 continue;
2604 }
2605 list<string>::const_iterator l= values.begin();
2606 string first = *l++;
2607 string second = *l++;
2608 string third = values.size() > 2 ? (*l++) : string();
2609
2610 list<string> first_list;
2611 if (CSymResolver::IsDefine(first)) {
2612 string resolved;
2613 site.ResolveDefine(CSymResolver::StripDefine(first), resolved);
2614 first = resolved;
2615 }
2616 NStr::Split(first, LIST_SEPARATOR_LIBS, first_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2617
2618 list<string> third_list;
2619 #if DO_PATCHTREEMAKEFILES
2620 if (!third.empty()) {
2621 third_list.push_back(third);
2622 }
2623 #else
2624 if (CSymResolver::IsDefine(third)) {
2625 string resolved;
2626 if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix) {
2627 string stripped(CSymResolver::StripDefine(third));
2628 if (stripped != "NCBI_C_ncbi") {
2629 site.ResolveDefine(stripped, resolved);
2630 }
2631 if (resolved.empty()) {
2632 resolved = "@" + stripped + "@";
2633 }
2634 } else {
2635 site.ResolveDefine(CSymResolver::StripDefine(third), resolved);
2636 }
2637 third = resolved;
2638 }
2639 NStr::Split(third, LIST_SEPARATOR_LIBS, third_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2640 #endif
2641 ITERATE(list<string>, f, first_list) {
2642 string f_name(*f);
2643 if (NStr::StartsWith(*f, "-l")) {
2644 f_name = f->substr(2);
2645 } else if (NStr::FindCase(*f,"-framework") != NPOS) {
2646 list<string> f_list;
2647 NStr::Split(f_name, ",", f_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2648 f_name = f_list.back();
2649 } else if (f->at(0) == '-') {
2650 continue;
2651 }
2652 map<string, set<string> > lib3Precedes;
2653 CSymResolver::StripSuffix(f_name);
2654 if (third_list.empty() && m_GraphDepPrecedes.find(f_name) == m_GraphDepPrecedes.end()) {
2655 m_GraphDepPrecedes[f_name] = set<string>();
2656 }
2657 ITERATE(list<string>, t, third_list) {
2658 string t_name(*t);
2659 CSymResolver::StripSuffix(t_name);
2660 bool is_lib = false;
2661 bool is_framework = false;
2662 if (NStr::StartsWith(*t, "-l")) {
2663 is_lib = true;
2664 t_name = t_name.substr(2);
2665 } else if (NStr::CompareNocase(*t,"-framework") == 0) {
2666 if (t != third_list.end()) {
2667 is_framework = true;
2668 t_name = *(++t);
2669 } else {
2670 continue;
2671 }
2672 } else {
2673 is_lib = t->at(0) != '-';
2674 }
2675 if (*f == t_name) {
2676 continue;
2677 }
2678 if (!is_lib && !is_framework) {
2679 if (second == "needs3party") {
2680 m_GraphDepFlags[*f].insert(t_name);
2681 }
2682 continue;
2683 }
2684 if (second == "includes") {
2685 m_GraphDepIncludes[*f].insert(t_name);
2686 } else if (second == "includes3party") {
2687 m_GraphDepIncludes[*f].insert(t_name);
2688 m_3PartyLibs.insert(t_name);
2689 if (is_framework) {
2690 m_Frameworks.insert(t_name);
2691 }
2692 } else if (second == "needs") {
2693 m_GraphDepPrecedes[*f].insert(t_name);
2694 } else if (second == "needs3party") {
2695 m_GraphDepPrecedes[*f].insert(t_name);
2696 m_3PartyLibs.insert(t_name);
2697 if (is_framework) {
2698 m_Frameworks.insert(t_name);
2699 }
2700 }
2701 }
2702 }
2703 }
2704 }
2705 for ( map<string, set<string> >::const_iterator i = m_GraphDepIncludes.begin();
2706 i != m_GraphDepIncludes.end(); ++i) {
2707 const set<string>& inc = i->second;
2708 for (set<string>::const_iterator m = inc.begin(); m != inc.end(); ++m) {
2709 CollectDep(i->first, *m);
2710 }
2711 }
2712 // RankDepGraph();
2713 }
2714
CollectDep(const string & libname,const string & incname)2715 void CProjBulderApp::CollectDep(const string& libname, const string& incname)
2716 {
2717 if (incname[0] == '@') {
2718 return;
2719 }
2720 const set<string>& deps = m_GraphDepPrecedes[incname];
2721 for (set<string>::const_iterator d = deps.begin(); d != deps.end(); ++d) {
2722 m_GraphDepPrecedes[libname].insert(*d);
2723 }
2724 if (m_GraphDepFlags.find(incname) != m_GraphDepFlags.end()) {
2725 const set<string>& flags = m_GraphDepFlags[incname];
2726 for (set<string>::const_iterator d = flags.begin(); d != flags.end(); ++d) {
2727 m_GraphDepFlags[libname].insert(*d);
2728 }
2729 }
2730 if (m_GraphDepIncludes.find(incname) != m_GraphDepIncludes.end()) {
2731 const set<string>& inc = m_GraphDepIncludes.find(incname)->second;
2732 for (set<string>::const_iterator m = inc.begin(); m != inc.end(); ++m) {
2733 CollectDep(libname, *m);
2734 }
2735 }
2736 }
2737
UpdateDepGraph(CProjectTreeBuilder::TFiles & files)2738 void CProjBulderApp::UpdateDepGraph( CProjectTreeBuilder::TFiles& files)
2739 {
2740 #if DO_PATCHTREEMAKEFILES
2741 return;
2742 #endif
2743 if (!IsScanningWholeTree()) {
2744 return;
2745 }
2746 const CMsvcSite& site = GetSite();
2747 ITERATE( CProjectTreeBuilder::TFiles, f, files) {
2748 const CSimpleMakeFileContents& fc( f->second);
2749 string libname;
2750 fc.GetValue("LIB", libname);
2751 list<string> libdep;
2752 fc.GetValue("USES_LIBRARIES", libdep);
2753 if (!libdep.empty()) {
2754 if (m_GraphDepPrecedes.find(libname) == m_GraphDepPrecedes.end()) {
2755 set<string> t;
2756 m_GraphDepPrecedes[libname] = t;
2757 }
2758 ITERATE(list<string>, l, libdep) {
2759 list<string> dep_list;
2760 string dep(*l);
2761 if (dep.at(0) == '#') {
2762 break;
2763 }
2764 if (CSymResolver::IsDefine(dep)) {
2765 string resolved;
2766 if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix) {
2767 string stripped(CSymResolver::StripDefine(dep));
2768 if (stripped != "NCBI_C_ncbi") {
2769 site.ResolveDefine(stripped, resolved);
2770 }
2771 if (resolved.empty()) {
2772 resolved = "@" + stripped + "@";
2773 }
2774 } else {
2775 site.ResolveDefine(CSymResolver::StripDefine(dep), resolved);
2776 }
2777 dep = resolved;
2778 }
2779 NStr::Split(dep, LIST_SEPARATOR_LIBS, dep_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
2780 ITERATE(list<string>, d, dep_list) {
2781 string dep_name = NStr::StartsWith(*d, "-l") ? d->substr(2) : *d;
2782 CSymResolver::StripSuffix(dep_name);
2783 if (dep_name.at(0) == '-' || libname == dep_name) {
2784 continue;
2785 }
2786 m_GraphDepPrecedes[libname].insert(dep_name);
2787 }
2788 }
2789 }
2790 }
2791 RankDepGraph();
2792 }
2793
RankDepGraph(void)2794 void CProjBulderApp::RankDepGraph(void)
2795 {
2796 #if DO_PATCHTREEMAKEFILES
2797 return;
2798 #endif
2799 if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix || !m_LibDep) {
2800 return;
2801 }
2802 vector< set<string> > graph;
2803 for (map<string, set<string> >::const_iterator d= m_GraphDepPrecedes.begin();
2804 d!= m_GraphDepPrecedes.end(); ++d) {
2805 list<string> done;
2806 done.push_back(d->first);
2807 InsertDep(graph, d->first, done);
2808 }
2809 for (size_t s= 0; s<graph.size(); ++s) {
2810 for (set<string>::const_iterator l = graph[s].begin(); l != graph[s].end(); ++l) {
2811 m_GraphDepRank[*l] = s;
2812 }
2813 }
2814 }
2815
InsertDep(vector<set<string>> & graph,const string & dep,list<string> & done)2816 bool CProjBulderApp::InsertDep(vector< set<string> >& graph, const string& dep, list<string>& done)
2817 {
2818 const set<string>& dependents = m_GraphDepPrecedes[dep];
2819 size_t graphset=0;
2820 for (set<string>::const_iterator d = dependents.begin(); d != dependents.end(); ++d) {
2821 if (m_GraphDepPrecedes.find(*d) == m_GraphDepPrecedes.end()) {
2822 continue;
2823 }
2824 if (find(done.begin(), done.end(), *d) != done.end()) {
2825 done.push_back(*d);
2826 PTB_ERROR_EX(m_Root, ePTB_ConfigurationError,
2827 "Library dependency cycle found: " << NStr::Join(done, " - "));
2828 done.pop_back();
2829 //m_GraphDepPrecedes.erase(*d);
2830 return false;
2831 }
2832 done.push_back(*d);
2833 for (bool found=false; !found; ) {
2834 for (size_t s= 0; !found && s<graph.size(); ++s) {
2835 if (graph[s].find(*d) != graph[s].end()) {
2836 graphset = max(graphset,s);
2837 found = true;
2838 }
2839 }
2840 if (!found) {
2841 found = !InsertDep(graph, *d, done);
2842 }
2843 }
2844 done.pop_back();
2845 }
2846 if (!dependents.empty()) {
2847 ++graphset;
2848 }
2849 if (graphset < graph.size()) {
2850 graph[graphset].insert(dep);
2851 } else {
2852 set<string> t;
2853 t.insert(dep);
2854 graph.push_back(t);
2855 }
2856 return true;
2857 }
2858
ProcessLocationMacros(string raw_data)2859 string CProjBulderApp::ProcessLocationMacros(string raw_data)
2860 {
2861 string data(raw_data), raw_macro, macro, definition;
2862 string::size_type start, end, done = 0;
2863 while ((start = data.find("$(", done)) != string::npos) {
2864 end = data.find(")", start);
2865 if (end == string::npos) {
2866 PTB_WARNING_EX(kEmptyStr, ePTB_MacroInvalid, "Possibly incorrect MACRO definition in: " + raw_data);
2867 return data;
2868 }
2869 raw_macro = data.substr(start,end-start+1);
2870 if (CSymResolver::IsDefine(raw_macro)) {
2871 macro = CSymResolver::StripDefine(raw_macro);
2872 definition.erase();
2873 definition = GetConfig().GetString(CMsvc7RegSettings::GetMsvcSection(), macro, "");
2874 if (!definition.empty()) {
2875 definition = CDirEntry::ConcatPath(
2876 m_ProjectTreeInfo->m_Compilers, definition);
2877 data = NStr::Replace(data, raw_macro, definition);
2878 } else {
2879 done = end;
2880 }
2881 }
2882 }
2883 return data;
2884 }
2885
GetConfigureMacro(string data)2886 string CProjBulderApp::GetConfigureMacro(string data)
2887 {
2888 string definition = GetConfig().GetString(CMsvc7RegSettings::GetMsvcSection(), data, "");
2889 if (!definition.empty()) {
2890 definition = CDirEntry::ConcatPath( m_ProjectTreeInfo->m_Compilers, definition);
2891 }
2892 return definition;
2893 }
2894
RegisterSuspiciousProject(const CProjKey & proj)2895 void CProjBulderApp::RegisterSuspiciousProject(const CProjKey& proj)
2896 {
2897 m_SuspiciousProj.insert(proj);
2898 }
2899
RegisterGeneratedFile(const string & file)2900 void CProjBulderApp::RegisterGeneratedFile( const string& file)
2901 {
2902 m_GeneratedFiles.push_back(file);
2903 }
2904
RegisterProjectWatcher(const string & project,const string & dir,const string & watcher)2905 void CProjBulderApp::RegisterProjectWatcher(
2906 const string& project, const string& dir, const string& watcher)
2907 {
2908 if (watcher.empty()) {
2909 return;
2910 }
2911 string sep;
2912 sep += CDirEntry::GetPathSeparator();
2913 string root(GetProjectTreeInfo().m_Src);
2914 if (!CDirEntry::IsAbsolutePath(root)) {
2915 root = CDirEntry::ConcatPath(CDir::GetCwd(), root);
2916 }
2917 string path(dir);
2918 if (!CDirEntry::IsAbsolutePath(path)) {
2919 path = CDirEntry::ConcatPath(CDir::GetCwd(), path);
2920 }
2921 path = CDirEntry::DeleteTrailingPathSeparator(
2922 CDirEntry::CreateRelativePath(root, path));
2923 NStr::ReplaceInPlace( path, sep, "/");
2924 m_ProjWatchers.push_back( project + ", " + path + ", " + watcher );
2925 }
2926
ExcludeProjectsByTag(CProjectItemsTree & tree) const2927 void CProjBulderApp::ExcludeProjectsByTag(CProjectItemsTree& tree) const
2928 {
2929 EraseIf(tree.m_Projects, PIsExcludedByTag());
2930 if (!m_ProjTags.empty() && m_ProjTags != "*") {
2931 NON_CONST_ITERATE(CProjectItemsTree::TProjects, p, tree.m_Projects) {
2932 if (p->second.m_ProjType == CProjKey::eDll) {
2933 p->second.m_External = false;
2934 }
2935 }
2936 }
2937 }
2938
ExcludeUnrequestedProjects(CProjectItemsTree & tree) const2939 void CProjBulderApp::ExcludeUnrequestedProjects(CProjectItemsTree& tree) const
2940 {
2941 EraseIf(tree.m_Projects, PIsExcludedByUser());
2942 }
2943
GetUtilityProjectsDir(void) const2944 string CProjBulderApp::GetUtilityProjectsDir(void) const
2945 {
2946 string utility_projects_dir = CDirEntry(m_Solution).GetDir();
2947 utility_projects_dir =
2948 CDirEntry::ConcatPath(utility_projects_dir, "UtilityProjects");
2949 utility_projects_dir =
2950 CDirEntry::AddTrailingPathSeparator(utility_projects_dir);
2951 return utility_projects_dir;
2952 }
2953
GetUtilityProjectsSrcDir(void)2954 string CProjBulderApp::GetUtilityProjectsSrcDir(void)
2955 {
2956 string prj = GetProjectTreeInfo().m_Compilers;
2957 prj = CDirEntry::ConcatPath(prj, GetRegSettings().m_CompilersSubdir);
2958 prj = CDirEntry::ConcatPath(prj, GetBuildType().GetTypeStr());
2959 prj = CDirEntry::ConcatPath(prj, GetRegSettings().m_ProjectsSubdir);
2960
2961 string sln = CDirEntry(m_Solution).GetDir();
2962 prj = CDirEntry::CreateRelativePath( prj, sln);
2963 prj = CDirEntry::ConcatPath(GetProjectTreeInfo().m_Src, prj);
2964 prj = CDirEntry::ConcatPath(prj, "UtilityProjects");
2965 prj = CDirEntry::AddTrailingPathSeparator(prj);
2966 return prj;
2967 }
2968
SetConfFileData(const string & src,const string & dest)2969 void CProjBulderApp::SetConfFileData(const string& src, const string& dest)
2970 {
2971 m_ConfSrc = src;
2972 m_ConfDest= dest;
2973 }
2974
GetBuildDir(void)2975 string CProjBulderApp::GetBuildDir(void)
2976 {
2977 return CDirEntry::AddTrailingPathSeparator(
2978 CDirEntry::ConcatPath( CDirEntry::ConcatPath( CDirEntry::ConcatPath(
2979 GetProjectTreeInfo().m_Compilers, GetRegSettings().m_CompilersSubdir),
2980 GetBuildType().GetTypeStr()), GetRegSettings().m_ProjectsSubdir));
2981 }
2982
GetApp(void)2983 CProjBulderApp& GetApp(void)
2984 {
2985 static CProjBulderApp theApp;
2986 return theApp;
2987 }
2988
2989 END_NCBI_SCOPE
2990
2991
2992 USING_NCBI_SCOPE;
2993
NcbiSys_main(int argc,TXChar * argv[])2994 int NcbiSys_main(int argc, TXChar* argv[])
2995 {
2996 // Execute main application function
2997 CDiagContext::SetLogTruncate(true);
2998 GetDiagContext().SetLogRate_Limit(CDiagContext::eLogRate_Err, (unsigned int)-1);
2999 return GetApp().AppMain(argc, argv);
3000 }
3001