1 /* $Id: mac_prj_generator.cpp 600896 2020-01-29 15:48:51Z 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: Andrei Gourianov
27 *
28 */
29
30 #include <ncbi_pch.hpp>
31
32 #include "mac_prj_generator.hpp"
33
34 #include "proj_builder_app.hpp"
35 #include "msvc_project_context.hpp"
36 #include "proj_tree_builder.hpp"
37
38
39 #include "msvc_prj_utils.hpp"
40 #include "msvc_prj_defines.hpp"
41 #include "msvc_prj_files_collector.hpp"
42 #include "ptb_err_codes.hpp"
43
44 #include <algorithm>
45
46 #if defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
47 # include <serial/objostrxml.hpp>
48 # include <serial/serial.hpp>
49 #endif
50
51 BEGIN_NCBI_SCOPE
52
53 #if defined(NCBI_XCODE_BUILD) || defined(PSEUDO_XCODE)
54
55 //
56 // 1 - use human-friendly names (still works with XCode, but generates lots of warnings)
57 // 0 - use XCode-friendly hexadecimal ids
58 #define USE_VERBOSE_NAMES 0
59
60 /////////////////////////////////////////////////////////////////////////////
61
62 const char* s_ptb_makecandidate = "__PTB__MAKE__CANDIDATE__";
63
s_ProjId_less(const CProjItem * x,const CProjItem * y)64 bool s_ProjId_less(const CProjItem* x, const CProjItem* y)
65 {
66 return NStr::CompareNocase(
67 CMacProjectGenerator::GetProjId(*x),
68 CMacProjectGenerator::GetProjId(*y)) < 0;
69 }
70
s_ProjItem_less(const CProjItem & x,const CProjItem & y)71 bool s_ProjItem_less(const CProjItem& x, const CProjItem& y)
72 {
73 ITERATE( list<CProjKey>, i, x.m_Depends) {
74 if (y.m_ID == i->Id()) {
75 return true;
76 }
77 }
78 return false;
79 }
80
s_String_less(const CRef<CArray::C_E> & x,const CRef<CArray::C_E> & y)81 bool s_String_less(const CRef<CArray::C_E>& x, const CRef<CArray::C_E>& y)
82 {
83 return NStr::CompareNocase(x->GetString(), y->GetString()) < 0;
84 }
85
s_Key_less(const CRef<CDict::C_E> & x,const CRef<CDict::C_E> & y)86 bool s_Key_less(const CRef<CDict::C_E>& x, const CRef<CDict::C_E>& y)
87 {
88 return NStr::CompareNocase(x->GetKey(), y->GetKey()) < 0;
89 }
90
91
92 /////////////////////////////////////////////////////////////////////////////
93
CMacProjectGenerator(const list<SConfigInfo> & configs,const CProjectItemsTree & projects_tree)94 CMacProjectGenerator::CMacProjectGenerator(
95 const list<SConfigInfo>& configs, const CProjectItemsTree& projects_tree)
96 :m_Configs(configs), m_Projects_tree(projects_tree)
97 {
98 }
99
~CMacProjectGenerator(void)100 CMacProjectGenerator::~CMacProjectGenerator(void)
101 {
102 }
103
Generate(const string & solution)104 void CMacProjectGenerator::Generate(const string& solution)
105 {
106 m_SolutionDir = CDirEntry::IsAbsolutePath(solution) ?
107 solution : CDirEntry::ConcatPath( CDir::GetCwd(), solution);
108 string solution_name = CDirEntry(m_SolutionDir).GetName();
109 m_SolutionDir = CDirEntry(m_SolutionDir).GetDir(CDirEntry::eIfEmptyPath_Empty);
110
111 m_OutputDir = CDirEntry::AddTrailingPathSeparator(
112 CDirEntry::ConcatPath( CDirEntry::ConcatPath(
113 GetApp().GetProjectTreeInfo().m_Compilers,
114 GetApp().GetRegSettings().m_CompilersSubdir),
115 GetApp().GetBuildType().GetTypeStr()));
116 m_OutputDir = GetRelativePath(m_OutputDir);
117
118 CRef<CPlist> xproj( new CPlist);
119 CDict& dict_root = xproj->SetPlistObject().SetDict();
120
121 xproj->SetAttlist().SetVersion("1.0");
122 AddString( dict_root, "archiveVersion", "1");
123 AddDict( dict_root, "classes");
124 // 39 42 44
125 AddString( dict_root, "objectVersion", GetApp().GetRegSettings().m_Version);
126 CRef<CDict> dict_objects( AddDict( dict_root, "objects"));
127 string configs_root( CreateBuildConfigurations( *dict_objects));
128
129 CRef<CArray> file_groups( new CArray);
130 CRef<CArray> targets( new CArray);
131 CRef<CArray> all_dependencies( new CArray);
132 CRef<CArray> app_dependencies( new CArray);
133 CRef<CArray> lib_dependencies( new CArray);
134 CRef<CArray> dataspec_dependencies( new CArray);
135 CRef<CArray> products( new CArray);
136 bool add_composite = GetApp().m_ProjTags == "*";
137 vector< CRef<CArray> > composite_dependencies;
138 for (map<string,string>::const_iterator composite = GetApp().m_CompositeProjectTags.begin();
139 composite != GetApp().m_CompositeProjectTags.end(); ++composite) {
140 composite_dependencies.push_back( CRef<CArray>(new CArray) );
141 }
142
143
144 #if USE_VERBOSE_NAMES
145 string root_name("ROOT_OBJECT");
146 #else
147 string root_name( GetUUID());
148 #endif
149 // set GUIDs
150 list<const CProjItem*> all_projects;
151 ITERATE(CProjectItemsTree::TProjects, p, m_Projects_tree.m_Projects) {
152 const CProjItem& prj(p->second);
153 prj.m_GUID = GetUUID();
154 all_projects.push_back(&prj);
155 }
156 all_projects.sort(s_ProjId_less);
157
158 // generate product IDs
159 m_TargetProduct.clear();
160 ITERATE(list<const CProjItem*>, p, all_projects) {
161 const CProjItem& prj(**p);
162 string target_id(GetProjId(prj));
163 m_TargetProduct[target_id] = GetUUID();
164 }
165 // generate targets
166 ITERATE(list<const CProjItem*>, p, all_projects) {
167 const CProjItem& prj(**p);
168
169 #if USE_VERBOSE_NAMES
170 string proj_dependency(GetProjDependency(prj));
171 string proj_container( GetProjContainer(prj));
172 #else
173 string proj_dependency(prj.m_GUID);
174 string proj_container( GetUUID());
175 #endif
176 string explicit_type( GetExplicitType( prj));
177 string target_name(GetTargetName(prj));
178 string target_id(GetProjId(prj));
179
180 CProjectFileCollector prj_files( prj, m_Configs, m_SolutionDir+m_OutputDir);
181 if (!prj_files.CheckProjectConfigs()) {
182 continue;
183 }
184 if (prj.m_MakeType == eMakeType_ExcludedByReq) {
185 PTB_WARNING_EX(prj.m_ID, ePTB_ProjectExcluded,
186 "Excluded due to unmet requirements");
187 continue;
188 }
189 // see CXX-542
190 bool excluded = (prj.m_MakeType >= eMakeType_Expendable);
191 // bool excluded = (prj.m_MakeType > eMakeType_Expendable);
192
193 prj_files.DoCollect();
194 if (!excluded) {
195 if (prj.m_ProjType == CProjKey::eLib || prj.m_ProjType == CProjKey::eDll) {
196 AddString( *lib_dependencies, proj_dependency);
197 // } else if (prj.m_ProjType == CProjKey::eApp) {
198 // AddString( *app_dependencies, proj_dependency);
199 // } else if (prj.m_ProjType == CProjKey::eDataSpec) {
200 }
201 if (!prj.m_DatatoolSources.empty()) {
202 AddString( *dataspec_dependencies, proj_dependency);
203 }
204 if (prj.m_ProjType != CProjKey::eLib && prj.m_ProjType != CProjKey::eDll &&
205 prj.m_ProjType != CProjKey::eApp && //prj.m_ProjType != CProjKey::eDataSpec &&
206 prj.m_ProjType != CProjKey::eMsvc) {
207 continue;
208 }
209 if (add_composite) {
210 int c = 0;
211 for (map<string,string>::const_iterator composite = GetApp().m_CompositeProjectTags.begin();
212 composite != GetApp().m_CompositeProjectTags.end(); ++composite, ++c) {
213
214 if (GetApp().IsAllowedProjectTag(prj, &composite->second)) {
215 AddString( *(composite_dependencies[c]), proj_dependency);
216 }
217 }
218 }
219 AddString( *all_dependencies, proj_dependency);
220 }
221
222 if (prj.m_ProjType == CProjKey::eApp) {
223 string app_type = prj_files.GetProjectContext().GetMsvcProjectMakefile().GetLinkerOpt("APP_TYPE",SConfigInfo());
224 if (app_type == "application") {
225 prj.m_IsBundle = true;
226 explicit_type = GetExplicitType( prj);
227 }
228 }
229
230 CRef<CArray> build_phases( new CArray);
231 CRef<CArray> build_files( new CArray);
232
233 // project file groups
234 AddString( *file_groups,
235 CreateProjectFileGroups(prj, prj_files, *dict_objects, *build_files));
236
237 // project custom script phase
238 string proj_prebuild_script(
239 CreateProjectCustomScriptPhase(prj, prj_files, *dict_objects, "PreBuild"));
240 if (!proj_prebuild_script.empty()) {
241 AddString( *build_phases, proj_prebuild_script);
242 }
243 // project script phase
244 string proj_script(
245 CreateProjectScriptPhase(prj, prj_files, *dict_objects));
246 if (!proj_script.empty()) {
247 AddString( *build_phases, proj_script);
248 }
249 // project build phase
250 string proj_build(
251 CreateProjectBuildPhase(prj, *dict_objects, build_files));
252 if (!proj_build.empty()) {
253 AddString( *build_phases, proj_build);
254 }
255 // project custom script phase
256 string proj_cust_script(
257 CreateProjectCustomScriptPhase(prj, prj_files, *dict_objects, "CustomScript"));
258 if (!proj_cust_script.empty()) {
259 AddString( *build_phases, proj_cust_script);
260 }
261 // link binary with libraries phase
262 string proj_link(
263 CreateProjectLinkPhase(prj, prj_files, *dict_objects));
264 if (!proj_link.empty()) {
265 AddString( *build_phases, proj_link);
266 }
267 // project copybin script phase
268 string proj_copybin_script(
269 CreateProjectCopyBinScript(prj, prj_files, *dict_objects));
270 if (!proj_copybin_script.empty()) {
271 AddString( *build_phases, proj_copybin_script);
272 }
273 // project target and dependencies
274 string proj_product( m_TargetProduct[target_id] );
275 string proj_target(
276 CreateProjectTarget( prj, prj_files, *dict_objects, build_phases,
277 proj_product));
278 if (!proj_target.empty()) {
279 AddString( *targets, proj_target);
280 }
281
282 // project dependency key
283 {
284 CRef<CDict> dict_dep( AddDict( *dict_objects, proj_dependency));
285 AddString( *dict_dep, "isa", "PBXTargetDependency");
286 AddString( *dict_dep, "target", proj_target);
287 AddString( *dict_dep, "targetProxy", proj_container);
288 }
289 // project container
290 {
291 CRef<CDict> dict_con( AddDict( *dict_objects, proj_container));
292 AddString( *dict_con, "containerPortal", root_name);
293 AddString( *dict_con, "isa", "PBXContainerItemProxy");
294 AddString( *dict_con, "proxyType", "1");
295 AddString( *dict_con, "remoteGlobalIDString", proj_target);
296 AddString( *dict_con, "remoteInfo", target_name);
297 }
298 // project product
299 if (!explicit_type.empty()) {
300 AddString( *products, proj_product);
301 CRef<CDict> dict_product( AddDict( *dict_objects, proj_product));
302 AddString( *dict_product, "explicitFileType", explicit_type);
303 AddString( *dict_product, "includeInIndex", "0");
304 AddString( *dict_product, "isa", "PBXFileReference");
305 if (prj.m_ProjType == CProjKey::eDll) {
306 AddString( *dict_product, "path", string("lib") + prj.m_ID + string(".dylib"));
307 } else if (prj.m_ProjType == CProjKey::eApp) {
308 AddString( *dict_product, "path", prj.m_ID);
309 } else if (prj.m_ProjType == CProjKey::eLib) {
310 if (prj.m_IsMetallib) {
311 AddString( *dict_product, "path", prj.m_ID + string(".metallib"));
312 } else {
313 AddString( *dict_product, "path", string("lib") + prj.m_ID + string(".a"));
314 }
315 }
316 AddString( *dict_product, "sourceTree", "BUILT_PRODUCTS_DIR");
317 }
318 // watchers
319 GetApp().RegisterProjectWatcher( target_name, prj.m_SourcesBaseDir, prj.m_Watchers);
320 }
321
322 // collect file groups
323 #if USE_VERBOSE_NAMES
324 string source_files("Source_Files");
325 string root_group("Main_Group");
326 string products_group("Products_Group");
327 #else
328 string source_files( GetUUID());
329 string root_group( GetUUID());
330 string products_group( GetUUID());
331 #endif
332
333 file_groups->Set().sort(s_String_less);
334 AddGroupDict( *dict_objects, source_files, file_groups, "Sources");
335 AddGroupDict( *dict_objects, products_group, products, "Products");
336 CRef<CArray> main_groups( new CArray);
337 AddString( *main_groups, source_files);
338 AddString( *main_groups, products_group);
339 AddGroupDict( *dict_objects, root_group, main_groups, "NCBI C++ Toolkit");
340
341 targets->Set().sort(s_String_less);
342 dataspec_dependencies->Set().sort(s_String_less);
343 lib_dependencies->Set().sort(s_String_less);
344 // app_dependencies->Set().sort(s_String_less);
345 all_dependencies->Set().sort(s_String_less);
346 if (add_composite) {
347 int c = 0;
348 for (map<string,string>::const_iterator composite = GetApp().m_CompositeProjectTags.begin();
349 composite != GetApp().m_CompositeProjectTags.end(); ++composite, ++c) {
350
351 if (!composite_dependencies[c]->Get().empty()) {
352 composite_dependencies[c]->Set().sort(s_String_less);
353 InsertString( *targets,
354 AddAggregateTarget("_TAG_" + composite->first, *dict_objects, composite_dependencies[c]));
355 }
356 }
357 }
358 // aggregate targets
359 string preconf_dependency(AddPreConfigureTarget(*targets,*dict_objects, root_name));
360 InsertString( *targets,
361 AddConfigureTarget(solution_name, *dict_objects, true, preconf_dependency));
362 InsertString( *targets,
363 AddConfigureTarget(solution_name, *dict_objects, false, preconf_dependency));
364 InsertString( *targets,
365 AddAggregateTarget("DATASPEC_ALL", *dict_objects, dataspec_dependencies));
366 InsertString( *targets,
367 AddAggregateTarget("LIBS_ALL", *dict_objects, lib_dependencies));
368 // InsertString( *targets,
369 // AddAggregateTarget("BUILD_APPS", *dict_objects, app_dependencies));
370 InsertString( *targets,
371 AddAggregateTarget("BUILD_ALL", *dict_objects, all_dependencies));
372
373 // root object
374 AddString( dict_root, "rootObject",
375 CreateRootObject(configs_root, *dict_objects, targets,
376 root_group, root_name, products_group));
377
378 #if !USE_VERBOSE_NAMES
379 dict_objects->Set().sort(s_Key_less);
380 #endif
381
382 // save project
383 Save(solution_name, *xproj);
384 }
385
Save(const string & solution_name,CPlist & xproj)386 void CMacProjectGenerator::Save(const string& solution_name, CPlist& xproj)
387 {
388 bool make_candidate = !GetApp().GetEnvironment().Get(s_ptb_makecandidate).empty();
389 string solution_dir(m_SolutionDir);
390 solution_dir = CDirEntry::ConcatPath(solution_dir, solution_name);
391 solution_dir += ".xcodeproj";
392 CDir(solution_dir).CreatePath();
393 string solution_file( CDirEntry::ConcatPath(solution_dir, "project.pbxproj"));
394 GetApp().RegisterGeneratedFile( solution_file );
395 if (make_candidate) {
396 solution_file += ".candidate";
397 }
398 {
399 unique_ptr<CObjectOStream> out(CObjectOStream::Open(solution_file, eSerial_Xml));
400 CObjectOStreamXml *ox = dynamic_cast<CObjectOStreamXml*>(out.get());
401 ox->SetReferenceDTD(true);
402 ox->SetDTDPublicId("-//Apple//DTD PLIST 1.0//EN");
403 ox->SetDTDFilePrefix("http://www.apple.com/DTDs/");
404 ox->SetDTDFileName("PropertyList-1.0");
405 ox->SetEncoding(eEncoding_UTF8);
406 *out << xproj;
407 }
408 CreateConfigureScript(solution_name, false);
409 CreateConfigureScript(solution_name, true);
410 }
411
CreateConfigureScript(const string & name,bool with_gui) const412 void CMacProjectGenerator::CreateConfigureScript(const string& name, bool with_gui) const
413 {
414 string script = CDirEntry::ConcatPath(m_SolutionDir,"UtilityProjects/configure_");
415 if (with_gui) {
416 script += "gui_";
417 }
418 script += name + ".sh";
419 string candidate = script + ".candidate";
420
421 CNcbiOfstream ofs(candidate.c_str(), IOS_BASE::out | IOS_BASE::trunc);
422 if ( !ofs )
423 NCBI_THROW(CProjBulderAppException, eFileCreation, script);
424
425 GetApp().RegisterGeneratedFile( script );
426 ofs << "#!/bin/sh\n";
427 ofs << "export PTB_FLAGS=\"";
428 if ( GetApp().GetBuildType().GetType() == CBuildType::eDll )
429 ofs << " -dll";
430 if (!GetApp().m_BuildPtb) {
431 ofs << " -nobuildptb";
432 }
433 if (GetApp().m_Dtdep) {
434 ofs << " -dtdep";
435 }
436 if (!GetApp().m_AddMissingDep) {
437 ofs << " -noadddep";
438 }
439 ofs << " -libdep " << (GetApp().m_LibDep ? "true" : "false");
440 if (GetApp().m_AddMissingLibs) {
441 ofs << " -ext";
442 }
443 if (!GetApp().m_ScanWholeTree) {
444 ofs << " -nws";
445 }
446 if (!GetApp().m_BuildRoot.empty()) {
447 ofs << " -extroot \"" << GetApp().m_BuildRoot << "\"";
448 }
449 if (with_gui /*|| GetApp().m_ConfirmCfg*/) {
450 ofs << " -cfg";
451 }
452 if (GetApp().m_ProjTagCmnd) {
453 if (GetApp().m_ProjTags != "*") {
454 ofs << " -projtag \\\"" << GetApp().m_ProjTags << "\\\"";
455 } else {
456 ofs << " -projtag #";
457 }
458 }
459 ofs << "\"\n";
460 ofs << "export PTB_PROJECT_REQ=" << GetApp().m_Subtree << "\n";
461 ofs << "$BUILD_TREE_ROOT/ptb.sh\n";
462 ofs.close();
463 PromoteIfDifferent(script, candidate);
464 CDirEntry(script).SetMode(
465 CDirEntry::fExecute | CDirEntry::fRead | CDirEntry::fWrite,
466 CDirEntry::fExecute | CDirEntry::fRead | CDirEntry::fWrite,
467 CDirEntry::fExecute | CDirEntry::fRead | CDirEntry::fWrite);
468 }
469
CreateProjectFileGroups(const CProjItem & prj,const CProjectFileCollector & prj_files,CDict & dict_objects,CArray & build_files)470 string CMacProjectGenerator::CreateProjectFileGroups(
471 const CProjItem& prj, const CProjectFileCollector& prj_files,
472 CDict& dict_objects, CArray& build_files)
473 {
474 CDllSrcFilesDistr& dll_src( GetApp().GetDllFilesDistr());
475 CProjKey proj_key(prj.m_ProjType, prj.m_ID);
476
477 string proj_id( GetProjId( prj) );
478 #if USE_VERBOSE_NAMES
479 string proj_src( proj_id + "_src");
480 string proj_include( proj_id + "_include");
481 string proj_specs( proj_id + "_specs");
482 string src_group_name( proj_id + "_sources");
483 #else
484 string proj_src( GetUUID());
485 string proj_include( GetUUID());
486 string proj_specs( GetUUID());
487 string src_group_name( GetUUID());
488 #endif
489
490 CRef<CArray> proj_cpps( new CArray);
491 CRef<CArray> proj_hpps( new CArray);
492 CRef<CArray> specs( new CArray);
493
494 map<string, CRef<CArray> > hosted_cpps;
495 map<string, CRef<CArray> > hosted_hpps;
496 map<string, CRef<CArray> > hosted_srcs;
497 ITERATE( list<string>, hosted_lib, prj.m_HostedLibs) {
498 hosted_cpps[ *hosted_lib] = new CArray;
499 hosted_hpps[ *hosted_lib] = new CArray;
500 hosted_srcs[ *hosted_lib] = new CArray;
501 }
502
503 // for each source file in project
504 ITERATE ( list<string>, f, prj_files.GetSources()) {
505 string src( AddFile( dict_objects, *f, prj.m_StyleObjcpp));
506 if (!src.empty()) {
507 bool added=false;
508 if (prj.m_ProjType == CProjKey::eDll) {
509 CProjKey hosted_key = dll_src.GetSourceLib( *f, proj_key);
510 if (!hosted_key.Id().empty()) {
511 AddString( *hosted_cpps[ hosted_key.Id() ], src);
512 added = true;
513 }
514 }
515 if (!added) {
516 AddString( *proj_cpps, src);
517 }
518 AddString( build_files, AddFileSource( dict_objects, src));
519 }
520 }
521 // for each header file in project
522 ITERATE ( list<string>, f, prj_files.GetHeaders()) {
523 string src( AddFile( dict_objects, *f, prj.m_StyleObjcpp));
524 if (!src.empty()) {
525 bool added=false;
526 if (prj.m_ProjType == CProjKey::eDll) {
527 CProjKey hosted_key = dll_src.GetHeaderLib( *f, proj_key);
528 if (!hosted_key.Id().empty()) {
529 AddString( *hosted_hpps[ hosted_key.Id() ], src);
530 added = true;
531 } else {
532 CProjKey hosted_inl = dll_src.GetInlineLib( *f, proj_key);
533 if (!hosted_inl.Id().empty()) {
534 AddString( *hosted_hpps[ hosted_inl.Id() ], src);
535 added = true;
536 }
537 }
538 }
539 if (!added) {
540 AddString( *proj_hpps, src);
541 }
542 }
543 }
544 // dataspecs
545 ITERATE ( list<string>, f, prj_files.GetDataSpecs()) {
546 string src( AddFile( dict_objects, *f, prj.m_StyleObjcpp));
547 if (!src.empty()) {
548 AddString( *specs,src);
549 }
550 }
551
552 string source_files( "Source Files");
553 string header_files( "Header Files");
554 string datatool_files("Datatool Files");
555 CRef<CArray> prj_sources( new CArray);
556 ITERATE( list<string>, hosted_lib, prj.m_HostedLibs) {
557 CRef<CArray>& cpps = hosted_cpps[ *hosted_lib];
558 CRef<CArray>& hpps = hosted_hpps[ *hosted_lib];
559 CRef<CArray>& srcs = hosted_srcs[ *hosted_lib];
560 #if USE_VERBOSE_NAMES
561 string hosted_src( *hosted_lib + "_hosted_src");
562 string hosted_inc( *hosted_lib + "_hosted_include");
563 string hosted_group( *hosted_lib + "_hosted_sources");
564 #else
565 string hosted_src( GetUUID());
566 string hosted_inc( GetUUID());
567 string hosted_group( GetUUID());
568 #endif
569 if (!cpps->Get().empty()) {
570 cpps->Set().sort(s_String_less);
571 AddString( *srcs, hosted_src);
572 AddGroupDict( dict_objects, hosted_src, cpps, source_files);
573 }
574 if (!hpps->Get().empty()) {
575 hpps->Set().sort(s_String_less);
576 AddString( *srcs, hosted_inc);
577 AddGroupDict( dict_objects, hosted_inc, hpps, header_files);
578 }
579 AddGroupDict( dict_objects, hosted_group, srcs, *hosted_lib);
580 AddString( *prj_sources, hosted_group);
581 }
582 if (!prj.m_HostedLibs.empty()) {
583 prj_sources->Set().sort(s_String_less);
584 }
585 if (!proj_cpps->Get().empty()) {
586 proj_cpps->Set().sort(s_String_less);
587 AddString( *prj_sources, proj_src);
588 AddGroupDict( dict_objects, proj_src, proj_cpps, source_files);
589 }
590 if (!proj_hpps->Get().empty()) {
591 proj_hpps->Set().sort(s_String_less);
592 AddString( *prj_sources, proj_include);
593 AddGroupDict( dict_objects, proj_include, proj_hpps, header_files);
594 }
595 if (!specs->Get().empty()) {
596 AddString( *prj_sources, proj_specs);
597 AddGroupDict( dict_objects, proj_specs, specs, datatool_files);
598 }
599 AddGroupDict( dict_objects, src_group_name, prj_sources, GetTargetName(prj));
600 return src_group_name;
601 }
602
CreateProjectScriptPhase(const CProjItem & prj,const CProjectFileCollector & prj_files,CDict & dict_objects)603 string CMacProjectGenerator::CreateProjectScriptPhase(
604 const CProjItem& prj, const CProjectFileCollector& prj_files,
605 CDict& dict_objects)
606 {
607 string script;
608 CRef<CArray> inputs( new CArray);
609 CRef<CArray> outputs( new CArray);
610 ITERATE( list<CProjKey>, p, prj_files.GetProjectContext().PreBuilds()) {
611 const CProjKey& proj_key = *p;
612 if (m_Projects_tree.m_Projects.find(proj_key) ==
613 m_Projects_tree.m_Projects.end()) {
614 PTB_WARNING_EX(
615 CDirEntry::ConcatPath(prj.m_SourcesBaseDir, CreateProjectName(CProjKey(prj.m_ProjType, prj.m_ID))),
616 ePTB_ProjectNotFound, " depends on missing project: " << proj_key.Id());
617 if (!SMakeProjectT::IsConfigurableDefine(proj_key.Id())) {
618 script += "echo ERROR: this project depends on missing " + CreateProjectName(proj_key);
619 script += "\nexit 1\n";
620 }
621 }
622 }
623 // configurable files
624 ITERATE ( list<string>, f, prj_files.GetConfigurableSources()) {
625 string outfile(GetRelativePath( *f));
626 // AddString( *outputs, outfile);
627 CDirEntry ent(outfile);
628 string infile(CDirEntry::ConcatPath( ent.GetDir(), ent.GetBase()));
629 infile += ".$CONFIGURATION";
630 infile += ent.GetExt();
631 script += "cmp -s " + infile + " " + outfile + "\n";
632 script += "if test $? -ne 0; then\n";
633 script += "cp -p " + infile + " " + outfile + "\n";
634 script += "fi\n";
635 AddString( *outputs, outfile);
636 }
637 // datatool
638 if (!prj.m_DatatoolSources.empty()) {
639 #if 0
640 ITERATE ( list<string>, f, prj_files.GetSources()) {
641 if (prj_files.IsProducedByDatatool(prj,*f)) {
642 string outfile(GetRelativePath( *f));
643 AddString( *outputs, outfile);
644 }
645 }
646 #endif
647 string pch_name = GetApp().GetMetaMakefile().GetDefaultPch();
648 bool dataspec_first = true;
649 ITERATE ( list<string>, f, prj_files.GetDataSpecs()) {
650 CDirEntry entry(*f);
651 string spec_base( CDirEntry(GetRelativePath(*f)).GetDir() + entry.GetBase());
652 string spec_ext = entry.GetExt();
653 AddString( *inputs, GetRelativePath(*f));
654 if (spec_ext == ".proto") {
655 AddString( *outputs, spec_base + ".pb.cc");
656 AddString( *outputs, spec_base + ".grpc.pb.cc");
657 } else {
658 AddString( *inputs, spec_base + ".def");
659 AddString( *outputs, spec_base + ".files");
660 AddString( *outputs, spec_base + "__.cpp");
661 AddString( *outputs, spec_base + "___.cpp");
662 {
663 string deffile(spec_base + ".def");
664 if (CFile(deffile).Exists()) {
665 CPtbRegistry reg;
666 CNcbiIfstream ifs(deffile.c_str());
667 reg.Read(ifs);
668 string clients = reg.GetString("-", "clients");
669 if (!clients.empty()) {
670 string clients_base = CDirEntry(GetRelativePath(*f)).GetDir() + clients;
671 AddString( *outputs, clients_base + ".cpp");
672 AddString( *outputs, clients_base + "_.cpp");
673 }
674 }
675 }
676 }
677 #if 0
678 script += "echo Generating C++ classes from " + entry.GetName() + "\n";
679 script += m_OutputDir + GetApp().GetDatatoolPathForApp();
680 #else
681 if (dataspec_first) {
682 script += "export PTB_PLATFORM=\"$ARCHS\"\n";
683 if (spec_ext == ".proto") {
684 script += "export GENERATOR_PATH=" + GetApp().GetSite().GetConfigureEntry("XCode_CustomCodeGenerator" + spec_ext) + "\n";
685 script += "export PROJECT_REQUIRES=" + NStr::Join(prj.m_Requires,";") + "\n";
686 } else {
687 script += "export DATATOOL_PATH=" + m_OutputDir + "../static/bin/ReleaseDLL\n";
688 }
689 script += "export TREE_ROOT=" +
690 CDirEntry::DeleteTrailingPathSeparator( GetRelativePath( GetApp().m_Root)) + "\n";
691 script += "export BUILD_TREE_ROOT=" +
692 CDirEntry::DeleteTrailingPathSeparator( GetRelativePath(
693 CDirEntry::AddTrailingPathSeparator( CDirEntry::ConcatPath(
694 GetApp().GetProjectTreeInfo().m_Compilers,
695 GetApp().GetRegSettings().m_CompilersSubdir)))) + "\n";
696 dataspec_first = false;
697 }
698 if (spec_ext == ".proto") {
699 script += "\"$BUILD_TREE_ROOT/protoc.sh\"";
700 } else {
701 script += "\"$BUILD_TREE_ROOT/datatool.sh\"";
702 }
703 #endif
704 script += " " + GetApp().GetDatatoolCommandLine() + " -pch " + pch_name;
705 script += " -m " + GetRelativePath( entry.GetPath(), &GetApp().GetProjectTreeInfo().m_Src);
706 string imports( prj_files.GetDataSpecImports(*f));
707 if (!imports.empty()) {
708 #ifdef PSEUDO_XCODE
709 NStr::ReplaceInPlace(imports, "\\", "/");
710 #endif
711 script += " -M \"" + imports + "\"";
712 }
713 script += " -oc " + entry.GetBase();
714 script += " -od " + spec_base + ".def";
715 script += " -or " + GetRelativePath( entry.GetDir(), &GetApp().GetProjectTreeInfo().m_Src);
716 script += " -oR " + GetRelativePath( GetApp().GetProjectTreeInfo().m_Root) + "\n";
717 }
718 }
719 if (!script.empty()) {
720 #if USE_VERBOSE_NAMES
721 string proj_script( GetProjId( prj) + "_script");
722 #else
723 string proj_script( GetUUID());
724 #endif
725 CRef<CDict> dict_script( AddDict( dict_objects, proj_script));
726 AddArray( *dict_script, "files");
727 AddArray( *dict_script, "inputPaths", inputs);
728 AddArray( *dict_script, "outputPaths", outputs);
729 AddString( *dict_script, "isa", "PBXShellScriptBuildPhase");
730 AddString( *dict_script, "shellPath", "/bin/sh");
731 AddString( *dict_script, "shellScript", script);
732 AddString( *dict_script, "showEnvVarsInLog", "0");
733 return proj_script;
734 }
735 return kEmptyStr;
736 }
737
CreateProjectCustomScriptPhase(const CProjItem & prj,const CProjectFileCollector & prj_files,CDict & dict_objects,const string & section)738 string CMacProjectGenerator::CreateProjectCustomScriptPhase(
739 const CProjItem& prj, const CProjectFileCollector& prj_files,
740 CDict& dict_objects, const string& section)
741 {
742 SCustomScriptInfo info;
743 prj_files.GetProjectContext().GetMsvcProjectMakefile().GetCustomScriptInfo(info, section);
744
745 if (!info.m_Script.empty()) {
746 #if USE_VERBOSE_NAMES
747 string proj_script( GetProjId( prj) + section);
748 #else
749 string proj_script( GetUUID());
750 #endif
751 CRef<CDict> dict_script( AddDict( dict_objects, proj_script));
752 string script_loc( prj.m_SourcesBaseDir);
753
754 CRef<CArray> inputs( new CArray);
755 CRef<CArray> outputs( new CArray);
756 list<string> in_list;
757 NStr::Split(info.m_Input, LIST_SEPARATOR, in_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
758 ITERATE( list<string>, i, in_list) {
759 AddString( *inputs,
760 GetRelativePath(CDirEntry::ConcatPath(script_loc,*i)));
761 }
762 list<string> out_list;
763 NStr::Split(info.m_Output, LIST_SEPARATOR, out_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
764 ITERATE( list<string>, o, out_list) {
765 AddString( *outputs,
766 GetRelativePath(CDirEntry::ConcatPath(script_loc,*o)));
767 }
768 AddArray( *dict_script, "files");
769 AddArray( *dict_script, "inputPaths", inputs);
770 AddArray( *dict_script, "outputPaths", outputs);
771 AddString( *dict_script, "isa", "PBXShellScriptBuildPhase");
772 if (info.m_Shell.empty()) {
773 info.m_Shell = "/bin/sh";
774 }
775 AddString( *dict_script, "shellPath", info.m_Shell);
776 AddString( *dict_script, "shellScript",
777 CDirEntry::IsAbsolutePath(info.m_Script) ? info.m_Script :
778 GetRelativePath(CDirEntry::ConcatPath(script_loc,info.m_Script)));
779 AddString( *dict_script, "showEnvVarsInLog", "0");
780 return proj_script;
781 }
782 return kEmptyStr;
783 }
784
CreateProjectCopyBinScript(const CProjItem & prj,const CProjectFileCollector & prj_files,CDict & dict_objects)785 string CMacProjectGenerator::CreateProjectCopyBinScript(
786 const CProjItem& prj, const CProjectFileCollector& prj_files,
787 CDict& dict_objects)
788 {
789 string bins_out_install(m_OutputDir + "bin/${CONFIGURATION}");
790 if (prj.m_ProjType == CProjKey::eApp ||
791 (prj.m_ProjType == CProjKey::eDll && prj.m_IsBundle)) {
792
793 string script;
794 script += "export BUILD_TREE_ROOT=" +
795 CDirEntry::DeleteTrailingPathSeparator( GetRelativePath(
796 CDirEntry::AddTrailingPathSeparator( CDirEntry::ConcatPath(
797 GetApp().GetProjectTreeInfo().m_Compilers,
798 GetApp().GetRegSettings().m_CompilersSubdir)))) + "\n";
799 script += "export BUILD_TREE_BIN=" + bins_out_install + "\n";
800 script += "\"$BUILD_TREE_ROOT/copybin.sh\"";
801 string proj_script( GetUUID());
802 CRef<CArray> inputs( new CArray);
803 AddString( *inputs, "$(TARGET_BUILD_DIR)/$(TARGET_NAME)");
804 CRef<CArray> outputs( new CArray);
805 CRef<CDict> dict_script( AddDict( dict_objects, proj_script));
806 AddArray( *dict_script, "files");
807 AddArray( *dict_script, "inputPaths", inputs);
808 AddArray( *dict_script, "outputPaths", outputs);
809 AddString( *dict_script, "isa", "PBXShellScriptBuildPhase");
810 AddString( *dict_script, "shellPath", "/bin/sh");
811 AddString( *dict_script, "shellScript", script);
812 AddString( *dict_script, "showEnvVarsInLog", "0");
813 return proj_script;
814 }
815 return kEmptyStr;
816 }
817
CreateProjectLinkPhase(const CProjItem & prj,const CProjectFileCollector & prj_files,CDict & dict_objects)818 string CMacProjectGenerator::CreateProjectLinkPhase(
819 const CProjItem& prj, const CProjectFileCollector& prj_files,
820 CDict& dict_objects)
821 {
822 if (prj.m_ProjType == CProjKey::eDll || prj.m_ProjType == CProjKey::eApp) {
823 list<CProjItem> ldlibs;
824 ITERATE( list<CProjKey>, d, prj.m_Depends) {
825 CProjectItemsTree::TProjects::const_iterator
826 dp = m_Projects_tree.m_Projects.find( *d);
827 if ( dp != m_Projects_tree.m_Projects.end() &&
828 (dp->first.Id() != prj.m_ID || dp->first.Type() != prj.m_ProjType) &&
829 (dp->first.Type() == CProjKey::eLib || dp->first.Type() == CProjKey::eDll)) {
830
831 if (dp->first.Type() == CProjKey::eLib &&
832 GetApp().GetSite().Is3PartyLib(dp->first.Id())) {
833 continue;
834 }
835 ldlibs.push_back(dp->second);
836 }
837 }
838 if (!ldlibs.empty()) {
839 string proj_link( GetUUID());
840 CRef<CDict> dict_link( AddDict( dict_objects, proj_link));
841 CRef<CArray> link_libs( AddArray( *dict_link, "files"));
842 ITERATE( list<CProjItem>, d, ldlibs) {
843 string lib_ref( GetUUID());
844 {
845 CRef<CDict> dict_lib_ref( AddDict( dict_objects, lib_ref));
846 AddString( *dict_lib_ref, "fileRef", m_TargetProduct[GetProjId(*d)]);
847 AddString( *dict_lib_ref, "isa", "PBXBuildFile");
848 }
849 AddString( *link_libs, lib_ref);
850 }
851 AddString( *dict_link, "isa", "PBXFrameworksBuildPhase");
852 return proj_link;
853 }
854 }
855 return kEmptyStr;
856 }
857
CreateProjectBuildPhase(const CProjItem & prj,CDict & dict_objects,CRef<CArray> & build_files)858 string CMacProjectGenerator::CreateProjectBuildPhase(
859 const CProjItem& prj,
860 CDict& dict_objects, CRef<CArray>& build_files)
861 {
862 if (prj.m_ProjType == CProjKey::eDataSpec || prj.m_ProjType == CProjKey::eMsvc) {
863 return kEmptyStr;
864 }
865 #if USE_VERBOSE_NAMES
866 string proj_build( GetProjBuild( prj));
867 #else
868 string proj_build( GetUUID());
869 #endif
870 CRef<CDict> dict_build( AddDict( dict_objects, proj_build));
871 AddArray( *dict_build, "files", build_files);
872 AddString( *dict_build, "isa", "PBXSourcesBuildPhase");
873 return proj_build;
874 }
875
CollectLibToLibDependencies(set<string> & dep,set<string> & visited,const CProjItem & lib,const CProjItem & lib_dep)876 void CMacProjectGenerator::CollectLibToLibDependencies(
877 set<string>& dep, set<string>& visited,
878 const CProjItem& lib, const CProjItem& lib_dep)
879 {
880 #if USE_VERBOSE_NAMES
881 string lib_name(GetProjDependency(lib));
882 string lib_dep_name(GetProjDependency(lib_dep));
883 #else
884 string lib_name(lib.m_GUID);
885 string lib_dep_name(lib_dep.m_GUID);
886 #endif
887 if (GetApp().m_AllDllBuild) {
888 dep.insert(lib_dep_name);
889 return;
890 }
891
892 if (visited.find(lib_dep_name) != visited.end() ||
893 lib_dep_name == lib_name) {
894 return;
895 }
896 visited.insert(lib_dep_name);
897 if (!lib_dep.m_DatatoolSources.empty() ||
898 !lib_dep.m_ExportHeaders.empty() ||
899 lib.m_UnconditionalDepends.find(
900 CProjKey(lib_dep.m_ProjType, lib_dep.m_ID)) !=
901 lib.m_UnconditionalDepends.end()) {
902 dep.insert(lib_dep_name);
903 }
904 ITERATE(list<CProjKey>, p, lib_dep.m_Depends) {
905 if (p->Type() == CProjKey::eLib) {
906 CProjectItemsTree::TProjects::const_iterator n =
907 m_Projects_tree.m_Projects.find(*p);
908 if (n != m_Projects_tree.m_Projects.end()) {
909 CollectLibToLibDependencies(dep, visited, lib, n->second);
910 }
911 }
912 }
913 }
914
CreateProjectTarget(const CProjItem & prj,const CProjectFileCollector & prj_files,CDict & dict_objects,CRef<CArray> & build_phases,const string & product_id)915 string CMacProjectGenerator::CreateProjectTarget(
916 const CProjItem& prj, const CProjectFileCollector& prj_files,
917 CDict& dict_objects, CRef<CArray>& build_phases,
918 const string& product_id)
919 {
920 #if USE_VERBOSE_NAMES
921 string proj_target( GetProjTarget( prj));
922 #else
923 string proj_target( GetUUID());
924 #endif
925 string target_name( GetTargetName( prj));
926 string product_type( GetProductType( prj));
927 CRef<CArray> dependencies( new CArray);
928 string configs_prj(
929 CreateProjectBuildConfigurations( prj, prj_files, dict_objects));
930 CRef<CDict> dict_target( AddDict( dict_objects, proj_target));
931 AddString( *dict_target, "buildConfigurationList",configs_prj);
932 AddArray( *dict_target, "buildPhases", build_phases);
933
934 list<string> proj_guid;
935 set<string> lib_guid, visited;
936 ITERATE( list<CProjKey>, d, prj.m_Depends) {
937 CProjectItemsTree::TProjects::const_iterator
938 dp = m_Projects_tree.m_Projects.find( *d);
939 if ( dp != m_Projects_tree.m_Projects.end() &&
940 (dp->first.Id() != prj.m_ID || dp->first.Type() != prj.m_ProjType)) {
941
942 if (dp->first.Type() == CProjKey::eLib &&
943 GetApp().GetSite().Is3PartyLib(dp->first.Id())) {
944 continue;
945 }
946 if (prj.m_ProjType == CProjKey::eLib && dp->first.Type() == CProjKey::eLib) {
947 CollectLibToLibDependencies(lib_guid, visited, prj, dp->second);
948 continue;
949 }
950 #if USE_VERBOSE_NAMES
951 proj_guid.push_back( GetProjDependency(dp->second));
952 #else
953 proj_guid.push_back( dp->second.m_GUID);
954 #endif
955 }
956 }
957 copy(lib_guid.begin(), lib_guid.end(), back_inserter(proj_guid));
958 if (!proj_guid.empty()) {
959 proj_guid.sort();
960 proj_guid.unique();
961 ITERATE(list<string>, p, proj_guid) {
962 AddString( *dependencies, *p);
963 }
964 }
965 AddArray( *dict_target, "dependencies", dependencies);
966 if (prj.m_ProjType == CProjKey::eDataSpec || prj.m_ProjType == CProjKey::eMsvc) {
967 AddString( *dict_target, "isa", "PBXAggregateTarget");
968 } else {
969 AddString( *dict_target, "isa", "PBXNativeTarget");
970 }
971 AddString( *dict_target, "name", target_name);
972 AddString( *dict_target, "productName", target_name);
973 if (prj.m_ProjType != CProjKey::eDataSpec && prj.m_ProjType != CProjKey::eMsvc) {
974 AddString( *dict_target, "productReference", product_id);
975 AddString( *dict_target, "productType", product_type);
976 }
977 return proj_target;
978 }
979
CreateBuildConfigurations(CDict & dict_objects)980 string CMacProjectGenerator::CreateBuildConfigurations(CDict& dict_objects)
981 {
982 CRef<CArray> build_settings( new CArray);
983 #if USE_VERBOSE_NAMES
984 string bld_cfg( "Build_Configuration_");
985 string bld_cfg_list( "Build_Configurations");
986 #else
987 string bld_cfg_list( GetUUID());
988 #endif
989
990 ITERATE(list<SConfigInfo>, cfg, m_Configs) {
991 if (cfg->m_rtType == SConfigInfo::rtSingleThreaded ||
992 cfg->m_rtType == SConfigInfo::rtSingleThreadedDebug ||
993 cfg->m_rtType == SConfigInfo::rtUnknown) {
994 continue;
995 }
996 #if USE_VERBOSE_NAMES
997 string bld_cfg_name(bld_cfg + cfg->m_Name);
998 #else
999 string bld_cfg_name( GetUUID());
1000 #endif
1001 CreateBuildSettings( *AddDict( dict_objects, bld_cfg_name), *cfg);
1002 AddString( *build_settings, bld_cfg_name);
1003 }
1004
1005 CRef<CDict> configs( AddDict( dict_objects, bld_cfg_list));
1006 AddArray( *configs, "buildConfigurations", build_settings);
1007 AddString( *configs, "defaultConfigurationIsVisible", "0");
1008 AddString( *configs, "defaultConfigurationName", "ReleaseDLL");
1009 AddString( *configs, "isa", "XCConfigurationList");
1010 return bld_cfg_list;
1011 }
1012
CreateProjectBuildConfigurations(const CProjItem & prj,const CProjectFileCollector & prj_files,CDict & dict_objects)1013 string CMacProjectGenerator::CreateProjectBuildConfigurations(
1014 const CProjItem& prj, const CProjectFileCollector& prj_files,
1015 CDict& dict_objects)
1016 {
1017 CRef<CArray> build_settings( new CArray);
1018 string proj_id( GetProjId( prj) );
1019 #if USE_VERBOSE_NAMES
1020 string bld_cfg( proj_id + "_Build_Configuration_");
1021 string bld_cfg_list( proj_id + "_Build_Configurations");
1022 #else
1023 string bld_cfg_list( GetUUID());
1024 #endif
1025
1026 ITERATE(list<SConfigInfo>, cfg, prj_files.GetEnabledConfigs()) {
1027 if (cfg->m_rtType == SConfigInfo::rtSingleThreaded ||
1028 cfg->m_rtType == SConfigInfo::rtSingleThreadedDebug ||
1029 cfg->m_rtType == SConfigInfo::rtUnknown) {
1030 continue;
1031 }
1032 prj.m_CheckConfigs.insert(cfg->GetConfigFullName());
1033 #if USE_VERBOSE_NAMES
1034 string bld_cfg_name(bld_cfg + cfg->m_Name);
1035 #else
1036 string bld_cfg_name( GetUUID());
1037 #endif
1038 CreateProjectBuildSettings( prj, prj_files,
1039 *AddDict( dict_objects, bld_cfg_name), *cfg);
1040 AddString( *build_settings, bld_cfg_name);
1041 }
1042
1043 CRef<CDict> configs( AddDict( dict_objects, bld_cfg_list));
1044 AddArray( *configs, "buildConfigurations", build_settings);
1045 AddString( *configs, "defaultConfigurationIsVisible", "0");
1046 AddString( *configs, "defaultConfigurationName", "ReleaseDLL");
1047 AddString( *configs, "isa", "XCConfigurationList");
1048 return bld_cfg_list;
1049 }
1050
CreateAggregateBuildConfigurations(const string & target_name,CDict & dict_objects)1051 string CMacProjectGenerator::CreateAggregateBuildConfigurations(
1052 const string& target_name, CDict& dict_objects)
1053 {
1054 CRef<CArray> build_settings( new CArray);
1055 string proj_id( target_name );
1056 #if USE_VERBOSE_NAMES
1057 string bld_cfg( target_name + "_Build_Configuration_");
1058 string bld_cfg_list( target_name + "_Build_Configurations");
1059 #else
1060 string bld_cfg_list( GetUUID());
1061 #endif
1062
1063 ITERATE(list<SConfigInfo>, cfg, m_Configs) {
1064 if (cfg->m_rtType == SConfigInfo::rtSingleThreaded ||
1065 cfg->m_rtType == SConfigInfo::rtSingleThreadedDebug ||
1066 cfg->m_rtType == SConfigInfo::rtUnknown) {
1067 continue;
1068 }
1069 #if USE_VERBOSE_NAMES
1070 string bld_cfg_name(bld_cfg + cfg->m_Name);
1071 #else
1072 string bld_cfg_name( GetUUID());
1073 #endif
1074 CreateAggregateBuildSettings( target_name,
1075 *AddDict( dict_objects, bld_cfg_name), *cfg);
1076 AddString( *build_settings, bld_cfg_name);
1077 }
1078
1079 CRef<CDict> configs( AddDict( dict_objects, bld_cfg_list));
1080 AddArray( *configs, "buildConfigurations", build_settings);
1081 AddString( *configs, "defaultConfigurationIsVisible", "0");
1082 AddString( *configs, "defaultConfigurationName", "ReleaseDLL");
1083 AddString( *configs, "isa", "XCConfigurationList");
1084 return bld_cfg_list;
1085 }
1086
CreateBuildSettings(CDict & dict_cfg,const SConfigInfo & cfg)1087 void CMacProjectGenerator::CreateBuildSettings(CDict& dict_cfg, const SConfigInfo& cfg)
1088 {
1089 string tmp_str;
1090 list<string> tmp_list;
1091
1092 CRef<CDict> settings( AddDict( dict_cfg, "buildSettings"));
1093 AddString( dict_cfg, "isa", "XCBuildConfiguration");
1094 AddString( dict_cfg, "name", cfg.m_Name);
1095
1096 tmp_str = CMsvc7RegSettings::GetRequestedArchs();
1097 if (tmp_str.empty()) {
1098 tmp_str = GetApp().GetMetaMakefile().GetCompilerOpt("ARCHS", cfg);
1099 }
1100 tmp_list.clear();
1101 NStr::Split(tmp_str, LIST_SEPARATOR, tmp_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
1102 CRef<CArray> archs( AddArray( *settings, "ARCHS"));
1103 ITERATE( list<string>, a, tmp_list) {
1104 AddString( *archs, *a);
1105 }
1106
1107 AddCompilerSetting( *settings, cfg, "GCC_WARN_ABOUT_RETURN_TYPE");
1108 AddCompilerSetting( *settings, cfg, "GCC_WARN_UNUSED_VARIABLE");
1109 AddCompilerSetting( *settings, cfg, "GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS");
1110 AddCompilerSetting( *settings, cfg, "GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS");
1111 AddCompilerSetting( *settings, cfg, "GCC_WARN_NON_VIRTUAL_DESTRUCTOR");
1112 AddCompilerSetting( *settings, cfg, "GCC_WARN_PEDANTIC");
1113 AddCompilerSetting( *settings, cfg, "GCC_WARN_SHADOW");
1114 AddCompilerSetting( *settings, cfg, "GCC_WARN_SIGN_COMPARE");
1115
1116 AddCompilerSetting( *settings, cfg, "GCC_DYNAMIC_NO_PIC");
1117 AddCompilerSetting( *settings, cfg, "GCC_ENABLE_FIX_AND_CONTINUE");
1118 AddCompilerSetting( *settings, cfg, "GCC_MODEL_TUNING");
1119 AddCompilerSetting( *settings, cfg, "GCC_ENABLE_CPP_EXCEPTIONS");
1120 AddCompilerSetting( *settings, cfg, "GCC_ENABLE_CPP_RTTI");
1121
1122 AddCompilerSetting( *settings, cfg, "COPY_PHASE_STRIP");
1123 AddCompilerSetting( *settings, cfg, "GCC_GENERATE_DEBUGGING_SYMBOLS");
1124 AddCompilerSetting( *settings, cfg, "GCC_OPTIMIZATION_LEVEL");
1125 AddCompilerSetting( *settings, cfg, "DEBUG_INFORMATION_FORMAT");
1126 AddCompilerSetting( *settings, cfg, "GCC_DEBUGGING_SYMBOLS");
1127
1128 AddCompilerSetting( *settings, cfg, "SDKROOT");
1129 AddCompilerSetting( *settings, cfg, "FRAMEWORK_SEARCH_PATHS");
1130 AddCompilerSetting( *settings, cfg, "USE_HEADERMAP");
1131
1132 AddCompilerSetting( *settings, cfg, "OTHER_CPLUSPLUSFLAGS");
1133
1134 AddLinkerSetting( *settings, cfg, "DEAD_CODE_STRIPPING");
1135 AddLinkerSetting( *settings, cfg, "PREBINDING");
1136 // AddLinkerSetting( *settings, cfg, "ZERO_LINK");
1137 if (cfg.m_rtType == SConfigInfo::rtMultiThreadedDebugDLL ||
1138 cfg.m_rtType == SConfigInfo::rtMultiThreadedDLL) {
1139 AddString( *settings, "STANDARD_C_PLUS_PLUS_LIBRARY_TYPE", "dynamic");
1140 } else {
1141 AddString( *settings, "STANDARD_C_PLUS_PLUS_LIBRARY_TYPE", "static");
1142 }
1143 }
1144
CreateProjectBuildSettings(const CProjItem & prj,const CProjectFileCollector & prj_files,CDict & dict_cfg,const SConfigInfo & cfg)1145 void CMacProjectGenerator::CreateProjectBuildSettings(
1146 const CProjItem& prj, const CProjectFileCollector& prj_files,
1147 CDict& dict_cfg, const SConfigInfo& cfg)
1148 {
1149 const CMsvcMetaMakefile& metamake( GetApp().GetMetaMakefile());
1150 bool dll_build = GetApp().GetBuildType().GetType() == CBuildType::eDll;
1151 string def_lib_path(m_OutputDir + "lib/$(CONFIGURATION)");
1152
1153 string libs_out(m_OutputDir + "lib/$(CONFIGURATION)");
1154 string libs_out_install(m_OutputDir + "lib/$(CONFIGURATION)");
1155 // CreateProjectCopyBinScript takes care of copying them into bin; CXX-1609
1156 // string bins_out(m_OutputDir + "bin/$(CONFIGURATION)");
1157 string bins_out(m_OutputDir + "lib/$(CONFIGURATION)");
1158 string bins_out_install(m_OutputDir + "bin/$(CONFIGURATION)");
1159
1160 string proj_dir("$(PROJECT_DIR)/");
1161
1162 // string temp_dir("$(BUILD_DIR)/$(CONFIGURATION)");
1163 string temp_dir("$(OBJROOT)/$(CONFIGURATION)");
1164 string objroot(m_OutputDir + "build");
1165
1166 CRef<CArray> lib_paths(new CArray);
1167 AddString(*lib_paths, def_lib_path);
1168 list<string> prj_lib_dirs;
1169 if (prj_files.GetLibraryDirs(prj_lib_dirs, cfg)) {
1170 ITERATE ( list<string>, f, prj_lib_dirs) {
1171 AddString( *lib_paths, GetRelativePath( *f));
1172 }
1173 }
1174
1175 CRef<CDict> settings( AddDict( dict_cfg, "buildSettings"));
1176 AddString( dict_cfg, "isa", "XCBuildConfiguration");
1177 AddString( dict_cfg, "name", cfg.m_Name);
1178
1179 if (prj.m_ProjType == CProjKey::eLib) {
1180
1181 AddLibrarianSetting( *settings, cfg, "GCC_ENABLE_SYMBOL_SEPARATION");
1182 AddLibrarianSetting( *settings, cfg, "GCC_INLINES_ARE_PRIVATE_EXTERN");
1183 AddLibrarianSetting( *settings, cfg, "GCC_SYMBOLS_PRIVATE_EXTERN");
1184
1185 AddString( *settings, "CONFIGURATION_BUILD_DIR", libs_out);
1186 AddString( *settings, "CONFIGURATION_TEMP_DIR", temp_dir);
1187 AddString( *settings, "INSTALL_PATH", proj_dir + libs_out_install);
1188 AddString( *settings, "OBJROOT", objroot);
1189
1190 } else if (prj.m_ProjType == CProjKey::eDll) {
1191
1192 string bld_out(libs_out);
1193 string bld_out_install(libs_out_install);
1194 if (prj.m_IsBundle) {
1195 bld_out = bins_out;
1196 bld_out_install = bins_out_install;
1197 }
1198 AddLinkerSetting( *settings, cfg, "GCC_INLINES_ARE_PRIVATE_EXTERN");
1199 AddLinkerSetting( *settings, cfg, "GCC_SYMBOLS_PRIVATE_EXTERN");
1200
1201 AddString( *settings, "CONFIGURATION_BUILD_DIR", bld_out);
1202 AddString( *settings, "CONFIGURATION_TEMP_DIR", temp_dir);
1203 AddString( *settings, "INSTALL_PATH", proj_dir + bld_out_install);
1204 AddString( *settings, "OBJROOT", objroot);
1205
1206 AddArray( *settings, "LIBRARY_SEARCH_PATHS", lib_paths);
1207 AddString( *settings, "EXECUTABLE_PREFIX", "lib");
1208
1209 } else if (prj.m_ProjType == CProjKey::eApp) {
1210
1211 AddLinkerSetting( *settings, cfg, "GCC_INLINES_ARE_PRIVATE_EXTERN");
1212 AddLinkerSetting( *settings, cfg, "GCC_SYMBOLS_PRIVATE_EXTERN");
1213
1214 AddString( *settings, "CONFIGURATION_BUILD_DIR", bins_out);
1215 AddString( *settings, "CONFIGURATION_TEMP_DIR", temp_dir);
1216 AddString( *settings, "INSTALL_PATH", proj_dir + bins_out_install);
1217 AddString( *settings, "OBJROOT", objroot);
1218
1219 AddArray( *settings, "LIBRARY_SEARCH_PATHS", lib_paths);
1220 }
1221 if (prj.m_ProjType != CProjKey::eDataSpec && prj.m_ProjType != CProjKey::eMsvc) {
1222 AddString( *settings, "MACH_O_TYPE", GetMachOType(prj));
1223 }
1224
1225 // library dependencies
1226 if (prj.m_ProjType == CProjKey::eDll || prj.m_ProjType == CProjKey::eApp) {
1227 string ldlib;
1228 #if 0
1229 list<CProjItem> ldlibs;
1230 ITERATE( list<CProjKey>, d, prj.m_Depends) {
1231 CProjectItemsTree::TProjects::const_iterator
1232 dp = m_Projects_tree.m_Projects.find( *d);
1233 if ( dp != m_Projects_tree.m_Projects.end() &&
1234 (dp->first.Id() != prj.m_ID || dp->first.Type() != prj.m_ProjType) &&
1235 (dp->first.Type() == CProjKey::eLib || dp->first.Type() == CProjKey::eDll)) {
1236
1237 if (dp->first.Type() == CProjKey::eLib &&
1238 GetApp().GetSite().Is3PartyLib(dp->first.Id())) {
1239 continue;
1240 }
1241 ldlibs.push_back(dp->second);
1242 }
1243 }
1244 ldlibs.sort(s_ProjItem_less);
1245 ITERATE( list<CProjItem>, d, ldlibs) {
1246 ldlib += string(" -l") + GetTargetName(*d);
1247 }
1248 #endif
1249 string add;
1250 add = prj_files.GetProjectContext().GetMsvcProjectMakefile().GetLinkerOpt("OTHER_LDFLAGS",cfg);
1251 if (!add.empty()) {
1252 ldlib += " " + add;
1253 }
1254 add = prj_files.GetProjectContext().AdditionalLinkerOptions(cfg);
1255 if (!add.empty()) {
1256 ldlib += " " + add;
1257 }
1258 add = metamake.GetLinkerOpt("OTHER_LDFLAGS", cfg);
1259 if (!add.empty()) {
1260 ldlib += " " + add;
1261 }
1262 AddString( *settings, "OTHER_LDFLAGS", ldlib);
1263 }
1264
1265 // AddString( *settings, "PRODUCT_NAME", GetTargetName(prj));
1266 AddString( *settings, "PRODUCT_NAME", prj.m_ID);
1267 if (prj.m_ProjType == CProjKey::eDataSpec || prj.m_ProjType == CProjKey::eMsvc) {
1268 return;
1269 }
1270
1271 CRef<CArray> inc_dirs( AddArray( *settings, "HEADER_SEARCH_PATHS"));
1272 list<string> prj_inc_dirs;
1273 if (prj_files.GetIncludeDirs(prj_inc_dirs, cfg)) {
1274 ITERATE ( list<string>, f, prj_inc_dirs) {
1275 /*
1276 if (CSymResolver::HasDefine(*f)) {
1277 continue;
1278 }
1279 */
1280 AddString( *inc_dirs, GetRelativePath( *f));
1281 }
1282 }
1283
1284 // preprocessor definitions
1285 list<string> tmp_list = prj.m_Defines;
1286 tmp_list = prj_files.GetProjectContext().Defines(cfg);
1287 string tmp_str = metamake.GetCompilerOpt("GCC_PREPROCESSOR_DEFINITIONS", cfg);
1288 NStr::Split(tmp_str, LIST_SEPARATOR, tmp_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
1289 if (dll_build) {
1290 tmp_str = GetApp().GetConfig().Get(CMsvc7RegSettings::GetMsvcSection(), "DllBuildDefine");
1291 NStr::Split(tmp_str, LIST_SEPARATOR, tmp_list, NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
1292 }
1293 if (prj.m_ProjType == CProjKey::eApp) {
1294 tmp_list.push_back("NCBI_APP_BUILT_AS=$(TARGET_NAME)");
1295 }
1296
1297 tmp_list.sort();
1298 tmp_list.unique();
1299 CRef<CArray> preproc( AddArray( *settings, "GCC_PREPROCESSOR_DEFINITIONS"));
1300 ITERATE( list<string>, a, tmp_list) {
1301 AddString( *preproc, *a);
1302 }
1303
1304 // precompiled header
1305 SConfigInfo cfg_tmp;
1306 if (prj_files.GetProjectContext().IsPchEnabled(cfg_tmp)) {
1307 string nofile = CDirEntry::ConcatPath(prj.m_SourcesBaseDir,"aanofile");
1308 string pch_name = prj_files.GetProjectContext().GetPchHeader(
1309 prj.m_ID, nofile, GetApp().GetProjectTreeInfo().m_Src, cfg_tmp);
1310 if (!pch_name.empty()) {
1311 string pch_path;
1312 // find header (MacOS requires? path)
1313 if (prj_files.GetIncludeDirs(prj_inc_dirs, cfg)) {
1314 ITERATE ( list<string>, f, prj_inc_dirs) {
1315 if (pch_path.empty()) {
1316 string t = CDirEntry::ConcatPath( *f, pch_name);
1317 if (CDirEntry(t).IsFile()) {
1318 pch_path = t;
1319 break;
1320 }
1321 }
1322 }
1323 }
1324 if (pch_path.empty()) {
1325 pch_path = CDirEntry::ConcatPath(
1326 GetApp().GetProjectTreeInfo().m_Include, pch_name);
1327 }
1328 AddString( *settings, "GCC_PRECOMPILE_PREFIX_HEADER", "YES");
1329 AddString( *settings, "GCC_PREFIX_HEADER", GetRelativePath( pch_path));
1330 // for some unknown reason, when I define NCBI_USE_PCH
1331 // xutil library does not compile
1332 string tmp(metamake.GetPchUsageDefine());
1333 if (!tmp.empty()) {
1334 AddString( *preproc, tmp);
1335 }
1336 }
1337 }
1338 }
1339
CreateAggregateBuildSettings(const string & target_name,CDict & dict_cfg,const SConfigInfo & cfg)1340 void CMacProjectGenerator::CreateAggregateBuildSettings(
1341 const string& target_name, CDict& dict_cfg, const SConfigInfo& cfg)
1342 {
1343 CRef<CDict> settings( AddDict( dict_cfg, "buildSettings"));
1344 AddString( dict_cfg, "isa", "XCBuildConfiguration");
1345 AddString( dict_cfg, "name", cfg.m_Name);
1346 AddString( *settings, "PRODUCT_NAME", target_name);
1347 }
1348
AddAggregateTarget(const string & target_name,CDict & dict_objects,CRef<CArray> & dependencies)1349 string CMacProjectGenerator::AddAggregateTarget(
1350 const string& target_name, CDict& dict_objects, CRef<CArray>& dependencies)
1351 {
1352 #if USE_VERBOSE_NAMES
1353 string proj_target( target_name + "_target");
1354 #else
1355 string proj_target( GetUUID());
1356 #endif
1357 string configs_prj(
1358 CreateAggregateBuildConfigurations( target_name, dict_objects));
1359 CRef<CDict> dict_target( AddDict( dict_objects, proj_target));
1360 AddString( *dict_target, "buildConfigurationList", configs_prj);
1361 AddArray( *dict_target, "buildPhases");
1362 AddString( *dict_target, "comments", NStr::NumericToString(dependencies->Get().size()) + " targets");
1363 AddArray( *dict_target, "dependencies", dependencies);
1364 AddString( *dict_target, "isa", "PBXAggregateTarget");
1365 AddString( *dict_target, "name", target_name);
1366 AddString( *dict_target, "productName", target_name);
1367 return proj_target;
1368 }
1369
AddPreConfigureTarget(CArray & targets,CDict & dict_objects,const string & root_name)1370 string CMacProjectGenerator::AddPreConfigureTarget(
1371 CArray& targets, CDict& dict_objects, const string& root_name)
1372 {
1373 string target_name("_pre_CONFIGURE");
1374 string proj_target( GetUUID());
1375 string configs_prj(
1376 CreateAggregateBuildConfigurations( target_name, dict_objects));
1377
1378 string build_tree_root (
1379 CDirEntry::DeleteTrailingPathSeparator( GetRelativePath(
1380 CDirEntry::AddTrailingPathSeparator( CDirEntry::ConcatPath(
1381 GetApp().GetProjectTreeInfo().m_Compilers,
1382 GetApp().GetRegSettings().m_CompilersSubdir)))));
1383 string script("$(PROJECT_DIR)/");
1384 script += build_tree_root + "/precfg.sh";
1385
1386 CRef<CDict> dict_target( AddDict( dict_objects, proj_target));
1387 AddString( *dict_target, "buildArgumentsString", script);
1388 AddString( *dict_target, "buildConfigurationList", configs_prj);
1389 AddArray( *dict_target, "buildPhases");
1390 AddString( *dict_target, "buildToolPath", "/bin/sh");
1391 AddArray( *dict_target, "dependencies");
1392 AddString( *dict_target, "isa", "PBXLegacyTarget");
1393 AddString( *dict_target, "name", target_name);
1394 AddString( *dict_target, "passBuildSettingsInEnvironment", "1");
1395 AddString( *dict_target, "productName", target_name);
1396
1397 InsertString(targets, proj_target);
1398
1399 string proj_dependency( GetUUID());
1400 string proj_container( GetUUID());
1401 // project dependency key
1402 {
1403 CRef<CDict> dict_dep( AddDict( dict_objects, proj_dependency));
1404 AddString( *dict_dep, "isa", "PBXTargetDependency");
1405 AddString( *dict_dep, "target", proj_target);
1406 AddString( *dict_dep, "targetProxy", proj_container);
1407 }
1408 // project container
1409 {
1410 CRef<CDict> dict_con( AddDict( dict_objects, proj_container));
1411 AddString( *dict_con, "containerPortal", root_name);
1412 AddString( *dict_con, "isa", "PBXContainerItemProxy");
1413 AddString( *dict_con, "proxyType", "1");
1414 AddString( *dict_con, "remoteGlobalIDString", proj_target);
1415 AddString( *dict_con, "remoteInfo", target_name);
1416 }
1417 return proj_dependency;
1418 }
1419
AddConfigureTarget(const string & solution_name,CDict & dict_objects,bool gui,const string & preconf_dependency)1420 string CMacProjectGenerator::AddConfigureTarget(
1421 const string& solution_name, CDict& dict_objects, bool gui,
1422 const string& preconf_dependency)
1423 {
1424 string target_name("CONFIGURE");
1425 if (gui) {
1426 target_name += "_DIALOG";
1427 }
1428 #if USE_VERBOSE_NAMES
1429 string proj_target( target_name + "_target");
1430 string proj_script( target_name + "_script");
1431 #else
1432 string proj_target( GetUUID());
1433 string proj_script( GetUUID());
1434 #endif
1435
1436 string configs_prj(
1437 CreateAggregateBuildConfigurations( target_name, dict_objects));
1438
1439 string script;
1440 script += "export PTB_PLATFORM=\"$ARCHS\"\n";
1441 script += "export PTB_PATH=" + m_OutputDir + "../static/bin/ReleaseDLL\n";
1442 script += "export SLN_PATH=" + m_OutputDir + "\"$PROJECT_NAME\""/*solution_name*/ + "\n";
1443 script += "export TREE_ROOT=" +
1444 CDirEntry::DeleteTrailingPathSeparator( GetRelativePath( GetApp().m_Root)) + "\n";
1445 script += "export BUILD_TREE_ROOT=" +
1446 CDirEntry::DeleteTrailingPathSeparator( GetRelativePath(
1447 CDirEntry::AddTrailingPathSeparator( CDirEntry::ConcatPath(
1448 GetApp().GetProjectTreeInfo().m_Compilers,
1449 GetApp().GetRegSettings().m_CompilersSubdir)))) + "\n";
1450 script += m_OutputDir + "UtilityProjects/configure_";
1451 if (gui) {
1452 script += "gui_";
1453 }
1454 script += solution_name + ".sh";
1455 CRef<CDict> dict_script( AddDict( dict_objects, proj_script));
1456 AddArray( *dict_script, "files");
1457 AddArray( *dict_script, "inputPaths");
1458 AddArray( *dict_script, "outputPaths");
1459 AddString( *dict_script, "isa", "PBXShellScriptBuildPhase");
1460 AddString( *dict_script, "shellPath", "/bin/sh");
1461 AddString( *dict_script, "shellScript", script);
1462 AddString( *dict_script, "showEnvVarsInLog", "0");
1463
1464 CRef<CDict> dict_target( AddDict( dict_objects, proj_target));
1465 AddString( *dict_target, "buildConfigurationList", configs_prj);
1466 CRef<CArray> build_phases(AddArray( *dict_target, "buildPhases"));
1467 AddString( *build_phases, proj_script);
1468 CRef<CArray> dependencies(AddArray( *dict_target, "dependencies"));
1469 AddString( *dependencies, preconf_dependency);
1470 AddString( *dict_target, "isa", "PBXAggregateTarget");
1471 AddString( *dict_target, "name", target_name);
1472 AddString( *dict_target, "productName", target_name);
1473 return proj_target;
1474 }
1475
CreateRootObject(const string & configs_root,CDict & dict_objects,CRef<CArray> & targets,const string & root_group,const string & root_name,const string & products_group)1476 string CMacProjectGenerator::CreateRootObject(
1477 const string& configs_root, CDict& dict_objects, CRef<CArray>& targets,
1478 const string& root_group, const string& root_name, const string& products_group)
1479 {
1480 CRef<CDict> root_obj( AddDict( dict_objects, root_name));
1481 AddString( *root_obj, "buildConfigurationList", configs_root);
1482 AddString( *root_obj, "compatibilityVersion", "Xcode 3.0");
1483 AddString( *root_obj, "hasScannedForEncodings", "1");
1484 AddString( *root_obj, "isa", "PBXProject");
1485 AddString( *root_obj, "mainGroup", root_group);
1486 AddString( *root_obj, "productRefGroup", products_group);
1487 AddString( *root_obj, "projectDirPath", "");
1488 AddString( *root_obj, "projectRoot", "");
1489 AddArray( *root_obj, "targets", targets);
1490 return root_name;
1491 }
1492
GetUUID(void)1493 string CMacProjectGenerator::GetUUID(void)
1494 {
1495 static Uint4 uuid = 1;
1496 char buffer[64];
1497 ::sprintf(buffer, "ABCDABCDABCDABCD%08X", uuid++);
1498 return buffer;
1499 }
1500
AddFile(CDict & dict,const string & name,bool style_objcpp)1501 string CMacProjectGenerator::AddFile(CDict& dict, const string& name, bool style_objcpp)
1502 {
1503 string filetype;
1504 CDirEntry entry(name);
1505 string ext = entry.GetExt();
1506 if ( ext == ".cpp" || ext == ".c") {
1507 if (style_objcpp) {
1508 filetype = "sourcecode.cpp.objcpp";
1509 } else {
1510 filetype = string("sourcecode") + ext + ext;
1511 }
1512 } else if (ext == ".cc" || ext == ".cxx") {
1513 filetype = "sourcecode.cpp.cpp";
1514 } else if (ext == ".hpp" || ext == ".inl") {
1515 filetype = "sourcecode.cpp.h";
1516 } else if (ext == ".h") {
1517 filetype = "sourcecode.c.h";
1518 } else if (ext == ".xsd") {
1519 filetype = "text.xml";
1520 } else if (ext == ".wsdl") {
1521 filetype = "text.xml";
1522 } else if (ext == ".jsd") {
1523 filetype = "text.json";
1524 } else if (ext == ".metal") {
1525 filetype = "sourcecode.metal";
1526 } else {
1527 filetype = "text";
1528 }
1529
1530 string base_name = entry.GetName();
1531 #if USE_VERBOSE_NAMES
1532 static size_t counter = 0;
1533 string name_id = "FILE" + NStr::UIntToString(counter++);
1534 #else
1535 string name_id( GetUUID());
1536 #endif
1537 CRef<CDict> file( AddDict( dict, name_id));
1538 AddString( *file, "isa", "PBXFileReference");
1539 if (!filetype.empty()) {
1540 AddString( *file, "lastKnownFileType", filetype);
1541 }
1542 AddString( *file, "name", base_name);
1543 AddString( *file, "path", GetRelativePath(name));
1544 AddString( *file, "sourceTree", "SOURCE_ROOT");
1545 return name_id;
1546 }
1547
AddFileSource(CDict & dict,const string & name)1548 string CMacProjectGenerator::AddFileSource(CDict& dict, const string& name)
1549 {
1550 #if USE_VERBOSE_NAMES
1551 string name_ref = "SRC_" + name;
1552 #else
1553 string name_ref( GetUUID());
1554 #endif
1555 CRef<CDict> file( AddDict( dict, name_ref));
1556 AddString( *file, "fileRef", name);
1557 AddString( *file, "isa", "PBXBuildFile");
1558 return name_ref;
1559 }
1560
AddGroupDict(CDict & dict,const string & key,CRef<CArray> & children,const string & name)1561 void CMacProjectGenerator::AddGroupDict(
1562 CDict& dict, const string& key, CRef<CArray>& children, const string& name)
1563 {
1564 CRef<CDict> group( AddDict( dict, key));
1565 AddArray( *group, "children", children);
1566 AddString( *group, "isa", "PBXGroup");
1567 AddString( *group, "name", name);
1568 AddString( *group, "sourceTree", "<group>");
1569 }
1570
1571
AddString(CArray & ar,const string & value)1572 void CMacProjectGenerator::AddString(CArray& ar, const string& value)
1573 {
1574 CRef<CArray::C_E> e(new CArray::C_E);
1575 e->SetString( value);
1576 ar.Set().push_back(e);
1577 }
1578
InsertString(CArray & ar,const string & value)1579 void CMacProjectGenerator::InsertString(CArray& ar, const string& value)
1580 {
1581 CRef<CArray::C_E> e(new CArray::C_E);
1582 e->SetString( value);
1583 ar.Set().push_front(e);
1584 }
1585
AddString(CDict & dict,const string & key,const string & value)1586 void CMacProjectGenerator::AddString(
1587 CDict& dict, const string& key, const string& value)
1588 {
1589 CRef<CDict::C_E> e(new CDict::C_E);
1590 e->SetKey(key);
1591 e->SetPlistObject().SetString(value);
1592 dict.Set().push_back(e);
1593 }
1594
AddArray(CDict & dict,const string & key)1595 CRef<CArray> CMacProjectGenerator::AddArray(
1596 CDict& dict, const string& key)
1597 {
1598 CRef<CDict::C_E> e(new CDict::C_E);
1599 e->SetKey(key);
1600 CArray& a = e->SetPlistObject().SetArray();
1601 dict.Set().push_back(e);
1602 return CRef<CArray>(&a);
1603 }
1604
AddArray(CDict & dict,const string & key,CRef<CArray> & array)1605 void CMacProjectGenerator::AddArray(
1606 CDict& dict, const string& key, CRef<CArray>& array)
1607 {
1608 CRef<CDict::C_E> e(new CDict::C_E);
1609 e->SetKey(key);
1610 e->SetPlistObject().SetArray(*array);
1611 dict.Set().push_back(e);
1612 }
1613
AddDict(CDict & dict,const string & key)1614 CRef<CDict> CMacProjectGenerator::AddDict(
1615 CDict& dict, const string& key)
1616 {
1617 CRef<CDict::C_E> e(new CDict::C_E);
1618 e->SetKey(key);
1619 CDict& d = e->SetPlistObject().SetDict();
1620 dict.Set().push_back(e);
1621 return CRef<CDict>(&d);
1622 }
1623
AddCompilerSetting(CDict & settings,const SConfigInfo & cfg,const string & key)1624 void CMacProjectGenerator::AddCompilerSetting(CDict& settings,
1625 const SConfigInfo& cfg, const string& key)
1626 {
1627 string value = GetApp().GetMetaMakefile().GetCompilerOpt(key,cfg);
1628 if (!value.empty()) {
1629 AddString( settings, key, value);
1630 }
1631 }
AddLinkerSetting(CDict & settings,const SConfigInfo & cfg,const string & key)1632 void CMacProjectGenerator::AddLinkerSetting(CDict& settings,
1633 const SConfigInfo& cfg, const string& key)
1634 {
1635 string value = GetApp().GetMetaMakefile().GetLinkerOpt(key,cfg);
1636 if (!value.empty()) {
1637 AddString( settings, key, value);
1638 }
1639 }
AddLibrarianSetting(CDict & settings,const SConfigInfo & cfg,const string & key)1640 void CMacProjectGenerator::AddLibrarianSetting(CDict& settings,
1641 const SConfigInfo& cfg, const string& key)
1642 {
1643 string value = GetApp().GetMetaMakefile().GetLibrarianOpt(key,cfg);
1644 if (!value.empty()) {
1645 AddString( settings, key, value);
1646 }
1647 }
1648
GetRelativePath(const string & name,const string * from) const1649 string CMacProjectGenerator::GetRelativePath(const string& name, const string* from) const
1650 {
1651 if (!from) {
1652 from = &m_SolutionDir;
1653 }
1654 if (GetApp().UseAbsolutePath(*from) || !SameRootDirs(name, *from)) {
1655 return name;
1656 }
1657 string file_path;
1658 try {
1659 file_path = CDirEntry::CreateRelativePath(*from, name);
1660 // On REAL MacOS, it is not needed
1661 #ifdef PSEUDO_XCODE
1662 NStr::ReplaceInPlace(file_path, "\\", "/");
1663 #endif
1664 } catch (CFileException&) {
1665 file_path = name;
1666 }
1667 return file_path;
1668 }
1669
GetProjId(const CProjItem & prj)1670 string CMacProjectGenerator::GetProjId( const CProjItem& prj)
1671 {
1672 string id(prj.m_ID);
1673 if (prj.m_ProjType == CProjKey::eLib) {
1674 id += "_ar";
1675 } else if (prj.m_ProjType == CProjKey::eDll) {
1676 id += "_dylib";
1677 } else if (prj.m_ProjType == CProjKey::eApp) {
1678 id += "_exe";
1679 }
1680 return id;
1681 }
GetProjTarget(const CProjItem & prj)1682 string CMacProjectGenerator::GetProjTarget(const CProjItem& prj)
1683 {
1684 return GetProjId(prj) + "_target";
1685 }
GetProjBuild(const CProjItem & prj)1686 string CMacProjectGenerator::GetProjBuild(const CProjItem& prj)
1687 {
1688 return GetProjId(prj) + "_build";
1689 }
GetProjProduct(const CProjItem & prj)1690 string CMacProjectGenerator::GetProjProduct(const CProjItem& prj)
1691 {
1692 return GetProjId(prj) + "_product";
1693 }
GetProjHeaders(const CProjItem & prj)1694 string CMacProjectGenerator::GetProjHeaders(const CProjItem& prj)
1695 {
1696 return GetProjId(prj) + "_headers";
1697 }
GetProjDependency(const CProjItem & prj)1698 string CMacProjectGenerator::GetProjDependency( const CProjItem& prj)
1699 {
1700 return GetProjId(prj) + "_dependency";
1701 }
GetProjContainer(const CProjItem & prj)1702 string CMacProjectGenerator::GetProjContainer( const CProjItem& prj)
1703 {
1704 return GetProjId(prj) + "_container";
1705 }
GetTargetName(const CProjItem & prj)1706 string CMacProjectGenerator::GetTargetName( const CProjItem& prj)
1707 {
1708 if (prj.m_ProjType == CProjKey::eLib) {
1709 return /*string("lib") +*/ prj.m_ID;
1710 }
1711 if (prj.m_ProjType == CProjKey::eApp) {
1712 CProjKey klib(CProjKey::eLib, prj.m_ID), kdll(CProjKey::eDll, prj.m_ID);
1713 if (m_Projects_tree.m_Projects.find(klib) != m_Projects_tree.m_Projects.end() ||
1714 m_Projects_tree.m_Projects.find(kdll) != m_Projects_tree.m_Projects.end()) {
1715 return string(prj.m_ID) + ".exe";
1716 }
1717 }
1718 return prj.m_ID;
1719 }
1720
GetMachOType(const CProjItem & prj)1721 string CMacProjectGenerator::GetMachOType( const CProjItem& prj)
1722 {
1723 if (prj.m_ProjType == CProjKey::eLib) {
1724 return "staticlib";
1725 } else if (prj.m_ProjType == CProjKey::eDll) {
1726 /*
1727 if (prj.m_IsBundle) {
1728 return "mh_bundle";
1729 }
1730 */
1731 return "mh_dylib";
1732 } else if (prj.m_ProjType == CProjKey::eApp) {
1733 /*
1734 if (prj.m_IsBundle) {
1735 return "mh_bundle";
1736 }
1737 */
1738 // return "mh_executable";
1739 return "mh_execute";
1740 }
1741 return "";
1742 }
1743
GetProductType(const CProjItem & prj)1744 string CMacProjectGenerator::GetProductType( const CProjItem& prj)
1745 {
1746 if (prj.m_ProjType == CProjKey::eLib) {
1747 if (prj.m_IsMetallib) {
1748 return "com.apple.product-type.metal-library";
1749 } else {
1750 return "com.apple.product-type.library.static";
1751 }
1752 } else if (prj.m_ProjType == CProjKey::eDll) {
1753 return "com.apple.product-type.library.dynamic";
1754 } else if (prj.m_ProjType == CProjKey::eApp) {
1755 if (prj.m_IsBundle) {
1756 return "com.apple.product-type.application";
1757 }
1758 return "com.apple.product-type.tool";
1759 }
1760 return "";
1761 }
GetExplicitType(const CProjItem & prj)1762 string CMacProjectGenerator::GetExplicitType( const CProjItem& prj)
1763 {
1764 if (prj.m_ProjType == CProjKey::eLib) {
1765 if (prj.m_IsMetallib) {
1766 return "archive.metal-library";
1767 } else {
1768 return "archive.ar";
1769 }
1770 } else if (prj.m_ProjType == CProjKey::eDll) {
1771 return "compiled.mach-o.dylib";
1772 } else if (prj.m_ProjType == CProjKey::eApp) {
1773 if (prj.m_IsBundle) {
1774 return "wrapper.application";
1775 }
1776 return "compiled.mach-o.executable";
1777 }
1778 return "";
1779 }
1780
1781 #endif
1782
1783
1784 END_NCBI_SCOPE
1785