NCBI C++ ToolKit
proj_builder_app.cpp
Go to the documentation of this file.
00001 /* $Id: proj_builder_app.cpp 54358 2012-05-10 13:36:48Z gouriano $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Author:  Viatcheslav Gorelenkov
00027  *
00028  */
00029 
00030 #include <ncbi_pch.hpp>
00031 #include "proj_builder_app.hpp"
00032 #include "proj_item.hpp"
00033 #include "proj_tree_builder.hpp"
00034 #include "msvc_prj_utils.hpp"
00035 #include "msvc_prj_generator.hpp"
00036 #include "mac_prj_generator.hpp"
00037 #include "msvc_sln_generator.hpp"
00038 #include "msvc_masterproject_generator.hpp"
00039 #include "proj_utils.hpp"
00040 #include "msvc_configure.hpp"
00041 #include "msvc_prj_defines.hpp"
00042 #include "msvc_configure_prj_generator.hpp"
00043 #include "proj_projects.hpp"
00044 #include "configurable_file.hpp"
00045 #include "ptb_err_codes.hpp"
00046 #include <corelib/ncbitime.hpp>
00047 #include <corelib/expr.hpp>
00048 
00049 #include <common/test_assert.h>  /* This header must go last */
00050 
00051 
00052 BEGIN_NCBI_SCOPE
00053 
00054 
00055 /////////////////////////////////////////////////////////////////////////////
00056 ///
00057 /// Windows-specific command-line logger
00058 /// This is used to format error output in such a way that the Windows error
00059 /// logger can pick this up
00060 
00061 class CWindowsCmdErrorHandler : public CDiagHandler
00062 {
00063 public:
00064     
00065     CWindowsCmdErrorHandler()
00066     {
00067         m_OrigHandler.reset(GetDiagHandler(true));
00068         CNcbiApplication* app = CNcbiApplication::Instance();
00069         if (app) {
00070             m_AppName = app->GetProgramDisplayName();
00071         } else {
00072             m_AppName = "unknown_app";
00073         }
00074     }
00075 
00076     ~CWindowsCmdErrorHandler()
00077     {
00078     }
00079 
00080     /// post a message
00081     void Post(const SDiagMessage& msg)
00082     {
00083         if (m_OrigHandler.get()) {
00084             m_OrigHandler->Post(msg);
00085         }
00086 
00087         CTempString str(msg.m_Buffer, msg.m_BufferLen);
00088         if (!msg.m_Buffer) {
00089             str.assign(kEmptyStr.c_str(),0);
00090         }
00091 
00092         /// screen for error message level data only
00093         /// MSVC doesn't handle the other parts
00094         switch (msg.m_Severity) {
00095         case eDiag_Error:
00096         case eDiag_Critical:
00097         case eDiag_Fatal:
00098         case eDiag_Warning:
00099             break;
00100 
00101         case eDiag_Info:
00102         case eDiag_Trace:
00103             if (msg.m_ErrCode == ePTB_NoError) {
00104                 /// simple pass-through to stderr
00105                 if (strlen(msg.m_File) != 0) {
00106                     cerr << msg.m_File << ": ";
00107                 }
00108                 cerr << str << endl;
00109                 return;
00110             }
00111             break;
00112         }
00113 
00114         /// REQUIRED: origin
00115         if (strlen(msg.m_File) == 0) {
00116             cerr << m_AppName;
00117         } else {
00118             cerr << msg.m_File;
00119         }
00120         if (msg.m_Line) {
00121             cerr << "(" << msg.m_Line << ")";
00122         }
00123         cerr << ": ";
00124 
00125         /// OPTIONAL: subcategory
00126         //cerr << m_AppName << " ";
00127 
00128         /// REQUIRED: category
00129         /// the MSVC system understands only 'error' and 'warning'
00130         switch (msg.m_Severity) {
00131         case eDiag_Error:
00132         case eDiag_Critical:
00133         case eDiag_Fatal:
00134             cerr << "error ";
00135             break;
00136 
00137         case eDiag_Warning:
00138             cerr << "warning ";
00139             break;
00140 
00141         case eDiag_Info:
00142         case eDiag_Trace:
00143             /// FIXME: find out how to get this in the messages tab
00144             cerr << "info ";
00145             break;
00146         }
00147 
00148         /// REQUIRED: error code
00149         cerr << msg.m_ErrCode << ": ";
00150 
00151         /// OPTIONAL: text
00152         cerr << str << endl;
00153     }
00154 
00155 private:
00156     auto_ptr<CDiagHandler> m_OrigHandler;
00157 
00158     /// the original diagnostics handler
00159     string        m_AppName;
00160 
00161 };
00162 
00163 /////////////////////////////////////////////////////////////////////////////
00164 
00165 
00166 // When defined, this environment variable
00167 // instructs PTB to exclude CONFIGURE, INDEX, and HIERARCHICAL VIEW
00168 // projects
00169 const char* s_ptb_skipconfig = "__PTB__SKIP__CONFIG__";
00170 
00171 #ifdef COMBINED_EXCLUDE
00172 struct PIsExcludedByProjectMakefile
00173 {
00174     typedef CProjectItemsTree::TProjects::value_type TValueType;
00175     bool operator() (const TValueType& item) const
00176     {
00177         const CProjItem& project = item.second;
00178         CMsvcPrjProjectContext prj_context(project);
00179         const list<string> implicit_exclude_dirs = 
00180             GetApp().GetProjectTreeInfo().m_ImplicitExcludedAbsDirs;
00181         ITERATE(list<string>, p, implicit_exclude_dirs) {
00182             const string& dir = *p;
00183             if ( IsSubdir(dir, project.m_SourcesBaseDir) ) {
00184                 // implicitly excluded from build
00185                 return prj_context.GetMsvcProjectMakefile().IsExcludeProject
00186                                                                         (true);
00187             }
00188         }
00189         // implicitly included to build
00190         return prj_context.GetMsvcProjectMakefile().IsExcludeProject(false);
00191     }
00192 };
00193 
00194 
00195 struct PIsExcludedMakefileIn
00196 {
00197     typedef CProjectItemsTree::TProjects::value_type TValueType;
00198 
00199     PIsExcludedMakefileIn(const string& root_src_dir)
00200         :m_RootSrcDir(CDirEntry::NormalizePath(root_src_dir))
00201     {
00202         ProcessDir(root_src_dir);
00203     }
00204 
00205     bool operator() (const TValueType& item) const
00206     {
00207         const CProjItem& project = item.second;
00208 
00209         const list<string> implicit_exclude_dirs = 
00210             GetApp().GetProjectTreeInfo().m_ImplicitExcludedAbsDirs;
00211         ITERATE(list<string>, p, implicit_exclude_dirs) {
00212             const string& dir = *p;
00213             if ( IsSubdir(dir, project.m_SourcesBaseDir) ) {
00214                 // implicitly excluded from build
00215                 return !IsExcplicitlyIncluded(project.m_SourcesBaseDir);
00216             }
00217         }
00218         return false;
00219     }
00220 
00221 private:
00222     string m_RootSrcDir;
00223 
00224     typedef map<string, AutoPtr<CPtbRegistry> > TMakefiles;
00225     TMakefiles m_Makefiles;
00226 
00227     void ProcessDir(const string& dir_name)
00228     {
00229         CDir dir(dir_name);
00230         CDir::TEntries contents = dir.GetEntries("*");
00231         ITERATE(CDir::TEntries, i, contents) {
00232             string name  = (*i)->GetName();
00233             if ( name == "."  ||  name == ".."  ||  
00234                  name == string(1,CDir::GetPathSeparator()) ) {
00235                 continue;
00236             }
00237             string path = (*i)->GetPath();
00238 
00239             if ( (*i)->IsFile()        &&
00240                 name          == "Makefile.in.msvc" ) {
00241                 m_Makefiles[path] = 
00242                     AutoPtr<CPtbRegistry>
00243                          (new CPtbRegistry(CNcbiIfstream(path.c_str(), 
00244                                             IOS_BASE::in | IOS_BASE::binary)));
00245             } 
00246             else if ( (*i)->IsDir() ) {
00247 
00248                 ProcessDir(path);
00249             }
00250         }
00251     }
00252 
00253     bool IsExcplicitlyIncluded(const string& project_base_dir) const
00254     {
00255         string dir = project_base_dir;
00256         for(;;) {
00257 
00258             if (dir == m_RootSrcDir) 
00259                 return false;
00260             string path = CDirEntry::ConcatPath(dir, "Makefile.in.msvc");
00261             TMakefiles::const_iterator p = 
00262                 m_Makefiles.find(path);
00263             if ( p != m_Makefiles.end() ) {
00264                 string val = 
00265                     (p->second)->GetString("Common", "ExcludeProject");
00266                 if (val == "FALSE")
00267                     return true;
00268             }
00269 
00270             dir = CDirEntry::ConcatPath(dir, "..");
00271             dir = CDirEntry::NormalizePath(dir);
00272         }
00273 
00274         return false;
00275     }
00276 };
00277 
00278 
00279 template <class T1, class T2, class V> class CCombine
00280 {
00281 public:
00282     CCombine(const T1& t1, const T2& t2)
00283         :m_T1(t1), m_T2(t2)
00284     {
00285     }
00286     bool operator() (const V& v) const
00287     {
00288         return m_T1(v)  &&  m_T2(v);
00289     }
00290 private:
00291     const T1 m_T1;
00292     const T2 m_T2;
00293 };
00294 #else
00295 // not def COMBINED_EXCLUDE
00296 struct PIsExcludedByProjectMakefile
00297 {
00298     typedef CProjectItemsTree::TProjects::value_type TValueType;
00299     bool operator() (const TValueType& item) const
00300     {
00301         const CProjItem& project = item.second;
00302         CMsvcPrjProjectContext prj_context(project);
00303         const list<string> implicit_exclude_dirs = 
00304             GetApp().GetProjectTreeInfo().m_ImplicitExcludedAbsDirs;
00305         ITERATE(list<string>, p, implicit_exclude_dirs) {
00306             const string& dir = *p;
00307             if ( IsSubdir(dir, project.m_SourcesBaseDir) ) {
00308                 // implicitly excluded from build
00309                 if (prj_context.GetMsvcProjectMakefile().IsExcludeProject(true)) {
00310                     LOG_POST(Warning << "Excluded:  project " << project.m_Name
00311                                 << " by ProjectTree/ImplicitExclude");
00312                     return true;
00313                 }
00314                 return false;
00315             }
00316         }
00317         // implicitly included into build
00318         if (prj_context.GetMsvcProjectMakefile().IsExcludeProject(false)) {
00319             LOG_POST(Warning << "Excluded:  project " << project.m_Name
00320                         << " by Makefile." << project.m_Name << ".*."
00321                         << GetApp().GetRegSettings().m_MakefilesExt);
00322             return true;
00323         }
00324         return false;
00325     }
00326 };
00327 
00328 #endif
00329 
00330 struct PIsExcludedByTag
00331 {
00332     typedef CProjectItemsTree::TProjects::value_type TValueType;
00333     bool operator() (const TValueType& item) const
00334     {
00335         const CProjItem& project = item.second;
00336         string unmet;
00337         if ( project.m_ProjType != CProjKey::eDataSpec && 
00338             !GetApp().IsAllowedProjectTag(project) ) {
00339             string unmet( NStr::Join(project.m_ProjTags,","));
00340             PTB_WARNING_EX(project.GetPath(), ePTB_ProjectExcluded,
00341                            "Excluded due to proj_tag; this project tags: " << unmet);
00342             return true;
00343         }
00344         return false;
00345     }
00346 };
00347 
00348 struct PIsExcludedByUser
00349 {
00350     typedef CProjectItemsTree::TProjects::value_type TValueType;
00351     bool operator() (const TValueType& item) const
00352     {
00353         const CProjItem& project = item.second;
00354         if (project.m_ProjType != CProjKey::eDll &&
00355             project.m_ProjType != CProjKey::eDataSpec &&
00356             !GetApp().m_CustomConfiguration.DoesValueContain(
00357             "__AllowedProjects",
00358             CreateProjectName(CProjKey(project.m_ProjType, project.m_ID)), true)) {
00359             PTB_WARNING_EX(project.GetPath(), ePTB_ProjectExcluded,
00360                            "Excluded by user request");
00361             return true;
00362         }
00363         return false;
00364 
00365     }
00366 };
00367 
00368 struct PIsExcludedByRequires
00369 {
00370     typedef CProjectItemsTree::TProjects::value_type TValueType;
00371     bool operator() (const TValueType& item) const
00372     {
00373         string unmet;
00374         const CProjItem& project = item.second;
00375         if ( !CMsvcPrjProjectContext::IsRequiresOk(project, &unmet) ) {
00376             PTB_WARNING_EX(project.GetPath(), ePTB_ProjectExcluded,
00377                            "Excluded due to unmet requirement: "
00378                            << unmet);
00379             return true;
00380         }
00381         return false;
00382 
00383     }
00384 };
00385 
00386 struct PIsExcludedByDisuse
00387 {
00388     typedef CProjectItemsTree::TProjects::value_type TValueType;
00389     bool operator() (const TValueType& item) const
00390     {
00391         const CProjItem& project = item.second;
00392         if (project.m_External) {
00393             PTB_WARNING_EX(project.GetPath(), ePTB_ProjectExcluded,
00394                            "Excluded unused external");
00395             return true;
00396         }
00397         return false;
00398     }
00399 };
00400 
00401 
00402 //-----------------------------------------------------------------------------
00403 CProjBulderApp::CProjBulderApp(void)
00404 {
00405     SetVersion( CVersionInfo(3,7,4) );
00406     m_ScanningWholeTree = false;
00407     m_Dll = false;
00408     m_AddMissingLibs = false;
00409     m_ScanWholeTree  = true;
00410     m_TweakVTuneR = false;
00411     m_TweakVTuneD = false;
00412     m_AddUnicode = false;
00413     m_CurrentBuildTree = 0;
00414     m_IncompleteBuildTree = 0;
00415     m_ProjTagCmnd = false;
00416     m_ConfirmCfg = false;
00417     m_AllDllBuild = false;
00418     m_InteractiveCfg = false;
00419     m_Dtdep = false;
00420     m_Ide = 0;
00421     m_ExitCode = 0;
00422 }
00423 
00424 
00425 void CProjBulderApp::Init(void)
00426 {
00427     string logfile = GetLogFile();
00428     if (CDirEntry(logfile).Exists()) {
00429         RegisterGeneratedFile(CDirEntry::NormalizePath(logfile));
00430     }
00431     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
00432         if (logfile != "STDERR") {
00433             SetDiagHandler(new CWindowsCmdErrorHandler);
00434         }
00435     }
00436     // Create command-line argument descriptions class
00437     auto_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
00438 
00439     // Specify USAGE context
00440     string context;
00441     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
00442         context = "MSVC ";
00443 /*
00444         context += CMsvc7RegSettings::GetProjectFileFormatVersion() +
00445             " (" + CMsvc7RegSettings::GetMsvcPlatformName() + ")";
00446 */
00447     } else if (CMsvc7RegSettings::GetMsvcPlatform() > CMsvc7RegSettings::eUnix) {
00448         context = "XCODE ";
00449 /*
00450         context += CMsvc7RegSettings::GetMsvcVersionName() +
00451             " (" + CMsvc7RegSettings::GetMsvcPlatformName() + ")";
00452 */
00453     } else {
00454         context = CMsvc7RegSettings::GetMsvcPlatformName();
00455     }
00456     context += " projects tree builder application";
00457     arg_desc->SetUsageContext(GetArguments().GetProgramBasename(),context);
00458 
00459     // Programm arguments:
00460 
00461     arg_desc->AddPositional("root",
00462                             "Root directory of the build tree. "\
00463                                 "This directory ends with \"c++\".",
00464                             CArgDescriptions::eString);
00465 
00466     arg_desc->AddPositional("subtree",
00467                             "Subtree, or a file with a list of subtrees to build."\
00468                             " Examples: src/corelib/ scripts/projects/ncbi_cpp.lst",
00469                             CArgDescriptions::eString);
00470 
00471     arg_desc->AddPositional("solution", 
00472                             "MSVC Solution to build.",
00473                             CArgDescriptions::eString);
00474 
00475     arg_desc->AddFlag      ("dll", 
00476                             "Dll(s) will be built instead of static libraries.",
00477                             true);
00478 
00479     arg_desc->AddFlag      ("nobuildptb", 
00480                             "Exclude \"build PTB\" step from CONFIGURE project.");
00481 
00482     arg_desc->AddFlag      ("ext", 
00483                             "Use external libraries instead of missing in-tree ones.");
00484     arg_desc->AddFlag      ("nws", 
00485                             "Do not scan the whole source tree for missing projects.");
00486     arg_desc->AddOptionalKey("extroot", "external_build_root",
00487                              "Subtree in which to look for external libraries.",
00488                              CArgDescriptions::eString);
00489 
00490     arg_desc->AddOptionalKey("projtag", "project_tag",
00491                              "Expression. Include only projects that match."\
00492                              " Example: \"core && (test || !demo)\"",
00493                              CArgDescriptions::eString);
00494 
00495 #if defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
00496     arg_desc->AddOptionalKey("ide", "xcode_version",
00497                              "Target version of Xcode, for example: 30",
00498                              CArgDescriptions::eInteger);
00499     arg_desc->AddOptionalKey("arch", "architecture",
00500                              "Target architecture, for example: ppc, i386",
00501                              CArgDescriptions::eString);
00502 #elif defined(NCBI_COMPILER_MSVC)
00503     arg_desc->AddOptionalKey("ide", "msvc_version",
00504                              "Target version of MS Visual Studio, for example: 800, 900, 1000",
00505                              CArgDescriptions::eInteger);
00506     arg_desc->AddOptionalKey("arch", "platform",
00507                              "Target platform, for example: Win32, x64",
00508                              CArgDescriptions::eString);
00509 #endif
00510 
00511     arg_desc->AddFlag      ("cfg", 
00512                             "Show GUI to confirm configuration parameters (MS Windows only).");
00513     arg_desc->AddFlag      ("i", 
00514                             "Run interactively. Can only be used by PTB GUI shell!");
00515     arg_desc->AddFlag      ("dtdep", 
00516                             "Add dependency on datatool where needed.");
00517 
00518     arg_desc->AddOptionalKey("args", "args_file",
00519                              "Read arguments from a file",
00520                              CArgDescriptions::eString);
00521 
00522     // Setup arg.descriptions for this application
00523     SetupArgDescriptions(arg_desc.release());
00524 }
00525 
00526 
00527 static 
00528 void s_ReportDependenciesStatus(const CCyclicDepends::TDependsCycles& cycles,
00529     CProjectItemsTree::TProjects& tree)
00530 {
00531     bool reported = false;
00532     ITERATE(CCyclicDepends::TDependsCycles, p, cycles) {
00533         const CCyclicDepends::TDependsChain& cycle = *p;
00534         bool real_cycle = false;
00535         string host0, host;
00536         ITERATE(CCyclicDepends::TDependsChain, m, cycle) {
00537             host = tree[*m].m_DllHost;
00538             if (m == cycle.begin()) {
00539                 host0 = host;
00540             } else {
00541                 real_cycle = (host0 != host) || (host0.empty() && host.empty());
00542                 if (real_cycle) {
00543                     break;
00544                 }
00545             }
00546         }
00547         if (!real_cycle) {
00548             continue;
00549         }
00550         string str_chain("Dependency cycle found: ");
00551         ITERATE(CCyclicDepends::TDependsChain, n, cycle) {
00552             const CProjKey& proj_id = *n;
00553             if (n != cycle.begin()) {
00554                 str_chain += " - ";
00555             }
00556             str_chain += proj_id.Id();
00557         }
00558         LOG_POST(Warning << str_chain);
00559         reported = true;
00560         CCyclicDepends::TDependsChain::const_iterator i = cycle.end();
00561         const CProjKey& last = *(--i);
00562         const CProjKey& prev = *(--i);
00563         if (last.Type() == CProjKey::eLib && prev.Type() == CProjKey::eLib) {
00564             CProjectItemsTree::TProjects::const_iterator t = tree.find(prev);
00565             if (t != tree.end()) {
00566                 CProjItem item = t->second;
00567                 item.m_Depends.remove(last);
00568                 tree[prev] = item;
00569                 LOG_POST(Warning << "Removing LIB dependency: "
00570                                << prev.Id() << " - " << last.Id());
00571             }
00572         }
00573     }
00574     if (!reported) {
00575         PTB_INFO("No dependency cycles found.");
00576     }
00577 }
00578 
00579 int CProjBulderApp::Run(void)
00580 {
00581     // Set error posting and tracing on maximum.
00582 //    SetDiagTrace(eDT_Enable);
00583     SetDiagPostAllFlags(eDPF_All & ~eDPF_DateTime);
00584     SetDiagPostLevel(eDiag_Info);
00585     LOG_POST(Info << "Started at " + CTime(CTime::eCurrent).AsString());
00586     LOG_POST(Info << "Project tree builder version " + GetVersion().Print());
00587 
00588     CStopWatch sw;
00589     sw.Start();
00590 
00591     // Get and check arguments
00592     ParseArguments();
00593     LOG_POST(Info << "Project tags filter: " + m_ProjTags);
00594     if (m_InteractiveCfg && !Gui_ConfirmConfiguration())
00595     {
00596         LOG_POST(Info << "Cancelled by request.");
00597         return 1;
00598     }
00599     else if (m_ConfirmCfg && !ConfirmConfiguration())
00600     {
00601         LOG_POST(Info << "Cancelled by request.");
00602         return 1;
00603     }
00604     VerifyArguments();
00605     m_CustomConfiguration.Save(m_CustomConfFile);
00606 
00607     // Configure 
00608     CMsvcConfigure configure;
00609     configure.Configure(const_cast<CMsvcSite&>(GetSite()), 
00610                         GetRegSettings().m_ConfigInfo, 
00611                         m_IncDir);
00612     m_AllDllBuild = GetSite().IsProvided("DLL_BUILD");
00613 
00614     // Build projects tree
00615 #ifndef _DEBUG
00616     {
00617         bool b = m_ScanWholeTree;
00618         m_ScanWholeTree = true;
00619         GetWholeTree();
00620         m_ScanWholeTree = b;
00621     }
00622 #endif
00623     CProjectItemsTree projects_tree(GetProjectTreeInfo().m_Src);
00624     CProjectTreeBuilder::BuildProjectTree(GetProjectTreeInfo().m_IProjectFilter.get(), 
00625                                           GetProjectTreeInfo().m_Src, 
00626                                           &projects_tree);
00627     if (m_ExitCode != 0) {
00628         LOG_POST(Info << "Cancelled by request.");
00629         return m_ExitCode;
00630     }
00631     configure.CreateConfH(const_cast<CMsvcSite&>(GetSite()), 
00632                         GetRegSettings().m_ConfigInfo, 
00633                         m_IncDir);
00634     
00635     // MSVC specific part:
00636     PTB_INFO("Checking project requirements...");
00637     // Exclude some projects from build:
00638 #ifdef COMBINED_EXCLUDE
00639     {{
00640         // Implicit/Exclicit exclude by msvc Makefiles.in.msvc
00641         // and project .msvc makefiles.
00642         PIsExcludedMakefileIn          p_make_in(GetProjectTreeInfo().m_Src);
00643         PIsExcludedByProjectMakefile   p_project_makefile;
00644         CCombine<PIsExcludedMakefileIn, 
00645                  PIsExcludedByProjectMakefile,  
00646                  CProjectItemsTree::TProjects::value_type> 
00647                                   logical_combine(p_make_in, p_project_makefile);
00648         EraseIf(projects_tree.m_Projects, logical_combine);
00649     }}
00650 #else
00651     {{
00652         // Implicit/Exclicit exclude by msvc Makefiles.in.msvc
00653         PIsExcludedByProjectMakefile   p_project_makefile;
00654         EraseIf(projects_tree.m_Projects, p_project_makefile);
00655     }}
00656 
00657 #endif
00658     {{
00659         // Project requires are not provided
00660         EraseIf(projects_tree.m_Projects, PIsExcludedByRequires());
00661     }}
00662 
00663     CProjectItemsTree dll_projects_tree;
00664     bool dll = (GetBuildType().GetType() == CBuildType::eDll);
00665     if (dll) {
00666         PTB_INFO("Assembling DLLs...");
00667 //        AnalyzeDllData(projects_tree);
00668         CreateDllBuildTree(projects_tree, &dll_projects_tree);
00669     }
00670     CProjectItemsTree& prj_tree = dll ? dll_projects_tree : projects_tree;
00671     prj_tree.VerifyExternalDepends();
00672     {{
00673         // Erase obsolete external projects
00674         EraseIf(prj_tree.m_Projects, PIsExcludedByDisuse());
00675     }}
00676     prj_tree.VerifyDataspecProj();
00677 
00678     PTB_INFO("Checking project inter-dependencies...");
00679     CCyclicDepends::TDependsCycles cycles;
00680     CCyclicDepends::FindCyclesNew(prj_tree.m_Projects, &cycles);
00681     s_ReportDependenciesStatus(cycles,projects_tree.m_Projects);
00682 
00683     if (!m_SuspiciousProj.empty()) {
00684         ITERATE( set<CProjKey>, key, m_SuspiciousProj) {
00685             if (prj_tree.m_Projects.find(*key) != prj_tree.m_Projects.end()) {
00686                 PTB_ERROR(prj_tree.m_Projects.find(*key)->second.GetPath(),
00687                     "More than one target with this name");
00688                 m_ExitCode = 1;
00689             }
00690         }
00691     }
00692     if (m_ExitCode != 0) {
00693         string subtree = CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, m_Subtree);
00694         if (CDirEntry(subtree).IsFile()) {
00695             return m_ExitCode;
00696         }
00697         m_ExitCode = 0;
00698     }
00699     PTB_INFO("Creating projects...");
00700     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
00701         GenerateMsvcProjects(prj_tree);
00702     }
00703     else if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
00704         GenerateUnixProjects(prj_tree);
00705     }
00706     else {
00707         GenerateMacProjects(prj_tree);
00708     }
00709     ReportGeneratedFiles();
00710     ReportProjectWatchers();
00711     //
00712     PTB_INFO("Done.  Elapsed time = " << sw.Elapsed() << " seconds");
00713     return m_ExitCode;
00714 }
00715 
00716 void CProjBulderApp::GenerateMsvcProjects(CProjectItemsTree& projects_tree)
00717 {
00718 #if NCBI_COMPILER_MSVC
00719     PTB_INFO("Generating MSBuild projects...");
00720 
00721     bool dll = (GetBuildType().GetType() == CBuildType::eDll);
00722     list<SConfigInfo> dll_configs;
00723     const list<SConfigInfo>* configurations = 0;
00724     bool skip_config = !GetEnvironment().Get(s_ptb_skipconfig).empty();
00725     string str_config;
00726 
00727     if (dll) {
00728         _TRACE("DLL build");
00729         GetBuildConfigs(&dll_configs);
00730         configurations = &dll_configs;
00731     } else {
00732         _TRACE("Static build");
00733         configurations = &GetRegSettings().m_ConfigInfo;
00734     }
00735     {{
00736         ITERATE(list<SConfigInfo>, p , *configurations) {
00737             str_config += p->GetConfigFullName() + " ";
00738         }
00739         PTB_INFO("Building configurations: " << str_config);
00740     }}
00741 
00742     m_CurrentBuildTree = &projects_tree;
00743     if ( m_AddMissingLibs ) {
00744         m_IncompleteBuildTree = &projects_tree;
00745     }
00746     // Projects
00747     CMsvcProjectGenerator prj_gen(*configurations);
00748     NON_CONST_ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
00749         prj_gen.Generate(p->second);
00750     }
00751 
00752     //Utility projects dir
00753     string utility_projects_dir = GetApp().GetUtilityProjectsDir();
00754 
00755     // MasterProject
00756     CMsvcMasterProjectGenerator master_prj_gen(projects_tree,
00757                                                *configurations,
00758                                                utility_projects_dir);
00759     if (!skip_config) {
00760         master_prj_gen.SaveProject();
00761     }
00762 
00763     // ConfigureProject
00764     string output_dir = GetProjectTreeInfo().m_Compilers;
00765     output_dir = CDirEntry::ConcatPath(output_dir, 
00766                                         GetRegSettings().m_CompilersSubdir);
00767     output_dir = CDirEntry::ConcatPath(output_dir, 
00768         (m_BuildPtb && dll) ? "static" : GetBuildType().GetTypeStr());
00769     output_dir = CDirEntry::ConcatPath(output_dir, "bin");
00770     output_dir = CDirEntry::AddTrailingPathSeparator(output_dir);
00771     CMsvcConfigureProjectGenerator configure_generator(
00772                                             output_dir,
00773                                             *configurations,
00774                                             dll,
00775                                             utility_projects_dir,
00776                                             GetProjectTreeInfo().m_Root,
00777                                             m_Subtree,
00778                                             m_Solution,
00779                                             m_BuildPtb);
00780     if (!skip_config) {
00781         configure_generator.SaveProject(false, &prj_gen);
00782         configure_generator.SaveProject(true, &prj_gen);
00783     }
00784 
00785     // INDEX dummy project
00786     string index_prj_path = CDirEntry::ConcatPath(utility_projects_dir, "_INDEX_");
00787     index_prj_path += CMsvc7RegSettings::GetVcprojExt();
00788     string index_prj_guid, index_prj_name;
00789     if (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000) {
00790         CVisualStudioProject xmlprj;
00791         CreateUtilityProject(" INDEX, see here: ", *configurations, &xmlprj);
00792         if (!skip_config) {
00793             SaveIfNewer(index_prj_path, xmlprj);
00794             index_prj_guid = xmlprj.GetAttlist().GetProjectGUID();
00795             index_prj_name = xmlprj.GetAttlist().GetName();
00796         }
00797     }
00798 
00799     string utils[] = {"_DATASPEC_ALL_", "-DATASPEC-ALL-",
00800                       "_LIBS_ALL_", "-LIBS-ALL-",
00801                       "_BUILD_ALL_","-BUILD-ALL-"};
00802     vector<string> utils_id;
00803     int i = 0, num_util = 3;
00804     
00805     for (i = 0; i < num_util; ++i) {
00806         string prj_path = CDirEntry::ConcatPath(utility_projects_dir, utils[i*2]);
00807         prj_path += CMsvc7RegSettings::GetVcprojExt();
00808         utils_id.push_back(prj_path);
00809         if (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000) {
00810             CVisualStudioProject xmlprj;
00811             CreateUtilityProject(utils[i*2+1], *configurations, &xmlprj);
00812             SaveIfNewer(prj_path, xmlprj);
00813             utils_id.push_back(xmlprj.GetAttlist().GetProjectGUID());
00814             utils_id.push_back(xmlprj.GetAttlist().GetName());
00815         } else {
00816             string prj_dir =  GetApp().GetUtilityProjectsSrcDir();
00817             CProjItem prj_item( CreateUtilityProjectItem(prj_dir, utils[i*2+1]));
00818             prj_gen.Generate(prj_item);
00819             utils_id.push_back(prj_item.m_GUID);
00820             utils_id.push_back(prj_item.m_Name);
00821         }
00822     }
00823     if (m_ProjTags == "*") {
00824         for (map<string,string>::const_iterator composite = m_CompositeProjectTags.begin();
00825             composite != m_CompositeProjectTags.end(); ++composite) {
00826             string composite_name = "_TAG_" + composite->first;
00827             string composite_filter = composite->second;
00828 
00829 
00830             string prj_path = CDirEntry::ConcatPath(utility_projects_dir, composite_name);
00831             prj_path += CMsvc7RegSettings::GetVcprojExt();
00832             utils_id.push_back(prj_path);
00833             if (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000) {
00834                 CVisualStudioProject xmlprj;
00835                 CreateUtilityProject(composite_name, *configurations, &xmlprj);
00836                 SaveIfNewer(prj_path, xmlprj);
00837                 utils_id.push_back(xmlprj.GetAttlist().GetProjectGUID());
00838                 utils_id.push_back(xmlprj.GetAttlist().GetName());
00839             } else {
00840                 string prj_dir =  GetApp().GetUtilityProjectsSrcDir();
00841                 CProjItem prj_item( CreateUtilityProjectItem(prj_dir, composite_name));
00842                 prj_gen.Generate(prj_item);
00843                 utils_id.push_back(prj_item.m_GUID);
00844                 utils_id.push_back(prj_item.m_Name);
00845             }
00846             utils_id.push_back(composite_filter);
00847             ++num_util;
00848         }
00849     }
00850 
00851     // Solution
00852     CMsvcSolutionGenerator sln_gen(*configurations);
00853     ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
00854         sln_gen.AddProject(p->second);
00855     }
00856     if (!skip_config) {
00857 
00858         if (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000) {
00859             sln_gen.AddUtilityProject( master_prj_gen.GetPath(),
00860                 master_prj_gen.GetVisualStudioProject().GetAttlist().GetProjectGUID(),
00861                 master_prj_gen.GetVisualStudioProject().GetAttlist().GetName());
00862 
00863             sln_gen.AddUtilityProject( index_prj_path, index_prj_guid, index_prj_name);
00864         }
00865 
00866         string cfg_path, cfg_guid, cfg_name;
00867         configure_generator.GetVisualStudioProject(cfg_path, cfg_guid, cfg_name, false);
00868         sln_gen.AddConfigureProject( cfg_path, cfg_guid, cfg_name);
00869 
00870         configure_generator.GetVisualStudioProject(cfg_path, cfg_guid, cfg_name, true);
00871         sln_gen.AddConfigureProject( cfg_path, cfg_guid, cfg_name);
00872     }
00873 
00874     int u = 0;
00875     for (i = 0; i < num_util; ++i) {
00876         switch (i) {
00877         case 0:
00878             sln_gen.AddAsnAllProject(   utils_id[u],  utils_id[u+1],  utils_id[u+2]);
00879             u += 3;
00880             break;
00881         case 1:
00882             sln_gen.AddLibsAllProject(  utils_id[u],  utils_id[u+1],  utils_id[u+2]);
00883             u += 3;
00884             break;
00885         case 2:
00886             sln_gen.AddBuildAllProject( utils_id[u],  utils_id[u+1],  utils_id[u+2]);
00887             u += 3;
00888             break;
00889         default:
00890             sln_gen.AddTagProject( utils_id[u],  utils_id[u+1],  utils_id[u+2],  utils_id[u+3]);
00891             u += 4;
00892             break;
00893         }
00894     }
00895 
00896     sln_gen.SaveSolution(m_Solution);
00897 
00898     CreateCheckList(configurations, projects_tree);
00899     list<string> enabled, disabled;
00900     CreateFeaturesAndPackagesFiles(configurations, enabled, disabled);
00901     GenerateSummary(*configurations, enabled, disabled);
00902 #endif //NCBI_COMPILER_MSVC
00903 }
00904 
00905 void CProjBulderApp::GenerateMacProjects(CProjectItemsTree& projects_tree)
00906 {
00907 #if defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
00908     PTB_INFO("Generating XCode projects...");
00909 
00910     bool dll = (GetBuildType().GetType() == CBuildType::eDll);
00911     list<SConfigInfo> dll_configs;
00912     const list<SConfigInfo>* configurations = 0;
00913 //    bool skip_config = !GetEnvironment().Get(s_ptb_skipconfig).empty();
00914     string str_config;
00915 
00916     if (dll) {
00917         _TRACE("DLL build");
00918         GetBuildConfigs(&dll_configs);
00919         configurations = &dll_configs;
00920     } else {
00921         _TRACE("Static build");
00922         configurations = &GetRegSettings().m_ConfigInfo;
00923     }
00924     {{
00925         ITERATE(list<SConfigInfo>, p , *configurations) {
00926             str_config += p->GetConfigFullName() + " ";
00927         }
00928         PTB_INFO("Building configurations: " << str_config);
00929     }}
00930 
00931     m_CurrentBuildTree = &projects_tree;
00932     if ( m_AddMissingLibs ) {
00933         m_IncompleteBuildTree = &projects_tree;
00934     }
00935     // Projects
00936     CMacProjectGenerator prj_gen(*configurations, projects_tree);
00937     prj_gen.Generate(m_Solution);
00938 
00939     CreateCheckList(configurations, projects_tree);
00940     list<string> enabled, disabled;
00941     CreateFeaturesAndPackagesFiles(configurations, enabled, disabled);
00942     GenerateSummary(*configurations, enabled, disabled);
00943 #endif
00944 }
00945 void CProjBulderApp::CollectLibToLibDependencies(
00946     CProjectItemsTree& projects_tree,
00947     set<string>& dep, set<string>& visited,
00948     CProjectItemsTree::TProjects::const_iterator& lib,
00949     CProjectItemsTree::TProjects::const_iterator& lib_dep)
00950 {
00951     string lib_name(CreateProjectName(lib->first));
00952     string lib_dep_name(CreateProjectName(lib_dep->first));
00953     if (m_AllDllBuild) {
00954         dep.insert(lib_dep_name);
00955 //        return;
00956     }
00957     if (visited.find(lib_dep_name) != visited.end() ||
00958         lib_dep_name == lib_name) {
00959         return;
00960     }
00961     visited.insert(lib_dep_name);
00962     if (!lib_dep->second.m_DatatoolSources.empty() ||
00963         !lib_dep->second.m_ExportHeaders.empty() ||
00964         lib->second.m_UnconditionalDepends.find(lib_dep->first) !=
00965             lib->second.m_UnconditionalDepends.end()) {
00966         dep.insert(lib_dep_name);
00967     }
00968     ITERATE(list<CProjKey>, p, lib_dep->second.m_Depends) {
00969         if (p->Type() == CProjKey::eLib) {
00970             CProjectItemsTree::TProjects::const_iterator n =
00971                 projects_tree.m_Projects.find(*p);
00972             if (n != projects_tree.m_Projects.end()) {
00973                 CollectLibToLibDependencies(projects_tree, dep, visited, lib, n);
00974             }
00975         }
00976     }
00977 }
00978 
00979 void CProjBulderApp::GenerateUnixProjects(CProjectItemsTree& projects_tree)
00980 {
00981     map< string, list< string > > path_to_target;
00982     CNcbiOfstream ofs(m_Solution.c_str(), IOS_BASE::out | IOS_BASE::trunc);
00983     if (!ofs.is_open()) {
00984         NCBI_THROW(CProjBulderAppException, eFileOpen, m_Solution);
00985         return;
00986     }
00987     GetApp().RegisterGeneratedFile( m_Solution );
00988     ofs << "# This file was generated by PROJECT_TREE_BUILDER v"
00989         <<  GetVersion().Print() << endl;
00990     ofs << "# on " << CTime(CTime::eCurrent).AsString() << endl << endl;
00991 
00992 // see CXX-950
00993 #if 0
00994     ofs << "# This is tricky part; it might work incorrectly on some platforms" << endl;
00995 //    ofs << "MARK=$(shell date +%Y%m%d%H%M%S)" << endl;
00996     ofs << "MARK=$(if $(MARK2),,$(eval MARK2=$(shell date +%Y%m%d%H%M%S)))$(MARK2)" << endl;
00997     ofs << "MARK:sh =date +%Y%m%d%H%M%S" << endl;
00998     ofs << endl;
00999     ofs << "prefix=.ncbi.signal." << endl;
01000     ofs << "s=$(prefix)$(MARK)" << endl;
01001     ofs << "sign=rm -f $(prefix)*.$@; touch $(s).$@" << endl;
01002     ofs << endl;
01003 #endif
01004 
01005     ofs << "MINPUT=" << CDirEntry(m_Solution).GetName() << endl << endl;
01006     ofs << "# Use empty MTARGET to build a project;" << endl;
01007     ofs << "# MTARGET=clean - to clean, or MTARGET=purge - to purge" << endl;
01008     ofs << "MTARGET =" << endl << endl;
01009 
01010     if (m_ExtSrcRoot.empty()) {
01011        ofs << "top_srcdir=" << m_Root << endl;
01012     } else {
01013         ofs << "top_srcdir=" << m_ExtSrcRoot << endl;
01014     }
01015     ofs << "# Non-redundant flags (will be overridden for GNU Make to avoid" << endl;
01016     ofs << "# --jobserver-fds=* proliferation)" << endl;
01017     ofs << "MFLAGS_NR = $(MFLAGS)" << endl;
01018     ofs << "SKIP_PRELIMINARIES= sources= configurables=configurables.null" << endl;
01019 
01020 // all dirs -----------------------------------------------------------------
01021     list<string> all_dirs;
01022     ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01023         if (p->first.Type() == CProjKey::eDataSpec) {
01024             continue;
01025         }
01026         all_dirs.push_back(
01027             CDirEntry::DeleteTrailingPathSeparator( CDirEntry::CreateRelativePath(
01028                 GetProjectTreeInfo().m_Src,p->second.m_SourcesBaseDir)));
01029     }
01030     all_dirs.sort();
01031     all_dirs.unique();
01032     ofs << "all_dirs =";
01033     ITERATE(list<string>, p, all_dirs) {
01034         ofs << " \\" <<endl << "    " << *p;
01035     }
01036     ofs << endl << endl;
01037 
01038     ofs << "include $(top_srcdir)/src/build-system/Makefile.is_gmake" << endl;
01039     ofs << "include $(top_srcdir)/src/build-system/Makefile.meta.$(is_gmake)" << endl;
01040     ofs << endl;
01041 
01042     string dotreal(".real");
01043     string dotfiles(".files");
01044 
01045 // all projects -------------------------------------------------------------
01046     ofs << "all_projects =";
01047     ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01048         if (p->second.m_MakeType == eMakeType_Excluded ||
01049             p->second.m_MakeType == eMakeType_ExcludedByReq) {
01050             LOG_POST(Info << "For reference only: " << CreateProjectName(p->first));
01051             continue;
01052         }
01053         if (p->first.Type() == CProjKey::eDataSpec) {
01054             continue;
01055         }
01056         ofs << " \\" <<endl << "    " << CreateProjectName(p->first);
01057     }
01058     ofs << endl << endl;
01059 
01060     ofs << "ptb_all :" << endl
01061         << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) ptb_all" << dotreal
01062         << " MTARGET=$(MTARGET)";
01063     ofs << endl << endl;
01064     ofs << "ptb_all" << dotreal << " :" << " $(all_projects:%=%" << dotreal << ")";
01065     ofs << endl << endl;
01066 
01067 // all libs -----------------------------------------------------------------
01068     ofs << "all_libraries =";
01069     ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01070         if (p->second.m_MakeType == eMakeType_Excluded ||
01071             p->second.m_MakeType == eMakeType_ExcludedByReq) {
01072             continue;
01073         }
01074         if (p->first.Type() == CProjKey::eLib ||
01075             p->first.Type() == CProjKey::eDll) {
01076             ofs << " \\" <<endl << "    " << CreateProjectName(p->first);
01077         }
01078     }
01079     ofs << endl << endl;
01080 
01081     ofs << "all_libs :" << endl
01082         << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) all_libs" << dotreal
01083         << " MTARGET=$(MTARGET)";
01084     ofs << endl << endl;
01085     ofs << "all_libs" << dotreal << " :" << " $(all_libraries:%=%" << dotreal << ")";
01086     ofs << endl << endl;
01087 
01088 // all sources --------------------------------------------------------------
01089     ofs << "all_dataspec =";
01090     ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01091         if (p->second.m_MakeType == eMakeType_Excluded ||
01092             p->second.m_MakeType == eMakeType_ExcludedByReq) {
01093             continue;
01094         }
01095         if (p->first.Type() == CProjKey::eDataSpec) {
01096             continue;
01097         }
01098         if (p->second.m_DatatoolSources.empty()) {
01099             continue;
01100         }
01101         ofs << " \\" <<endl << "    " << CreateProjectName(p->first) << dotfiles;
01102     }
01103     ofs << endl << endl;
01104 
01105     ofs << "all_files :" << endl
01106         << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) all_files" << dotreal;
01107     ofs << endl << endl;
01108     ofs << "all_files" << dotreal << " :" << " $(all_dataspec:%=%" << dotreal << ")";
01109     ofs << endl << endl;
01110 
01111 // all apps -----------------------------------------------------------------
01112     ofs << "all_apps =";
01113     ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01114         if (p->second.m_MakeType == eMakeType_Excluded ||
01115             p->second.m_MakeType == eMakeType_ExcludedByReq) {
01116             continue;
01117         }
01118         if (p->first.Type() == CProjKey::eApp) {
01119             ofs << " \\" <<endl << "    " << CreateProjectName(p->first);
01120         }
01121     }
01122     ofs << endl << endl;
01123 
01124 // all Unix -------------------------------------------------------------
01125     ofs << "all_unix =";
01126     ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01127         if (p->second.m_MakeType == eMakeType_Excluded ||
01128             p->second.m_MakeType == eMakeType_ExcludedByReq) {
01129             continue;
01130         }
01131         if (p->first.Type() == CProjKey::eMsvc) {
01132             ofs << " \\" <<endl << "    " << CreateProjectName(p->first);
01133         }
01134     }
01135     ofs << endl << endl;
01136 
01137 // all excluded -------------------------------------------------------------
01138     ofs << "all_excluded =";
01139     ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01140         if (p->first.Type() == CProjKey::eDataSpec) {
01141             continue;
01142         }
01143         if (p->second.m_MakeType == eMakeType_Excluded ||
01144             p->second.m_MakeType == eMakeType_ExcludedByReq) {
01145             ofs << " \\" <<endl << "    " << CreateProjectName(p->first);
01146         }
01147     }
01148     ofs << endl << endl;
01149 
01150 // CompositeProjectTags -----------------------------------------------------
01151 // (add always)
01152     vector<string> existing_composite_names;
01153     ITERATE(set<string>, r, m_RegisteredProjectTags) {
01154         m_CompositeProjectTags[*r] = *r;
01155     }
01156     /*if (m_ProjTags == "*")*/ {
01157         for (map<string,string>::const_iterator composite = m_CompositeProjectTags.begin();
01158             composite != m_CompositeProjectTags.end(); ++composite) {
01159             string composite_name = "TAG_" + composite->first;
01160             string composite_filter = composite->second;
01161             vector<string> matching;
01162 
01163             ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01164                 if (p->second.m_MakeType == eMakeType_Excluded ||
01165                     p->second.m_MakeType == eMakeType_ExcludedByReq) {
01166                     continue;
01167                 }
01168                 if (p->first.Type() == CProjKey::eDataSpec) {
01169                     continue;
01170                 }
01171                 if (IsAllowedProjectTag(p->second, &composite_filter)) {
01172                     matching.push_back( CreateProjectName(p->first));
01173                 }
01174             }
01175             if (!matching.empty()) {
01176                 existing_composite_names.push_back(composite_name);
01177                 ofs << composite_name << "_projects =";
01178                 ITERATE(vector<string>, c, matching) {
01179                     ofs << " \\" <<endl << "    " << *c;
01180                 }
01181                 ofs << endl << endl;
01182 
01183                 ofs << composite_name << " :" << endl
01184                     << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) " << composite_name << dotreal
01185                     << " MTARGET=$(MTARGET)";
01186                 ofs << endl << endl;
01187                 ofs << composite_name << dotreal << " :" << " $("
01188                     << composite_name << "_projects" << ":%=%" << dotreal << ")";
01189                 ofs << endl << endl;
01190                 
01191             }
01192         }
01193     }
01194 
01195 
01196 // help and list targets ----------------------------------------------------
01197     ofs << "help :"
01198         << endl << "\t@echo Build all projects"
01199         << endl << "\t@echo \"    make -f $(MINPUT) -j 12 ptb_all\""
01200         << endl << "\t@echo Build a project, for example, xncbi.lib"
01201         << endl << "\t@echo \"    make -f $(MINPUT) -j 12 xncbi.lib\""
01202         << endl << "\t@echo Clean project intermediate files"
01203         << endl << "\t@echo \"    make -f $(MINPUT) -j 12 xncbi.lib MTARGET=clean\""
01204         << endl << "\t@echo Clean project intermediate and output files"
01205         << endl << "\t@echo \"    make -f $(MINPUT) -j 12 xncbi.lib MTARGET=purge\""
01206         << endl << "\t@echo Target lists: "
01207         << endl << "\t@echo \"    list-all         - list all targets\""
01208         << endl << "\t@echo \"    list-apps        - list all applications\""
01209         << endl << "\t@echo \"    list-libs        - list all libraries\""
01210         << endl << "\t@echo \"    list-unix        - list all native Unix projects\""
01211         << endl << "\t@echo \"    list-excluded    - list 'excluded' targets\""
01212         << endl << "\t@echo \"    list-tags        - list composite targets\""
01213         << endl << "\t@echo \"    list-tag-TagName - list all targets in a composite target TagName\"";
01214     ofs << endl << endl;
01215 
01216     ofs << "list-all :"
01217         << endl << "\t@echo"
01218         << endl << "\t@echo"
01219         << endl << "\t@echo --------------------------------------"
01220         << endl << "\t@echo APPLICATIONS"
01221         << endl << "\t@echo"
01222         << endl << "\t@for i in $(all_apps); do echo $$i; done"
01223         << endl << "\t@echo"
01224         << endl << "\t@echo"
01225         << endl << "\t@echo --------------------------------------"
01226         << endl << "\t@echo LIBRARIES"
01227         << endl << "\t@echo"
01228         << endl << "\t@for i in $(all_libraries); do echo $$i; done";
01229 
01230     if (!existing_composite_names.empty()) {
01231        ofs 
01232             << endl << "\t@echo"
01233             << endl << "\t@echo"
01234             << endl << "\t@echo --------------------------------------"
01235             << endl << "\t@echo COMPOSITE TARGETS"
01236             << endl << "\t@echo";
01237         ITERATE(vector<string>, c, existing_composite_names) {
01238             ofs  << endl << "\t@echo " << *c;
01239         }
01240     }
01241     ofs
01242         << endl << "\t@echo"
01243         << endl << "\t@echo"
01244         << endl << "\t@echo --------------------------------------"
01245         << endl << "\t@echo DIRECTORIES"
01246         << endl << "\t@echo"
01247         << endl << "\t@for i in $(all_dirs); do echo $$i/; done";
01248     ofs << endl << endl;
01249     ofs << "list-apps :"
01250         << endl << "\t@for i in $(all_apps); do echo $$i; done";
01251     ofs << endl << endl;
01252     ofs << "list-libs :"
01253         << endl << "\t@for i in $(all_libraries); do echo $$i; done";
01254     ofs << endl << endl;
01255     ofs << "list-unix :"
01256         << endl << "\t@for i in $(all_unix); do echo $$i; done";
01257     ofs << endl << endl;
01258     ofs << "list-excluded :"
01259         << endl << "\t@for i in $(all_excluded); do echo $$i; done";
01260     ofs << endl << endl;
01261 
01262     ofs << "list-tags :";
01263     if (!existing_composite_names.empty()) {
01264         ITERATE(vector<string>, c, existing_composite_names) {
01265             ofs  << endl << "\t@echo " << *c;
01266         }
01267     }
01268     ofs << endl << endl;
01269     ITERATE(vector<string>, c, existing_composite_names) {
01270         ofs << "list-tag-" << *c << " :"
01271             << endl << "\t@for i in $(" << *c << "_projects); do echo $$i; done";
01272         ofs << endl << endl;
01273     }
01274 
01275 // --------------------------------------------------------------------------
01276     string datatool_key;
01277     string datatool( GetDatatoolId() );
01278     set<string> dataspec_dirs;
01279     if (!datatool.empty()) {
01280         CProjKey t(CProjKey::eApp, datatool);
01281         if (projects_tree.m_Projects.find(t) != projects_tree.m_Projects.end()) {
01282             datatool_key = CreateProjectName(t);
01283         }
01284     }
01285     
01286     ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01287 
01288         if (p->first.Type() == CProjKey::eDataSpec) {
01289             continue;
01290         }
01291 
01292         bool isLibrary = p->first.Type() == CProjKey::eLib;
01293         bool hasDataspec = !p->second.m_DatatoolSources.empty();
01294         string target, target_app, target_lib, target_user;
01295         list<string> dependencies;
01296         CProjectItemsTree::TProjects::const_iterator n;
01297 
01298         target = CreateProjectName(p->first);
01299         target_app = target_lib = target_user = "\"\"";
01300         if (p->first.Type() == CProjKey::eApp) {
01301             target_app = p->second.m_Name;
01302         } else if (p->first.Type() == CProjKey::eMsvc) {
01303             target_user = p->second.m_Name;
01304         } else if (p->first.Type() == CProjKey::eLib) {
01305             target_lib = p->second.m_Name;
01306         } else {
01307             target_lib = p->second.m_Name;
01308         }
01309         string rel_path = CDirEntry::CreateRelativePath(
01310             GetProjectTreeInfo().m_Src,p->second.m_SourcesBaseDir);
01311 
01312 // check for missing dependencies -------------------------------------------
01313         string error;
01314         if (p->second.m_MakeType != eMakeType_Expendable && m_BuildRoot.empty()) {
01315             ITERATE(set<CProjKey>, u, p->second.m_UnconditionalDepends) {
01316                 CProjKey proj_key = *u;
01317                 if (projects_tree.m_Projects.find(proj_key) ==
01318                     projects_tree.m_Projects.end()) {
01319                     bool depfound = false;
01320                     string dll(GetDllHost(projects_tree, proj_key.Id()));
01321                     if (!dll.empty()) {
01322                         CProjKey id_alt(CProjKey::eDll,dll);
01323                         depfound = (projects_tree.m_Projects.find(id_alt) !=
01324                             projects_tree.m_Projects.end());
01325                     }
01326                     if (!depfound &&
01327                         !SMakeProjectT::IsConfigurableDefine(proj_key.Id())) {
01328                         error = "@echo ERROR: this project depends on missing " +
01329                             CreateProjectName(proj_key);
01330                     }
01331                 }
01332             }
01333         }
01334 
01335 // collect dependencies -----------------------------------------------------
01336         set<string> lib_guid, visited;
01337         ITERATE(list<CProjKey>, i, p->second.m_Depends) {
01338 
01339             const CProjKey& id = *i;
01340             // exclude 3rd party libs
01341             if ( GetSite().IsLibWithChoice(id.Id()) ) {
01342                 if ( GetSite().GetChoiceForLib(id.Id()) == CMsvcSite::e3PartyLib ) {
01343                     continue;
01344                 }
01345             }
01346             // exclude missing projects
01347             n = projects_tree.m_Projects.find(id);
01348             if (n == projects_tree.m_Projects.end()) {
01349 /*
01350                 CProjKey id_alt(CProjKey::eDll,GetDllsInfo().GetDllHost(id.Id()));
01351                 n = projects_tree.m_Projects.find(id_alt);
01352                 if (n == projects_tree.m_Projects.end())
01353 */
01354                 {
01355                     if (!SMakeProjectT::IsConfigurableDefine(id.Id())) {
01356                         LOG_POST(Warning << "Project " + p->first.Id() + 
01357                                  " depends on missing project " + id.Id());
01358                     }
01359                     continue;
01360                 }
01361             }
01362             if (isLibrary && id.Type() == CProjKey::eLib) {
01363                 CollectLibToLibDependencies(projects_tree, lib_guid, visited, p, n);
01364                 continue;
01365             }
01366             dependencies.push_back(CreateProjectName(n->first));
01367         }
01368         copy(lib_guid.begin(), lib_guid.end(), back_inserter(dependencies));
01369         dependencies.sort();
01370         dependencies.unique();
01371         CProjectTreeBuilder::VerifyBuildOrder( p->second, dependencies, projects_tree);
01372 
01373         if (isLibrary && !m_AllDllBuild) {
01374             list<string> new_dependencies;
01375 //            new_dependencies.push_back( target + dotfiles);
01376             ITERATE(list<string>, d, dependencies) {
01377                 if (*d == datatool_key) {
01378                     continue;
01379                 }
01380                 n = projects_tree.m_Projects.find(CreateProjKey(*d));
01381                 if (n != projects_tree.m_Projects.end() &&
01382                     !n->second.m_DatatoolSources.empty()) {
01383                     new_dependencies.push_back(*d + dotfiles);
01384                     continue;
01385                 }
01386                 new_dependencies.push_back(*d);
01387             }
01388             dependencies = new_dependencies;
01389         }
01390 
01391 // collect paths ------------------------------------------------------------
01392         if (p->first.Type() != CProjKey::eDataSpec) {
01393 
01394             path_to_target[rel_path].push_back(target);
01395             if (p->second.m_MakeType != eMakeType_Excluded &&
01396                 p->second.m_MakeType != eMakeType_ExcludedByReq) {
01397                 string stop_path(CDirEntry::AddTrailingPathSeparator("."));
01398                 string parent_path, prev_parent(rel_path);
01399                 for (;;) {
01400                     parent_path = ParentDir(prev_parent);
01401 // see CXX-950
01402 #if 0
01403                     path_to_target[parent_path].push_back(prev_parent + ".real");
01404 #else
01405                     path_to_target[parent_path].push_back(prev_parent);
01406 #endif
01407                     if (parent_path == stop_path) {
01408                         break;
01409                     }
01410                     prev_parent = parent_path;
01411                 }
01412             }
01413         }
01414                                                             
01415 #if NCBI_COMPILER_MSVC
01416         rel_path = NStr::Replace(rel_path,"\\","/");
01417 #endif //NCBI_COMPILER_MSVC
01418 
01419 // see CXX-950
01420 #if 0
01421             ofs << target << " : " << rel_path << "$(s)." << target << ".real";
01422         ofs << endl << endl;
01423         ofs << rel_path << "$(s)." << target << ".real" << " :" << endl
01424             << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) " << target << ".real"
01425             << " MTARGET=$(MTARGET) MARK=$(MARK)";
01426         ofs << endl << endl;
01427         ofs << target << ".real" << " :";
01428         ITERATE(list<string>, d, dependencies) {
01429             ofs << " " << *d;
01430         }
01431         ofs << endl << "\t";
01432         if (!error.empty()) {
01433             ofs << error << endl << "\t@exit 1" << endl << "\t";
01434         }
01435         ofs << "+";
01436         if (p->second.m_MakeType == eMakeType_Expendable) {
01437             ofs << "-";
01438             }
01439         ofs << "cd " << rel_path << "; $(MAKE) $(MFLAGS_NR)"
01440             << " APP_PROJ=" << target_app
01441         << " LIB_PROJ=" << target_lib
01442         << " $(MTARGET)" << endl
01443         << "\t@" << "cd " << rel_path << "; $(sign)";
01444         ofs << endl << endl;
01445 #else
01446         ofs << target << " :" << endl
01447             << "\t$(MAKE) $(MFLAGS) -f $(MINPUT) " << target << dotreal
01448             << " MTARGET=$(MTARGET)";
01449         ofs << endl << endl;
01450         ofs << target << dotreal << " :";
01451 
01452         if (hasDataspec) {
01453             dataspec_dirs.insert(rel_path);
01454         }
01455         ITERATE(list<string>, d, dependencies) {
01456             if (*d == datatool_key) {
01457                 dataspec_dirs.insert(rel_path);
01458             } else {
01459                 ofs << " " << *d << dotreal;
01460             }
01461         }
01462         ofs << " " << rel_path << dotfiles << dotreal;
01463 
01464 
01465         ofs << endl << "\t";
01466         if (!error.empty()) {
01467             ofs << error << endl << "\t@exit 1" << endl << "\t";
01468         }
01469         ofs << "+";
01470         if (p->second.m_MakeType >= eMakeType_Expendable) {
01471             ofs << "-";
01472         }
01473         ofs << "cd " << rel_path << " && ";
01474         if (p->second.m_MakeType == eMakeType_Expendable) {
01475             ofs << " NCBI_BUT_EXPENDABLE=' (but expendable)'";
01476         }
01477         ofs << " $(MAKE) $(MFLAGS)"
01478             << " APP_PROJ=" << target_app
01479             << " LIB_PROJ=" << target_lib
01480             << " UNIX_PROJ=" << target_user
01481             << " $(MTARGET) $(SKIP_PRELIMINARIES)" << endl << endl;
01482  #endif
01483         if (hasDataspec) {
01484             ofs << target << dotfiles << " :" << endl
01485                 << "\t$(MAKE) $(MFLAGS) -f $(MINPUT) $(SKIP_PRELIMINARIES) "
01486                 << target << dotfiles << dotreal;
01487             ofs << endl << endl;
01488             ofs << target << dotfiles << dotreal << " :";
01489             ofs << " " << rel_path << dotfiles << dotreal;
01490             ofs << endl << endl;
01491         }
01492     }
01493 
01494 // folder targets -----------------------------------------------------------
01495     map< string, list< string > >::const_iterator pt;
01496     for ( pt = path_to_target.begin(); pt != path_to_target.end(); ++pt) {
01497         string target(pt->first);
01498         ofs << ".PHONY : " << target << endl << endl;
01499         ofs << target << " :" << endl
01500             << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) " << target << dotreal
01501             << " MTARGET=$(MTARGET)";
01502         ofs << endl << endl;
01503         ofs << target << dotreal << " :";
01504         if (!pt->second.empty()) {
01505             list< string > tt(pt->second);
01506             tt.sort();
01507             tt.unique();
01508 // see CXX-950
01509 #if 0
01510             ofs << " " << NStr::Join( tt, " ");
01511 #else
01512             ofs << " " << NStr::Join( tt, dotreal + " ") << dotreal;
01513 #endif
01514             ofs << endl << endl;
01515         }
01516 
01517         ofs << target << dotfiles << " :" << endl
01518             << "\t$(MAKE) $(MFLAGS_NR) -f $(MINPUT) " << target << dotfiles << dotreal
01519             << " MTARGET=$(MTARGET)";
01520         ofs << endl << endl;
01521         ofs << target << dotfiles << dotreal << " :";
01522         if (m_Dtdep && !datatool_key.empty() &&
01523             dataspec_dirs.find(target) != dataspec_dirs.end()) {
01524             ofs << " " << datatool_key << dotreal;
01525         }
01526         ofs << endl << "\t";
01527         ofs << "-";
01528         ofs << "cd " << target << " && $(MAKE) $(MFLAGS) sources";
01529         ofs << endl << endl;
01530     }
01531 }
01532 
01533 
01534 void CProjBulderApp::CreateFeaturesAndPackagesFiles(
01535     const list<SConfigInfo>* configs,
01536     list<string>& list_enabled, list<string>& list_disabled)
01537 {
01538     PTB_INFO("Generating Features_And_Packages files...");
01539     // Create makefile path
01540     string base_path = GetProjectTreeInfo().m_Compilers;
01541     base_path = CDirEntry::ConcatPath(base_path, 
01542         GetRegSettings().m_CompilersSubdir);
01543 
01544     base_path = CDirEntry::ConcatPath(base_path, GetBuildType().GetTypeStr());
01545     ITERATE(list<SConfigInfo>, c , *configs) {
01546         string file_path = CDirEntry::ConcatPath(base_path, c->GetConfigFullName());
01547         CDir(file_path).CreatePath();
01548         string enabled = CDirEntry::ConcatPath(file_path, 
01549             "features_and_packages.txt");
01550         string disabled = CDirEntry::ConcatPath(file_path, 
01551             "features_and_packages_disabled.txt");
01552         file_path = CDirEntry::ConcatPath(file_path, 
01553                                           "features_and_packages.txt");
01554         CNcbiOfstream ofs(enabled.c_str(), IOS_BASE::out | IOS_BASE::trunc );
01555         if ( !ofs )
01556             NCBI_THROW(CProjBulderAppException, eFileCreation, enabled);
01557         GetApp().RegisterGeneratedFile( enabled );
01558 
01559         CNcbiOfstream ofsd(disabled.c_str(), IOS_BASE::out | IOS_BASE::trunc );
01560         if ( !ofsd )
01561             NCBI_THROW(CProjBulderAppException, eFileCreation, disabled);
01562         GetApp().RegisterGeneratedFile( disabled );
01563 
01564         if (c->m_rtType == SConfigInfo::rtMultiThreaded) {
01565             ofs << "MT" << endl;
01566         } else if (c->m_rtType == SConfigInfo::rtMultiThreadedDebug) {
01567             ofs << "MT" << endl << "Debug" << endl;
01568         } else if (c->m_rtType == SConfigInfo::rtMultiThreadedDLL) {
01569             ofs << "MT" << endl;
01570         } else if (c->m_rtType == SConfigInfo::rtMultiThreadedDebugDLL) {
01571             ofs << "MT" << endl << "Debug" << endl;
01572         } else if (c->m_rtType == SConfigInfo::rtSingleThreaded) {
01573         } else if (c->m_rtType == SConfigInfo::rtSingleThreadedDebug) {
01574             ofs << "Debug" << endl;
01575         }
01576         if (GetBuildType().GetType() == CBuildType::eDll) {
01577             ofs << "DLL" << endl;
01578         }
01579         const set<string>& epackages =
01580             CMsvcPrjProjectContext::GetEnabledPackages(c->GetConfigFullName());
01581         ITERATE(set<string>, e, epackages) {
01582             ofs << *e << endl;
01583             list_enabled.push_back(*e);
01584         }
01585 
01586         list<string> std_features;
01587         GetSite().GetStandardFeatures(std_features);
01588         ITERATE(list<string>, s, std_features) {
01589             ofs << *s << endl;
01590             list_enabled.push_back(*s);
01591         }
01592 
01593         const set<string>& dpackages =
01594             CMsvcPrjProjectContext::GetDisabledPackages(c->GetConfigFullName());
01595         ITERATE(set<string>, d, dpackages) {
01596             ofsd << *d << endl;
01597             list_disabled.push_back(*d);
01598         }
01599     }
01600     list_enabled.sort();
01601     list_enabled.unique();
01602     list_disabled.sort();
01603     list_disabled.unique();
01604 }
01605 
01606 void CProjBulderApp::GenerateSummary(const list<SConfigInfo> configs, 
01607     const list<string>& enabled, const list<string>& disabled)
01608 {
01609     if (!m_ConfSrc.empty() && !m_ConfDest.empty()) {
01610         string orig_ext = CDirEntry( CDirEntry(m_ConfSrc).GetBase() ).GetExt();
01611         ITERATE(list<SConfigInfo>, p , configs) {
01612             const SConfigInfo& cfg_info = *p;
01613             string file_dst_path;
01614             file_dst_path = m_ConfDest + "." +
01615                             ConfigurableFileSuffix(cfg_info.GetConfigFullName())+
01616                             orig_ext;
01617             CreateConfigurableFile(m_ConfSrc, file_dst_path,
01618                                    cfg_info.GetConfigFullName());
01619         }
01620     }
01621 
01622     string str_config;
01623     // summary
01624     SetDiagPostAllFlags(eDPF_Log);
01625     PTB_INFO("===========================================================");
01626     PTB_INFO("SOLUTION: " << m_Solution);
01627     PTB_INFO("PROJECTS: " << CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, m_Subtree));
01628     PTB_INFO("CONFIGURATIONS: " << str_config);
01629     PTB_INFO("FEATURES AND PACKAGES: ");
01630     string str_pkg = "     enabled: ";
01631     ITERATE( list<string>, p, enabled) {
01632         if (str_pkg.length() > 70) {
01633             PTB_INFO(str_pkg);
01634             str_pkg = "              ";
01635         }
01636         str_pkg += " ";
01637         str_pkg += *p;
01638     }
01639     if (!str_pkg.empty()) {
01640         PTB_INFO(str_pkg);
01641     }
01642     str_pkg = "    disabled: ";
01643     ITERATE( list<string>, p, disabled) {
01644         if (str_pkg.length() > 70) {
01645             PTB_INFO(str_pkg);
01646             str_pkg = "              ";
01647         }
01648         str_pkg += " ";
01649         str_pkg += *p;
01650     }
01651     if (!str_pkg.empty()) {
01652         PTB_INFO(str_pkg);
01653     }
01654     string str_path = GetProjectTreeInfo().m_Compilers;
01655     str_path = CDirEntry::ConcatPath(str_path, 
01656         GetRegSettings().m_CompilersSubdir);
01657     str_path = CDirEntry::ConcatPath(str_path, GetBuildType().GetTypeStr());
01658 
01659     PTB_INFO(" ");
01660     PTB_INFO("    If a package is present in both lists,");
01661     PTB_INFO("    it is disabled in SOME configurations only");
01662     PTB_INFO("    For details see 'features_and_packages' files in");
01663     PTB_INFO("    " << str_path << "/%ConfigurationName%");
01664     PTB_INFO("===========================================================");
01665 }
01666 
01667 void CProjBulderApp::CreateCheckList(const list<SConfigInfo>* configs,
01668     CProjectItemsTree& projects_tree)
01669 {
01670     PTB_INFO("Generating check.sh.list files...");
01671     string output_dir(m_Solution);
01672     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
01673         string::size_type n = output_dir.find_last_of('.');
01674         if (n != string::npos) {
01675             output_dir = output_dir.substr(0,n);
01676         }
01677     }
01678     output_dir += ".check";
01679     ITERATE(list<SConfigInfo>, c , *configs) {
01680         string cfg(c->GetConfigFullName());
01681         string file_path = CDirEntry::ConcatPath(output_dir, cfg);
01682         CDir dir(file_path);
01683         if (!dir.Exists()) {
01684             dir.CreatePath();
01685         }
01686         file_path = CDirEntry::ConcatPath(file_path, "check.sh.list");
01687         CNcbiOfstream ofs(file_path.c_str(), IOS_BASE::out | IOS_BASE::trunc );
01688         if ( !ofs )
01689             NCBI_THROW(CProjBulderAppException, eFileCreation, file_path);
01690         GetApp().RegisterGeneratedFile( file_path );
01691         list<string> all_cmd;
01692         ITERATE(CProjectItemsTree::TProjects, p, projects_tree.m_Projects) {
01693             const CProjItem& project = p->second;
01694             if (project.m_MakeType == eMakeType_Excluded ||
01695                 project.m_MakeType == eMakeType_ExcludedByReq) {
01696                 continue;
01697             }
01698             if (project.m_CheckConfigs.find(cfg) != project.m_CheckConfigs.end()) {
01699                 ITERATE( list<string>, cmd, project.m_CheckInfo) {
01700                     all_cmd.push_back(*cmd);
01701                 }
01702             } else if (!project.m_CheckInfo.empty()) {
01703                 PTB_INFO("Project: " << p->first.Id() << ": CHECK_CMD disabled in " << cfg);
01704             }
01705         }
01706         all_cmd.sort();
01707         all_cmd.unique();
01708         ITERATE(list<string>, cmd, all_cmd) {
01709             ofs << *cmd << endl;
01710         }
01711     }
01712 }
01713 
01714 void CProjBulderApp::ReportGeneratedFiles(void)
01715 {
01716     m_GeneratedFiles.sort();
01717     string file_path( m_Solution + "_generated_files.txt");
01718     string sep;
01719     sep += CDirEntry::GetPathSeparator();
01720     string root(m_Root);
01721     if (!CDirEntry::IsAbsolutePath(root)) {
01722         root = CDirEntry::ConcatPath(CDir::GetCwd(), root);
01723     }
01724     CNcbiOfstream ofs(file_path.c_str(), IOS_BASE::out | IOS_BASE::trunc );
01725     if (ofs.is_open()) {
01726         ITERATE( list<string>, f, m_GeneratedFiles) {
01727             string path(*f);
01728             if (!CDirEntry::IsAbsolutePath(path)) {
01729                 path = CDirEntry::ConcatPath(CDir::GetCwd(), path);
01730             }
01731             path = CDirEntry::CreateRelativePath(root, path);
01732             ofs << NStr::ReplaceInPlace( path, sep, "/") << endl;
01733         }
01734     }
01735 }
01736 
01737 void CProjBulderApp::ReportProjectWatchers(void)
01738 {
01739     m_ProjWatchers.sort();
01740     string file_path( m_Solution + "_watchers.txt");
01741     CNcbiOfstream ofs(file_path.c_str(), IOS_BASE::out | IOS_BASE::trunc );
01742     if (ofs.is_open()) {
01743         ITERATE( list<string>, f, m_ProjWatchers) {
01744             ofs << *f << endl;
01745         }
01746     }
01747 }
01748 
01749 void CProjBulderApp::Exit(void)
01750 {
01751 }
01752 
01753 
01754 void CProjBulderApp::ParseArguments(void)
01755 {
01756     const CArgs& args = GetArgs();
01757     string root;
01758     bool extroot = false;
01759     bool argfile = false;
01760     string argsfile;
01761 
01762     if ( args["args"] ) {
01763         argsfile = args["args"].AsString();
01764         if (CDirEntry(argsfile).Exists()) {
01765             argfile = true;
01766             m_CustomConfiguration.LoadFrom(argsfile,&m_CustomConfiguration);
01767         } else {
01768             NCBI_THROW(CProjBulderAppException, eFileOpen, 
01769                                     argsfile + " not found");
01770         }
01771     }
01772 
01773     root = args["root"].AsString();
01774     if (root == "\"\"") {
01775         root = "";
01776     }
01777     if (argfile && root.empty()) {
01778         m_CustomConfiguration.GetPathValue("__arg_root", root);
01779     }
01780     m_Root = CDirEntry::IsAbsolutePath(root) ? 
01781         root : CDirEntry::ConcatPath( CDir::GetCwd(), root);
01782     m_Root = CDirEntry::AddTrailingPathSeparator(m_Root);
01783     m_Root = CDirEntry::NormalizePath(m_Root);
01784     m_Root = CDirEntry::AddTrailingPathSeparator(m_Root);
01785 
01786     m_Subtree        = args["subtree"].AsString();
01787     if (m_Subtree == "\"\"") {
01788         m_Subtree = "";
01789     }
01790     if (CDirEntry::IsAbsolutePath(m_Subtree)) {
01791         m_Subtree = CDirEntry::NormalizePath(
01792                         CDirEntry::CreateRelativePath(m_Root, m_Subtree));
01793     }
01794     m_Solution       = CDirEntry::NormalizePath(args["solution"].AsString());
01795     if (m_Solution == "\"\"") {
01796         m_Solution = "";
01797     }
01798     if (!m_Solution.empty() && !CDirEntry::IsAbsolutePath(m_Solution)) {
01799         m_Solution = CDirEntry::ConcatPath( CDir::GetCwd(), m_Solution);
01800     }
01801 
01802     if (argfile) {
01803         string v;
01804         if (GetConfigPath().empty() && 
01805             m_CustomConfiguration.GetPathValue("__arg_conffile", v)) {
01806             if (!CDirEntry::IsAbsolutePath(v)) {
01807                 v = CDirEntry::ConcatPath(m_Root,v);
01808             }
01809             LoadConfig(GetConfig(),&v);
01810         }
01811         string subtree;
01812         m_CustomConfiguration.GetPathValue("__arg_subtree", subtree);
01813         if (m_Subtree.empty()) {
01814             m_Subtree = subtree;
01815         } else if (m_Subtree != subtree) {
01816             m_CustomConfiguration.RemoveDefinition("__AllowedProjects");
01817         }
01818         if (m_Solution.empty()) {
01819             m_CustomConfiguration.GetPathValue("__arg_solution", m_Solution);
01820             if (!CDirEntry::IsAbsolutePath(m_Solution)) {
01821                 m_Solution = CDirEntry::ConcatPath(m_Root,m_Solution);
01822             }
01823         }
01824 
01825         if (m_CustomConfiguration.GetValue("__arg_dll", v)) {
01826             m_Dll = NStr::StringToBool(v);
01827         }
01828         if (m_CustomConfiguration.GetValue("__arg_nobuildptb", v)) {
01829             m_BuildPtb = !NStr::StringToBool(v);
01830         }
01831 
01832         if (m_CustomConfiguration.GetValue("__arg_ext", v)) {
01833             m_AddMissingLibs = NStr::StringToBool(v);
01834         }
01835         if (m_CustomConfiguration.GetValue("__arg_nws", v)) {
01836             m_ScanWholeTree = !NStr::StringToBool(v);
01837         }
01838         extroot = m_CustomConfiguration.GetPathValue("__arg_extroot", m_BuildRoot);
01839         m_CustomConfiguration.GetValue("__arg_projtag", m_ProjTags);
01840 
01841 #if defined(NCBI_COMPILER_MSVC) || defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
01842         if (m_CustomConfiguration.GetValue("__arg_ide", v)) {
01843             m_Ide = NStr::StringToInt(v);
01844         }
01845         m_CustomConfiguration.GetValue("__arg_arch", m_Arch);
01846 #endif
01847     } else {
01848         m_Dll            =   (bool)args["dll"];
01849         m_BuildPtb       = !((bool)args["nobuildptb"]);
01850         m_AddMissingLibs =   (bool)args["ext"];
01851         m_ScanWholeTree  = !((bool)args["nws"]);
01852         extroot     = (bool)args["extroot"];
01853         if (extroot) {
01854             m_BuildRoot      = args["extroot"].AsString();
01855         }
01856         if ( const CArgValue& t = args["projtag"] ) {
01857             m_ProjTags = t.AsString();
01858             m_ProjTagCmnd = true;
01859         } else {
01860             m_ProjTags = CProjectsLstFileFilter::GetAllowedTagsInfo(
01861                 CDirEntry::ConcatPath(m_Root, m_Subtree));
01862             m_ProjTagCmnd = false;
01863         }
01864 #if defined(NCBI_COMPILER_MSVC) || defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
01865         const CArgValue& ide = args["ide"];
01866         if ((bool)ide) {
01867             m_Ide = ide.AsInteger();
01868         }
01869         const CArgValue& arch = args["arch"];
01870         if ((bool)arch) {
01871             m_Arch = arch.AsString();
01872         }
01873 #endif
01874     }
01875 
01876     CMsvc7RegSettings::IdentifyPlatform();
01877 
01878     string entry[] = {"","",""};
01879     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
01880         entry[0] = "ThirdPartyBasePath";
01881         entry[1] = "ThirdParty_C_ncbi";
01882     }
01883     else if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode) {
01884         entry[0] = "XCode_ThirdPartyBasePath";
01885         entry[1] = "XCode_ThirdParty_C_ncbi";
01886     }
01887     if (argfile) {
01888         // this replaces path separators in entry[j] with a native one
01889         string v;
01890         for (int j=0; !entry[j].empty(); ++j) {
01891             if (m_CustomConfiguration.GetPathValue(entry[j], v)) {
01892                 m_CustomConfiguration.AddDefinition(entry[j], v);
01893             }
01894         }
01895     }
01896 
01897     m_ConfirmCfg = false;
01898 #if defined(NCBI_COMPILER_MSVC)
01899     m_ConfirmCfg =   (bool)args["cfg"];
01900 #endif
01901     m_InteractiveCfg = (bool)args["i"];
01902     m_Dtdep = (bool)args["dtdep"];
01903 
01904     // Solution
01905     PTB_INFO("Solution: " << m_Solution);
01906     m_StatusDir = 
01907         CDirEntry::NormalizePath( CDirEntry::ConcatPath( CDirEntry::ConcatPath( 
01908             CDirEntry(m_Solution).GetDir(),".."),"status"));
01909 //    m_BuildPtb = m_BuildPtb &&
01910 //        CMsvc7RegSettings::GetMsvcVersion() == CMsvc7RegSettings::eMsvc710;
01911 
01912     if ( extroot ) {
01913         if (CDirEntry(m_BuildRoot).Exists()) {
01914 // verify status dir
01915             if (!CDirEntry(m_StatusDir).Exists() && !m_BuildRoot.empty()) {
01916                 m_StatusDir = CDirEntry::NormalizePath(
01917                     CDirEntry::ConcatPath( CDirEntry::ConcatPath( 
01918                         m_BuildRoot,".."),"status"));
01919             }
01920 
01921             string t, try_dir;
01922             string src = GetConfig().Get("ProjectTree", "src");
01923             for ( t = try_dir = m_BuildRoot; ; try_dir = t) {
01924                 if (CDirEntry(
01925                     CDirEntry::ConcatPath(try_dir, src)).Exists()) {
01926                     m_ExtSrcRoot = try_dir;
01927                     break;
01928                 }
01929                 t = CDirEntry(try_dir).GetDir();
01930                 if (t == try_dir) {
01931                     break;
01932                 }
01933             }
01934         }
01935     }
01936     if (m_ProjTags.empty() || m_ProjTags == "\"\"" || m_ProjTags == "#") {
01937         m_ProjTags = "*";
01938     }
01939 
01940     string tmp(GetConfig().Get("ProjectTree", "CustomConfiguration"));
01941     if (!tmp.empty()) {
01942         m_CustomConfFile = CDirEntry::ConcatPath( CDirEntry(m_Solution).GetDir(), tmp);
01943     }
01944     CDir sln_dir(CDirEntry(m_Solution).GetDir());
01945     if ( !sln_dir.Exists() ) {
01946         sln_dir.CreatePath();
01947     }
01948     if (!argfile) {
01949         if (CFile(m_CustomConfFile).Exists()) {
01950             m_CustomConfiguration.LoadFrom(m_CustomConfFile,&m_CustomConfiguration);
01951 
01952             string subtree;
01953             m_CustomConfiguration.GetPathValue("__arg_subtree", subtree);
01954             if (m_Subtree.empty()) {
01955                 m_Subtree = subtree;
01956             } else if (m_Subtree != subtree) {
01957                 m_CustomConfiguration.RemoveDefinition("__AllowedProjects");
01958             }
01959         } else {
01960             if (CMsvc7RegSettings::GetMsvcPlatform() != CMsvc7RegSettings::eUnix) {
01961                 for (int j=0; !entry[j].empty(); ++j) {
01962                     m_CustomConfiguration.AddDefinition(entry[j], GetSite().GetConfigureEntry(entry[j]));
01963                 }
01964             }
01965             if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
01966                 m_CustomConfiguration.AddDefinition("__TweakVTuneR", "no");
01967                 m_CustomConfiguration.AddDefinition("__TweakVTuneD", "no");
01968             }
01969         }
01970 
01971         string v;
01972         v = GetConfigPath();
01973         if (CDirEntry::IsAbsolutePath(v)) {
01974             try {
01975                 v = CDirEntry::CreateRelativePath(m_Root, v);
01976             } catch (CFileException&) {
01977             }
01978         }
01979         m_CustomConfiguration.AddDefinition("__arg_conffile", v);
01980 
01981         m_CustomConfiguration.AddDefinition("__arg_root", root);
01982         m_CustomConfiguration.AddDefinition("__arg_subtree", m_Subtree);
01983         v = m_Solution;
01984         if (CDirEntry::IsAbsolutePath(v)) {
01985             try {
01986                 v = CDirEntry::CreateRelativePath(m_Root, v);
01987             } catch (CFileException&) {
01988             }
01989         }
01990         m_CustomConfiguration.AddDefinition("__arg_solution", v);
01991 
01992         m_CustomConfiguration.AddDefinition("__arg_dll", m_Dll ? "yes" : "no");
01993         m_CustomConfiguration.AddDefinition("__arg_nobuildptb", m_BuildPtb ? "no" : "yes");
01994         m_CustomConfiguration.AddDefinition("__arg_ext", m_AddMissingLibs ? "yes" : "no");
01995         m_CustomConfiguration.AddDefinition("__arg_nws", m_ScanWholeTree ? "no" : "yes");
01996         m_CustomConfiguration.AddDefinition("__arg_extroot", m_BuildRoot);
01997         m_CustomConfiguration.AddDefinition("__arg_projtag", m_ProjTags);
01998 
01999 #if defined(NCBI_COMPILER_MSVC) || defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
02000         m_CustomConfiguration.AddDefinition("__arg_ide", NStr::IntToString(m_Ide));
02001         m_CustomConfiguration.AddDefinition("__arg_arch", m_Arch);
02002 #endif
02003         // this replaces path separators in entry[j] with a native one
02004         for (int j=0; !entry[j].empty(); ++j) {
02005             if (m_CustomConfiguration.GetPathValue(entry[j], v)) {
02006                 m_CustomConfiguration.AddDefinition(entry[j], v);
02007             }
02008         }
02009     }
02010     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
02011         string v;
02012         if (m_CustomConfiguration.GetValue("__TweakVTuneR", v)) {
02013             m_TweakVTuneR = NStr::StringToBool(v);
02014         }
02015         if (m_CustomConfiguration.GetValue("__TweakVTuneD", v)) {
02016             m_TweakVTuneD = NStr::StringToBool(v);
02017         }
02018         m_AddUnicode = GetSite().IsProvided("Ncbi-Unicode", false);
02019     }
02020     tmp = GetConfig().Get("Configure", "UserRequests");
02021     if (!tmp.empty()) {
02022         m_CustomConfiguration.AddDefinition("__UserRequests", tmp);
02023     } else {
02024         m_CustomConfiguration.RemoveDefinition("__UserRequests");
02025     }
02026     if ( m_MsvcRegSettings.get() ) {
02027         GetBuildConfigs(&m_MsvcRegSettings->m_ConfigInfo);
02028     }
02029     m_AbsDirs.clear();
02030     for (int j=0; !entry[j].empty(); ++j) {
02031         string v;
02032         if (m_CustomConfiguration.GetPathValue(entry[j], v)) {
02033             m_AbsDirs.push_back(v);
02034         }
02035     }
02036 }
02037 
02038 void CProjBulderApp::VerifyArguments(void)
02039 {
02040     m_Root = CDirEntry::AddTrailingPathSeparator(m_Root);
02041     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
02042         NStr::ToLower(m_Root);
02043     }
02044 
02045     m_IncDir = GetProjectTreeInfo().m_Compilers;
02046     if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
02047         m_IncDir = CDirEntry(m_Solution).GetDir();
02048         m_IncDir = CDirEntry::ConcatPath(m_IncDir,"..");
02049     } else {
02050         m_IncDir = CDirEntry::ConcatPath(m_IncDir,GetRegSettings().m_CompilersSubdir);
02051         m_IncDir = CDirEntry::ConcatPath(m_IncDir, GetBuildType().GetTypeStr());
02052     }
02053     m_IncDir = CDirEntry::ConcatPath(m_IncDir, "inc");
02054     m_IncDir = CDirEntry::ConcatPath(m_IncDir, CMsvc7RegSettings::GetConfigNameKeyword());
02055 }
02056 
02057 
02058 int CProjBulderApp::EnumOpt(const string& enum_name, 
02059                             const string& enum_val) const
02060 {
02061     int opt = GetConfig().GetInt(enum_name, enum_val, -1);
02062     if (opt == -1) {
02063         NCBI_THROW(CProjBulderAppException, eEnumValue, 
02064                                 enum_name + "::" + enum_val);
02065     }
02066     return opt;
02067 }
02068 
02069 
02070 void CProjBulderApp::DumpFiles(const TFiles& files, 
02071                                const string& filename) const
02072 {
02073     CNcbiOfstream  ofs(filename.c_str(), IOS_BASE::out | IOS_BASE::trunc);
02074     if ( !ofs ) {
02075         NCBI_THROW(CProjBulderAppException, eFileCreation, filename);
02076     }
02077 
02078     ITERATE(TFiles, p, files) {
02079         ofs << "+++++++++++++++++++++++++\n";
02080         ofs << p->first << endl;
02081         p->second.Dump(ofs);
02082         ofs << "-------------------------\n";
02083     }
02084 }
02085 
02086 bool CProjBulderApp::UseAbsolutePath(const string& path) const
02087 {
02088     ITERATE(list<string>, p, m_AbsDirs) {
02089         if (NStr::strncasecmp(path.c_str(), p->c_str(), p->length()) == 0) {
02090             return true;
02091         }
02092     }
02093     return false;
02094 }
02095 
02096 void CProjBulderApp::AddCustomMetaData(const string& file)
02097 {
02098     string s( CDirEntry::CreateRelativePath(GetProjectTreeInfo().m_Src, file));
02099     if ( find(m_CustomMetaData.begin(), m_CustomMetaData.end(), s) ==
02100               m_CustomMetaData.end()) {
02101         m_CustomMetaData.push_back( s );
02102     }
02103 }
02104 
02105 void CProjBulderApp::GetMetaDataFiles(list<string>* files) const
02106 {
02107     *files = m_CustomMetaData;
02108     NStr::Split(GetConfig().Get("ProjectTree", "MetaData"), LIST_SEPARATOR,
02109                 *files);
02110 }
02111 
02112 void CProjBulderApp::AddCustomConfH(const string& file)
02113 {
02114     m_CustomConfH.push_back(file);
02115 }
02116 
02117 void CProjBulderApp::GetCustomConfH(list<string>* files) const
02118 {
02119     *files = m_CustomConfH;
02120 }
02121 
02122 
02123 void CProjBulderApp::GetBuildConfigs(list<SConfigInfo>* configs)
02124 {
02125     configs->clear();
02126     string name = m_Dll ? "DllConfigurations" : "Configurations";
02127     const string& config_str
02128       = GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), name);
02129     list<string> configs_list;
02130     NStr::Split(config_str, LIST_SEPARATOR, configs_list);
02131     LoadConfigInfoByNames(GetConfig(), configs_list, configs);
02132 }
02133 
02134 
02135 const CMsvc7RegSettings& CProjBulderApp::GetRegSettings(void)
02136 {
02137     if ( !m_MsvcRegSettings.get() ) {
02138         m_MsvcRegSettings.reset(new CMsvc7RegSettings());
02139 
02140         string section(CMsvc7RegSettings::GetMsvcRegSection());
02141 
02142         m_MsvcRegSettings->m_MakefilesExt = 
02143             GetConfig().GetString(section, "MakefilesExt", "msvc");
02144     
02145         m_MsvcRegSettings->m_ProjectsSubdir  = 
02146             GetConfig().GetString(section, "Projects", "build");
02147 
02148         m_MsvcRegSettings->m_MetaMakefile = CDirEntry::ConvertToOSPath(
02149             GetConfig().Get(section, "MetaMakefile"));
02150 
02151         m_MsvcRegSettings->m_DllInfo = 
02152             GetConfig().Get(section, "DllInfo");
02153     
02154         m_MsvcRegSettings->m_Version = 
02155             GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), "Version");
02156 
02157         m_MsvcRegSettings->m_CompilersSubdir  = 
02158             GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), "msvc_prj");
02159 
02160         GetBuildConfigs(&m_MsvcRegSettings->m_ConfigInfo);
02161     }
02162     return *m_MsvcRegSettings;
02163 }
02164 
02165 
02166 const CMsvcSite& CProjBulderApp::GetSite(void)
02167 {
02168     if ( !m_MsvcSite.get() ) {
02169         m_MsvcSite.reset(new CMsvcSite(GetConfigPath()));
02170     }
02171     
02172     return *m_MsvcSite;
02173 }
02174 
02175 
02176 const CMsvcMetaMakefile& CProjBulderApp::GetMetaMakefile(void)
02177 {
02178     if ( !m_MsvcMetaMakefile.get() ) {
02179         //Metamakefile must be in RootSrc directory
02180         m_MsvcMetaMakefile.reset(new CMsvcMetaMakefile
02181                     (CDirEntry::ConcatPath(GetProjectTreeInfo().m_Src,
02182                                            GetRegSettings().m_MetaMakefile)));
02183         
02184         //Metamakefile must present and must not be empty
02185         if ( m_MsvcMetaMakefile->IsEmpty() )
02186             NCBI_THROW(CProjBulderAppException, 
02187                        eMetaMakefile, GetRegSettings().m_MetaMakefile);
02188     }
02189 
02190     return *m_MsvcMetaMakefile;
02191 }
02192 
02193 
02194 const SProjectTreeInfo& CProjBulderApp::GetProjectTreeInfo(void)
02195 {
02196     if ( m_ProjectTreeInfo.get() )
02197         return *m_ProjectTreeInfo;
02198         
02199     m_ProjectTreeInfo.reset(new SProjectTreeInfo);
02200     
02201     // Root, etc.
02202     m_ProjectTreeInfo->m_Root = m_Root;
02203     PTB_INFO("Project tree root: " << m_Root);
02204 
02205     // all possible project tags
02206     const string& tagsfile = CDirEntry::ConvertToOSPath(
02207         GetConfig().Get("ProjectTree", "ProjectTags"));
02208     if (!tagsfile.empty()) {
02209         string fileloc(CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, tagsfile));
02210         if (!CDirEntry(fileloc).Exists() && !m_ExtSrcRoot.empty()) {
02211             fileloc = CDirEntry::ConcatPath(m_ExtSrcRoot,tagsfile);
02212         }
02213         LoadProjectTags(fileloc);
02214     }
02215     
02216     /// <include> branch of tree
02217     const string& include = GetConfig().Get("ProjectTree", "include");
02218     m_ProjectTreeInfo->m_Include = 
02219             CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, 
02220                                   include);
02221     m_ProjectTreeInfo->m_Include = 
02222         CDirEntry::AddTrailingPathSeparator(m_ProjectTreeInfo->m_Include);
02223     
02224 
02225     /// <src> branch of tree
02226     const string& src = GetConfig().Get("ProjectTree", "src");
02227     m_ProjectTreeInfo->m_Src = 
02228             CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, 
02229                                   src);
02230     m_ProjectTreeInfo->m_Src =
02231         CDirEntry::AddTrailingPathSeparator(m_ProjectTreeInfo->m_Src);
02232 
02233     // Subtree to build - projects filter
02234     string subtree = CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, m_Subtree);
02235     LOG_POST(Info << "Project list or subtree: " << subtree);
02236     if (!CDirEntry(subtree).Exists()) {
02237         LOG_POST(Info << "WARNING: " << subtree << " does not exist");
02238     }
02239     m_ProjectTreeInfo->m_IProjectFilter.reset(
02240         new CProjectsLstFileFilter(m_ProjectTreeInfo->m_Src, subtree));
02241 
02242     /// <compilers> branch of tree
02243     const string& compilers = GetConfig().Get("ProjectTree", "compilers");
02244     m_ProjectTreeInfo->m_Compilers = 
02245             CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, 
02246                                   compilers);
02247     m_ProjectTreeInfo->m_Compilers = 
02248         CDirEntry::AddTrailingPathSeparator
02249                    (m_ProjectTreeInfo->m_Compilers);
02250 
02251     /// ImplicitExcludedBranches - all subdirs will be excluded by default
02252     const string& implicit_exclude_str 
02253         = GetConfig().Get("ProjectTree", "ImplicitExclude");
02254     list<string> implicit_exclude_list;
02255     NStr::Split(implicit_exclude_str, 
02256                 LIST_SEPARATOR, 
02257                 implicit_exclude_list);
02258     ITERATE(list<string>, p, implicit_exclude_list) {
02259         const string& subdir = *p;
02260         string dir = CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Src, 
02261                                            subdir);
02262         dir = CDirEntry::AddTrailingPathSeparator(dir);
02263         m_ProjectTreeInfo->m_ImplicitExcludedAbsDirs.push_back(dir);
02264     }
02265 
02266     /// <projects> branch of tree (scripts\projects)
02267     const string& projects = CDirEntry::ConvertToOSPath(
02268         GetConfig().Get("ProjectTree", "projects"));
02269     m_ProjectTreeInfo->m_Projects = 
02270             CDirEntry::ConcatPath(m_ProjectTreeInfo->m_Root, 
02271                                   projects);
02272     m_ProjectTreeInfo->m_Projects = 
02273         CDirEntry::AddTrailingPathSeparator
02274                    (m_ProjectTreeInfo->m_Compilers);
02275 
02276     /// impl part if include project node
02277     m_ProjectTreeInfo->m_Impl = 
02278         GetConfig().Get("ProjectTree", "impl");
02279 
02280     /// Makefile in tree node
02281     m_ProjectTreeInfo->m_TreeNode = 
02282         GetConfig().Get("ProjectTree", "TreeNode");
02283 
02284     m_ProjectTreeInfo->m_CustomMetaData =
02285         GetConfig().Get("ProjectTree", "CustomMetaData");
02286     m_ProjectTreeInfo->m_CustomConfH =
02287         GetConfig().Get("ProjectTree", "CustomConfH");
02288 
02289     return *m_ProjectTreeInfo;
02290 }
02291 
02292 
02293 const CBuildType& CProjBulderApp::GetBuildType(void)
02294 {
02295     if ( !m_BuildType.get() ) {
02296         m_BuildType.reset(new CBuildType(m_Dll));
02297     }    
02298     return *m_BuildType;
02299 }
02300 
02301 const CProjectItemsTree& CProjBulderApp::GetWholeTree(void)
02302 {
02303     if ( !m_WholeTree.get() ) {
02304         m_WholeTree.reset(new CProjectItemsTree);
02305         if (m_ScanWholeTree) {
02306             m_ScanningWholeTree = true;
02307             CProjectsLstFileFilter pass_all_filter(m_ProjectTreeInfo->m_Src, m_ProjectTreeInfo->m_Src);
02308 //            pass_all_filter.SetExcludePotential(false);
02309             CProjectTreeBuilder::BuildProjectTree(&pass_all_filter, 
02310                                                 GetProjectTreeInfo().m_Src, 
02311                                                 m_WholeTree.get());
02312             m_ScanningWholeTree = false;
02313         }
02314     }    
02315     return *m_WholeTree;
02316 }
02317 
02318 
02319 CDllSrcFilesDistr& CProjBulderApp::GetDllFilesDistr(void)
02320 {
02321     if (m_DllSrcFilesDistr.get())
02322         return *m_DllSrcFilesDistr;
02323 
02324     m_DllSrcFilesDistr.reset ( new CDllSrcFilesDistr() );
02325     return *m_DllSrcFilesDistr;
02326 }
02327 
02328 string CProjBulderApp::GetDataspecProjId(void) const
02329 {
02330     return "_generate_all_objects";
02331 }
02332 
02333 string CProjBulderApp::GetDatatoolId(void) const
02334 {
02335     return GetConfig().GetString("Datatool", "datatool",
02336         CMsvc7RegSettings::GetMsvcPlatform() >= CMsvc7RegSettings::eUnix ? "datatool" : "");
02337 }
02338 
02339 
02340 string CProjBulderApp::GetDatatoolPathForApp(void) const
02341 {
02342     if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode) {
02343         return GetConfig().GetString("Datatool", "Location.xcode", "datatool");
02344     }
02345     return GetConfig().GetString("Datatool", "Location.App", "datatool.exe");
02346 }
02347 
02348 
02349 string CProjBulderApp::GetDatatoolPathForLib(void) const
02350 {
02351     if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode) {
02352         return GetConfig().GetString("Datatool", "Location.xcode", "datatool");
02353     }
02354     return GetConfig().GetString("Datatool", "Location.Lib", "datatool.exe");
02355 }
02356 
02357 
02358 string CProjBulderApp::GetDatatoolCommandLine(void) const
02359 {
02360     if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eXCode) {
02361         return GetConfig().GetString("Datatool", "CommandLine.xcode", "");
02362     }
02363     return GetConfig().Get("Datatool", "CommandLine");
02364 }
02365 
02366 string CProjBulderApp::GetProjectTreeRoot(void) const
02367 {
02368     string path = CDirEntry::ConcatPath(
02369         m_ProjectTreeInfo->m_Compilers,
02370         m_MsvcRegSettings->m_CompilersSubdir);
02371     return CDirEntry::AddTrailingPathSeparator(path);
02372 }
02373 
02374 bool CProjBulderApp::IsAllowedProjectTag(
02375     const CProjItem& project, const string* filter /*= NULL*/) const
02376 {
02377     // verify that all project tags are registered
02378     list<string>::const_iterator i;
02379     for (i = project.m_ProjTags.begin(); i != project.m_ProjTags.end(); ++i) {
02380         if (m_RegisteredProjectTags.find(*i) == m_RegisteredProjectTags.end()) {
02381             NCBI_THROW(CProjBulderAppException, eUnknownProjectTag,
02382                 project.GetPath() + ": Unregistered project tag: " + *i);
02383             return false;
02384         }
02385     }
02386 
02387     if (filter == NULL) {
02388         filter = &m_ProjTags;
02389     }
02390     // no filter - everything is allowed
02391     if (filter->empty() || *filter == "*") {
02392         return true;
02393     }
02394 
02395     CExprParser parser;
02396     ITERATE( set<string>, p, m_RegisteredProjectTags) {
02397         parser.AddSymbol(p->c_str(),
02398             find( project.m_ProjTags.begin(), project.m_ProjTags.end(), *p) != project.m_ProjTags.end());
02399     }
02400     parser.Parse(filter->c_str());
02401     return parser.GetResult().GetBool();
02402 }
02403 
02404 void CProjBulderApp::LoadProjectTags(const string& filename)
02405 {
02406     CNcbiIfstream ifs(filename.c_str(), IOS_BASE::in | IOS_BASE::binary);
02407     if ( ifs.is_open() ) {
02408         string line;
02409         while ( NcbiGetlineEOL(ifs, line) ) {
02410             if (line.empty() || line[0] == '#') {
02411                 continue;
02412             }
02413             list<string> values;
02414             if (line.find('=') != string::npos) {
02415                 NStr::Split(line, "=", values);
02416                 if (values.size() > 1) {
02417                     string first = NStr::TruncateSpaces(values.front());
02418                     string second = NStr::TruncateSpaces(values.back());
02419                     m_CompositeProjectTags[first] = second;
02420                     
02421                 }
02422                 continue;
02423             }
02424             NStr::Split(line, LIST_SEPARATOR, values);
02425             ITERATE(list<string>,v,values) {
02426                 m_RegisteredProjectTags.insert(*v);
02427             }
02428         }
02429     }
02430     m_RegisteredProjectTags.insert("exe");
02431     m_RegisteredProjectTags.insert("lib");
02432     m_RegisteredProjectTags.insert("dll");
02433     m_RegisteredProjectTags.insert("public");
02434     m_RegisteredProjectTags.insert("internal");
02435 }
02436 
02437 string CProjBulderApp::ProcessLocationMacros(string raw_data)
02438 {
02439     string data(raw_data), raw_macro, macro, definition;
02440     string::size_type start, end, done = 0;
02441     while ((start = data.find("$(", done)) != string::npos) {
02442         end = data.find(")", start);
02443         if (end == string::npos) {
02444             LOG_POST(Warning << "Possibly incorrect MACRO definition in: " + raw_data);
02445             return data;
02446         }
02447         raw_macro = data.substr(start,end-start+1);
02448         if (CSymResolver::IsDefine(raw_macro)) {
02449             macro = CSymResolver::StripDefine(raw_macro);
02450             definition.erase();
02451             definition = GetConfig().GetString(CMsvc7RegSettings::GetMsvcSection(), macro, "");
02452             if (!definition.empty()) {
02453                 definition = CDirEntry::ConcatPath(
02454                     m_ProjectTreeInfo->m_Compilers, definition);
02455                 data = NStr::Replace(data, raw_macro, definition);
02456             } else {
02457                 done = end;
02458             }
02459         }
02460     }
02461     return data;
02462 }
02463 
02464 void CProjBulderApp::RegisterSuspiciousProject(const CProjKey& proj)
02465 {
02466     m_SuspiciousProj.insert(proj);
02467 }
02468 
02469 void CProjBulderApp::RegisterGeneratedFile( const string& file)
02470 {
02471     m_GeneratedFiles.push_back(file);
02472 }
02473 
02474 void CProjBulderApp::RegisterProjectWatcher(
02475     const string& project, const string& dir,  const string& watcher)
02476 {
02477     if (watcher.empty()) {
02478         return;
02479     }
02480     string sep;
02481     sep += CDirEntry::GetPathSeparator();
02482     string root(GetProjectTreeInfo().m_Src);
02483     if (!CDirEntry::IsAbsolutePath(root)) {
02484         root = CDirEntry::ConcatPath(CDir::GetCwd(), root);
02485     }
02486     string path(dir);
02487     if (!CDirEntry::IsAbsolutePath(path)) {
02488         path = CDirEntry::ConcatPath(CDir::GetCwd(), path);
02489     }
02490     path = CDirEntry::DeleteTrailingPathSeparator(
02491         CDirEntry::CreateRelativePath(root, path));
02492     NStr::ReplaceInPlace( path, sep, "/");
02493     m_ProjWatchers.push_back( project + ", " + path + ", " + watcher );
02494 }
02495 
02496 void CProjBulderApp::ExcludeProjectsByTag(CProjectItemsTree& tree) const
02497 {
02498     EraseIf(tree.m_Projects, PIsExcludedByTag());
02499     if (!m_ProjTags.empty() && m_ProjTags != "*") {
02500         NON_CONST_ITERATE(CProjectItemsTree::TProjects, p, tree.m_Projects) {
02501             if (p->second.m_ProjType == CProjKey::eDll) {
02502                 p->second.m_External = false;
02503             }
02504         }
02505     }
02506 }
02507 
02508 void CProjBulderApp::ExcludeUnrequestedProjects(CProjectItemsTree& tree) const
02509 {
02510     EraseIf(tree.m_Projects, PIsExcludedByUser());
02511 }
02512 
02513 string CProjBulderApp::GetUtilityProjectsDir(void) const
02514 {
02515     string utility_projects_dir = CDirEntry(m_Solution).GetDir();
02516     utility_projects_dir = 
02517         CDirEntry::ConcatPath(utility_projects_dir, "UtilityProjects");
02518     utility_projects_dir = 
02519         CDirEntry::AddTrailingPathSeparator(utility_projects_dir);
02520     return utility_projects_dir;
02521 }
02522 
02523 string CProjBulderApp::GetUtilityProjectsSrcDir(void)
02524 {
02525     string prj = GetProjectTreeInfo().m_Compilers;
02526     prj = CDirEntry::ConcatPath(prj, GetRegSettings().m_CompilersSubdir);
02527     prj = CDirEntry::ConcatPath(prj, GetBuildType().GetTypeStr());
02528     prj = CDirEntry::ConcatPath(prj, GetRegSettings().m_ProjectsSubdir);
02529 
02530     string sln = CDirEntry(m_Solution).GetDir();
02531     prj = CDirEntry::CreateRelativePath( prj, sln);
02532     prj = CDirEntry::ConcatPath(GetProjectTreeInfo().m_Src, prj);
02533     prj = CDirEntry::ConcatPath(prj, "UtilityProjects");
02534     prj = CDirEntry::AddTrailingPathSeparator(prj);
02535     return prj;
02536 }
02537 
02538 void CProjBulderApp::SetConfFileData(const string& src, const string& dest)
02539 {
02540     m_ConfSrc = src;
02541     m_ConfDest= dest;
02542 }
02543 
02544 CProjBulderApp& GetApp(void)
02545 {
02546     static CProjBulderApp theApp;
02547     return theApp;
02548 }
02549 
02550 END_NCBI_SCOPE
02551 
02552 
02553 USING_NCBI_SCOPE;
02554 
02555 int NcbiSys_main(int argc, TXChar* argv[])
02556 {
02557     // Execute main application function
02558     CDiagContext::SetLogTruncate(true);
02559     GetDiagContext().SetLogRate_Limit(CDiagContext::eLogRate_Err, (unsigned int)-1);
02560     return GetApp().AppMain(argc, argv, 0, eDS_Default);
02561 }
Modified on Wed May 23 13:13:17 2012 by modify_doxy.py rev. 337098