1 /* $Id: msvc_configure.cpp 622157 2020-12-21 15:39:27Z ivanov $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author:  Viatcheslav Gorelenkov
27  *
28  */
29 
30 #include <ncbi_pch.hpp>
31 #include "msvc_configure.hpp"
32 #include "proj_builder_app.hpp"
33 #include "util/random_gen.hpp"
34 
35 #include "ptb_err_codes.hpp"
36 #ifdef NCBI_XCODE_BUILD
37   #include <sys/utsname.h>
38   #include <unistd.h>
39 #endif
40 
41 #include <corelib/ncbiexec.hpp>
42 #include <util/xregexp/regexp.hpp>
43 
44 
45 BEGIN_NCBI_SCOPE
46 
47 
CMsvcConfigure(void)48 CMsvcConfigure::CMsvcConfigure(void)
49     : m_HaveBuildVer(false)
50 {
51 }
52 
53 
~CMsvcConfigure(void)54 CMsvcConfigure::~CMsvcConfigure(void)
55 {
56 }
57 
58 
s_ResetLibInstallKey(const string & dir,const string & lib)59 void s_ResetLibInstallKey(const string& dir,
60                           const string& lib)
61 {
62     string key_file_name(lib);
63     NStr::ToLower(key_file_name);
64     key_file_name += ".installed";
65     string key_file_path = CDirEntry::ConcatPath(dir, key_file_name);
66     if ( CDirEntry(key_file_path).Exists() ) {
67         CDirEntry(key_file_path).Remove();
68     }
69 }
70 
71 
s_CreateThirdPartyLibsInstallMakefile(CMsvcSite & site,const list<string> libs_to_install,const SConfigInfo & config,const CBuildType & build_type)72 static void s_CreateThirdPartyLibsInstallMakefile
73                                             (CMsvcSite&   site,
74                                              const list<string> libs_to_install,
75                                              const SConfigInfo& config,
76                                              const CBuildType&  build_type)
77 {
78     // Create makefile path
79     string makefile_path = GetApp().GetProjectTreeInfo().m_Compilers;
80     makefile_path =
81         CDirEntry::ConcatPath(makefile_path,
82                               GetApp().GetRegSettings().m_CompilersSubdir);
83 
84     makefile_path = CDirEntry::ConcatPath(makefile_path, build_type.GetTypeStr());
85     makefile_path = CDirEntry::ConcatPath(makefile_path, config.GetConfigFullName());
86     makefile_path = CDirEntry::ConcatPath(makefile_path,
87                                           "Makefile.third_party.mk");
88 
89     // Create dir if no such dir...
90     string dir;
91     CDirEntry::SplitPath(makefile_path, &dir);
92     CDir makefile_dir(dir);
93     if ( !makefile_dir.Exists() ) {
94         CDir(dir).CreatePath();
95     }
96 
97     CNcbiOfstream ofs(makefile_path.c_str(),
98                       IOS_BASE::out | IOS_BASE::trunc );
99     if ( !ofs )
100         NCBI_THROW(CProjBulderAppException, eFileCreation, makefile_path);
101 
102     GetApp().RegisterGeneratedFile( makefile_path );
103     ITERATE(list<string>, n, libs_to_install) {
104         const string& lib = *n;
105         SLibInfo lib_info;
106         site.GetLibInfo(lib, config, &lib_info);
107         if ( !lib_info.m_LibPath.empty() ) {
108             string bin_dir = lib_info.m_LibPath;
109             string bin_path = lib_info.m_BinPath;
110             if (bin_path.empty()) {
111                 bin_path = site.GetThirdPartyLibsBinSubDir();
112             }
113             bin_dir =
114                 CDirEntry::ConcatPath(bin_dir, bin_path);
115             bin_dir = CDirEntry::NormalizePath(bin_dir);
116             if ( CDirEntry(bin_dir).Exists() ) {
117                 //
118                 string key(lib);
119                 NStr::ToUpper(key);
120                 key += site.GetThirdPartyLibsBinPathSuffix();
121 
122                 ofs << key << " = " << bin_dir << "\n";
123 
124                 s_ResetLibInstallKey(dir, lib);
125                 site.SetThirdPartyLibBin(lib, bin_dir);
126             } else {
127                 PTB_WARNING_EX(bin_dir, ePTB_PathNotFound,
128                                lib << "|" << config.GetConfigFullName()
129                                << " disabled, path not found");
130             }
131         } else {
132             PTB_WARNING_EX(kEmptyStr, ePTB_PathNotFound,
133                            lib << "|" << config.GetConfigFullName()
134                            << ": no LIBPATH specified");
135         }
136     }
137 }
138 
139 
Configure(CMsvcSite & site,const list<SConfigInfo> & configs,const string & root_dir)140 void CMsvcConfigure::Configure(CMsvcSite&         site,
141                                const list<SConfigInfo>& configs,
142                                const string&            root_dir)
143 {
144     _TRACE("*** Analyzing 3rd party libraries availability ***");
145 
146     site.InitializeLibChoices();
147     InitializeFrom(site);
148     site.ProcessMacros(configs);
149 
150     if (CMsvc7RegSettings::GetMsvcPlatform() >= CMsvc7RegSettings::eUnix) {
151         return;
152     }
153     _TRACE("*** Creating Makefile.third_party.mk files ***");
154     // Write makefile uses to install 3-rd party dlls
155     list<string> third_party_to_install;
156     site.GetThirdPartyLibsToInstall(&third_party_to_install);
157     // For static buid
158     ITERATE(list<SConfigInfo>, p, configs) {
159         const SConfigInfo& config = *p;
160         s_CreateThirdPartyLibsInstallMakefile(site,
161                                               third_party_to_install,
162                                               config,
163                                               GetApp().GetBuildType());
164     }
165 }
166 
CreateConfH(CMsvcSite & site,const list<SConfigInfo> & configs,const string & root_dir)167 void CMsvcConfigure::CreateConfH(
168     CMsvcSite& site,
169     const list<SConfigInfo>& configs,
170     const string& root_dir)
171 {
172     CMsvc7RegSettings::EMsvcPlatform platform = CMsvc7RegSettings::GetMsvcPlatform();
173 
174     ITERATE(list<SConfigInfo>, p, configs) {
175         WriteExtraDefines(site, root_dir, *p);
176         // Windows and XCode only. On Unix build version header file is generated by configure, not PTB.
177         if (platform != CMsvc7RegSettings::eUnix) {
178             WriteBuildVer(site, root_dir, *p);
179         }
180     }
181     if (platform == CMsvc7RegSettings::eUnix) {
182         return;
183     }
184     _TRACE("*** Creating local ncbiconf headers ***");
185     const CBuildType& build_type(GetApp().GetBuildType());
186     ITERATE(list<SConfigInfo>, p, configs) {
187         /*if (!p->m_VTuneAddon && !p->m_Unicode)*/ {
188             AnalyzeDefines( site, root_dir, *p, build_type);
189         }
190     }
191 }
192 
193 
InitializeFrom(const CMsvcSite & site)194 void CMsvcConfigure::InitializeFrom(const CMsvcSite& site)
195 {
196     m_ConfigSite.clear();
197 
198     m_ConfigureDefinesPath = site.GetConfigureDefinesPath();
199     if ( m_ConfigureDefinesPath.empty() ) {
200         NCBI_THROW(CProjBulderAppException,
201            eConfigureDefinesPath,
202            "Configure defines file name is not specified");
203     }
204 
205     site.GetConfigureDefines(&m_ConfigureDefines);
206     if( m_ConfigureDefines.empty() ) {
207         PTB_ERROR(m_ConfigureDefinesPath,
208                   "No configurable macro definitions specified.");
209     } else {
210         _TRACE("Configurable macro definitions: ");
211         ITERATE(list<string>, p, m_ConfigureDefines) {
212             _TRACE(*p);
213         }
214     }
215 }
216 
217 
ProcessDefine(const string & define,const CMsvcSite & site,const SConfigInfo & config) const218 bool CMsvcConfigure::ProcessDefine(const string& define,
219                                    const CMsvcSite& site,
220                                    const SConfigInfo& config) const
221 {
222     if ( !site.IsDescribed(define) ) {
223         PTB_ERROR_EX(kEmptyStr, ePTB_MacroUndefined,
224                      define << ": Macro not defined");
225         return false;
226     }
227     list<string> components;
228     site.GetComponents(define, &components);
229     ITERATE(list<string>, p, components) {
230         const string& component = *p;
231         if (site.IsBanned(component)) {
232             PTB_WARNING_EX("", ePTB_ConfigurationError,
233                             component << "|" << config.GetConfigFullName()
234                             << ": " << define << " not provided, disabled");
235             return false;
236         }
237         if (site.IsProvided( component, false)) {
238             continue;
239         }
240         SLibInfo lib_info;
241         site.GetLibInfo(component, config, &lib_info);
242         if ( !site.IsLibOk(lib_info)  ||
243              !site.IsLibEnabledInConfig(component, config)) {
244             if (!lib_info.IsEmpty()) {
245                 PTB_WARNING_EX("", ePTB_ConfigurationError,
246                                component << "|" << config.GetConfigFullName()
247                                << ": " << define << " not satisfied, disabled");
248             }
249             return false;
250         }
251     }
252     return true;
253 }
254 
255 
WriteExtraDefines(CMsvcSite & site,const string & root_dir,const SConfigInfo & config)256 void CMsvcConfigure::WriteExtraDefines(CMsvcSite& site, const string& root_dir, const SConfigInfo& config)
257 {
258     string cfg = CMsvc7RegSettings::GetConfigNameKeyword();
259     string cfg_root_inc(root_dir);
260     if (!cfg.empty()) {
261         NStr::ReplaceInPlace(cfg_root_inc,cfg,config.GetConfigFullName());
262     }
263     string extra = site.GetConfigureEntry("ExtraDefines");
264     string filename = CDirEntry::ConcatPath(cfg_root_inc, extra);
265     int random_count = NStr::StringToInt(site.GetConfigureEntry("RandomValueCount"), NStr::fConvErr_NoThrow);
266 
267     if (extra.empty() || random_count <= 0 || CFile(filename).Exists()) {
268         return;
269     }
270 
271     string dir;
272     CDirEntry::SplitPath(filename, &dir);
273     CDir(dir).CreatePath();
274 
275     CNcbiOfstream ofs(filename.c_str(), IOS_BASE::out | IOS_BASE::trunc);
276     if ( !ofs ) {
277 	    NCBI_THROW(CProjBulderAppException, eFileCreation, filename);
278     }
279     WriteNcbiconfHeader(ofs);
280 
281     CRandom rnd(CRandom::eGetRand_Sys);
282     string prefix("#define NCBI_RANDOM_VALUE_");
283     ofs << prefix << "TYPE   Uint4" << endl;
284     ofs << prefix << "MIN    0" << endl;
285     ofs << prefix << "MAX    "  << std::hex
286         << std::showbase << rnd.GetMax() << endl << endl;
287     for (int i = 0; i < random_count; ++i) {
288         ofs << prefix  << std::noshowbase << i
289             << setw(16) << std::showbase << rnd.GetRand() << endl;
290     }
291     ofs << endl;
292     GetApp().RegisterGeneratedFile( filename );
293 }
294 
295 
296 
WriteBuildVer(CMsvcSite & site,const string & root_dir,const SConfigInfo & config)297 void CMsvcConfigure::WriteBuildVer(CMsvcSite& site, const string& root_dir, const SConfigInfo& config)
298 {
299     static TXChar* filename_cache = NULL;
300 
301     string cfg = CMsvc7RegSettings::GetConfigNameKeyword();
302     string cfg_root_inc(root_dir);
303     if (!cfg.empty()) {
304         NStr::ReplaceInPlace(cfg_root_inc, cfg, config.GetConfigFullName());
305     }
306     string extra = CDirEntry::ConvertToOSPath(site.GetConfigureEntry("BuildVerPath"));
307     string filename = CDirEntry::ConcatPath(cfg_root_inc, extra);
308 
309     if (extra.empty()) {
310         return;
311     }
312 
313     string dir;
314     CDirEntry::SplitPath(filename, &dir);
315     CDir(dir).CreatePath();
316 
317     // Each file with build version information is the same for each configuration,
318     // so create it once and copy to each configuration on next calls.
319 
320     if (filename_cache) {
321         CFile src(_T_STDSTRING(filename_cache));
322         CFile dst(filename);
323         if (!dst.Exists() || src.IsNewer(dst.GetPath(),0)) {
324             src.Copy(filename, CFile::fCF_Overwrite);
325             GetApp().RegisterGeneratedFile( filename );
326         }
327         return;
328     }
329 
330     // get vars
331     string tc_ver   = GetApp().GetEnvironment().Get("TEAMCITY_VERSION");
332     string tc_build = GetApp().GetEnvironment().Get("BUILD_NUMBER");
333     string tc_build_id;
334     string tc_prj   = GetApp().GetEnvironment().Get("TEAMCITY_PROJECT_NAME");
335     string tc_conf  = GetApp().GetEnvironment().Get("TEAMCITY_BUILDCONF_NAME");
336     string svn_rev  = GetApp().GetEnvironment().Get("SVNREV");
337     string sc_ver   = GetApp().GetEnvironment().Get("SCVER");
338 
339     // Get content of the Teamcity property file, if any
340     string prop_file_name = GetApp().GetEnvironment().Get("TEAMCITY_BUILD_PROPERTIES_FILE");
341     string prop_file_info;
342     if (!prop_file_name.empty()) {
343         CNcbiIfstream is(prop_file_name.c_str(), IOS_BASE::in);
344         if (is.good()) {
345             NcbiStreamToString(&prop_file_info, is);
346             // teamcity.build.id
347             if (!prop_file_info.empty()) {
348                 CRegexp re("teamcity.build.id=(\\d+)");
349                 tc_build_id = re.GetMatch(prop_file_info, 0, 1);
350             }
351         }
352     }
353     string tree_root = GetApp().GetEnvironment().Get("TREE_ROOT");
354     if (tree_root.empty()) {
355         tree_root = GetApp().GetProjectTreeInfo().m_Root;
356     }
357     if (!tree_root.empty()) {
358         // Get SVN info
359         string tmp_file = CFile::GetTmpName();
360 
361         string cmd = "svn info " + tree_root + " > " + tmp_file;
362         TExitCode ret = CExec::System(cmd.c_str());
363         if (ret == 0) {
364             // SVN client present, parse results
365             string info;
366             {
367                 CNcbiIfstream is(tmp_file.c_str(), IOS_BASE::in);
368                 NcbiStreamToString(&info, is);
369                 CFile(tmp_file).Remove();
370                 if (!info.empty()) {
371                     CRegexp re("Revision: (\\d+)");
372                     svn_rev = re.GetMatch(info, 0, 1);
373                 }
374             }
375             cmd = "svn info " + CDir::ConcatPath(tree_root, "src/build-system") + " > " + tmp_file;
376             ret = CExec::System(cmd.c_str());
377             if (ret == 0) {
378                 CNcbiIfstream is(tmp_file.c_str(), IOS_BASE::in);
379                 NcbiStreamToString(&info, is);
380                 CFile(tmp_file).Remove();
381                 if (!info.empty()) {
382                     CRegexp re("/production/components/[^/]*/(\\d+)");
383                     sc_ver = re.GetMatch(info, 0, 1);
384                 }
385             }
386         }
387         else {
388             // Fallback
389             if (sc_ver.empty()) {
390                 sc_ver = GetApp().GetEnvironment().Get("NCBI_SC_VERSION");
391             }
392             // try to get revision bumber from teamcity property file
393             if (svn_rev.empty() && !prop_file_info.empty()) {
394                 CRegexp re("build.vcs.number=(\\d+)");
395                 svn_rev = re.GetMatch(prop_file_info, 0, 1);
396             }
397         }
398     }
399     if (tc_build.empty()) {tc_build = "0";}
400     if (sc_ver.empty())   {sc_ver = "0";}
401     if (svn_rev.empty())  {svn_rev = "0";}
402 
403     map<string,string> build_vars;
404     build_vars["NCBI_TEAMCITY_BUILD_NUMBER"] = tc_build;
405     build_vars["NCBI_TEAMCITY_BUILD_ID"] = tc_build_id;
406     build_vars["NCBI_TEAMCITY_PROJECT_NAME"] = tc_prj;
407     build_vars["NCBI_TEAMCITY_BUILDCONF_NAME"] = tc_conf;
408     build_vars["NCBI_SUBVERSION_REVISION"] = svn_rev;
409     build_vars["NCBI_SC_VERSION"] = sc_ver;
410 
411     auto converter = [](const string& file_in, const string& file_out, const map<string,string>& vocabulary) {
412         string candidate = file_out + ".candidate";
413         CNcbiOfstream ofs(candidate.c_str(), IOS_BASE::out | IOS_BASE::trunc);
414         if ( ofs.is_open() ) {
415 
416             CNcbiIfstream ifs(file_in.c_str());
417             if (ifs.is_open()) {
418                 string line;
419                 while( getline(ifs, line) ) {
420                     for (string::size_type from = line.find("@"); from != string::npos; from = line.find("@")) {
421                         string::size_type  to = line.find("@", from + 1);
422                         if (to != string::npos) {
423                             string key = line.substr(from+1, to-from-1);
424                             if (vocabulary.find(key) != vocabulary.end()) {
425                                 line.replace(from, to-from+1, vocabulary.at(key));
426                             } else {
427                                 line.replace(from, to-from+1, "");
428                             }
429                         }
430                     }
431                     ofs << line << endl;
432                 }
433                 ifs.close();
434             }
435             ofs.close();
436             PromoteIfDifferent(file_out, candidate);
437         }
438     };
439 
440     string file_in = CDirEntry::ConvertToOSPath(CDirEntry::ConcatPath(GetApp().GetProjectTreeInfo().m_Include, "common/ncbi_build_ver.h.in"));
441     converter(file_in, filename, build_vars);
442     // Cache file name for the generated file
443     filename_cache = NcbiSys_strdup(_T_XCSTRING(filename));
444     m_HaveBuildVer = true;
445 
446     filename = CDirEntry::ConvertToOSPath(CDirEntry::ConcatPath(GetApp().GetProjectTreeInfo().m_Include, "common/ncbi_revision.h"));
447     file_in = CDirEntry::ConvertToOSPath(CDirEntry::ConcatPath(GetApp().GetProjectTreeInfo().m_Include, "common/ncbi_revision.h.in"));
448     converter(file_in, filename, build_vars);
449 }
450 
451 
AnalyzeDefines(CMsvcSite & site,const string & root_dir,const SConfigInfo & config,const CBuildType & build_type)452 void CMsvcConfigure::AnalyzeDefines(
453     CMsvcSite& site, const string& root_dir,
454     const SConfigInfo& config, const CBuildType&  build_type)
455 {
456     string cfg_root_inc = NStr::Replace(root_dir,
457         CMsvc7RegSettings::GetConfigNameKeyword(),config.GetConfigFullName());
458     string filename =
459         CDirEntry::ConcatPath(cfg_root_inc, m_ConfigureDefinesPath);
460     string dir;
461     CDirEntry::SplitPath(filename, &dir);
462 
463     _TRACE("Configuration " << config.m_Name << ":");
464 
465     m_ConfigSite.clear();
466 
467     ITERATE(list<string>, p, m_ConfigureDefines) {
468         const string& define = *p;
469         if( ProcessDefine(define, site, config) ) {
470             _TRACE("Macro definition Ok  " << define);
471             m_ConfigSite[define] = '1';
472         } else {
473             PTB_WARNING_EX(kEmptyStr, ePTB_MacroUndefined,
474                            "Macro definition not satisfied: " << define);
475             m_ConfigSite[define] = '0';
476         }
477     }
478     if (m_HaveBuildVer) {
479         // Add define that we have build version info file
480         m_ConfigSite["HAVE_COMMON_NCBI_BUILD_VER_H"] = '1';
481     }
482 
483     string signature;
484     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
485         signature = "MSVC";
486     } else if (CMsvc7RegSettings::GetMsvcPlatform() > CMsvc7RegSettings::eUnix) {
487         signature = "XCODE";
488     } else {
489         signature = CMsvc7RegSettings::GetMsvcPlatformName();
490     }
491     signature += "_";
492     signature += CMsvc7RegSettings::GetMsvcVersionName();
493     signature += "-" + config.GetConfigFullName();
494     if (config.m_rtType == SConfigInfo::rtMultiThreadedDLL ||
495         config.m_rtType == SConfigInfo::rtMultiThreadedDebugDLL) {
496         signature += "MT";
497     }
498 #ifdef NCBI_XCODE_BUILD
499     string tmp = CMsvc7RegSettings::GetRequestedArchs();
500     NStr::ReplaceInPlace(tmp, " ", "_");
501     signature += "_" + tmp;
502     signature += "--";
503     struct utsname u;
504     if (uname(&u) == 0) {
505 //        signature += string(u.machine) + string("-apple-") + string(u.sysname) + string(u.release);
506         signature +=
507             GetApp().GetSite().GetPlatformInfo( u.sysname, "arch", u.machine) +
508             string("-apple-") +
509             GetApp().GetSite().GetPlatformInfo( u.sysname, "os", u.sysname) +
510             string(u.release);
511     } else {
512         signature += HOST;
513     }
514     signature += "-";
515     {
516         char hostname[255];
517         string tmp1, tmp2;
518         if (0 == gethostname(hostname, 255))
519             NStr::SplitInTwo(hostname,".", tmp1, tmp2);
520             signature += tmp1;
521     }
522 #else
523     signature += "--";
524     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
525         signature += "i386-pc-";
526         signature += CMsvc7RegSettings::GetRequestedArchs();
527     } else {
528         signature += HOST;
529     }
530     signature += "-";
531     if (CMsvc7RegSettings::GetMsvcPlatform() < CMsvc7RegSettings::eUnix) {
532         signature += GetApp().GetEnvironment().Get("COMPUTERNAME");
533     }
534 #endif
535 
536     string candidate_path = filename + ".candidate";
537     CDirEntry::SplitPath(filename, &dir);
538     CDir(dir).CreatePath();
539     WriteNcbiconfMsvcSite(candidate_path, signature);
540     if (PromoteIfDifferent(filename, candidate_path)) {
541         PTB_WARNING_EX(filename, ePTB_FileModified,
542                        "Configuration file modified");
543     } else {
544         PTB_INFO_EX(filename, ePTB_NoError,
545                     "Configuration file unchanged");
546     }
547 }
548 
WriteNcbiconfHeader(CNcbiOfstream & ofs) const549 CNcbiOfstream& CMsvcConfigure::WriteNcbiconfHeader(CNcbiOfstream& ofs) const
550 {
551     ofs <<"/* $" << "Id" << "$" << endl;
552     ofs <<"* ===========================================================================" << endl;
553     ofs <<"*" << endl;
554     ofs <<"*                            PUBLIC DOMAIN NOTICE" << endl;
555     ofs <<"*               National Center for Biotechnology Information" << endl;
556     ofs <<"*" << endl;
557     ofs <<"*  This software/database is a \"United States Government Work\" under the" << endl;
558     ofs <<"*  terms of the United States Copyright Act.  It was written as part of" << endl;
559     ofs <<"*  the author's official duties as a United States Government employee and" << endl;
560     ofs <<"*  thus cannot be copyrighted.  This software/database is freely available" << endl;
561     ofs <<"*  to the public for use. The National Library of Medicine and the U.S." << endl;
562     ofs <<"*  Government have not placed any restriction on its use or reproduction." << endl;
563     ofs <<"*" << endl;
564     ofs <<"*  Although all reasonable efforts have been taken to ensure the accuracy" << endl;
565     ofs <<"*  and reliability of the software and data, the NLM and the U.S." << endl;
566     ofs <<"*  Government do not and cannot warrant the performance or results that" << endl;
567     ofs <<"*  may be obtained by using this software or data. The NLM and the U.S." << endl;
568     ofs <<"*  Government disclaim all warranties, express or implied, including" << endl;
569     ofs <<"*  warranties of performance, merchantability or fitness for any particular" << endl;
570     ofs <<"*  purpose." << endl;
571     ofs <<"*" << endl;
572     ofs <<"*  Please cite the author in any work or product based on this material." << endl;
573     ofs <<"*" << endl;
574     ofs <<"* ===========================================================================" << endl;
575     ofs <<"*" << endl;
576     ofs <<"* Author:  ......." << endl;
577     ofs <<"*" << endl;
578     ofs <<"* File Description:" << endl;
579     ofs <<"*   ......." << endl;
580     ofs <<"*" << endl;
581     ofs <<"* ATTENTION:" << endl;
582     ofs <<"*   Do not edit or commit this file into SVN as this file will" << endl;
583     ofs <<"*   be overwritten (by PROJECT_TREE_BUILDER) without warning!" << endl;
584     ofs <<"*/" << endl;
585     ofs << endl;
586     ofs << endl;
587     return ofs;
588 }
589 
WriteNcbiconfMsvcSite(const string & full_path,const string & signature) const590 void CMsvcConfigure::WriteNcbiconfMsvcSite(
591     const string& full_path, const string& signature) const
592 {
593     CNcbiOfstream  ofs(full_path.c_str(),
594                        IOS_BASE::out | IOS_BASE::trunc );
595     if ( !ofs )
596 	    NCBI_THROW(CProjBulderAppException, eFileCreation, full_path);
597 
598     WriteNcbiconfHeader(ofs);
599 
600     ITERATE(TConfigSite, p, m_ConfigSite) {
601         if (p->second == '1') {
602             ofs << "#define " << p->first << " " << p->second << endl;
603         } else {
604             ofs << "/* #undef " << p->first << " */" << endl;
605         }
606     }
607     ofs << endl;
608     ofs << "#define NCBI_SIGNATURE \\" << endl << "  \"" << signature << "\"" << endl;
609 
610     list<string> customH;
611     GetApp().GetCustomConfH(&customH);
612     ITERATE(list<string>, c, customH) {
613         string file (CDirEntry::CreateRelativePath(GetApp().m_Root, *c));
614         NStr::ReplaceInPlace(file, "\\", "/");
615         ofs << endl << "/*"
616             << endl << "* ==========================================================================="
617             << endl << "* Included contents of " << file
618             << endl << "*/"
619             << endl;
620 
621             CNcbiIfstream is(c->c_str(), IOS_BASE::in | IOS_BASE::binary);
622             if ( !is ) {
623                 continue;
624             }
625             char   buf[1024];
626             while ( is ) {
627                 is.read(buf, sizeof(buf));
628                 ofs.write(buf, is.gcount());
629             }
630     }
631 }
632 
633 
634 END_NCBI_SCOPE
635