1 #ifndef MAKEFILE_GENERATOR
12 static define app = ((GuiApplication)__thisModule);
15 bool eString_PathInsideOfMore(char * path, char * of, char * pathRest)
17 if(!path[0] || !of[0])
18 return false; // What to do here? Ever used?
21 char ofPart[MAX_FILENAME], ofRest[MAX_LOCATION];
22 char pathPart[MAX_FILENAME]; //, pathRest[MAX_LOCATION];
24 strcpy(pathRest, path);
25 for(; ofRest[0] && pathRest[0];)
27 SplitDirectory(ofRest, ofPart, ofRest);
28 SplitDirectory(pathRest, pathPart, pathRest);
29 if(fstrcmp(pathPart, ofPart))
32 if(!ofRest[0] && !pathRest[0])
34 else if(!pathRest[0]) // not inside of, it's the other way around
40 enum NodeTypes { project, file, folder, resources, folderOpen };
43 genFile, ewsFile, epjFile, folder, openFolder, ecFile, ehFile,
44 cFile, hFile, cppFile, hppFile, textFile, webFile, pictureFile, soundFile,
45 archiveFile, packageFile, opticalMediaImageFile, mFile;
47 NodeIcons ::SelectFileIcon(char * filePath)
50 if(filePath && filePath[0])
52 char extension[MAX_EXTENSION];
53 GetExtension(filePath, extension);
56 if(!strcmpi(extension, WorkspaceExtension))
58 else if(!strcmpi(extension, ProjectExtension))
60 else if(!strcmpi(extension, "ec"))
62 else if(!strcmpi(extension, "eh"))
64 else if(!strcmpi(extension, "cpp") || !strcmpi(extension, "cc") ||
65 !strcmpi(extension, "cxx"))
67 else if(!strcmpi(extension, "hpp") || !strcmpi(extension, "hh") ||
68 !strcmpi(extension, "hxx"))
70 else if(!strcmpi(extension, "c"))
72 else if(!strcmpi(extension, "h"))
74 else if(!strcmpi(extension, "m"))
76 else if(!strcmpi(extension, "txt") || !strcmpi(extension, "text") ||
77 !strcmpi(extension, "nfo") || !strcmpi(extension, "info"))
79 else if(!strcmpi(extension, "htm") || !strcmpi(extension, "html") ||
80 !strcmpi(extension, "css") || !strcmpi(extension, "php") ||
81 !strcmpi(extension, "js"))
83 else if(!strcmpi(extension, "bmp") || !strcmpi(extension, "pcx") ||
84 !strcmpi(extension, "jpg") || !strcmpi(extension, "jpeg") ||
85 !strcmpi(extension, "gif") || !strcmpi(extension, "png") ||
86 !strcmpi(extension, "ico"))
88 else if(!strcmpi(extension, "wav") || !strcmpi(extension, "mp3") ||
89 !strcmpi(extension, "ogg") || !strcmpi(extension, "snd"))
91 else if(!strcmpi(extension, "ear") || !strcmpi(extension, "7z") ||
92 !strcmpi(extension, "rar") || !strcmpi(extension, "zip") ||
93 !strcmpi(extension, "gz") || !strcmpi(extension, "bz2") ||
94 !strcmpi(extension, "tar") || !strcmpi(extension, "arj") ||
95 !strcmpi(extension, "lza") || !strcmpi(extension, "lzh") ||
96 !strcmpi(extension, "cpio") || !strcmpi(extension, "z"))
98 else if(!strcmpi(extension, "cab") || !strcmpi(extension, "deb") ||
99 !strcmpi(extension, "rpm"))
101 else if(!strcmpi(extension, "iso") || !strcmpi(extension, "mds") ||
102 !strcmpi(extension, "cue") || !strcmpi(extension, "bin") ||
103 !strcmpi(extension, "ccd") || !strcmpi(extension, "bwt") ||
104 !strcmpi(extension, "cdi") || !strcmpi(extension, "nrg"))
105 icon = opticalMediaImageFile;
113 icon = genFile; // tocheck: error icon?
117 NodeIcons ::SelectNodeIcon(NodeTypes type)
136 #define SELECTION_COLOR Color { 10, 36, 106 }
142 // this is so not working, why!
144 // return result was not even executed (did not step on while debugging)
145 class TwoStrings : struct
165 class ProjectNode : ListItem
170 set { return { fileName = value }; }
171 // TOCHECK: Is this isset necessary at all?
172 isset { return nodeType == file && !options && !configurations && !platforms && !files; }
174 property String folder
179 if(strchr(value, '/'))
181 char p[MAX_LOCATION];
182 char n[MAX_FILENAME];
183 GetLastDirectory(value, n);
184 StripLastDirectory(value, p);
185 name = CopyString(n);
186 path = CopyString(p);
189 name = CopyString(value);
193 // TOCHECK: Non Reentrant
194 static char insidePath[MAX_LOCATION];
196 strcpy(insidePath, (parent.type == project) ? "" : parent.path);
197 PathCatSlash(insidePath, name);
199 if(!fstrcmp(path, insidePath))
203 strcpy(insidePath, path);
204 if(!insidePath[0]) strcpy(insidePath, ".");
205 PathCatSlash(insidePath, name);
209 isset { return nodeType == folder; }
211 property String fileName
216 if(strchr(value, '/'))
218 char p[MAX_LOCATION];
219 char n[MAX_FILENAME];
220 GetLastDirectory(value, n);
221 StripLastDirectory(value, p);
222 name = CopyValidateMakefilePath(n);
223 path = CopyValidateMakefilePath(p);
226 name = CopyValidateMakefilePath(value);
230 // TOCHECK: Non Reentrant
231 static char insidePath[MAX_LOCATION];
233 strcpy(insidePath, (parent.type == project) ? "" : parent.path);
234 if(!fstrcmp(path, insidePath))
238 strcpy(insidePath, path);
239 if(!insidePath[0]) strcpy(insidePath, ".");
240 PathCatSlash(insidePath, name);
244 isset { return nodeType == file && (options || configurations || platforms); }
247 LinkList<ProjectNode> files;
248 ProjectOptions options;
249 Array<PlatformOptions> platforms;
250 List<ProjectConfig> configurations;
252 property ProjectConfig config
257 ProjectConfig result = null;
262 if(configurations && (prj = property::project) && prj.config)
264 const char * projectConfigName = prj.config.name;
265 for(config : configurations)
267 if(!strcmpi(config.name, projectConfigName))
278 ProjectConfig GetMatchingNodeConfig(ProjectConfig config)
280 ProjectConfig nodeConfig = null;
283 const char * configName = config.name;
284 for(cfg : configurations)
286 if(!strcmpi(cfg.name, configName))
296 property bool ecflags
300 ProjectConfig config = this.config;
301 ProjectOptions options = this.options;
302 SetBool memoryGuard = localMemoryGuard;
303 String defaultNameSpace = localDefaultNameSpace;
304 SetBool strictNameSpaces = localStrictNameSpaces;
305 SetBool noLineNumbers = localNoLineNumbers;
307 if(memoryGuard || defaultNameSpace || strictNameSpaces || noLineNumbers)
309 else if(parent.parent)
310 return parent.ecflags;
315 property bool memoryGuard
319 ProjectConfig config = this.config;
320 ProjectOptions options = this.options;
321 SetBool memoryGuard = localMemoryGuard;
325 return parent.memoryGuard;
327 return memoryGuard == true;
330 property String defaultNameSpace
334 ProjectConfig config = this.config;
335 ProjectOptions options = this.options;
336 String defaultNameSpace = localDefaultNameSpace;
337 if(!defaultNameSpace)
340 return parent.defaultNameSpace;
342 return defaultNameSpace;
345 property bool strictNameSpaces
349 ProjectConfig config = this.config;
350 ProjectOptions options = this.options;
351 SetBool strictNameSpaces = localStrictNameSpaces;
352 if(!strictNameSpaces)
355 return parent.strictNameSpaces;
357 return strictNameSpaces == true;
360 property bool noLineNumbers
364 ProjectConfig config = this.config;
365 ProjectOptions options = this.options;
366 SetBool noLineNumbers = localNoLineNumbers;
370 return parent.noLineNumbers;
372 return noLineNumbers == true;
376 property ProjectNode root { get { ProjectNode n; for(n = this; n.parent; n = n.parent); return n; } }
378 property bool containsFile
387 if(child.type == file ||
388 ((child.type == folder || child.type == folderOpen) && child.containsFile))
401 char * GetFullFilePath(char * buffer)
405 strcpy(buffer, root.path);
406 PathCatSlash(buffer, path);
407 PathCatSlash(buffer, name);
412 char * GetFileSysMatchingPath(char * buffer)
416 ProjectNode n, root = this.root;
417 for(n = this; n && (n.type == folder || n.type == project); n = n.parent)
419 strcpy(buffer, root.path);
421 PathCatSlash(buffer, n.path);
422 if(FileExists(buffer).isDirectory)
425 if(!(n && (n.type == folder || n.type == project)))
431 void CollectPerFileAndDirOptions(ProjectConfig projectConfig, Array<String> perFilePreprocessorDefs, Array<DirPath> perFileIncludeDirs)
433 ProjectNode node = null;
434 ProjectConfig config = GetMatchingNodeConfig(projectConfig);
435 List<ProjectNode> nodeStack { };
437 for(node = this; node && node.parent; node = node.parent)
440 // Should we reverse this stack to give priority to the per-file includes? Does the following technique already reverse?
442 // TODO: Check how to fix duplication of following options when configuration is made per-config-per-file
443 while((node = nodeStack.lastIterator.data))
445 if(node.options && node.options.preprocessorDefinitions)
447 for(def : node.options.preprocessorDefinitions)
448 perFilePreprocessorDefs.Add(CopyString(def));
450 if(config && config.options && config.options.preprocessorDefinitions)
452 for(def : config.options.preprocessorDefinitions)
453 perFilePreprocessorDefs.Add(CopyString(def));
455 if(node.options && node.options.includeDirs)
457 for(dir : node.options.includeDirs)
458 perFileIncludeDirs.Add(CopySystemPath(dir));
460 if(config && config.options && config.options.includeDirs)
462 for(dir : config.options.includeDirs)
463 perFileIncludeDirs.Add(CopySystemPath(dir));
465 nodeStack.lastIterator.Remove();
471 ProjectNodeType nodeType;
476 // This holds the absolute path of the .epj for the project topnode (without the filename)
477 // It holds a relative path to the topNode (project) for other nodes (folders and files)
478 // For folders, it includes the folder it refers to. If there is a name difference between the
479 // file system folder and the grouping folder of the project view, it maps to that folder.
489 // This is only set for Top Nodes
492 property Project project
496 ProjectNode n = this;
497 while(n && n.type != project) n = n.parent;
498 return n ? (*&n.project) : null;
502 void RenameConfig(char * oldName, char * newName)
506 for(f : files; (f.configurations || f.files)) { f.RenameConfig(oldName, newName); }
510 for(c : configurations; !strcmp(c.name, oldName))
513 c.name = CopyString(newName);
518 void DeleteConfig(ProjectConfig configToDelete)
522 for(f : files; (f.configurations || f.files)) { f.DeleteConfig(configToDelete); }
526 Iterator<ProjectConfig> c { configurations };
529 ProjectConfig config = c.data;
530 if(!strcmp(configToDelete.name, config.name))
537 if(!configurations.count)
539 delete configurations;
546 ProjectNode backupNode { };
550 backupNode.files = { };
551 for(f : files) backupNode.files.Add(f.Backup());
554 backupNode.options = options.Copy();
558 backupNode.platforms = { };
560 backupNode.platforms.Add(p.Copy());
565 backupNode.configurations = { };
566 for(c : configurations)
567 backupNode.configurations.Add(c.Copy());
572 void Revert(ProjectNode backupNode)
576 Iterator<ProjectNode> it { backupNode.files };
592 configurations.Free();
593 delete configurations;
596 options = backupNode.options ? backupNode.options.Copy() : null;
597 if(backupNode.platforms)
600 for(p : backupNode.platforms)
601 platforms.Add(p.Copy());
603 if(backupNode.configurations)
605 configurations = { };
606 for(c : backupNode.configurations)
607 configurations.Add(c.Copy());
611 void FixupNode(char * parentPath)
617 else if(nodeType == file)
622 path = CopyString((parent.type == folder || parent.type == resources) ? parentPath : "");
625 else if(nodeType == folder)
631 char temp[MAX_LOCATION];
632 strcpy(temp, (parent.type == folder || parent.type == resources) ? parentPath : "");
633 PathCatSlash(temp, name);
634 path = CopyString(temp);
638 indent = parent ? parent.indent + 1 : 0;
641 icon = NodeIcons::SelectFileIcon(name);
643 icon = NodeIcons::SelectNodeIcon(type);
652 parentPath[0] = '\0';
653 else if(type == resources || type == folder)
654 strcpy(parentPath, path);
656 f.FixupNode(parentPath);
661 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
665 // TOCHECK: Called from JSON writer
666 if(nodeType == file && !options && !configurations && !platforms && name)
668 strcpy(tempString, "\"");
669 strcat(tempString, property::fileName);
670 strcat(tempString, "\"");
677 // TOCHECK: Called from ProjectView rendering
678 return name ? name : "";
697 configurations.Free();
698 delete configurations;
701 /////////////////////////////
707 property bool isInResources
712 for(node = this; node; node = node.parent)
714 if(node.type == resources)
721 property TwoStrings platformSpecificFu
725 TwoStrings result { a = CopyString(""), b = CopyString("") };
726 // note: unknown platform is for common
727 Map<Platform, SetBool> exclusionInfo { };
728 MapNode<Platform, SetBool> mn;
733 CollectExclusionInfo(exclusionInfo);
734 common = exclusionInfo[unknown];
736 Map<Platform, SetBool> cleaned { };
737 SetBool opposite = common == true ? false : true;
738 for(mn = exclusionInfo.root.minimum; mn; mn = mn.next)
740 if(mn.key == unknown || mn.value == opposite)
741 cleaned[mn.key] = mn.value;
743 delete exclusionInfo;
744 exclusionInfo = cleaned;
747 if(exclusionInfo.count > 1)
749 if(exclusionInfo.count > 2)
752 len = strlen(exp) + strlen("$(if $(or ");
753 exp = renew exp char[len+1];
754 strcat(exp, "$(if $(or ");
757 for(mn = exclusionInfo.root.minimum; mn; mn = mn.next)
759 if(mn.key != unknown)
761 char * comma = mn.next ? "," : "";
763 var = PlatformToMakefileVariable(mn.key);
766 len = strlen(exp) + strlen("$(") + strlen(var) + strlen(")") + strlen(comma);
767 exp = renew exp char[len+1];
777 len = strlen(exp) + strlen("),");
778 exp = renew exp char[len+1];
782 if(exclusionInfo.root.minimum.key != unknown)
783 var = PlatformToMakefileVariable(exclusionInfo.root.minimum.key);
785 var = PlatformToMakefileVariable(exclusionInfo.root.minimum.next.key);
788 len = strlen(exp) + strlen("$(if $(") + strlen(var) + strlen("),");
789 exp = renew exp char[len+1];
790 strcat(exp, "$(if $(");
797 exp = common == true ? result.b : result.a;
798 len = strlen(exp) + strlen(",");
799 exp = renew exp char[len+1];
801 if(common == true) result.b = exp; else result.a = exp;
804 len = strlen(exp) + strlen(")");
805 exp = renew exp char[len+1];
814 property bool isExcluded
819 // note: unknown platform is for common
820 Map<Platform, SetBool> exclusionInfo { };
821 CollectExclusionInfo(exclusionInfo);
822 if(exclusionInfo.count == 0)
824 else if(exclusionInfo.count == 1)
825 result = exclusionInfo.root.minimum.value == true;
828 SetBool check = exclusionInfo.root.minimum.value;
829 MapNode<Platform, SetBool> mn;
830 for(mn = exclusionInfo.root.minimum; mn; mn = mn.next)
832 if(check != mn.value)
835 if(!mn) // all are same
836 result = check == true;
840 delete exclusionInfo;
846 void CollectExclusionInfo(Map<Platform, SetBool> output)
848 // note: unknown platform is for common
850 ProjectConfig config = property::config;
853 parent.CollectExclusionInfo(output);
855 output[unknown] = unset;
857 if(options && options.excludeFromBuild)
858 output[unknown] = options.excludeFromBuild;
860 if(config && config.options && config.options.excludeFromBuild)
861 output[unknown] = config.options.excludeFromBuild;
867 if(p.options.excludeFromBuild && (platform = p.name))
868 output[platform] = p.options.excludeFromBuild;
871 if(config && config.platforms)
873 for(p : config.platforms)
875 if(p.options.excludeFromBuild && (platform = p.name))
876 output[platform] = p.options.excludeFromBuild;
884 parent.EnsureVisible();
885 row.collapsed = false;
891 parent.files.Delete(this);
894 ProjectNode Find(char * name, bool includeResources)
896 ProjectNode result = null;
901 if(includeResources || child.type != resources)
903 if(child.type != folder && child.name && !strcmpi(child.name, name))
908 result = child.Find(name, includeResources);
917 ProjectNode FindWithPath(char * name, bool includeResources)
919 ProjectNode result = null;
924 if(includeResources || child.type != resources)
926 char path[MAX_LOCATION];
927 strcpy(path, child.path);
928 if(child.type != folder && child.name)
930 PathCatSlash(path, child.name);
931 if(!strcmpi(path, name))
937 result = child.FindWithPath(name, includeResources);
946 ProjectNode FindSpecial(char * name, bool recursive, bool includeResources, bool includeFolders)
948 ProjectNode result = null;
953 if(includeResources || child.type != resources)
955 if((includeFolders || child.type != folder) && child.name && !strcmpi(child.name, name))
961 result = child.FindSpecial(name, recursive, includeResources, includeFolders);
970 ProjectNode Add(Project project, char * filePath, ProjectNode after, NodeTypes type, NodeIcons icon, bool checkIfExists)
972 ProjectNode node = null;
973 char temp[MAX_LOCATION];
975 GetLastDirectory(filePath, temp);
976 if(!checkIfExists || !project.topNode.Find(temp, false))
978 // Do the check for folder in the same parent or resource files only here
979 if(type == folder || !checkIfExists)
983 if(node.name && !strcmpi(node.name, temp))
988 node = ProjectNode { parent = this, indent = indent + 1, type = type, icon = icon, name = CopyString(temp) };
992 node.nodeType = folder;
998 StripLastDirectory(filePath, temp);
999 MakePathRelative(temp, project.topNode.path, temp);
1000 node.path = CopyUnixPath(temp);
1002 node.nodeType = file;
1006 strcpy(temp, (type == NodeTypes::project) ? "" : path);
1007 PathCatSlash(temp, node.name);
1008 node.path = CopyString(temp);
1010 files.Insert(after, node);
1015 #ifndef MAKEFILE_GENERATOR
1016 void OnDisplay(Surface surface, int x, int y, int width, ProjectView projectView, Alignment alignment, DataDisplayFlags displayFlags)
1018 char label[MAX_FILENAME];
1024 bool showConfig = true;
1029 projectView = ide.projectView;
1032 bmp = projectView.icons[icon].bitmap;
1033 xStart = /*indent * indent + */x + (bmp ? (bmp.width + 5) : 0);
1035 GetLastDirectory(name, label);
1036 if(!showConfig || projectView.drawingInProjectSettingsDialogHeader)
1038 if(projectView.drawingInProjectSettingsDialogHeader || (type == project && info))
1040 if(projectView.projectSettingsDialog && projectView.projectSettingsDialog.buildTab)
1043 addendum = projectView.projectSettingsDialog.buildTab.selectedConfigName;
1044 if(strlen(addendum))
1046 strcat(label, " (");
1047 strcat(label, addendum);
1050 addendum = projectView.projectSettingsDialog.buildTab.selectedPlatformName;
1051 if(strlen(addendum))
1053 strcat(label, " (");
1054 strcat(label, addendum);
1060 else if(!projectView.drawingInProjectSettingsDialog)
1063 strcat(label, " *");
1064 if(type == project && info)
1066 int len = strlen(info) + 4;
1067 char * more = new char[len];
1068 sprintf(more, " (%s)", info);
1069 strcat(label, more);
1073 len = strlen(label);
1077 if(type == folder || type == folderOpen)
1078 surface.SetForeground(yellow);
1082 surface.TextOpacity(false);
1083 surface.TextExtent(label, len, &w, &h);
1086 // Draw the current row stipple
1087 if(displayFlags.selected)
1088 //surface.Area(xStart - 1, y, xStart - 1, y + h - 1);
1089 //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1);
1090 surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1);
1092 surface.WriteTextDots(alignment, xStart, y + 2, width, label, len);
1096 if(displayFlags.current)
1098 if(displayFlags.active)
1100 surface.LineStipple(0x5555);
1101 if(displayFlags.selected)
1102 surface.SetForeground(projectView.fileList.stippleColor);
1104 surface.SetForeground(projectView.fileList.foreground);
1108 surface.SetForeground(SELECTION_COLOR);
1110 surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1);
1111 surface.LineStipple(0);
1116 surface.SetForeground(white);
1117 surface.Blit(bmp, x /*+ indent * indent*/,y,0,0, bmp.width, bmp.height);
1123 int OnCompare(ProjectNode b)
1126 if(type == b.type /*|| type >= TYPE_DRIVE*/)
1127 result = strcmpi(name, b.name);
1130 if(type == folder && b.type == file) result = -1;
1131 else if(type == file && b.type == folder) result = 1;
1136 void GenFileFlags(File f, Project project)
1138 ProjectNode node = null;
1139 List<ProjectNode> nodeStack { };
1141 for(node = this; node && node.parent; node = node.parent)
1142 nodeStack.Add(node);
1144 // Should we reverse this stack to give priority to the per-file includes?
1146 while((node = nodeStack.lastIterator.data))
1148 ProjectConfig config = node.config;
1149 if(node.options && node.options.preprocessorDefinitions)
1150 OutputListOption(f, "D", node.options.preprocessorDefinitions, inPlace, false);
1151 if(config && config.options && config.options.preprocessorDefinitions)
1152 OutputListOption(f, "D", config.options.preprocessorDefinitions, inPlace, false);
1153 if(node.options && node.options.includeDirs)
1154 OutputListOption(f, "I", node.options.includeDirs, inPlace, true);
1155 if(config && config.options && config.options.includeDirs)
1156 OutputListOption(f, "I", config.options.includeDirs, inPlace, true);
1158 nodeStack.lastIterator.Remove();
1163 void GenMakefileGetNameCollisionInfo(Map<String, NameCollisionInfo> namesInfo)
1167 char extension[MAX_EXTENSION];
1168 GetExtension(name, extension);
1169 if(!strcmpi(extension, "ec") || !strcmpi(extension, "c") ||
1170 !strcmpi(extension, "cpp") || !strcmpi(extension, "cc") ||
1171 !strcmpi(extension, "cxx") || !strcmpi(extension, "m"))
1173 char moduleName[MAX_FILENAME];
1174 NameCollisionInfo info;
1175 ReplaceSpaces(moduleName, name);
1176 StripExtension(moduleName);
1177 info = namesInfo[moduleName];
1179 info = NameCollisionInfo { };
1180 info.count++; // += 1; unless this is for a bug?
1181 if(!strcmpi(extension, "ec"))
1183 else if(!strcmpi(extension, "c"))
1185 else if(!strcmpi(extension, "cpp"))
1187 else if(!strcmpi(extension, "cc"))
1189 else if(!strcmpi(extension, "cxx"))
1191 else if(!strcmpi(extension, "m"))
1193 namesInfo[moduleName] = info;
1200 if(child.type != resources && (child.type == folder || !child.isExcluded))
1201 child.GenMakefileGetNameCollisionInfo(namesInfo);
1206 int GenMakefilePrintNode(File f, Project project, GenMakefilePrintTypes printType, Map<String, NameCollisionInfo> namesInfo, Array<String> items)
1212 TwoStrings ts = platformSpecificFu;
1213 char moduleName[MAX_FILENAME];
1214 char extension[MAX_EXTENSION];
1215 GetExtension(name, extension);
1216 if(printType == resources)
1219 char tempPath[MAX_LOCATION];
1220 char modulePath[MAX_LOCATION];
1223 if(eString_PathInsideOfMore(path, project.resNode.path, tempPath))
1226 PathCatSlash(tempPath, name);
1231 strcpy(tempPath, path);
1232 PathCatSlash(tempPath, name);
1234 ReplaceSpaces(modulePath, tempPath);
1235 sprintf(s, "%s%s%s%s", ts.a, useRes ? "$(RES)" : "", modulePath, ts.b);
1236 items.Add(CopyString(s));
1238 else if(printType == sources)
1240 if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1241 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
1242 !strcmpi(extension, "ec") || !strcmpi(extension, "m"))
1244 char modulePath[MAX_LOCATION];
1246 ReplaceSpaces(modulePath, path);
1247 ReplaceSpaces(moduleName, name);
1248 sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b);
1249 items.Add(CopyString(s));
1252 else if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1253 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
1254 !strcmpi(extension, "m"))
1256 if(printType == objects)
1259 NameCollisionInfo info;
1260 ReplaceSpaces(moduleName, name);
1261 StripExtension(moduleName);
1262 info = namesInfo[moduleName];
1263 collision = info ? info.IsExtensionColliding(extension) : false;
1264 sprintf(s, "%s$(OBJ)%s%s%s.o%s", ts.a, moduleName, collision ? "." : "", collision ? extension : "", ts.b);
1265 items.Add(CopyString(s));
1268 else if(!strcmpi(extension, "ec"))
1270 ReplaceSpaces(moduleName, name);
1271 StripExtension(moduleName);
1272 if(printType == objects)
1275 if(printType == objects)
1276 sprintf(s, "%s$(OBJ)%s.o%s", ts.a, moduleName, ts.b);
1277 else if(printType == cObjects)
1278 sprintf(s, "%s$(OBJ)%s.c%s", ts.a, moduleName, ts.b);
1279 else if(printType == symbols)
1280 sprintf(s, "%s$(OBJ)%s.sym%s", ts.a, moduleName, ts.b);
1281 else if(printType == imports)
1282 sprintf(s, "%s$(OBJ)%s.imp%s", ts.a, moduleName, ts.b);
1284 items.Add(CopyString(s));
1292 if(child.type != resources && (child.type == folder || !child.isExcluded))
1293 count += child.GenMakefilePrintNode(f, project, printType, namesInfo, items);
1299 void GenMakefilePrintSymbolRules(File f, Project project)
1301 //ProjectNode child;
1302 //char objDir[MAX_LOCATION];
1303 CompilerConfig compiler = GetCompilerConfig();
1304 //ReplaceSpaces(objDir, project.config.objDir.dir);
1306 //eSystem_Log("Printing Symbol Rules\n");
1309 char extension[MAX_EXTENSION];
1310 char modulePath[MAX_LOCATION];
1311 char moduleName[MAX_FILENAME];
1313 GetExtension(name, extension);
1314 if(!strcmpi(extension, "ec"))
1319 ReplaceSpaces(moduleName, name);
1320 StripExtension(moduleName);
1322 ReplaceSpaces(modulePath, path);
1323 if(modulePath[0]) strcat(modulePath, SEPS);
1326 // *** Dependency command ***
1327 sprintf(command, "gcc -MT $(OBJ)%s.o -MM %s%s.%s", moduleName,
1328 modulePath, moduleName, extension);
1330 // System Includes (from global settings)
1331 for(item : compiler.dirs[Includes])
1333 strcat(command, " -isystem ");
1334 if(strchr(item, ' '))
1336 strcat(command, "\"");
1337 strcat(command, item);
1338 strcat(command, "\"");
1341 strcat(command, item);
1344 for(item : project.includeDirs)
1346 strcat(command, " -I");
1347 if(strchr(item, ' '))
1349 strcat(command, "\"");
1350 strcat(command, item);
1351 strcat(command, "\"");
1354 strcat(command, item);
1356 for(item : project.preprocessorDefs)
1358 strcat(command, " -D");
1359 strcat(command, item);
1363 if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
1366 bool firstLine = true;
1369 // To do some time: auto save external dependencies?
1372 if(dep.GetLine(line, sizeof(line)-1))
1376 char * colon = strstr(line, ":");
1377 if(strstr(line, "No such file") || strstr(line, ",") || (colon && strstr(colon+1, ":")))
1391 // If we failed to generate dependencies...
1395 f.Printf("$(OBJ)%s.sym: %s%s.%s\n",
1396 moduleName, modulePath, moduleName, extension);
1402 f.Printf("\t$(ECP) %s%s.%s %s.sym\n\n",
1403 modulePath, moduleName, extension, moduleName);
1406 f.Printf("\t$(ECP) $(CECFLAGS)");
1410 f.Printf(" -memguard");
1411 if(strictNameSpaces)
1412 f.Printf(" -strictns");
1414 char * s = defaultNameSpace;
1416 f.Printf(" -defaultns %s", s);
1420 f.Printf(" $(ECFLAGS)");
1421 f.Printf(" $(CFLAGS)");
1422 GenFileFlags(f, project);
1423 f.Printf(" -c %s%s.%s -o $(OBJ)%s.sym\n\n",
1424 modulePath, moduleName, extension, moduleName);
1431 // TODO: Platform specific options
1432 if(child.type != resources && (child.type == folder || !child.isExcluded))
1433 child.GenMakefilePrintSymbolRules(f, project);
1439 void GenMakefilePrintCObjectRules(File f, Project project)
1441 //ProjectNode child;
1442 //char objDir[MAX_LOCATION];
1443 CompilerConfig compiler = GetCompilerConfig();
1444 //ReplaceSpaces(objDir, project.config.objDir.dir);
1445 //eSystem_Log("Printing C Object Rules\n");
1448 char extension[MAX_EXTENSION];
1449 char modulePath[MAX_LOCATION];
1450 char moduleName[MAX_FILENAME];
1452 GetExtension(name, extension);
1453 if(!strcmpi(extension, "ec"))
1458 ReplaceSpaces(moduleName, name);
1459 StripExtension(moduleName);
1461 ReplaceSpaces(modulePath, path);
1462 if(modulePath[0]) strcat(modulePath, SEPS);
1465 // *** Dependency command ***
1466 sprintf(command, "gcc -MT $(OBJ)%s.o -MM %s%s.%s",
1467 moduleName, modulePath, moduleName, extension);
1469 // System Includes (from global settings)
1470 for(item : compiler.dirs[Includes])
1472 strcat(command, " -isystem ");
1473 if(strchr(item, ' '))
1475 strcat(command, "\"");
1476 strcat(command, item);
1477 strcat(command, "\"");
1480 strcat(command, item);
1483 for(item : project.config.includeDirs)
1485 strcat(command, " -I");
1486 if(strchr(item, ' '))
1488 strcat(command, "\"");
1489 strcat(command, item);
1490 strcat(command, "\"");
1493 strcat(command, item);
1495 for(item : project.config.preprocessorDefs)
1497 strcat(command, " -D");
1498 strcat(command, item);
1502 if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
1506 bool firstLine = true;
1508 // To do some time: auto save external dependencies?
1511 if(dep.GetLine(line, sizeof(line)-1))
1515 char * colon = strstr(line, ":");
1516 if(strstr(line, "No such file") || strstr(line, ",") || (colon && strstr(colon+1, ":")))
1530 // If we failed to generate dependencies...
1533 /* COMMENTED OUT FOR NOW
1534 f.Printf("$(OBJ)%s.c: %s%s.%s $(Symbols)\n",
1535 moduleName, modulePath, moduleName, extension);
1538 f.Printf("$(OBJ)%s.c: %s%s.%s $(OBJ)%s.sym | $(SYMBOLS)\n",
1539 moduleName, modulePath, moduleName, extension, moduleName);
1545 f.Printf("\t$(ECC) %s%s.%s $(OBJ)%s.c\n\n",
1546 modulePath, moduleName, extension, moduleName);
1549 f.Printf("\t$(ECC)");
1552 f.Printf("%s $(CECFLAGS)", noLineNumbers ? " -nolinenumbers" : "");
1554 f.Printf(" -memguard");
1555 if(strictNameSpaces)
1556 f.Printf(" -strictns");
1558 char * s = defaultNameSpace;
1560 f.Printf(" -defaultns %s", s);
1564 f.Printf(" $(CECFLAGS) $(ECFLAGS)");
1565 f.Printf(" $(CFLAGS) $(FVISIBILITY)");
1566 GenFileFlags(f, project);
1567 f.Printf(" -c %s%s.%s -o $(OBJ)%s.c -symbols $(OBJ)\n\n",
1568 modulePath, moduleName, extension, moduleName);
1575 // TODO: Platform specific options
1576 if(child.type != resources && (child.type == folder || !child.isExcluded))
1577 child.GenMakefilePrintCObjectRules(f, project);
1583 void GenMakefilePrintObjectRules(File f, Project project, Map<String, NameCollisionInfo> namesInfo)
1585 //ProjectNode child;
1586 //char objDir[MAX_LOCATION];
1587 CompilerConfig compiler = GetCompilerConfig();
1588 //ReplaceSpaces(objDir, project.config.objDir.dir);
1589 //eSystem_Log("Printing Object Rules\n");
1593 char extension[MAX_EXTENSION];
1594 char modulePath[MAX_LOCATION];
1595 char moduleName[MAX_FILENAME];
1597 GetExtension(name, extension);
1598 /*if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1599 !strcmpi(extension, "ec") || !strcmpi(extension, "cc") ||
1600 !strcmpi(extension, "cxx"))*/
1601 if((!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1602 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx")) ||
1603 !strcmpi(extension, "ec"))
1607 NameCollisionInfo info;
1609 ReplaceSpaces(moduleName, name);
1610 StripExtension(moduleName);
1612 info = namesInfo[moduleName];
1613 collision = info ? info.IsExtensionColliding(extension) : false;
1615 ReplaceSpaces(modulePath, path);
1616 if(modulePath[0]) strcat(modulePath, SEPS);
1618 // *** Dependency command ***
1619 if(!strcmpi(extension, "ec"))
1620 sprintf(command, "%s -MT $(OBJ)%s.o -MM $(OBJ)%s.c", compiler.ccCommand, moduleName, moduleName);
1622 sprintf(command, "%s -MT $(OBJ)%s.o -MM %s%s.%s", compiler.ccCommand, moduleName, modulePath, moduleName, extension);
1624 if(!strcmpi(extension, "ec"))
1625 f.Printf("$(OBJ)%s.o: $(OBJ)%s.c\n", moduleName, moduleName);
1629 // System Includes (from global settings)
1630 for(item : compiler.dirs[includes])
1632 strcat(command, " -isystem ");
1633 if(strchr(item, ' '))
1635 strcat(command, "\"");
1636 strcat(command, item);
1637 strcat(command, "\"");
1640 strcat(command, item);
1643 for(item : project.config.includeDirs)
1645 strcat(command, " -I");
1646 if(strchr(item, ' '))
1648 strcat(command, "\"");
1649 strcat(command, item);
1650 strcat(command, "\"");
1653 strcat(command, item);
1655 for(item : project.config.preprocessorDefs)
1657 strcat(command, " -D");
1658 strcat(command, item);
1662 if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
1665 bool firstLine = true;
1668 // To do some time: auto save external dependencies?
1672 if(dep.GetLine(line, sizeof(line)-1))
1676 char * colon = strstr(line, ":");
1677 if(strstr(line, "No such file") || strstr(line, ",") || (colon && strstr(colon+1, ":")))
1691 // If we failed to generate dependencies...
1695 /*if(!strcmpi(extension, "ec"))
1696 f.Printf("$(OBJ)%s.o: $(OBJ)%s.c\n", moduleName, moduleName);
1698 f.Printf("$(OBJ)%s%s%s.o: %s%s.%s\n", moduleName,
1699 collision ? "." : "", collision ? extension : "", modulePath, moduleName, extension);
1705 f.Printf("\t$(CC) $(CFLAGS)");
1706 GenFileFlags(f, project);
1707 if(!strcmpi(extension, "ec"))
1708 f.Printf(" $(FVISIBILITY) -c $(OBJ)%s.c -o $(OBJ)%s.o\n\n", moduleName, moduleName);
1710 f.Printf(" -c %s%s.%s -o $(OBJ)%s%s%s.o\n\n",
1711 modulePath, moduleName, !strcmpi(extension, "ec") ? "c" : extension, moduleName,
1712 collision ? "." : "", collision ? extension : "");
1719 // TODO: Platform specific options
1720 if(child.type != resources && (child.type == folder || !child.isExcluded))
1721 child.GenMakefilePrintObjectRules(f, project, namesInfo);
1727 void GenMakefileAddResources(File f, String resourcesPath)
1734 //Iterator<ProjectNode> i { files };
1735 //Iterator<ProjectNode> prev { files };
1736 //for(child : files)
1738 for(c = 0; c < files.count; c++)
1740 ProjectNode child = files[c];
1741 TwoStrings ts = child.platformSpecificFu;
1744 if(child.type == file && !child.isExcluded && !(count > 0 && ts))
1747 char tempPath[MAX_LOCATION];
1748 char resPath[MAX_LOCATION];
1752 // $(EAR) aw%s --- /*quiet ? "q" : */""
1754 f.Printf("\t%s$(EAR) aw $(TARGET)", ts.a);
1757 if(eString_PathInsideOfMore(child.path, resourcesPath, tempPath))
1760 PathCatSlash(tempPath, child.name);
1765 strcpy(tempPath, child.path);
1766 PathCatSlash(tempPath, child.name);
1768 ReplaceSpaces(resPath, tempPath);
1769 if(strchr(tempPath, ' '))
1773 f.Printf(" %s%s%s%s", quotes, useRes ? "$(RES)" : "", resPath, quotes);
1776 if(count == 10 || (count > 0 && (ts || !child.next)))
1778 char path[MAX_LOCATION] = "", temp[MAX_LOCATION];
1781 for(parent = this; parent.type == folder; parent = parent.parent)
1784 strcpy(path, parent.name);
1791 f.Printf(" \"%s\"%s\n", path, ts.b);
1803 if(child.type == folder)
1804 child.GenMakefileAddResources(f, resourcesPath);
1810 class NameCollisionInfo
1820 bool IsExtensionColliding(char * extension)
1823 if(count > 1 && ((!strcmpi(extension, "c") && ec) ||
1824 (!strcmpi(extension, "cpp") && (ec || c)) ||
1825 (!strcmpi(extension, "cc") && (ec || c || cpp)) ||
1826 (!strcmpi(extension, "cxx") && (ec || c || cpp || cc)) ||
1827 !strcmpi(extension, "m")))