1 /* $Id: msvc_prj_utils.cpp 602953 2020-03-04 19:52:40Z gouriano $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Viatcheslav Gorelenkov
27 *
28 */
29
30 #include <ncbi_pch.hpp>
31 #include "msvc_prj_utils.hpp"
32 #include "proj_builder_app.hpp"
33 #include "msvc_prj_defines.hpp"
34 #include "ptb_err_codes.hpp"
35 #include <corelib/ncbi_system.hpp>
36
37 #ifdef NCBI_COMPILER_MSVC
38 # include <serial/objostrxml.hpp>
39 # include <serial/objistr.hpp>
40 # include <serial/serial.hpp>
41
42 # include <objbase.h>
43 #endif
44
45
46
47 BEGIN_NCBI_SCOPE
48
49 #if NCBI_COMPILER_MSVC
50
LoadFromXmlFile(const string & file_path)51 CVisualStudioProject* LoadFromXmlFile(const string& file_path)
52 {
53 unique_ptr<CObjectIStream> in(CObjectIStream::Open(eSerial_Xml,
54 file_path,
55 eSerial_StdWhenAny));
56 if ( in->fail() )
57 NCBI_THROW(CProjBulderAppException, eFileOpen, file_path);
58
59 unique_ptr<CVisualStudioProject> prj(new CVisualStudioProject());
60 in->Read(prj.get(), prj->GetThisTypeInfo());
61 return prj.release();
62 }
63
64
SaveToXmlFile(const string & file_path,const CSerialObject & project)65 void SaveToXmlFile(const string& file_path, const CSerialObject& project)
66 {
67 // Create dir if no such dir...
68 string dir;
69 CDirEntry::SplitPath(file_path, &dir);
70 CDir project_dir(dir);
71 if ( !project_dir.Exists() ) {
72 CDir(dir).CreatePath();
73 }
74
75 CNcbiOfstream ofs(file_path.c_str(),
76 IOS_BASE::out | IOS_BASE::trunc);
77 if ( !ofs )
78 NCBI_THROW(CProjBulderAppException, eFileCreation, file_path);
79
80 CObjectOStreamXml xs(ofs, eNoOwnership);
81 if (CMsvc7RegSettings::GetMsvcVersion() >= CMsvc7RegSettings::eMsvc1000) {
82 xs.SetReferenceSchema();
83 xs.SetUseSchemaLocation(false);
84 } else {
85 xs.SetReferenceDTD(false);
86 }
87 xs.SetEncoding(eEncoding_UTF8);
88 xs.SetDefaultStringEncoding(eEncoding_UTF8);
89
90 xs << project;
91 }
92
SaveIfNewer(const string & file_path,const CSerialObject & project)93 void SaveIfNewer(const string& file_path, const CSerialObject& project)
94 {
95 // If no such file then simple write it
96 if ( !CDirEntry(file_path).Exists() ) {
97 SaveToXmlFile(file_path, project);
98 GetApp().RegisterGeneratedFile( file_path );
99 PTB_INFO_EX(file_path, ePTB_FileModified,
100 "Project created");
101 return;
102 }
103
104 // Save new file to tmp path.
105 string candidate_file_path = file_path + ".candidate";
106 SaveToXmlFile(candidate_file_path, project);
107 if (PromoteIfDifferent(file_path, candidate_file_path)) {
108 PTB_WARNING_EX(file_path, ePTB_FileModified,
109 "Project updated");
110 } else {
111 PTB_TRACE("Left intact: " << file_path);
112 }
113 }
114
SaveIfNewer(const string & file_path,const CSerialObject & project,const string & ignore)115 void SaveIfNewer (const string& file_path,
116 const CSerialObject& project,
117 const string& ignore)
118 {
119 string candidate_file_path = file_path + ".candidate";
120 SaveToXmlFile(candidate_file_path, project);
121 if (!PromoteIfDifferent(file_path, candidate_file_path, ignore)) {
122 PTB_TRACE("Left intact: " << file_path);
123 }
124 }
125
126 #endif //NCBI_COMPILER_MSVC
127
PromoteIfDifferent(const string & present_path,const string & candidate_path,const string & ignore)128 bool PromoteIfDifferent(const string& present_path,
129 const string& candidate_path,
130 const string& ignore)
131 {
132 CNcbiIfstream ifs_present(present_path.c_str(),
133 IOS_BASE::in | IOS_BASE::binary);
134 if (ifs_present.is_open()) {
135 CNcbiIfstream ifs_new (candidate_path.c_str(),
136 IOS_BASE::in | IOS_BASE::binary);
137 if ( !ifs_new ) {
138 NCBI_THROW(CProjBulderAppException, eFileOpen, candidate_path);
139 }
140 string str_present, str_new;
141 bool eol_present=false, eol_new = false;
142 for (;;) {
143 eol_present=false;
144 for (;;) {
145 if (!NcbiGetlineEOL(ifs_present, str_present) ) {
146 break;
147 }
148 NStr::TruncateSpacesInPlace(str_present);
149 if (!NStr::StartsWith(str_present, ignore)) {
150 eol_present=true;
151 break;
152 }
153 }
154 eol_new = false;
155 for (;;) {
156 if (!NcbiGetlineEOL(ifs_new, str_new) ) {
157 break;
158 }
159 NStr::TruncateSpacesInPlace(str_new);
160 if (!NStr::StartsWith(str_new, ignore)) {
161 eol_new=true;
162 break;
163 }
164 }
165 if (!eol_present && !eol_new) {
166 ifs_new.close();
167 CDirEntry(candidate_path).Remove();
168 return false;
169 }
170 if (NStr::CompareCase(str_present, str_new) != 0) {
171 break;
172 }
173 }
174 ifs_present.close();
175 }
176 CDirEntry(present_path).Remove();
177 for (int a=0; a<2 && !CDirEntry(candidate_path).Rename(present_path); ++a)
178 SleepSec(1);
179 GetApp().RegisterGeneratedFile( present_path );
180 return true;
181 }
182
PromoteIfDifferent(const string & present_path,const string & candidate_path)183 bool PromoteIfDifferent(const string& present_path,
184 const string& candidate_path)
185 {
186 // Open both files
187 CNcbiIfstream ifs_present(present_path.c_str(),
188 IOS_BASE::in | IOS_BASE::binary);
189 if ( !ifs_present ) {
190 CDirEntry(present_path).Remove();
191 for (int a=0; a<2 && !CDirEntry(candidate_path).Rename(present_path); ++a)
192 SleepSec(1);
193 GetApp().RegisterGeneratedFile( present_path );
194 return true;
195 }
196
197 ifs_present.seekg(0, ios::end);
198 size_t file_length_present = ifs_present.tellg() - streampos(0);
199
200 ifs_present.seekg(0, ios::beg);
201
202 CNcbiIfstream ifs_new (candidate_path.c_str(),
203 IOS_BASE::in | IOS_BASE::binary);
204 if ( !ifs_new ) {
205 NCBI_THROW(CProjBulderAppException, eFileOpen, candidate_path);
206 }
207
208 ifs_new.seekg(0, ios::end);
209 size_t file_length_new = ifs_new.tellg() - streampos(0);
210 ifs_new.seekg(0, ios::beg);
211
212 if (file_length_present != file_length_new) {
213 ifs_present.close();
214 ifs_new.close();
215 CDirEntry(present_path).Remove();
216 for (int a=0; a<2 && !CDirEntry(candidate_path).Rename(present_path); ++a)
217 SleepSec(1);
218 GetApp().RegisterGeneratedFile( present_path );
219 return true;
220 }
221
222 // Load both to memory
223 typedef AutoPtr<char, ArrayDeleter<char> > TAutoArray;
224 TAutoArray buf_present = TAutoArray(new char [file_length_present]);
225 TAutoArray buf_new = TAutoArray(new char [file_length_new]);
226
227 ifs_present.read(buf_present.get(), file_length_present);
228 ifs_new.read (buf_new.get(), file_length_new);
229
230 ifs_present.close();
231 ifs_new.close();
232
233 // If candidate file is not the same as present file it'll be a new file
234 if (memcmp(buf_present.get(), buf_new.get(), file_length_present) != 0) {
235 CDirEntry(present_path).Remove();
236 for (int a=0; a<2 && !CDirEntry(candidate_path).Rename(present_path); ++a)
237 SleepSec(1);
238 GetApp().RegisterGeneratedFile( present_path );
239 return true;
240 } else {
241 CDirEntry(candidate_path).Remove();
242 }
243 return false;
244 }
245
246 //-----------------------------------------------------------------------------
247
248 class CGuidGenerator
249 {
250 public:
251 CGuidGenerator(void);
252 ~CGuidGenerator(void);
253
254 string DoGenerateSlnGUID();
255 bool Insert(const string& guid, const string& path);
256 const string& GetGuidUser(const string& guid) const;
257
258 private:
259 string Generate12Chars(void);
260
261 const string root_guid; // root GUID for MSVC solutions
262 const string guid_base;
263 unsigned int m_Seed;
264 map<string,string> m_Trace;
265 };
266
267 CGuidGenerator guid_gen;
268
GenerateSlnGUID(void)269 string GenerateSlnGUID(void)
270 {
271 return guid_gen.DoGenerateSlnGUID();
272 }
273
IdentifySlnGUID(const string & source_dir,const CProjKey & proj)274 string IdentifySlnGUID(const string& source_dir, const CProjKey& proj)
275 {
276 string vcproj;
277 if (proj.Type() == CProjKey::eMsvc) {
278 vcproj = source_dir;
279 } else {
280 vcproj = GetApp().GetProjectTreeInfo().m_Compilers;
281 vcproj = CDirEntry::ConcatPath(vcproj,
282 GetApp().GetRegSettings().m_CompilersSubdir);
283 vcproj = CDirEntry::ConcatPath(vcproj,
284 GetApp().GetBuildType().GetTypeStr());
285 vcproj = CDirEntry::ConcatPath(vcproj,
286 GetApp().GetRegSettings().m_ProjectsSubdir);
287 vcproj = CDirEntry::ConcatPath(vcproj,
288 CDirEntry::CreateRelativePath(
289 GetApp().GetProjectTreeInfo().m_Src, source_dir));
290 vcproj = CDirEntry::AddTrailingPathSeparator(vcproj);
291 vcproj += CreateProjectName(proj);
292 vcproj += CMsvc7RegSettings::GetVcprojExt();
293 }
294 string guid;
295 if ( CDirEntry(vcproj).Exists() ) {
296 char buf[1024];
297 CNcbiIfstream is(vcproj.c_str(), IOS_BASE::in);
298 if (is.is_open()) {
299 while ( !is.eof() ) {
300 is.getline(buf, sizeof(buf));
301 buf[sizeof(buf)-1] = char(0);
302 string data(buf);
303 string::size_type start, end;
304 start = data.find("ProjectGUID");
305 if (start == string::npos) {
306 start = data.find("ProjectGuid");
307 }
308 if (start != string::npos) {
309 start = data.find('{',start);
310 if (start != string::npos) {
311 end = data.find('}',++start);
312 if (end != string::npos) {
313 guid = data.substr(start,end-start);
314 }
315 }
316 break;
317 }
318 }
319 }
320 }
321 if (!guid.empty() && !guid_gen.Insert(guid,vcproj)) {
322 PTB_WARNING_EX(vcproj, ePTB_ConfigurationError,
323 "MSVC Project GUID already in use by "
324 << guid_gen.GetGuidUser(guid));
325 if (proj.Type() != CProjKey::eMsvc) {
326 guid.erase();
327 }
328 }
329 if (!guid.empty()) {
330 return "{" + guid + "}";
331 }
332 return GenerateSlnGUID();
333 }
334
335
CGuidGenerator(void)336 CGuidGenerator::CGuidGenerator(void)
337 :root_guid("8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"),
338 guid_base("8BC9CEB8-8B4A-11D0-8D11-"),
339 m_Seed(0)
340 {
341 }
342
343
~CGuidGenerator(void)344 CGuidGenerator::~CGuidGenerator(void)
345 {
346 }
347
348
Generate12Chars(void)349 string CGuidGenerator::Generate12Chars(void)
350 {
351 CNcbiOstrstream ost;
352 ost.unsetf(ios::showbase);
353 ost.setf (ios::uppercase);
354 ost << hex << setw(12) << setfill('A') << m_Seed++ << ends << flush;
355 return ost.str();
356 }
357
Insert(const string & guid,const string & path)358 bool CGuidGenerator::Insert(const string& guid, const string& path)
359 {
360 if (!guid.empty() && guid != root_guid) {
361 if (m_Trace.find(guid) == m_Trace.end()) {
362 m_Trace[guid] = path;
363 return true;
364 }
365 if (!path.empty()) {
366 return m_Trace[guid] == path;
367 }
368 }
369 return false;
370 }
371
GetGuidUser(const string & guid) const372 const string& CGuidGenerator::GetGuidUser(const string& guid) const
373 {
374 map<string,string>::const_iterator i = m_Trace.find(guid);
375 if (i != m_Trace.end()) {
376 return i->second;
377 }
378 return kEmptyStr;
379 }
380
DoGenerateSlnGUID(void)381 string CGuidGenerator::DoGenerateSlnGUID(void)
382 {
383 for ( ;; ) {
384 //GUID prototype
385 string proto;// = guid_base + Generate12Chars();
386 #if NCBI_COMPILER_MSVC
387 GUID guid;
388 if (SUCCEEDED(CoCreateGuid(&guid))) {
389 CNcbiOstrstream out;
390 out.fill('0');
391 out.flags(ios::hex | ios::uppercase);
392 out << setw(8) << guid.Data1 << '-'
393 << setw(4) << guid.Data2 << '-'
394 << setw(4) << guid.Data3 << '-'
395 << setw(2) << (unsigned int)guid.Data4[0]
396 << setw(2) << (unsigned int)guid.Data4[1] << '-'
397 << setw(2) << (unsigned int)guid.Data4[2]
398 << setw(2) << (unsigned int)guid.Data4[3]
399 << setw(2) << (unsigned int)guid.Data4[4]
400 << setw(2) << (unsigned int)guid.Data4[5]
401 << setw(2) << (unsigned int)guid.Data4[6]
402 << setw(2) << (unsigned int)guid.Data4[7];
403 proto = CNcbiOstrstreamToString(out);
404 } else {
405 proto = guid_base + Generate12Chars();
406 }
407 #else
408 proto = guid_base + Generate12Chars();
409 #endif
410 if (Insert(proto,kEmptyStr)) {
411 return "{" + proto + "}";
412 }
413 }
414 }
415
416
SourceFileExt(const string & file_path)417 string SourceFileExt(const string& file_path)
418 {
419 string ext;
420 CDirEntry::SplitPath(file_path, NULL, NULL, &ext);
421
422 bool explicit_c = NStr::CompareNocase(ext, ".c" )== 0;
423 if (explicit_c && CFile(file_path).Exists()) {
424 return ".c";
425 }
426 bool explicit_cpp = NStr::CompareNocase(ext, ".cpp")== 0
427 || NStr::CompareNocase(ext, ".cxx")== 0
428 || NStr::CompareNocase(ext, ".cc")== 0;
429 if (explicit_cpp && CFile(file_path).Exists()) {
430 return ext;
431 }
432 string file = file_path + ".cpp";
433 if ( CFile(file).Exists() ) {
434 return ".cpp";
435 }
436 file += ".in";
437 if ( CFile(file).Exists() ) {
438 return ".cpp.in";
439 }
440 file = file_path + ".c";
441 if ( CFile(file).Exists() ) {
442 return ".c";
443 }
444 file += ".in";
445 if ( CFile(file).Exists() ) {
446 return ".c.in";
447 }
448 file += ".metal";
449 if ( CFile(file).Exists() ) {
450 return ".metal";
451 }
452 return "";
453 }
454
455
456 //-----------------------------------------------------------------------------
SConfigInfo(void)457 SConfigInfo::SConfigInfo(void)
458 :m_Debug(false), m_VTuneAddon(false), m_Unicode(false), m_rtType(rtUnknown)
459 {
460 }
461
SConfigInfo(const string & name,bool debug,const string & runtime_library)462 SConfigInfo::SConfigInfo(const string& name,
463 bool debug,
464 const string& runtime_library)
465 :m_Name (name),
466 m_RuntimeLibrary(runtime_library),
467 m_Debug (debug),
468 m_VTuneAddon(false),
469 m_Unicode(false),
470 m_rtType(rtUnknown)
471 {
472 DefineRtType();
473 }
474
SetRuntimeLibrary(const string & lib)475 void SConfigInfo::SetRuntimeLibrary(const string& lib)
476 {
477 m_RuntimeLibrary = CMsvcMetaMakefile::TranslateOpt(lib, "Configuration", "RuntimeLibrary");
478 DefineRtType();
479 }
480
DefineRtType()481 void SConfigInfo::DefineRtType()
482 {
483 if (m_RuntimeLibrary == "0" || m_RuntimeLibrary == "MultiThreaded") {
484 m_rtType = rtMultiThreaded;
485 } else if (m_RuntimeLibrary == "1" || m_RuntimeLibrary == "MultiThreadedDebug") {
486 m_rtType = rtMultiThreadedDebug;
487 } else if (m_RuntimeLibrary == "2" || m_RuntimeLibrary == "MultiThreadedDLL") {
488 m_rtType = rtMultiThreadedDLL;
489 } else if (m_RuntimeLibrary == "3" || m_RuntimeLibrary == "MultiThreadedDebugDLL") {
490 m_rtType = rtMultiThreadedDebugDLL;
491 } else if (m_RuntimeLibrary == "4") {
492 m_rtType = rtSingleThreaded;
493 } else if (m_RuntimeLibrary == "5") {
494 m_rtType = rtSingleThreadedDebug;
495 }
496 }
497
GetConfigFullName(void) const498 string SConfigInfo::GetConfigFullName(void) const
499 {
500 if (m_VTuneAddon && m_Unicode) {
501 return string("VTune_Unicode_") + m_Name;
502 } else if (m_VTuneAddon) {
503 return string("VTune_") + m_Name;
504 } else if (m_Unicode) {
505 return string("Unicode_") + m_Name;
506 } else {
507 return m_Name;
508 }
509 }
510
operator ==(const SConfigInfo & cfg) const511 bool SConfigInfo::operator== (const SConfigInfo& cfg) const
512 {
513 return
514 m_Name == cfg.m_Name &&
515 m_Debug == cfg.m_Debug &&
516 m_VTuneAddon == cfg.m_VTuneAddon &&
517 m_Unicode == cfg.m_Unicode &&
518 m_rtType == cfg.m_rtType;
519 }
520
s_Config_less(const SConfigInfo & x,const SConfigInfo & y)521 bool s_Config_less(const SConfigInfo& x, const SConfigInfo& y)
522 {
523 return NStr::CompareNocase(x.GetConfigFullName(), y.GetConfigFullName()) < 0;
524 }
525
LoadConfigInfoByNames(const CNcbiRegistry & registry,const list<string> & config_names,list<SConfigInfo> * configs)526 void LoadConfigInfoByNames(const CNcbiRegistry& registry,
527 const list<string>& config_names,
528 list<SConfigInfo>* configs)
529 {
530 ITERATE(list<string>, p, config_names) {
531
532 const string& config_name = *p;
533 SConfigInfo config;
534 config.m_Name = config_name;
535 config.m_Debug = registry.GetString(config_name,
536 "debug",
537 "FALSE") != "FALSE";
538 config.SetRuntimeLibrary( registry.GetString(config_name,
539 "runtimeLibraryOption","0"));
540 configs->push_back(config);
541 #if 0
542 // per CXX-4211
543 if (( config.m_Debug && GetApp().m_TweakVTuneD) ||
544 (!config.m_Debug && GetApp().m_TweakVTuneR))
545 {
546 config.m_VTuneAddon = true;
547 configs->push_back(config);
548 config.m_VTuneAddon = false;
549 }
550 #else
551 if (GetApp().m_AddUnicode) {
552 config.m_Unicode = true;
553 configs->push_back(config);
554 }
555 if (GetApp().m_TweakVTuneR) {
556 if (!config.m_Debug /*&& config.m_rtType == SConfigInfo::rtMultiThreadedDLL*/)
557 {
558 config.m_Unicode = false;
559 config.m_VTuneAddon = true;
560 configs->push_back(config);
561 if (GetApp().m_AddUnicode) {
562 config.m_Unicode = true;
563 configs->push_back(config);
564 }
565 }
566 }
567 #endif
568 }
569 configs->sort(s_Config_less);
570 }
571
572
573 //-----------------------------------------------------------------------------
574 #if defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
575 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion =
576 CMsvc7RegSettings::eXCode30;
577 string CMsvc7RegSettings::sm_MsvcVersionName = "30";
578
579 CMsvc7RegSettings::EMsvcPlatform CMsvc7RegSettings::sm_MsvcPlatform =
580 CMsvc7RegSettings::eXCode;
581 string CMsvc7RegSettings::sm_MsvcPlatformName = "i386";
582
583 #elif defined(NCBI_COMPILER_MSVC)
584
585 #if _MSC_VER >= 1900
586 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion =
587 CMsvc7RegSettings::eMsvc1400;
588 string CMsvc7RegSettings::sm_MsvcVersionName = "1400";
589 #elif _MSC_VER >= 1800
590 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion =
591 CMsvc7RegSettings::eMsvc1200;
592 string CMsvc7RegSettings::sm_MsvcVersionName = "1200";
593 #elif _MSC_VER >= 1700
594 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion =
595 CMsvc7RegSettings::eMsvc1100;
596 string CMsvc7RegSettings::sm_MsvcVersionName = "1100";
597 #elif _MSC_VER >= 1600
598 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion =
599 CMsvc7RegSettings::eMsvc1000;
600 string CMsvc7RegSettings::sm_MsvcVersionName = "1000";
601 #elif _MSC_VER >= 1500
602 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion =
603 CMsvc7RegSettings::eMsvc900;
604 string CMsvc7RegSettings::sm_MsvcVersionName = "900";
605 #elif _MSC_VER >= 1400
606 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion =
607 CMsvc7RegSettings::eMsvc800;
608 string CMsvc7RegSettings::sm_MsvcVersionName = "800";
609 #else
610 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion =
611 CMsvc7RegSettings::eMsvc710;
612 string CMsvc7RegSettings::sm_MsvcVersionName = "710";
613 #endif
614
615 #ifdef _WIN64
616 CMsvc7RegSettings::EMsvcPlatform CMsvc7RegSettings::sm_MsvcPlatform =
617 CMsvc7RegSettings::eMsvcX64;
618 string CMsvc7RegSettings::sm_MsvcPlatformName = "x64";
619 #else
620 CMsvc7RegSettings::EMsvcPlatform CMsvc7RegSettings::sm_MsvcPlatform =
621 CMsvc7RegSettings::eMsvcWin32;
622 string CMsvc7RegSettings::sm_MsvcPlatformName = "Win32";
623 #endif
624
625 #else // NCBI_COMPILER_MSVC
626
627 CMsvc7RegSettings::EMsvcVersion CMsvc7RegSettings::sm_MsvcVersion =
628 CMsvc7RegSettings::eMsvcNone;
629 string CMsvc7RegSettings::sm_MsvcVersionName = "none";
630
631 CMsvc7RegSettings::EMsvcPlatform CMsvc7RegSettings::sm_MsvcPlatform =
632 CMsvc7RegSettings::eUnix;
633 string CMsvc7RegSettings::sm_MsvcPlatformName = "Unix";
634
635 #endif // NCBI_COMPILER_MSVC
636 string CMsvc7RegSettings::sm_RequestedArchs = "";
637
IdentifyPlatform()638 void CMsvc7RegSettings::IdentifyPlatform()
639 {
640 #if defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
641 /*
642 string native( CNcbiApplication::Instance()->GetEnvironment().Get("HOSTTYPE"));
643 if (!native.empty()) {
644 sm_MsvcPlatformName = native;
645 }
646 string xcode( CNcbiApplication::Instance()->GetEnvironment().Get("XCODE_VERSION_MAJOR"));
647 if (xcode >= "0300") {
648 sm_MsvcVersion = eXCode30;
649 sm_MsvcVersionName = "30";
650 }
651 sm_MsvcPlatform = eXCode;
652 */
653 // sm_RequestedArchs = sm_MsvcPlatformName;
654
655 int ide = GetApp().m_Ide;
656 if (ide != 0) {
657 int i = ide;
658 if (i == 30) {
659 sm_MsvcVersion = eXCode30;
660 sm_MsvcVersionName = "30";
661 } else {
662 NCBI_THROW(CProjBulderAppException, eBuildConfiguration, "Unsupported IDE version");
663 }
664 }
665 if (!GetApp().m_Arch.empty()) {
666 string a = GetApp().m_Arch;
667 sm_MsvcPlatform = eXCode;
668 sm_RequestedArchs = a;
669 string tmp;
670 NStr::SplitInTwo(a, " ", sm_MsvcPlatformName, tmp);
671 }
672 #elif defined(NCBI_COMPILER_MSVC)
673 int ide = GetApp().m_Ide;
674 if (ide != 0) {
675 switch (ide) {
676 case 710:
677 sm_MsvcVersion = eMsvc710;
678 sm_MsvcVersionName = "710";
679 break;
680 case 800:
681 sm_MsvcVersion = eMsvc800;
682 sm_MsvcVersionName = "800";
683 break;
684 case 900:
685 sm_MsvcVersion = eMsvc900;
686 sm_MsvcVersionName = "900";
687 break;
688 case 1000:
689 sm_MsvcVersion = eMsvc1000;
690 sm_MsvcVersionName = "1000";
691 break;
692 case 1100:
693 sm_MsvcVersion = eMsvc1100;
694 sm_MsvcVersionName = "1100";
695 break;
696 case 1200:
697 sm_MsvcVersion = eMsvc1200;
698 sm_MsvcVersionName = "1200";
699 break;
700 case 1400:
701 sm_MsvcVersion = eMsvc1400;
702 sm_MsvcVersionName = NStr::NumericToString(ide);
703 break;
704 case 1500:
705 default:
706 sm_MsvcVersion = eMsvc1500;
707 sm_MsvcVersionName = NStr::NumericToString(ide);
708 // NCBI_THROW(CProjBulderAppException, eBuildConfiguration, "Unsupported IDE version");
709 break;
710 }
711 }
712 if (!GetApp().m_Arch.empty()) {
713 string a = GetApp().m_Arch;
714 if (a == "Win32") {
715 sm_MsvcPlatform = eMsvcWin32;
716 sm_RequestedArchs = sm_MsvcPlatformName = "Win32";
717 } else if (a == "x64") {
718 sm_MsvcPlatform = eMsvcX64;
719 sm_RequestedArchs = sm_MsvcPlatformName = "x64";
720 } else {
721 NCBI_THROW(CProjBulderAppException, eBuildConfiguration, "Unsupported build platform");
722 }
723 }
724 #endif
725 }
726
GetMsvcRegSection(void)727 string CMsvc7RegSettings::GetMsvcRegSection(void)
728 {
729 if (GetMsvcPlatform() == eUnix) {
730 return UNIX_REG_SECTION;
731 } else if (GetMsvcPlatform() == eXCode) {
732 return XCODE_REG_SECTION;
733 }
734 return MSVC_REG_SECTION;
735 }
736
GetMsvcSection(void)737 string CMsvc7RegSettings::GetMsvcSection(void)
738 {
739 string s(GetMsvcRegSection());
740 if (GetMsvcPlatform() == eUnix) {
741 return s;
742 } else if (GetMsvcPlatform() == eXCode) {
743 s += GetMsvcVersionName();
744 string arch(GetRequestedArchs());
745 if (arch != "i386") {
746 NStr::ReplaceInPlace(arch, ",", " ");
747 list<string> lst;
748 NStr::Split(arch, " ", lst, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
749 lst.sort();
750 arch = NStr::Join(lst,"_");
751 s += "." + arch;
752 }
753 return s;
754 }
755 s += GetMsvcVersionName();
756 if (GetMsvcPlatform() != eMsvcWin32) {
757 s += "." + GetMsvcPlatformName();
758 }
759 return s;
760 }
761
CMsvc7RegSettings(void)762 CMsvc7RegSettings::CMsvc7RegSettings(void)
763 {
764 }
765
GetProjectFileFormatVersion(void)766 string CMsvc7RegSettings::GetProjectFileFormatVersion(void)
767 {
768 if (GetMsvcVersion() == eMsvc710) {
769 return "7.10";
770 } else if (GetMsvcVersion() == eMsvc800) {
771 return "8.00";
772 } else if (GetMsvcVersion() == eMsvc900) {
773 return "9.00";
774 } else if (GetMsvcVersion() == eMsvc1000 ||
775 GetMsvcVersion() == eMsvc1100 ||
776 GetMsvcVersion() == eMsvc1200) {
777 return "10.0.30319.1";
778 }
779 return "";
780 }
GetSolutionFileFormatVersion(void)781 string CMsvc7RegSettings::GetSolutionFileFormatVersion(void)
782 {
783 if (GetMsvcVersion() == eMsvc710) {
784 return "8.00";
785 } else if (GetMsvcVersion() == eMsvc800) {
786 return "9.00";
787 } else if (GetMsvcVersion() == eMsvc900) {
788 return "10.00\n# Visual Studio 2008";
789 } else if (GetMsvcVersion() == eMsvc1000) {
790 return "11.00\n# Visual Studio 2010";
791 } else if (GetMsvcVersion() == eMsvc1100) {
792 return "12.00\n# Visual Studio 2012";
793 } else if (GetMsvcVersion() == eMsvc1200) {
794 return "12.00\n# Visual Studio 2013";
795 } else if (GetMsvcVersion() >= eMsvc1400) {
796 return GetApp().GetRegSettings().m_Version;
797 }
798 return "";
799 }
800
GetConfigNameKeyword(void)801 string CMsvc7RegSettings::GetConfigNameKeyword(void)
802 {
803 if (GetMsvcPlatform() < eUnix) {
804 if (GetMsvcVersion() < eMsvc1000) {
805 return MSVC_CONFIGNAME;
806 } else {
807 return "$(Configuration)";
808 }
809 } else if (GetMsvcPlatform() == eXCode) {
810 return XCODE_CONFIGNAME;
811 }
812 return "";
813 }
814
GetVcprojExt(void)815 string CMsvc7RegSettings::GetVcprojExt(void)
816 {
817 if (GetMsvcPlatform() < eUnix) {
818 if (GetMsvcVersion() < eMsvc1000) {
819 return MSVC_PROJECT_FILE_EXT;
820 } else {
821 return ".vcxproj";
822 }
823 } else if (GetMsvcPlatform() == eXCode) {
824 return ".xcodeproj";
825 }
826 return "";
827 }
828
GetTopBuilddir(void)829 string CMsvc7RegSettings::GetTopBuilddir(void)
830 {
831 string section(CMsvc7RegSettings::GetMsvcRegSection());
832 string top( GetApp().GetConfig().GetString(section, "TopBuilddir", ""));
833 if (!top.empty()) {
834 top = CDirEntry::ConcatPath(CDirEntry(GetApp().m_Solution).GetDir(), top);
835 if (!CFile(top).Exists()) {
836 top.clear();
837 }
838
839 }
840 return top;
841 }
842
IsSubdir(const string & abs_parent_dir,const string & abs_dir)843 bool IsSubdir(const string& abs_parent_dir, const string& abs_dir)
844 {
845 return NStr::StartsWith(abs_dir, abs_parent_dir);
846 }
847
848
GetOpt(const CPtbRegistry & registry,const string & section,const string & opt,const string & config)849 string GetOpt(const CPtbRegistry& registry,
850 const string& section,
851 const string& opt,
852 const string& config)
853 {
854 string section_spec = section + '.' + config;
855 string val_spec = registry.Get(section_spec, opt);
856 if ( !val_spec.empty() )
857 return val_spec;
858
859 return registry.Get(section, opt);
860 }
861
862
GetOpt(const CPtbRegistry & registry,const string & section,const string & opt,const SConfigInfo & config)863 string GetOpt(const CPtbRegistry& registry,
864 const string& section,
865 const string& opt,
866 const SConfigInfo& config)
867 {
868 const string& version = CMsvc7RegSettings::GetMsvcVersionName();
869 const string& platform = CMsvc7RegSettings::GetMsvcPlatformName();
870 string build = GetApp().GetBuildType().GetTypeStr();
871 string spec = config.m_Debug ? "debug": "release";
872 string cfgName(config.m_Name), cfgFullName(config.GetConfigFullName());
873 string value, s;
874
875 if (cfgName != cfgFullName) {
876 s.assign(section).append(1,'.').append(build).append(1,'.').append(spec).append(1,'.').append(cfgFullName);
877 value = registry.Get(s, opt); if (!value.empty()) { return value;}
878
879 s.assign(section).append(1,'.').append(spec).append(1,'.').append(cfgFullName);
880 value = registry.Get(s, opt); if (!value.empty()) { return value;}
881 }
882 s.assign(section).append(1,'.').append(build).append(1,'.').append(spec).append(1,'.').append(cfgName);
883 value = registry.Get(s, opt); if (!value.empty()) { return value;}
884
885 s.assign(section).append(1,'.').append(spec).append(1,'.').append(cfgName);
886 value = registry.Get(s, opt); if (!value.empty()) { return value;}
887
888 s.assign(section).append(1,'.').append(build).append(1,'.').append(spec);
889 value = registry.Get(s, opt); if (!value.empty()) { return value;}
890
891 s.assign(section).append(1,'.').append(version).append(1,'.').append(spec);
892 value = registry.Get(s, opt); if (!value.empty()) { return value;}
893
894 s.assign(section).append(1,'.').append(spec);
895 value = registry.Get(s, opt); if (!value.empty()) { return value;}
896
897 s.assign(section).append(1,'.').append(build);
898 value = registry.Get(s, opt); if (!value.empty()) { return value;}
899
900 s.assign(section).append(1,'.').append(platform);
901 value = registry.Get(s, opt); if (!value.empty()) { return value;}
902
903 s.assign(section).append(1,'.').append(version);
904 value = registry.Get(s, opt); if (!value.empty()) { return value;}
905
906 s.assign(section);
907 value = registry.Get(s, opt); if (!value.empty()) { return value;}
908 return value;
909 }
910
911
912
ConfigName(const string & config)913 string ConfigName(const string& config)
914 {
915 return config +'|'+ CMsvc7RegSettings::GetMsvcPlatformName();
916 }
917
918
919 //-----------------------------------------------------------------------------
920 #if NCBI_COMPILER_MSVC
921
CSrcToFilterInserterWithPch(const string & project_id,const list<SConfigInfo> & configs,const string & project_dir)922 CSrcToFilterInserterWithPch::CSrcToFilterInserterWithPch
923 (const string& project_id,
924 const list<SConfigInfo>& configs,
925 const string& project_dir)
926 : m_ProjectId (project_id),
927 m_Configs (configs),
928 // see __USE_DISABLED_CFGS__ in msvc_prj_generator.cpp
929 #if 1
930 m_AllConfigs (GetApp().GetRegSettings().m_ConfigInfo),
931 #else
932 m_AllConfigs (configs),
933 #endif
934 m_ProjectDir (project_dir)
935 {
936 }
937
938
~CSrcToFilterInserterWithPch(void)939 CSrcToFilterInserterWithPch::~CSrcToFilterInserterWithPch(void)
940 {
941 }
942
943
InsertFile(CRef<CFilter> & filter,const string & rel_source_file,const string & pch_default,const string & enable_cfg)944 void CSrcToFilterInserterWithPch::InsertFile(CRef<CFilter>& filter,
945 const string& rel_source_file,
946 const string& pch_default,
947 const string& enable_cfg)
948 {
949 CRef<CFFile> file(new CFFile());
950 file->SetAttlist().SetRelativePath(rel_source_file);
951 //
952 TPch pch_usage = DefinePchUsage(m_ProjectDir, rel_source_file, pch_default);
953 //
954 // For each configuration
955 ITERATE(list<SConfigInfo>, iconfig, m_AllConfigs) {
956 const string& config = (*iconfig).GetConfigFullName();
957 CRef<CFileConfiguration> file_config(new CFileConfiguration());
958 file_config->SetAttlist().SetName(ConfigName(config));
959
960 if (m_Configs.size() != m_AllConfigs.size() &&
961 find(m_Configs.begin(), m_Configs.end(), *iconfig) == m_Configs.end()) {
962 file_config->SetAttlist().SetExcludedFromBuild("true");
963 }
964 else if ( !enable_cfg.empty() && enable_cfg != config ) {
965 file_config->SetAttlist().SetExcludedFromBuild("true");
966 }
967
968 CRef<CTool> compilerl_tool(new CTool());
969 compilerl_tool->SetAttlist().SetName("VCCLCompilerTool");
970
971 if (pch_usage.first == eCreate) {
972 compilerl_tool->SetAttlist().SetPreprocessorDefinitions
973 (GetApp().GetMetaMakefile().GetPchUsageDefine());
974 compilerl_tool->SetAttlist().SetUsePrecompiledHeader("1");
975 compilerl_tool->SetAttlist().SetPrecompiledHeaderThrough
976 (pch_usage.second);
977 } else if (pch_usage.first == eUse) {
978 compilerl_tool->SetAttlist().SetPreprocessorDefinitions
979 (GetApp().GetMetaMakefile().GetPchUsageDefine());
980 #if 0
981 // moved into msvc_prj_generator.cpp to become project default
982 if (CMsvc7RegSettings::GetMsvcVersion() >= CMsvc7RegSettings::eMsvc800) {
983 compilerl_tool->SetAttlist().SetUsePrecompiledHeader("2");
984 } else {
985 compilerl_tool->SetAttlist().SetUsePrecompiledHeader("3");
986 }
987 #endif
988 if (pch_usage.second != pch_default) {
989 compilerl_tool->SetAttlist().SetPrecompiledHeaderThrough
990 (pch_usage.second);
991 }
992 }
993 else {
994 compilerl_tool->SetAttlist().SetUsePrecompiledHeader("0");
995 // compilerl_tool->SetAttlist().SetPrecompiledHeaderThrough("");
996 }
997 file_config->SetTool(*compilerl_tool);
998 file->SetFileConfiguration().push_back(file_config);
999 }
1000 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1001 ce->SetFile(*file);
1002 filter->SetFF().SetFF().push_back(ce);
1003 return;
1004 }
1005
1006
1007 void
operator ()(CRef<CFilter> & filter,const string & rel_source_file,const string & pch_default)1008 CSrcToFilterInserterWithPch::operator()(CRef<CFilter>& filter,
1009 const string& rel_source_file,
1010 const string& pch_default)
1011 {
1012 if ( NStr::Find(rel_source_file, ".@config@") == NPOS ) {
1013 // Ordinary file
1014 InsertFile(filter, rel_source_file, pch_default);
1015 } else {
1016 // Configurable file
1017
1018 // Exclude from build all file versions
1019 // except one for current configuration.
1020 ITERATE(list<SConfigInfo>, icfg, m_AllConfigs) {
1021 const string& cfg = (*icfg).GetConfigFullName();
1022 string source_file = NStr::Replace(rel_source_file,
1023 ".@config@", "." + cfg);
1024 InsertFile(filter, source_file, pch_default, cfg);
1025 }
1026 }
1027 }
1028
1029 CSrcToFilterInserterWithPch::TPch
DefinePchUsage(const string & project_dir,const string & rel_source_file,const string & pch_file)1030 CSrcToFilterInserterWithPch::DefinePchUsage(const string& project_dir,
1031 const string& rel_source_file,
1032 const string& pch_file)
1033 {
1034 if ( pch_file.empty() )
1035 return TPch(eNotUse, "");
1036
1037 string abs_source_file =
1038 CDirEntry::ConcatPath(project_dir, rel_source_file);
1039 abs_source_file = CDirEntry::NormalizePath(abs_source_file);
1040
1041 // .c files - not use PCH
1042 string ext;
1043 CDirEntry::SplitPath(abs_source_file, NULL, NULL, &ext);
1044 if ( NStr::CompareNocase(ext, ".c") == 0)
1045 return TPch(eNotUse, "");
1046
1047 /*
1048 MSVC documentation says:
1049 Although you can use only one precompiled header (.pch) file per source file,
1050 you can use multiple .pch files in a project.
1051 Apple XCode:
1052 Each target can have only one prefix header
1053 */
1054 if (m_PchHeaders.find(pch_file) == m_PchHeaders.end()) {
1055 // New PCH - this source file will create it
1056 m_PchHeaders.insert(pch_file);
1057 return TPch(eCreate, pch_file);
1058 } else {
1059 // Use PCH (previously created)
1060 return TPch(eUse, pch_file);
1061 }
1062 }
1063
1064
1065 //-----------------------------------------------------------------------------
1066
CBasicProjectsFilesInserter(CVisualStudioProject * vcproj,const string & project_id,const list<SConfigInfo> & configs,const string & project_dir)1067 CBasicProjectsFilesInserter::CBasicProjectsFilesInserter
1068 (CVisualStudioProject* vcproj,
1069 const string& project_id,
1070 const list<SConfigInfo>& configs,
1071 const string& project_dir)
1072 : m_Vcproj (vcproj),
1073 m_SrcInserter(project_id, configs, project_dir),
1074 m_Filters (project_dir)
1075 {
1076 m_Filters.Initilize();
1077 }
1078
1079
~CBasicProjectsFilesInserter(void)1080 CBasicProjectsFilesInserter::~CBasicProjectsFilesInserter(void)
1081 {
1082 }
1083
AddSourceFile(const string & rel_file_path,const string & pch_default)1084 void CBasicProjectsFilesInserter::AddSourceFile(
1085 const string& rel_file_path, const string& pch_default)
1086 {
1087 m_Filters.AddSourceFile(m_SrcInserter, rel_file_path, pch_default);
1088 }
1089
AddHeaderFile(const string & rel_file_path)1090 void CBasicProjectsFilesInserter::AddHeaderFile(const string& rel_file_path)
1091 {
1092 m_Filters.AddHeaderFile(rel_file_path);
1093 }
1094
AddInlineFile(const string & rel_file_path)1095 void CBasicProjectsFilesInserter::AddInlineFile(const string& rel_file_path)
1096 {
1097 m_Filters.AddInlineFile(rel_file_path);
1098 }
1099
Finalize(void)1100 void CBasicProjectsFilesInserter::Finalize(void)
1101 {
1102 if (m_Filters.m_SourceFiles->IsSetFF()) {
1103 m_Vcproj->SetFiles().SetFilter().push_back(m_Filters.m_SourceFiles);
1104 }
1105 if ( m_Filters.m_HeaderFilesPrivate->IsSetFF() ) {
1106 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1107 ce->SetFilter(*m_Filters.m_HeaderFilesPrivate);
1108 m_Filters.m_HeaderFiles->SetFF().SetFF().push_back(ce);
1109 }
1110 if ( m_Filters.m_HeaderFilesImpl->IsSetFF() ) {
1111 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1112 ce->SetFilter(*m_Filters.m_HeaderFilesImpl);
1113 m_Filters.m_HeaderFiles->SetFF().SetFF().push_back(ce);
1114 }
1115 if (m_Filters.m_HeaderFiles->IsSetFF()) {
1116 m_Vcproj->SetFiles().SetFilter().push_back(m_Filters.m_HeaderFiles);
1117 }
1118 if (m_Filters.m_InlineFiles->IsSetFF()) {
1119 m_Vcproj->SetFiles().SetFilter().push_back(m_Filters.m_InlineFiles);
1120 }
1121 }
1122
1123 //-----------------------------------------------------------------------------
1124
s_IsPrivateHeader(const string & header_abs_path)1125 static bool s_IsPrivateHeader(const string& header_abs_path)
1126 {
1127 string src_dir = GetApp().GetProjectTreeInfo().m_Src;
1128 return header_abs_path.find(src_dir) != NPOS;
1129
1130 }
1131
s_IsImplHeader(const string & header_abs_path)1132 static bool s_IsImplHeader(const string& header_abs_path)
1133 {
1134 string src_trait = CDirEntry::GetPathSeparator() +
1135 GetApp().GetProjectTreeInfo().m_Impl +
1136 CDirEntry::GetPathSeparator();
1137 return header_abs_path.find(src_trait) != NPOS;
1138 }
1139
1140 //-----------------------------------------------------------------------------
1141
SFiltersItem(void)1142 CBasicProjectsFilesInserter::SFiltersItem::SFiltersItem(void)
1143 {
1144 }
SFiltersItem(const string & project_dir)1145 CBasicProjectsFilesInserter::SFiltersItem::SFiltersItem
1146 (const string& project_dir)
1147 :m_ProjectDir(project_dir)
1148 {
1149 }
1150
Initilize(void)1151 void CBasicProjectsFilesInserter::SFiltersItem::Initilize(void)
1152 {
1153 m_SourceFiles.Reset(new CFilter());
1154 m_SourceFiles->SetAttlist().SetName("Source Files");
1155 m_SourceFiles->SetAttlist().SetFilter
1156 ("cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx");
1157
1158 m_HeaderFiles.Reset(new CFilter());
1159 m_HeaderFiles->SetAttlist().SetName("Header Files");
1160 m_HeaderFiles->SetAttlist().SetFilter("h;hpp;hxx;hm;inc");
1161
1162 m_HeaderFilesPrivate.Reset(new CFilter());
1163 m_HeaderFilesPrivate->SetAttlist().SetName("Private");
1164 m_HeaderFilesPrivate->SetAttlist().SetFilter("h;hpp;hxx;hm;inc");
1165
1166 m_HeaderFilesImpl.Reset(new CFilter());
1167 m_HeaderFilesImpl->SetAttlist().SetName("Impl");
1168 m_HeaderFilesImpl->SetAttlist().SetFilter("h;hpp;hxx;hm;inc");
1169
1170 m_InlineFiles.Reset(new CFilter());
1171 m_InlineFiles->SetAttlist().SetName("Inline Files");
1172 m_InlineFiles->SetAttlist().SetFilter("inl");
1173 }
1174
1175
AddSourceFile(CSrcToFilterInserterWithPch & inserter_w_pch,const string & rel_file_path,const string & pch_default)1176 void CBasicProjectsFilesInserter::SFiltersItem::AddSourceFile
1177 (CSrcToFilterInserterWithPch& inserter_w_pch,
1178 const string& rel_file_path,
1179 const string& pch_default)
1180 {
1181 inserter_w_pch(m_SourceFiles, rel_file_path, pch_default);
1182 }
1183
AddHeaderFile(const string & rel_file_path)1184 void CBasicProjectsFilesInserter::SFiltersItem::AddHeaderFile
1185 (const string& rel_file_path)
1186 {
1187 CRef< CFFile > file(new CFFile());
1188 file->SetAttlist().SetRelativePath(rel_file_path);
1189
1190 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1191 ce->SetFile(*file);
1192
1193 string abs_header_path =
1194 CDirEntry::ConcatPath(m_ProjectDir, rel_file_path);
1195 abs_header_path = CDirEntry::NormalizePath(abs_header_path);
1196 if ( s_IsPrivateHeader(abs_header_path) ) {
1197 m_HeaderFilesPrivate->SetFF().SetFF().push_back(ce);
1198 } else if ( s_IsImplHeader(abs_header_path) ) {
1199 m_HeaderFilesImpl->SetFF().SetFF().push_back(ce);
1200 } else {
1201 m_HeaderFiles->SetFF().SetFF().push_back(ce);
1202 }
1203 }
1204
1205
AddInlineFile(const string & rel_file_path)1206 void CBasicProjectsFilesInserter::SFiltersItem::AddInlineFile
1207 (const string& rel_file_path)
1208 {
1209 CRef< CFFile > file(new CFFile());
1210 file->SetAttlist().SetRelativePath(rel_file_path);
1211
1212 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1213 ce->SetFile(*file);
1214 m_InlineFiles->SetFF().SetFF().push_back(ce);
1215 }
1216
1217
1218 //-----------------------------------------------------------------------------
1219
CDllProjectFilesInserter(CVisualStudioProject * vcproj,const CProjKey dll_project_key,const list<SConfigInfo> & configs,const string & project_dir)1220 CDllProjectFilesInserter::CDllProjectFilesInserter
1221 (CVisualStudioProject* vcproj,
1222 const CProjKey dll_project_key,
1223 const list<SConfigInfo>& configs,
1224 const string& project_dir)
1225 :m_Vcproj (vcproj),
1226 m_DllProjectKey (dll_project_key),
1227 m_SrcInserter (dll_project_key.Id(),
1228 configs,
1229 project_dir),
1230 m_ProjectDir (project_dir),
1231 m_PrivateFilters(project_dir)
1232 {
1233 // Private filters initilization
1234 m_PrivateFilters.m_SourceFiles.Reset(new CFilter());
1235 m_PrivateFilters.m_SourceFiles->SetAttlist().SetName("Source Files");
1236 m_PrivateFilters.m_SourceFiles->SetAttlist().SetFilter
1237 ("cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx");
1238
1239 m_PrivateFilters.m_HeaderFiles.Reset(new CFilter());
1240 m_PrivateFilters.m_HeaderFiles->SetAttlist().SetName("Header Files");
1241 m_PrivateFilters.m_HeaderFiles->SetAttlist().SetFilter("h;hpp;hxx;hm;inc");
1242
1243 m_PrivateFilters.m_HeaderFilesPrivate.Reset(new CFilter());
1244 m_PrivateFilters.m_HeaderFilesPrivate->SetAttlist().SetName("Private");
1245 m_PrivateFilters.m_HeaderFilesPrivate->SetAttlist().SetFilter("h;hpp;hxx;hm;inc");
1246
1247 m_PrivateFilters.m_HeaderFilesImpl.Reset(new CFilter());
1248 m_PrivateFilters.m_HeaderFilesImpl->SetAttlist().SetName("Impl");
1249 m_PrivateFilters.m_HeaderFilesImpl->SetAttlist().SetFilter("h;hpp;hxx;hm;inc");
1250
1251 m_PrivateFilters.m_InlineFiles.Reset(new CFilter());
1252 m_PrivateFilters.m_InlineFiles->SetAttlist().SetName("Inline Files");
1253 m_PrivateFilters.m_InlineFiles->SetAttlist().SetFilter("inl");
1254
1255 // Hosted Libraries filter (folder)
1256 m_HostedLibrariesRootFilter.Reset(new CFilter());
1257 m_HostedLibrariesRootFilter->SetAttlist().SetName("Hosted Libraries");
1258 m_HostedLibrariesRootFilter->SetAttlist().SetFilter("");
1259 }
1260
1261
~CDllProjectFilesInserter(void)1262 CDllProjectFilesInserter::~CDllProjectFilesInserter(void)
1263 {
1264 }
1265
1266
AddSourceFile(const string & rel_file_path,const string & pch_default)1267 void CDllProjectFilesInserter::AddSourceFile (
1268 const string& rel_file_path, const string& pch_default)
1269 {
1270 string abs_path = CDirEntry::ConcatPath(m_ProjectDir, rel_file_path);
1271 abs_path = CDirEntry::NormalizePath(abs_path);
1272
1273 CProjKey proj_key = GetApp().GetDllFilesDistr().GetSourceLib(abs_path, m_DllProjectKey);
1274
1275 if (proj_key == CProjKey()) {
1276 m_PrivateFilters.AddSourceFile(m_SrcInserter, rel_file_path, pch_default);
1277 return;
1278 }
1279
1280 THostedLibs::iterator p = m_HostedLibs.find(proj_key);
1281 if (p != m_HostedLibs.end()) {
1282 TFiltersItem& filters_item = p->second;
1283 filters_item.AddSourceFile(m_SrcInserter, rel_file_path, pch_default);
1284 return;
1285 }
1286
1287 TFiltersItem new_item(m_ProjectDir);
1288 new_item.Initilize();
1289 new_item.AddSourceFile(m_SrcInserter, rel_file_path, pch_default);
1290 m_HostedLibs[proj_key] = new_item;
1291 }
1292
AddHeaderFile(const string & rel_file_path)1293 void CDllProjectFilesInserter::AddHeaderFile(const string& rel_file_path)
1294 {
1295 string abs_path = CDirEntry::ConcatPath(m_ProjectDir, rel_file_path);
1296 abs_path = CDirEntry::NormalizePath(abs_path);
1297
1298 CProjKey proj_key = GetApp().GetDllFilesDistr().GetHeaderLib(abs_path, m_DllProjectKey);
1299
1300 if (proj_key == CProjKey()) {
1301 CProjectItemsTree::TProjects::const_iterator p =
1302 GetApp().GetWholeTree().m_Projects.find(m_DllProjectKey);
1303 if (p != GetApp().GetWholeTree().m_Projects.end()) {
1304 const CProjItem& proj_item = p->second;
1305 if (NStr::StartsWith(abs_path, proj_item.m_SourcesBaseDir, NStr::eNocase)) {
1306 m_PrivateFilters.AddHeaderFile(rel_file_path);
1307 }
1308 }
1309 return;
1310 }
1311
1312 THostedLibs::iterator p = m_HostedLibs.find(proj_key);
1313 if (p != m_HostedLibs.end()) {
1314 TFiltersItem& filters_item = p->second;
1315 filters_item.AddHeaderFile(rel_file_path);
1316 return;
1317 }
1318
1319 TFiltersItem new_item(m_ProjectDir);
1320 new_item.Initilize();
1321 new_item.AddHeaderFile(rel_file_path);
1322 m_HostedLibs[proj_key] = new_item;
1323 }
1324
AddInlineFile(const string & rel_file_path)1325 void CDllProjectFilesInserter::AddInlineFile(const string& rel_file_path)
1326 {
1327 string abs_path = CDirEntry::ConcatPath(m_ProjectDir, rel_file_path);
1328 abs_path = CDirEntry::NormalizePath(abs_path);
1329
1330 CProjKey proj_key = GetApp().GetDllFilesDistr().GetInlineLib(abs_path, m_DllProjectKey);
1331
1332 if (proj_key == CProjKey()) {
1333 m_PrivateFilters.AddInlineFile(rel_file_path);
1334 return;
1335 }
1336
1337 THostedLibs::iterator p = m_HostedLibs.find(proj_key);
1338 if (p != m_HostedLibs.end()) {
1339 TFiltersItem& filters_item = p->second;
1340 filters_item.AddInlineFile(rel_file_path);
1341 return;
1342 }
1343
1344 TFiltersItem new_item(m_ProjectDir);
1345 new_item.Initilize();
1346 new_item.AddInlineFile(rel_file_path);
1347 m_HostedLibs[proj_key] = new_item;
1348 }
1349
1350
Finalize(void)1351 void CDllProjectFilesInserter::Finalize(void)
1352 {
1353 m_Vcproj->SetFiles().SetFilter().push_back(m_PrivateFilters.m_SourceFiles);
1354
1355 if ( !m_PrivateFilters.m_HeaderFilesPrivate->IsSetFF() ) {
1356 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1357 ce->SetFilter(*m_PrivateFilters.m_HeaderFilesPrivate);
1358 m_PrivateFilters.m_HeaderFiles->SetFF().SetFF().push_back(ce);
1359 }
1360 if ( !m_PrivateFilters.m_HeaderFilesImpl->IsSetFF() ) {
1361 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1362 ce->SetFilter(*m_PrivateFilters.m_HeaderFilesImpl);
1363 m_PrivateFilters.m_HeaderFiles->SetFF().SetFF().push_back(ce);
1364 }
1365 m_Vcproj->SetFiles().SetFilter().push_back(m_PrivateFilters.m_HeaderFiles);
1366
1367 m_Vcproj->SetFiles().SetFilter().push_back(m_PrivateFilters.m_InlineFiles);
1368
1369 NON_CONST_ITERATE(THostedLibs, p, m_HostedLibs) {
1370
1371 const CProjKey& proj_key = p->first;
1372 TFiltersItem& filters_item = p->second;
1373
1374 CRef<CFilter> hosted_lib_filter(new CFilter());
1375 hosted_lib_filter->SetAttlist().SetName(CreateProjectName(proj_key));
1376 hosted_lib_filter->SetAttlist().SetFilter("");
1377
1378 {{
1379 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1380 ce->SetFilter(*(filters_item.m_SourceFiles));
1381 hosted_lib_filter->SetFF().SetFF().push_back(ce);
1382 }}
1383
1384 if ( filters_item.m_HeaderFilesPrivate->IsSetFF() ) {
1385 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1386 ce->SetFilter(*filters_item.m_HeaderFilesPrivate);
1387 filters_item.m_HeaderFiles->SetFF().SetFF().push_back(ce);
1388 }
1389 if ( filters_item.m_HeaderFilesImpl->IsSetFF() ) {
1390 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1391 ce->SetFilter(*filters_item.m_HeaderFilesImpl);
1392 filters_item.m_HeaderFiles->SetFF().SetFF().push_back(ce);
1393 }
1394 {{
1395 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1396 ce->SetFilter(*(filters_item.m_HeaderFiles));
1397 hosted_lib_filter->SetFF().SetFF().push_back(ce);
1398 }}
1399 {{
1400 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1401 ce->SetFilter(*(filters_item.m_InlineFiles));
1402 hosted_lib_filter->SetFF().SetFF().push_back(ce);
1403 }}
1404 {{
1405 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1406 ce->SetFilter(*hosted_lib_filter);
1407 m_HostedLibrariesRootFilter->SetFF().SetFF().push_back(ce);
1408 }}
1409 }
1410 m_Vcproj->SetFiles().SetFilter().push_back(m_HostedLibrariesRootFilter);
1411 }
1412
1413
1414 //-----------------------------------------------------------------------------
1415
AddCustomBuildFileToFilter(CRef<CFilter> & filter,const list<SConfigInfo> configs,const string & project_dir,const SCustomBuildInfo & build_info)1416 void AddCustomBuildFileToFilter(CRef<CFilter>& filter,
1417 const list<SConfigInfo> configs,
1418 const string& project_dir,
1419 const SCustomBuildInfo& build_info)
1420 {
1421 CRef<CFFile> file(new CFFile());
1422 file->SetAttlist().SetRelativePath
1423 (CDirEntry::CreateRelativePath(project_dir,
1424 build_info.m_SourceFile));
1425
1426 ITERATE(list<SConfigInfo>, n, configs) {
1427 // Iterate all configurations
1428 const string& config = (*n).GetConfigFullName();
1429
1430 CRef<CFileConfiguration> file_config(new CFileConfiguration());
1431 file_config->SetAttlist().SetName(ConfigName(config));
1432
1433 CRef<CTool> custom_build(new CTool());
1434 custom_build->SetAttlist().SetName("VCCustomBuildTool");
1435 custom_build->SetAttlist().SetDescription(build_info.m_Description);
1436 custom_build->SetAttlist().SetCommandLine(build_info.m_CommandLine);
1437 custom_build->SetAttlist().SetOutputs(build_info.m_Outputs);
1438 custom_build->SetAttlist().SetAdditionalDependencies
1439 (build_info.m_AdditionalDependencies);
1440 file_config->SetTool(*custom_build);
1441
1442 file->SetFileConfiguration().push_back(file_config);
1443 }
1444 CRef< CFilter_Base::C_FF::C_E > ce(new CFilter_Base::C_FF::C_E());
1445 ce->SetFile(*file);
1446 filter->SetFF().SetFF().push_back(ce);
1447 }
1448
1449 #endif //NCBI_COMPILER_MSVC
1450
1451
SameRootDirs(const string & dir1,const string & dir2)1452 bool SameRootDirs(const string& dir1, const string& dir2)
1453 {
1454 if ( dir1.empty() )
1455 return false;
1456 if ( dir2.empty() )
1457 return false;
1458 #if NCBI_COMPILER_MSVC
1459 return tolower((unsigned char)(dir1[0])) == tolower((unsigned char)(dir2[0]));
1460 // return dir1[0] == dir2[0];
1461 #else
1462 if (dir1[0] == '/' && dir2[0] == '/') {
1463 string::size_type n1= dir1.find_first_of('/', 1);
1464 string::size_type n2= dir2.find_first_of('/', 1);
1465 if (n1 != string::npos && n1 == n2) {
1466 return dir1.compare(0,n1,dir2,0,n2) == 0;
1467 }
1468 }
1469 #endif
1470 return false;
1471 }
1472
1473
CreateProjectName(const CProjKey & project_id)1474 string CreateProjectName(const CProjKey& project_id)
1475 {
1476 switch (project_id.Type()) {
1477 case CProjKey::eApp:
1478 return project_id.Id() + ".exe";
1479 case CProjKey::eLib:
1480 return project_id.Id() + ".lib";
1481 case CProjKey::eDll:
1482 return project_id.Id() + ".dll";
1483 case CProjKey::eMsvc:
1484 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
1485 return project_id.Id() + ".unix";
1486 }
1487 return project_id.Id();// + ".vcproj";
1488 case CProjKey::eDataSpec:
1489 return project_id.Id() + ".dataspec";
1490 case CProjKey::eUtility:
1491 return project_id.Id();
1492 default:
1493 NCBI_THROW(CProjBulderAppException, eProjectType, project_id.Id());
1494 return "";
1495 }
1496 }
1497
CreateProjKey(const string & project_name)1498 CProjKey CreateProjKey(const string& project_name)
1499 {
1500 CProjKey::TProjType type = CProjKey::eNoProj;
1501 CDirEntry d(project_name);
1502 string ext(d.GetExt());
1503 string base(d.GetBase());
1504 if (ext == ".exe") {
1505 type = CProjKey::eApp;
1506 } else if (ext == ".lib") {
1507 type = CProjKey::eLib;
1508 } else if (ext == ".dll") {
1509 type = CProjKey::eDll;
1510 } else if (ext == ".dataspec") {
1511 type = CProjKey::eDataSpec;
1512 } else {
1513 type = CProjKey::eMsvc;
1514 }
1515 return CProjKey(type,base);
1516 }
1517
1518
1519 //-----------------------------------------------------------------------------
1520
CBuildType(bool dll_flag)1521 CBuildType::CBuildType(bool dll_flag)
1522 :m_Type(dll_flag? eDll: eStatic)
1523 {
1524
1525 }
1526
1527
GetType(void) const1528 CBuildType::EBuildType CBuildType::GetType(void) const
1529 {
1530 return m_Type;
1531 }
1532
1533
GetTypeStr(void) const1534 string CBuildType::GetTypeStr(void) const
1535 {
1536 switch (m_Type) {
1537 case eStatic:
1538 return "static";
1539 case eDll:
1540 return "dll";
1541 }
1542 NCBI_THROW(CProjBulderAppException,
1543 eProjectType,
1544 NStr::IntToString(m_Type));
1545 return "";
1546 }
1547
1548
1549 //-----------------------------------------------------------------------------
1550
CDllSrcFilesDistr(void)1551 CDllSrcFilesDistr::CDllSrcFilesDistr(void)
1552 {
1553 }
1554
RegisterSource(const string & src_file_path,const CProjKey & dll_project_id,const CProjKey & lib_project_id)1555 void CDllSrcFilesDistr::RegisterSource(const string& src_file_path,
1556 const CProjKey& dll_project_id,
1557 const CProjKey& lib_project_id)
1558 {
1559 m_SourcesMap[ TDllSrcKey(src_file_path,dll_project_id) ] = lib_project_id;
1560 }
1561
RegisterHeader(const string & hdr_file_path,const CProjKey & dll_project_id,const CProjKey & lib_project_id)1562 void CDllSrcFilesDistr::RegisterHeader(const string& hdr_file_path,
1563 const CProjKey& dll_project_id,
1564 const CProjKey& lib_project_id)
1565 {
1566 m_HeadersMap[ TDllSrcKey(hdr_file_path,dll_project_id) ] = lib_project_id;
1567 }
1568
RegisterInline(const string & inl_file_path,const CProjKey & dll_project_id,const CProjKey & lib_project_id)1569 void CDllSrcFilesDistr::RegisterInline(const string& inl_file_path,
1570 const CProjKey& dll_project_id,
1571 const CProjKey& lib_project_id)
1572 {
1573 m_InlinesMap[ TDllSrcKey(inl_file_path,dll_project_id) ] = lib_project_id;
1574 }
1575
RegisterExtraFile(const string & ex_file_path,const CProjKey & dll_project_id,const CProjKey & lib_project_id)1576 void CDllSrcFilesDistr::RegisterExtraFile(const string& ex_file_path,
1577 const CProjKey& dll_project_id,
1578 const CProjKey& lib_project_id)
1579 {
1580 m_ExtraFileMap[ TDllSrcKey(ex_file_path,dll_project_id) ] = lib_project_id;
1581 }
1582
GetSourceLib(const string & src_file_path,const CProjKey & dll_project_id) const1583 CProjKey CDllSrcFilesDistr::GetSourceLib(const string& src_file_path,
1584 const CProjKey& dll_project_id) const
1585 {
1586 TDllSrcKey key(src_file_path, dll_project_id);
1587 TDistrMap::const_iterator p = m_SourcesMap.find(key);
1588 if (p != m_SourcesMap.end()) {
1589 const CProjKey& lib_id = p->second;
1590 return lib_id;
1591 }
1592 return CProjKey();
1593 }
1594
1595
GetHeaderLib(const string & hdr_file_path,const CProjKey & dll_project_id) const1596 CProjKey CDllSrcFilesDistr::GetHeaderLib(const string& hdr_file_path,
1597 const CProjKey& dll_project_id) const
1598 {
1599 TDllSrcKey key(hdr_file_path, dll_project_id);
1600 TDistrMap::const_iterator p = m_HeadersMap.find(key);
1601 if (p != m_HeadersMap.end()) {
1602 const CProjKey& lib_id = p->second;
1603 return lib_id;
1604 }
1605 return CProjKey();
1606 }
1607
GetInlineLib(const string & inl_file_path,const CProjKey & dll_project_id) const1608 CProjKey CDllSrcFilesDistr::GetInlineLib(const string& inl_file_path,
1609 const CProjKey& dll_project_id) const
1610 {
1611 TDllSrcKey key(inl_file_path, dll_project_id);
1612 TDistrMap::const_iterator p = m_InlinesMap.find(key);
1613 if (p != m_InlinesMap.end()) {
1614 const CProjKey& lib_id = p->second;
1615 return lib_id;
1616 }
1617 return CProjKey();
1618 }
1619
GetExtraFileLib(const string & ex_file_path,const CProjKey & dll_project_id) const1620 CProjKey CDllSrcFilesDistr::GetExtraFileLib(const string& ex_file_path,
1621 const CProjKey& dll_project_id) const
1622 {
1623 TDllSrcKey key(ex_file_path, dll_project_id);
1624 TDistrMap::const_iterator p = m_ExtraFileMap.find(key);
1625 if (p != m_ExtraFileMap.end()) {
1626 const CProjKey& lib_id = p->second;
1627 return lib_id;
1628 }
1629 return CProjKey();
1630 }
1631
GetFileLib(const string & file_path,const CProjKey & dll_project_id) const1632 CProjKey CDllSrcFilesDistr::GetFileLib(const string& file_path,
1633 const CProjKey& dll_project_id) const
1634 {
1635 CProjKey empty;
1636 if (dll_project_id.Type() != CProjKey::eDll) {
1637 return empty;
1638 }
1639 CProjKey test;
1640 test = GetSourceLib(file_path, dll_project_id);
1641 if (test != empty) {
1642 return test;
1643 }
1644 test = GetHeaderLib(file_path, dll_project_id);
1645 if (test != empty) {
1646 return test;
1647 }
1648 test = GetInlineLib(file_path, dll_project_id);
1649 if (test != empty) {
1650 return test;
1651 }
1652 test = GetExtraFileLib(file_path, dll_project_id);
1653 if (test != empty) {
1654 return test;
1655 }
1656 return empty;
1657 }
1658
1659
1660 const CDataToolGeneratedSrc*
IsProducedByDatatool(const string & src_path_abs,const CProjItem & project)1661 IsProducedByDatatool(const string& src_path_abs,
1662 const CProjItem& project)
1663 {
1664 if ( project.m_DatatoolSources.empty() ) {
1665 ITERATE( list<CProjKey>, d, project.m_Depends) {
1666 if (d->Type() == CProjKey::eDataSpec) {
1667 CProjectItemsTree::TProjects::const_iterator n =
1668 GetApp().GetWholeTree().m_Projects.find(*d);
1669 if (n != GetApp().GetWholeTree().m_Projects.end()) {
1670 const CDataToolGeneratedSrc *pFound =
1671 IsProducedByDatatool(src_path_abs, n->second);
1672 if (pFound) {
1673 return pFound;
1674 }
1675 }
1676 }
1677 }
1678 return NULL;
1679 }
1680
1681 string src_base;
1682 CDirEntry::SplitPath(src_path_abs, NULL, &src_base);
1683
1684 // guess name.asn file name from name__ or name___
1685 string asn_base;
1686 if ( NStr::EndsWith(src_base, "___") ) {
1687 asn_base = src_base.substr(0, src_base.length() -3);
1688 } else if ( NStr::EndsWith(src_base, "__") ) {
1689 asn_base = src_base.substr(0, src_base.length() -2);
1690 } else {
1691 return NULL;
1692 }
1693 string asn_name = asn_base + ".asn";
1694 string dtd_name = asn_base + ".dtd";
1695 string xsd_name = asn_base + ".xsd";
1696 string wsdl_name = asn_base + ".wsdl";
1697 string jsd_name = asn_base + ".jsd";
1698
1699 //try to find this name in datatool generated sources container
1700 ITERATE(list<CDataToolGeneratedSrc>, p, project.m_DatatoolSources) {
1701 const CDataToolGeneratedSrc& asn = *p;
1702 if ((asn.m_SourceFile == asn_name) ||
1703 (asn.m_SourceFile == dtd_name) ||
1704 (asn.m_SourceFile == xsd_name) ||
1705 (asn.m_SourceFile == wsdl_name) ||
1706 (asn.m_SourceFile == jsd_name)
1707 ) {
1708 return &(*p);
1709 }
1710 }
1711
1712 try {
1713 ITERATE(list<CDataToolGeneratedSrc>, p, project.m_DatatoolSources) {
1714 const CDataToolGeneratedSrc& asn = *p;
1715 string def( CDirEntry::ConcatPath(asn.m_SourceBaseDir, CDirEntry(asn.m_SourceFile).GetBase()) + ".def");
1716 if (CFile(def).Exists()) {
1717 CNcbiIfstream in(def.c_str(), IOS_BASE::in | IOS_BASE::binary);
1718 CNcbiRegistry reg(in);
1719 if (reg.GetString("-", "-oc", "") == asn_base) {
1720 return &(*p);
1721 }
1722 }
1723 }
1724 } catch (...) {
1725 }
1726 return NULL;
1727 }
1728
1729 END_NCBI_SCOPE
1730