1 /* $Id: msvc_makefile.cpp 576401 2018-12-14 15:04:17Z 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 "stl_msvc_usage.hpp"
32 #include "msvc_makefile.hpp"
33 #include "proj_builder_app.hpp"
34 #include "msvc_prj_defines.hpp"
35
36 #include <algorithm>
37
38 #include <corelib/ncbistr.hpp>
39
40 BEGIN_NCBI_SCOPE
41
42 //-----------------------------------------------------------------------------
CMsvcMetaMakefile(const string & file_path)43 CMsvcMetaMakefile::CMsvcMetaMakefile(const string& file_path)
44 {
45 #if defined(NCBI_COMPILER_MSVC) || defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
46 if (CFile(file_path).Exists()) {
47 CNcbiIfstream ifs(file_path.c_str(), IOS_BASE::in | IOS_BASE::binary);
48 //read registry
49 m_MakeFile.Read(ifs);
50 //and remember dir from where it has been loaded
51 CDirEntry::SplitPath(file_path, &m_MakeFileBaseDir);
52 // LOG_POST(Info << "Using rules from " << file_path);
53 }
54 #endif //NCBI_COMPILER_MSVC
55 }
56
57
IsEmpty(void) const58 bool CMsvcMetaMakefile::IsEmpty(void) const
59 {
60 return m_MakeFile.Empty();
61 }
62
TranslateOpt(const string & value,const string & section,const string & opt)63 string CMsvcMetaMakefile::TranslateOpt(
64 const string& value, const string& section, const string& opt)
65 {
66 if (value.empty() ||
67 (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000 ||
68 CMsvc7RegSettings::GetMsvcVersion() >= CMsvc7RegSettings::eXCode30) ) {
69 return value;
70 }
71 string name(section+"_"+opt+"_"+value);
72 return GetApp().GetMetaMakefile().m_MakeFile.GetString(
73 "Translate", name, value);
74 }
75
TranslateCommand(const string & value)76 string CMsvcMetaMakefile::TranslateCommand(const string& value)
77 {
78 if (value.empty() ||
79 (CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000 ||
80 CMsvc7RegSettings::GetMsvcVersion() >= CMsvc7RegSettings::eXCode30) ) {
81 return value;
82 }
83 const CMsvcMetaMakefile& meta = GetApp().GetMetaMakefile();
84
85 string data(value), raw_macro, macro, definition;
86 string::size_type start, end, done = 0;
87 for (;;) {
88 if ((start = data.find("$(", done)) == string::npos) {
89 break;
90 }
91 end = data.find(")", start);
92 if (end == string::npos) {
93 break;
94 }
95 raw_macro = data.substr(start,end-start+1);
96 if (CSymResolver::IsDefine(raw_macro)) {
97 macro = CSymResolver::StripDefine(raw_macro);
98 definition = meta.m_MakeFile.Get("Translate", string("Macro_") + macro);
99 if (definition.empty()) {
100 done = end;
101 } else {
102 data = NStr::Replace(data, raw_macro, definition);
103 done = 0;
104 }
105 }
106 }
107 data = NStr::Replace(data, "@echo", "%40echo");
108 return data;
109 }
110
GetConfigurationOpt(const string & opt,const SConfigInfo & config) const111 string CMsvcMetaMakefile::GetConfigurationOpt(const string& opt,
112 const SConfigInfo& config) const
113 {
114 string sec("Configuration");
115 return TranslateOpt( GetOpt(m_MakeFile, sec, opt, config), sec, opt);
116 }
117
GetCompilerOpt(const string & opt,const SConfigInfo & config) const118 string CMsvcMetaMakefile::GetCompilerOpt(const string& opt,
119 const SConfigInfo& config) const
120 {
121 string sec("Compiler");
122 return TranslateOpt( GetOpt(m_MakeFile, sec, opt, config), sec, opt);
123 }
124
125
GetLinkerOpt(const string & opt,const SConfigInfo & config) const126 string CMsvcMetaMakefile::GetLinkerOpt(const string& opt,
127 const SConfigInfo& config) const
128 {
129 string sec("Linker");
130 return TranslateOpt( GetOpt(m_MakeFile, sec, opt, config), sec, opt);
131 }
132
133
GetLibrarianOpt(const string & opt,const SConfigInfo & config) const134 string CMsvcMetaMakefile::GetLibrarianOpt(const string& opt,
135 const SConfigInfo& config) const
136 {
137 string sec("Librarian");
138 return TranslateOpt( GetOpt(m_MakeFile, sec, opt, config), sec, opt);
139 }
140
141
GetResourceCompilerOpt(const string & opt,const SConfigInfo & config) const142 string CMsvcMetaMakefile::GetResourceCompilerOpt
143 (const string& opt, const SConfigInfo& config) const
144 {
145 string sec("ResourceCompiler");
146 return TranslateOpt( GetOpt(m_MakeFile, sec, opt, config), sec, opt);
147 }
148
GetConfigOpt(const string & section,const string & opt,const SConfigInfo & config) const149 string CMsvcMetaMakefile::GetConfigOpt(
150 const string& section, const string& opt, const SConfigInfo& config) const
151 {
152 return GetOpt(m_MakeFile, section, opt, config);
153 }
154
155
IsPchEnabled(void) const156 bool CMsvcMetaMakefile::IsPchEnabled(void) const
157 {
158 return GetPchInfo().m_UsePch;
159 }
160
161
GetUsePchThroughHeader(const string & project_id,const string & source_file_full_path,const string & tree_src_dir) const162 string CMsvcMetaMakefile::GetUsePchThroughHeader
163 (const string& project_id,
164 const string& source_file_full_path,
165 const string& tree_src_dir) const
166 {
167 const SPchInfo& pch_info = GetPchInfo();
168
169 if (find(pch_info.m_DontUsePchList.begin(),
170 pch_info.m_DontUsePchList.end(),
171 project_id) != pch_info.m_DontUsePchList.end()) {
172 return kEmptyStr;
173 }
174
175 string source_file_dir;
176 CDirEntry::SplitPath(source_file_full_path, &source_file_dir);
177 source_file_dir = CDirEntry::AddTrailingPathSeparator(source_file_dir);
178
179 size_t max_match = 0;
180 string pch_file;
181 bool found = false;
182 ITERATE(SPchInfo::TSubdirPchfile, p, pch_info.m_PchUsageMap) {
183 const string& branch_subdir = p->first;
184 string abs_branch_subdir =
185 CDirEntry::ConcatPath(tree_src_dir, branch_subdir);
186 abs_branch_subdir =
187 CDirEntry::AddTrailingPathSeparator(abs_branch_subdir);
188 if ( IsSubdir(abs_branch_subdir, source_file_dir) ) {
189 if ( branch_subdir.length() > max_match ) {
190 max_match = branch_subdir.length();
191 pch_file = p->second;
192 found = true;
193 }
194 }
195 }
196 if (found) {
197 return pch_file;
198 }
199 return m_PchInfo->m_DefaultPch;
200 }
201
202
GetPchInfo(void) const203 const CMsvcMetaMakefile::SPchInfo& CMsvcMetaMakefile::GetPchInfo(void) const
204 {
205 if ( m_PchInfo.get() )
206 return *m_PchInfo;
207
208 (const_cast<CMsvcMetaMakefile&>(*this)).m_PchInfo.reset(new SPchInfo);
209
210 string use_pch_str = m_MakeFile.GetString("UsePch", "UsePch", "TRUE");
211 m_PchInfo->m_UsePch = NStr::StringToBool(use_pch_str);
212 m_PchInfo->m_PchUsageDefine = m_MakeFile.GetString("UsePch", "PchUsageDefine");
213 m_PchInfo->m_DefaultPch = m_MakeFile.GetString("UsePch", "DefaultPch");
214 string do_not_use_pch_str = m_MakeFile.GetString("UsePch", "DoNotUsePch");
215 NStr::Split(do_not_use_pch_str, LIST_SEPARATOR, m_PchInfo->m_DontUsePchList, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
216 string irrelevant[] = {"UsePch","PchUsageDefine","DefaultPch","DoNotUsePch",""};
217
218 list<string> projects_with_pch_dirs;
219 m_MakeFile.EnumerateEntries("UsePch", &projects_with_pch_dirs);
220 ITERATE(list<string>, p, projects_with_pch_dirs) {
221 const string& key = *p;
222 bool ok = true;
223 for (int i=0; ok && !irrelevant[i].empty(); ++i) {
224 ok = key != irrelevant[i];
225 }
226 if (!ok)
227 continue;
228
229 string val = m_MakeFile.GetString("UsePch", key, "-");
230 if ( val == "-" ) {
231 val = "";
232 }
233 string tmp = CDirEntry::ConvertToOSPath(key);
234 m_PchInfo->m_PchUsageMap[tmp] = val;
235 }
236 return *m_PchInfo;
237 }
238
GetPchUsageDefine(void) const239 string CMsvcMetaMakefile::GetPchUsageDefine(void) const
240 {
241 return GetPchInfo().m_PchUsageDefine;
242 }
243 //-----------------------------------------------------------------------------
CreateMsvcProjectMakefileName(const string & project_name,CProjItem::TProjType type)244 string CreateMsvcProjectMakefileName(const string& project_name,
245 CProjItem::TProjType type)
246 {
247 string name("Makefile.");
248
249 name += project_name + '.';
250
251 switch (type) {
252 case CProjKey::eApp:
253 name += "app.";
254 break;
255 case CProjKey::eLib:
256 name += "lib.";
257 break;
258 case CProjKey::eDll:
259 name += "dll.";
260 break;
261 case CProjKey::eMsvc:
262 if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eMsvcWin32 ||
263 CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eMsvcX64) {
264 name += "msvcproj.";
265 }
266 break;
267 case CProjKey::eDataSpec:
268 name += "dataspec.";
269 break;
270 case CProjKey::eUtility:
271 name += "utility.";
272 break;
273 default:
274 NCBI_THROW(CProjBulderAppException,
275 eProjectType,
276 NStr::IntToString(type));
277 break;
278 }
279 name += GetApp().GetRegSettings().m_MakefilesExt;
280 return name;
281 }
282
283
CreateMsvcProjectMakefileName(const CProjItem & project)284 string CreateMsvcProjectMakefileName(const CProjItem& project)
285 {
286 return CreateMsvcProjectMakefileName(project.m_Name,
287 project.m_ProjType);
288 }
289
290
291 //-----------------------------------------------------------------------------
CMsvcProjectMakefile(const string & file_path,bool compound)292 CMsvcProjectMakefile::CMsvcProjectMakefile(const string& file_path, bool compound)
293 :CMsvcMetaMakefile(file_path)
294 {
295 CDirEntry::SplitPath(file_path, &m_ProjectBaseDir);
296 m_FilePath = file_path;
297 m_Compound = compound;
298 }
299
300
GetGUID(void) const301 string CMsvcProjectMakefile::GetGUID(void) const
302 {
303 return m_MakeFile.GetString("Common", "ProjectGUID");
304 }
305
Redefine(const string & value,list<string> & redef) const306 bool CMsvcProjectMakefile::Redefine(const string& value, list<string>& redef) const
307 {
308 redef.clear();
309 if (IsEmpty()) {
310 return false;
311 }
312 string::size_type start, end;
313 if ((start = value.find("$(")) != string::npos &&
314 (end = value.find(")")) != string::npos && (end > start)) {
315 string raw_define = value.substr(start+2,end-start-2);
316 string new_val = m_MakeFile.GetString("Redefine", raw_define);
317 if (!new_val.empty()) {
318 redef.push_back("$(" + new_val + ")");
319 _TRACE(m_FilePath << " redefines: " << raw_define << " = " << new_val);
320 return true;
321 }
322 } else if (NStr::StartsWith(value, "@") && NStr::EndsWith(value, "@")) {
323 string raw_define = value.substr(1,value.length()-2);
324 string new_val = m_MakeFile.GetString("Redefine", raw_define);
325 if (!new_val.empty()) {
326 redef.push_back("@" + new_val + "@");
327 _TRACE(m_FilePath << " redefines: " << raw_define << " = " << new_val);
328 return true;
329 }
330 } else {
331 string new_val = m_MakeFile.GetString("Redefine", value);
332 if (!new_val.empty()) {
333 redef.clear();
334 NStr::Split(new_val, LIST_SEPARATOR, redef, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
335 _TRACE(m_FilePath << " redefines: " << value << " = " << new_val);
336 return true;
337 }
338 }
339 return false;
340 }
341
Redefine(const list<string> & value,list<string> & redef) const342 bool CMsvcProjectMakefile::Redefine(const list<string>& value, list<string>& redef) const
343 {
344 bool res=false;
345 redef.clear();
346 if (IsEmpty()) {
347 redef.insert(redef.end(),value.begin(), value.end());
348 } else {
349 list<string> newval;
350 ITERATE(list<string>, k, value) {
351 if (Redefine(*k,newval)) {
352 redef.insert(redef.end(),newval.begin(), newval.end());
353 res=true;
354 } else {
355 redef.push_back(*k);
356 }
357 }
358 }
359 return res;
360 }
361
Append(list<string> & values,const string & def) const362 void CMsvcProjectMakefile::Append( list<string>& values, const string& def) const
363 {
364 if (IsEmpty()) {
365 values.push_back(def);
366 } else {
367 list<string> redef;
368 if (Redefine(def,redef)) {
369 values.insert(values.end(), redef.begin(), redef.end());
370 } else {
371 values.push_back(def);
372 }
373 }
374 }
375
Append(list<string> & values,const list<string> & def) const376 void CMsvcProjectMakefile::Append( list<string>& values, const list<string>& def) const
377 {
378 if (IsEmpty()) {
379 values.insert(values.end(), def.begin(), def.end());
380 } else {
381 ITERATE(list<string>, k, def) {
382 Append(values,*k);
383 }
384 }
385 }
386
IsExcludeProject(bool default_val) const387 bool CMsvcProjectMakefile::IsExcludeProject(bool default_val) const
388 {
389 string val = m_MakeFile.GetString("Common", "ExcludeProject");
390
391 if ( val.empty() )
392 return default_val;
393
394 return val != "FALSE";
395 }
396
397
GetAdditionalSourceFiles(const SConfigInfo & config,list<string> * files) const398 void CMsvcProjectMakefile::GetAdditionalSourceFiles(const SConfigInfo& config,
399 list<string>* files) const
400 {
401 string files_string =
402 GetOpt(m_MakeFile, "AddToProject", "SourceFiles", config);
403
404 NStr::Split(files_string, LIST_SEPARATOR, *files, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
405 }
406
407
GetAdditionalLIB(const SConfigInfo & config,list<string> * lib_ids) const408 void CMsvcProjectMakefile::GetAdditionalLIB(const SConfigInfo& config,
409 list<string>* lib_ids) const
410 {
411 string lib_string =
412 GetOpt(m_MakeFile, "AddToProject", "LIB", config);
413
414 NStr::Split(lib_string, LIST_SEPARATOR, *lib_ids, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
415 }
416
417
GetExcludedSourceFiles(const SConfigInfo & config,list<string> * files) const418 void CMsvcProjectMakefile::GetExcludedSourceFiles(const SConfigInfo& config,
419 list<string>* files) const
420 {
421 string files_string =
422 GetOpt(m_MakeFile,
423 "ExcludedFromProject", "SourceFiles", config);
424
425 NStr::Split(files_string, LIST_SEPARATOR, *files, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
426 }
427
428
GetExcludedLIB(const SConfigInfo & config,list<string> * lib_ids) const429 void CMsvcProjectMakefile::GetExcludedLIB(const SConfigInfo& config,
430 list<string>* lib_ids) const
431 {
432 string lib_string =
433 GetOpt(m_MakeFile,
434 "ExcludedFromProject", "LIB", config);
435
436 NStr::Split(lib_string, LIST_SEPARATOR, *lib_ids, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
437 }
438
439
GetAdditionalIncludeDirs(const SConfigInfo & config,list<string> * dirs) const440 void CMsvcProjectMakefile::GetAdditionalIncludeDirs(const SConfigInfo& config,
441 list<string>* dirs) const
442 {
443 string dirs_string =
444 GetOpt(m_MakeFile, "AddToProject", "IncludeDirs", config);
445
446 NStr::Split(dirs_string, LIST_SEPARATOR, *dirs, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate | NStr::fSplit_CanQuote);
447 }
448
GetHeadersInInclude(const SConfigInfo & config,list<string> * files) const449 void CMsvcProjectMakefile::GetHeadersInInclude(const SConfigInfo& config,
450 list<string>* files) const
451 {
452 x_GetHeaders(config, "HeadersInInclude", files);
453 }
454
GetHeadersInSrc(const SConfigInfo & config,list<string> * files) const455 void CMsvcProjectMakefile::GetHeadersInSrc(const SConfigInfo& config,
456 list<string>* files) const
457 {
458 x_GetHeaders(config, "HeadersInSrc", files);
459 }
460
x_GetHeaders(const SConfigInfo & config,const string & entry,list<string> * files) const461 void CMsvcProjectMakefile::x_GetHeaders(
462 const SConfigInfo& config, const string& entry, list<string>* files) const
463 {
464 string dirs_string = GetOpt(m_MakeFile, "AddToProject", entry, config);
465 string separator;
466 separator += CDirEntry::GetPathSeparator();
467 dirs_string = NStr::Replace(dirs_string,"/",separator);
468 dirs_string = NStr::Replace(dirs_string,"\\",separator);
469
470 files->clear();
471 NStr::Split(dirs_string, LIST_SEPARATOR, *files, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
472 if (files->empty() && !m_Compound) {
473 files->push_back("*.h");
474 files->push_back("*.hpp");
475 }
476 }
477
GetInlinesInInclude(const SConfigInfo &,list<string> * files) const478 void CMsvcProjectMakefile::GetInlinesInInclude(const SConfigInfo& ,
479 list<string>* files) const
480 {
481 files->clear();
482 files->push_back("*.inl");
483 }
484
GetInlinesInSrc(const SConfigInfo &,list<string> * files) const485 void CMsvcProjectMakefile::GetInlinesInSrc(const SConfigInfo& ,
486 list<string>* files) const
487 {
488 files->clear();
489 files->push_back("*.inl");
490 }
491
492 void
GetCustomBuildInfo(list<SCustomBuildInfo> * info) const493 CMsvcProjectMakefile::GetCustomBuildInfo(list<SCustomBuildInfo>* info) const
494 {
495 info->clear();
496
497 string source_files_str =
498 m_MakeFile.GetString("CustomBuild", "SourceFiles");
499 if (source_files_str.empty()) {
500 return;
501 }
502
503 list<string> source_files;
504 NStr::Split(source_files_str, LIST_SEPARATOR, source_files, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
505
506 ITERATE(list<string>, p, source_files){
507 const string& source_file = *p;
508
509 SCustomBuildInfo build_info;
510 string source_file_path_abs =
511 CDirEntry::ConcatPath(m_MakeFileBaseDir, source_file);
512 build_info.m_SourceFile =
513 CDirEntry::NormalizePath(source_file_path_abs);
514 build_info.m_CommandLine =
515 GetApp().GetSite().ProcessMacros(
516 m_MakeFile.GetString(source_file, "CommandLine"));
517 build_info.m_Description =
518 m_MakeFile.GetString(source_file, "Description");
519 build_info.m_Outputs =
520 m_MakeFile.GetString(source_file, "Outputs");
521 build_info.m_AdditionalDependencies =
522 GetApp().GetSite().ProcessMacros(
523 m_MakeFile.GetString(source_file, "AdditionalDependencies"));
524
525 if ( !build_info.IsEmpty() )
526 info->push_back(build_info);
527 }
528 }
529
530 void
GetCustomScriptInfo(SCustomScriptInfo & info,const string & sec) const531 CMsvcProjectMakefile::GetCustomScriptInfo(SCustomScriptInfo& info, const string& sec) const
532 {
533 info.m_Input = m_MakeFile.GetString(sec, "Input");
534 info.m_Output = m_MakeFile.GetString(sec, "Output");
535 info.m_Shell = m_MakeFile.GetString(sec, "Shell");
536 info.m_Script = m_MakeFile.GetString(sec, "Script");
537 }
538
539
GetResourceFiles(const SConfigInfo & config,list<string> * files) const540 void CMsvcProjectMakefile::GetResourceFiles(const SConfigInfo& config,
541 list<string>* files) const
542 {
543 string files_string =
544 GetOpt(m_MakeFile, "AddToProject", "ResourceFiles", config);
545
546 NStr::Split(files_string, LIST_SEPARATOR, *files, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
547 }
548
GetExtraFiles(map<string,list<string>> * files_map) const549 void CMsvcProjectMakefile::GetExtraFiles(map<string, list<string> >* files_map) const
550 {
551 string prefix("ExtraFileGroup.");
552 list<string> sections;
553 m_MakeFile.EnumerateSections(§ions);
554 ITERATE(list<string>, s, sections) {
555 if (NStr::StartsWith(*s,prefix)) {
556 string section(*s);
557 string group_name = NStr::Replace(s->substr(prefix.size()),"_"," ");
558 string files_string = m_MakeFile.Get(section, "Files");
559 list<string> raw_files, files;
560 NStr::Split(files_string, LIST_SEPARATOR, raw_files, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
561 string fname;
562 bool started = false;
563 ITERATE(list<string>, f, raw_files) {
564 string part(*f);
565 if (part[0] == '\"' && !started) {
566 fname = part.substr(1);
567 started = true;
568 continue;
569 }
570 else if (part[part.size()-1] == '\"') {
571 fname += ' ';
572 fname += part.substr(0,part.size()-1);
573 }
574 else if (started) {
575 fname += ' ';
576 fname += part;
577 continue;
578 }
579 else {
580 fname = part;
581 }
582 files.push_back(fname);
583 fname.clear();
584 started = false;
585 }
586 if (!group_name.empty() && !files.empty()) {
587 (*files_map)[group_name] = files;
588 }
589 }
590 }
591 }
592
593 //-----------------------------------------------------------------------------
CMsvcProjectRuleMakefile(const string & file_path,bool compound)594 CMsvcProjectRuleMakefile::CMsvcProjectRuleMakefile(const string& file_path, bool compound)
595 :CMsvcProjectMakefile(file_path, compound)
596 {
597 }
598
599
GetRulePriority(const SConfigInfo & config) const600 int CMsvcProjectRuleMakefile::GetRulePriority(const SConfigInfo& config) const
601 {
602 string priority_string =
603 GetOpt(m_MakeFile, "Rule", "Priority", config);
604
605 if ( priority_string.empty() )
606 return 0;
607
608 return NStr::StringToInt(priority_string);
609 }
610
611
612 //-----------------------------------------------------------------------------
s_CreateRuleMakefileFilename(CProjItem::TProjType project_type,const string & requires)613 static string s_CreateRuleMakefileFilename(CProjItem::TProjType project_type,
614 const string& requires)
615 {
616 string name = "Makefile." + requires;
617 switch (project_type) {
618 case CProjKey::eApp:
619 name += ".app";
620 break;
621 case CProjKey::eLib:
622 name += ".lib";
623 break;
624 case CProjKey::eDll:
625 name += ".dll";
626 break;
627 default:
628 break;
629 }
630 return name + "." + GetApp().GetRegSettings().m_MakefilesExt;
631 }
632
CMsvcCombinedProjectMakefile(CProjItem::TProjType project_type,const CMsvcProjectMakefile * project_makefile,const string & rules_basedir,const list<string> requires_list)633 CMsvcCombinedProjectMakefile::CMsvcCombinedProjectMakefile
634 (CProjItem::TProjType project_type,
635 const CMsvcProjectMakefile* project_makefile,
636 const string& rules_basedir,
637 const list<string> requires_list)
638 :m_ProjectMakefile(project_makefile)
639 {
640 ITERATE(list<string>, p, requires_list) {
641 const string& requires = *p;
642 string rule_path = rules_basedir;
643 rule_path =
644 CDirEntry::ConcatPath(rule_path,
645 s_CreateRuleMakefileFilename(project_type,
646 requires));
647
648 TRule rule(new CMsvcProjectRuleMakefile(rule_path, project_type== CProjKey::eDll));
649 if ( !rule->IsEmpty() )
650 m_Rules.push_back(rule);
651 }
652 }
653
654
~CMsvcCombinedProjectMakefile(void)655 CMsvcCombinedProjectMakefile::~CMsvcCombinedProjectMakefile(void)
656 {
657 }
658
659 #define IMPLEMENT_COMBINED_MAKEFILE_OPT(X) \
660 string CMsvcCombinedProjectMakefile::X(const string& opt, \
661 const SConfigInfo& config) const \
662 { \
663 string prj_val = m_ProjectMakefile->X(opt, config); \
664 if ( !prj_val.empty() ) \
665 return prj_val; \
666 string val; \
667 int priority = 0; \
668 ITERATE(TRules, p, m_Rules) { \
669 const TRule& rule = *p; \
670 string rule_val = rule->X(opt, config); \
671 if ( !rule_val.empty() && priority < rule->GetRulePriority(config)) { \
672 val = rule_val; \
673 priority = rule->GetRulePriority(config); \
674 } \
675 } \
676 return val; \
677 }
678
679
680 IMPLEMENT_COMBINED_MAKEFILE_OPT(GetConfigurationOpt)
IMPLEMENT_COMBINED_MAKEFILE_OPT(GetCompilerOpt)681 IMPLEMENT_COMBINED_MAKEFILE_OPT(GetCompilerOpt)
682 IMPLEMENT_COMBINED_MAKEFILE_OPT(GetLinkerOpt)
683 IMPLEMENT_COMBINED_MAKEFILE_OPT(GetLibrarianOpt)
684 IMPLEMENT_COMBINED_MAKEFILE_OPT(GetResourceCompilerOpt)
685
686 bool CMsvcCombinedProjectMakefile::IsExcludeProject(bool default_val) const
687 {
688 return m_ProjectMakefile->IsExcludeProject(default_val);
689 }
690
691
s_ConvertRelativePaths(const string & rule_base_dir,const list<string> & rules_paths_list,const string & project_base_dir,list<string> * project_paths_list)692 static void s_ConvertRelativePaths(const string& rule_base_dir,
693 const list<string>& rules_paths_list,
694 const string& project_base_dir,
695 list<string>* project_paths_list)
696 {
697 project_paths_list->clear();
698 ITERATE(list<string>, p, rules_paths_list) {
699 const string& rules_path = *p;
700 string rules_abs_path =
701 CDirEntry::ConcatPath(rule_base_dir, rules_path);
702 string project_path =
703 CDirEntry::CreateRelativePath(project_base_dir, rules_abs_path);
704 project_paths_list->push_back(project_path);
705 }
706 }
707
708
709 #define IMPLEMENT_COMBINED_MAKEFILE_VALUES(X) \
710 void CMsvcCombinedProjectMakefile::X(const SConfigInfo& config, \
711 list<string>* values_list) const \
712 { \
713 list<string> prj_val; \
714 m_ProjectMakefile->X(config, &prj_val); \
715 if ( !prj_val.empty() ) { \
716 *values_list = prj_val; \
717 return; \
718 } \
719 list<string> val; \
720 int priority = 0; \
721 ITERATE(TRules, p, m_Rules) { \
722 const TRule& rule = *p; \
723 list<string> rule_val; \
724 rule->X(config, &rule_val); \
725 if ( !rule_val.empty() && priority < rule->GetRulePriority(config)) { \
726 val = rule_val; \
727 priority = rule->GetRulePriority(config); \
728 } \
729 } \
730 *values_list = val; \
731 }
732
733
734 #define IMPLEMENT_COMBINED_MAKEFILE_FILESLIST(X) \
735 void CMsvcCombinedProjectMakefile::X(const SConfigInfo& config, \
736 list<string>* values_list) const \
737 { \
738 list<string> prj_val; \
739 m_ProjectMakefile->X(config, &prj_val); \
740 if ( !prj_val.empty() ) { \
741 *values_list = prj_val; \
742 return; \
743 } \
744 list<string> val; \
745 int priority = 0; \
746 string rule_base_dir; \
747 ITERATE(TRules, p, m_Rules) { \
748 const TRule& rule = *p; \
749 list<string> rule_val; \
750 rule->X(config, &rule_val); \
751 if ( !rule_val.empty() && priority < rule->GetRulePriority(config)) { \
752 val = rule_val; \
753 priority = rule->GetRulePriority(config); \
754 rule_base_dir = rule->m_ProjectBaseDir; \
755 } \
756 } \
757 s_ConvertRelativePaths(rule_base_dir, \
758 val, \
759 m_ProjectMakefile->m_ProjectBaseDir, \
760 values_list); \
761 }
762
763
764 IMPLEMENT_COMBINED_MAKEFILE_FILESLIST(GetAdditionalSourceFiles)
IMPLEMENT_COMBINED_MAKEFILE_VALUES(GetAdditionalLIB)765 IMPLEMENT_COMBINED_MAKEFILE_VALUES (GetAdditionalLIB)
766 IMPLEMENT_COMBINED_MAKEFILE_FILESLIST(GetExcludedSourceFiles)
767 IMPLEMENT_COMBINED_MAKEFILE_VALUES (GetExcludedLIB)
768 IMPLEMENT_COMBINED_MAKEFILE_FILESLIST(GetAdditionalIncludeDirs)
769 IMPLEMENT_COMBINED_MAKEFILE_FILESLIST(GetHeadersInInclude)
770 IMPLEMENT_COMBINED_MAKEFILE_FILESLIST(GetHeadersInSrc)
771 IMPLEMENT_COMBINED_MAKEFILE_FILESLIST(GetInlinesInInclude)
772 IMPLEMENT_COMBINED_MAKEFILE_FILESLIST(GetInlinesInSrc)
773 IMPLEMENT_COMBINED_MAKEFILE_FILESLIST(GetResourceFiles)
774
775 void CMsvcCombinedProjectMakefile::GetExtraFiles(map<string, list<string> >* files) const
776 {
777 m_ProjectMakefile->GetExtraFiles(files); \
778 }
779
GetCustomBuildInfo(list<SCustomBuildInfo> * info) const780 void CMsvcCombinedProjectMakefile::GetCustomBuildInfo
781 (list<SCustomBuildInfo>* info) const
782 {
783 m_ProjectMakefile->GetCustomBuildInfo(info);
784 }
785
GetCustomScriptInfo(SCustomScriptInfo & info,const string & section) const786 void CMsvcCombinedProjectMakefile::GetCustomScriptInfo
787 (SCustomScriptInfo& info, const string& section) const
788 {
789 m_ProjectMakefile->GetCustomScriptInfo(info, section);
790 }
791
792
793 //-----------------------------------------------------------------------------
GetConfigurationOpt(const IMsvcMetaMakefile & meta_file,const IMsvcMetaMakefile & project_file,const string & opt,const SConfigInfo & config)794 string GetConfigurationOpt(const IMsvcMetaMakefile& meta_file,
795 const IMsvcMetaMakefile& project_file,
796 const string& opt,
797 const SConfigInfo& config)
798 {
799 string val = project_file.GetConfigurationOpt(opt, config);
800 if ( val.empty() ) {
801 val = meta_file.GetConfigurationOpt(opt, config);
802 }
803 if (val == "-") {
804 return kEmptyStr;
805 }
806 return val;
807 }
808
GetCompilerOpt(const IMsvcMetaMakefile & meta_file,const IMsvcMetaMakefile & project_file,const string & opt,const SConfigInfo & config)809 string GetCompilerOpt(const IMsvcMetaMakefile& meta_file,
810 const IMsvcMetaMakefile& project_file,
811 const string& opt,
812 const SConfigInfo& config)
813 {
814 string val = project_file.GetCompilerOpt(opt, config);
815 if ( val.empty() && CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000 ) {
816 val = meta_file.GetCompilerOpt(opt, config);
817 }
818 if (val == "-") {
819 return kEmptyStr;
820 }
821 return val;
822 }
823
824
GetLinkerOpt(const IMsvcMetaMakefile & meta_file,const IMsvcMetaMakefile & project_file,const string & opt,const SConfigInfo & config)825 string GetLinkerOpt(const IMsvcMetaMakefile& meta_file,
826 const IMsvcMetaMakefile& project_file,
827 const string& opt,
828 const SConfigInfo& config)
829 {
830 string val = project_file.GetLinkerOpt(opt, config);
831 if ( val.empty() && CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000 ) {
832 val = meta_file.GetLinkerOpt(opt, config);
833 }
834 if (val == "-") {
835 return kEmptyStr;
836 }
837 return val;
838 }
839
840
GetLibrarianOpt(const IMsvcMetaMakefile & meta_file,const IMsvcMetaMakefile & project_file,const string & opt,const SConfigInfo & config)841 string GetLibrarianOpt(const IMsvcMetaMakefile& meta_file,
842 const IMsvcMetaMakefile& project_file,
843 const string& opt,
844 const SConfigInfo& config)
845 {
846 string val = project_file.GetLibrarianOpt(opt, config);
847 if ( val.empty() && CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000 ) {
848 val = meta_file.GetLibrarianOpt(opt, config);
849 }
850 if (val == "-") {
851 return kEmptyStr;
852 }
853 return val;
854 }
855
GetResourceCompilerOpt(const IMsvcMetaMakefile & meta_file,const IMsvcMetaMakefile & project_file,const string & opt,const SConfigInfo & config)856 string GetResourceCompilerOpt(const IMsvcMetaMakefile& meta_file,
857 const IMsvcMetaMakefile& project_file,
858 const string& opt,
859 const SConfigInfo& config)
860 {
861 string val = project_file.GetResourceCompilerOpt(opt, config);
862 if ( val.empty() && CMsvc7RegSettings::GetMsvcVersion() < CMsvc7RegSettings::eMsvc1000 ) {
863 val = meta_file.GetResourceCompilerOpt(opt, config);
864 }
865 if (val == "-") {
866 return kEmptyStr;
867 }
868 return val;
869 }
870
871 END_NCBI_SCOPE
872