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 BuildExclusionInfo : struct
168 Map<Platform, bool> platformSpecific { };
171 class ProjectNode : ListItem
176 set { return { fileName = value }; }
177 // TOCHECK: Is this isset necessary at all?
178 isset { return nodeType == file && !options && !configurations && !platforms && !files; }
180 property String folder
185 if(strchr(value, '/'))
187 char p[MAX_LOCATION];
188 char n[MAX_FILENAME];
189 GetLastDirectory(value, n);
190 StripLastDirectory(value, p);
191 name = CopyString(n);
192 path = CopyString(p);
195 name = CopyString(value);
199 // TOCHECK: Non Reentrant
200 static char insidePath[MAX_LOCATION];
202 strcpy(insidePath, (parent.type == project) ? "" : parent.path);
203 PathCatSlash(insidePath, name);
205 if(!fstrcmp(path, insidePath))
209 strcpy(insidePath, path);
210 if(!insidePath[0]) strcpy(insidePath, ".");
211 PathCatSlash(insidePath, name);
215 isset { return nodeType == folder; }
217 property String fileName
222 if(strchr(value, '/'))
224 char p[MAX_LOCATION];
225 char n[MAX_FILENAME];
226 GetLastDirectory(value, n);
227 StripLastDirectory(value, p);
228 name = CopyValidateMakefilePath(n);
229 path = CopyValidateMakefilePath(p);
232 name = CopyValidateMakefilePath(value);
236 // TOCHECK: Non Reentrant
237 static char insidePath[MAX_LOCATION];
239 strcpy(insidePath, (parent.type == project) ? "" : parent.path);
240 if(!fstrcmp(path, insidePath))
244 strcpy(insidePath, path);
245 if(!insidePath[0]) strcpy(insidePath, ".");
246 PathCatSlash(insidePath, name);
250 isset { return nodeType == file && (options || configurations || platforms); }
253 LinkList<ProjectNode> files;
254 ProjectOptions options;
255 Array<PlatformOptions> platforms;
256 List<ProjectConfig> configurations;
258 property ProjectConfig config
263 ProjectConfig result = null;
268 if(configurations && (prj = property::project) && prj.config)
270 const char * projectConfigName = prj.config.name;
271 for(config : configurations)
273 if(!strcmpi(config.name, projectConfigName))
284 ProjectConfig GetMatchingNodeConfig(ProjectConfig config)
286 ProjectConfig nodeConfig = null;
289 const char * configName = config.name;
290 for(cfg : configurations)
292 if(!strcmpi(cfg.name, configName))
302 property bool ecflags
306 ProjectConfig config = this.config;
307 ProjectOptions options = this.options;
308 SetBool memoryGuard = localMemoryGuard;
309 String defaultNameSpace = localDefaultNameSpace;
310 SetBool strictNameSpaces = localStrictNameSpaces;
311 SetBool noLineNumbers = localNoLineNumbers;
313 if(memoryGuard || defaultNameSpace || strictNameSpaces || noLineNumbers)
315 else if(parent.parent)
316 return parent.ecflags;
321 property bool memoryGuard
325 ProjectConfig config = this.config;
326 ProjectOptions options = this.options;
327 SetBool memoryGuard = localMemoryGuard;
331 return parent.memoryGuard;
333 return memoryGuard == true;
336 property String defaultNameSpace
340 ProjectConfig config = this.config;
341 ProjectOptions options = this.options;
342 String defaultNameSpace = localDefaultNameSpace;
343 if(!defaultNameSpace)
346 return parent.defaultNameSpace;
348 return defaultNameSpace;
351 property bool strictNameSpaces
355 ProjectConfig config = this.config;
356 ProjectOptions options = this.options;
357 SetBool strictNameSpaces = localStrictNameSpaces;
358 if(!strictNameSpaces)
361 return parent.strictNameSpaces;
363 return strictNameSpaces == true;
366 property bool noLineNumbers
370 ProjectConfig config = this.config;
371 ProjectOptions options = this.options;
372 SetBool noLineNumbers = localNoLineNumbers;
376 return parent.noLineNumbers;
378 return noLineNumbers == true;
382 property ProjectNode root { get { ProjectNode n; for(n = this; n.parent; n = n.parent); return n; } }
384 property bool containsFile
393 if(child.type == file ||
394 ((child.type == folder || child.type == folderOpen) && child.containsFile))
407 char * GetFullFilePath(char * buffer)
411 strcpy(buffer, root.path);
412 PathCatSlash(buffer, path);
413 PathCatSlash(buffer, name);
418 char * GetFileSysMatchingPath(char * buffer)
422 ProjectNode n, root = this.root;
423 for(n = this; n && (n.type == folder || n.type == project); n = n.parent)
425 strcpy(buffer, root.path);
427 PathCatSlash(buffer, n.path);
428 if(FileExists(buffer).isDirectory)
431 if(!(n && (n.type == folder || n.type == project)))
437 void CollectPerFileAndDirOptions(ProjectConfig projectConfig, Array<String> perFilePreprocessorDefs, Array<DirPath> perFileIncludeDirs)
439 ProjectNode node = null;
440 ProjectConfig config = GetMatchingNodeConfig(projectConfig);
441 List<ProjectNode> nodeStack { };
443 for(node = this; node && node.parent; node = node.parent)
446 // Should we reverse this stack to give priority to the per-file includes? Does the following technique already reverse?
448 // TODO: Check how to fix duplication of following options when configuration is made per-config-per-file
449 while((node = nodeStack.lastIterator.data))
451 if(node.options && node.options.preprocessorDefinitions)
453 for(def : node.options.preprocessorDefinitions)
454 perFilePreprocessorDefs.Add(CopyString(def));
456 if(config && config.options && config.options.preprocessorDefinitions)
458 for(def : config.options.preprocessorDefinitions)
459 perFilePreprocessorDefs.Add(CopyString(def));
461 if(node.options && node.options.includeDirs)
463 for(dir : node.options.includeDirs)
464 perFileIncludeDirs.Add(CopySystemPath(dir));
466 if(config && config.options && config.options.includeDirs)
468 for(dir : config.options.includeDirs)
469 perFileIncludeDirs.Add(CopySystemPath(dir));
471 nodeStack.lastIterator.Remove();
477 ProjectNodeType nodeType;
482 // This holds the absolute path of the .epj for the project topnode (without the filename)
483 // It holds a relative path to the topNode (project) for other nodes (folders and files)
484 // For folders, it includes the folder it refers to. If there is a name difference between the
485 // file system folder and the grouping folder of the project view, it maps to that folder.
495 // This is only set for Top Nodes
498 property Project project
502 ProjectNode n = this;
503 while(n && n.type != project) n = n.parent;
504 return n ? (*&n.project) : null;
508 void RenameConfig(char * oldName, char * newName)
512 for(f : files; (f.configurations || f.files)) { f.RenameConfig(oldName, newName); }
516 for(c : configurations; !strcmp(c.name, oldName))
519 c.name = CopyString(newName);
524 void DeleteConfig(ProjectConfig configToDelete)
528 for(f : files; (f.configurations || f.files)) { f.DeleteConfig(configToDelete); }
532 Iterator<ProjectConfig> c { configurations };
535 ProjectConfig config = c.data;
536 if(!strcmp(configToDelete.name, config.name))
543 if(!configurations.count)
545 delete configurations;
552 ProjectNode backupNode { };
556 backupNode.files = { };
557 for(f : files) backupNode.files.Add(f.Backup());
560 backupNode.options = options.Copy();
564 backupNode.platforms = { };
566 backupNode.platforms.Add(p.Copy());
571 backupNode.configurations = { };
572 for(c : configurations)
573 backupNode.configurations.Add(c.Copy());
578 void Revert(ProjectNode backupNode)
582 Iterator<ProjectNode> it { backupNode.files };
598 configurations.Free();
599 delete configurations;
602 options = backupNode.options ? backupNode.options.Copy() : null;
603 if(backupNode.platforms)
606 for(p : backupNode.platforms)
607 platforms.Add(p.Copy());
609 if(backupNode.configurations)
611 configurations = { };
612 for(c : backupNode.configurations)
613 configurations.Add(c.Copy());
617 void FixupNode(char * parentPath)
623 else if(nodeType == file)
628 path = CopyString((parent.type == folder || parent.type == resources) ? parentPath : "");
631 else if(nodeType == folder)
637 char temp[MAX_LOCATION];
638 strcpy(temp, (parent.type == folder || parent.type == resources) ? parentPath : "");
639 PathCatSlash(temp, name);
640 path = CopyString(temp);
644 indent = parent ? parent.indent + 1 : 0;
647 icon = NodeIcons::SelectFileIcon(name);
649 icon = NodeIcons::SelectNodeIcon(type);
658 parentPath[0] = '\0';
659 else if(type == resources || type == folder)
660 strcpy(parentPath, path);
662 f.FixupNode(parentPath);
667 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
671 // TOCHECK: Called from JSON writer
672 if(nodeType == file && !options && !configurations && !platforms && name)
674 strcpy(tempString, "\"");
675 strcat(tempString, property::fileName);
676 strcat(tempString, "\"");
683 // TOCHECK: Called from ProjectView rendering
684 return name ? name : "";
703 configurations.Free();
704 delete configurations;
707 /////////////////////////////
713 property bool isInResources
718 for(node = this; node; node = node.parent)
720 if(node.type == resources)
727 property TwoStrings platformSpecificFu
731 TwoStrings result { a = CopyString(""), b = CopyString("") };
732 BuildExclusionInfo exclusion = exclusionInfo;
736 if(exclusion.platformSpecific.count > 1)
738 MapNode<Platform, bool> mn;
741 len = strlen(exp) + strlen("$(if $(or ");
742 exp = renew exp char[len+1];
743 strcat(exp, "$(if $(or ");
746 for(mn = exclusion.platformSpecific.root.minimum; mn; mn = mn.next)
750 char * comma = mn.next ? "," : "";
753 var = PlatformToMakefileVariable(platform);
756 len = strlen(exp) + strlen("$(") + strlen(var) + strlen(")") + strlen(comma);
757 exp = renew exp char[len+1];
767 len = strlen(exp) + strlen("),");
768 exp = renew exp char[len+1];
772 exp = exclusion.excluded == true ? result.b : result.a;
773 len = strlen(exp) + strlen(",");
774 exp = renew exp char[len+1];
776 if(exclusion.excluded == true) result.b = exp; else result.a = exp;
779 len = strlen(exp) + strlen(")");
780 exp = renew exp char[len+1];
784 else if(exclusion.platformSpecific.count)
786 platform = exclusion.platformSpecific.root.minimum.key;
787 var = PlatformToMakefileVariable(platform);
790 len = strlen(exp) + strlen("$(if $(") + strlen(var) + strlen("),");
791 exp = renew exp char[len+1];
792 strcat(exp, "$(if $(");
797 exp = exclusion.excluded == true ? result.b : result.a;
798 len = strlen(exp) + strlen(",");
799 exp = renew exp char[len+1];
801 if(exclusion.excluded == true) result.b = exp; else result.a = exp;
804 len = strlen(exp) + strlen(")");
805 exp = renew exp char[len+1];
813 property bool isExcluded
817 return exclusionInfo.excluded == true && exclusionInfo.platformSpecific.count == 0;
821 property BuildExclusionInfo exclusionInfo
825 BuildExclusionInfo result { };
826 ProjectConfig config = property::config;
827 if(config && config.options && config.options.excludeFromBuild)
828 result.excluded = config.options.excludeFromBuild;
829 else if(options && options.excludeFromBuild)
830 result.excluded = options.excludeFromBuild;
833 BuildExclusionInfo parentExclusion = parent.exclusionInfo;
834 if(parentExclusion.excluded)
836 result.excluded = parentExclusion.excluded;
837 if(parentExclusion.platformSpecific.count)
839 MapNode<Platform, bool> mn;
840 for(mn = parentExclusion.platformSpecific.root.minimum; mn; mn = mn.next)
844 result.platformSpecific[mn.key] = true;
852 SetBool opposite = result.excluded == true ? false : true;
858 if(p.options.excludeFromBuild == opposite && (platform = p.name))
859 result.platformSpecific[platform] = true;
862 if(config && config.platforms)
864 for(p : config.platforms)
866 if(p.options.excludeFromBuild == opposite && (platform = p.name))
867 result.platformSpecific[platform] = true;
878 parent.EnsureVisible();
879 row.collapsed = false;
885 parent.files.Delete(this);
888 ProjectNode Find(char * name, bool includeResources)
890 ProjectNode result = null;
895 if(includeResources || child.type != resources)
897 if(child.type != folder && child.name && !strcmpi(child.name, name))
902 result = child.Find(name, includeResources);
911 ProjectNode FindWithPath(char * name, bool includeResources)
913 ProjectNode result = null;
918 if(includeResources || child.type != resources)
920 char path[MAX_LOCATION];
921 strcpy(path, child.path);
922 if(child.type != folder && child.name)
924 PathCatSlash(path, child.name);
925 if(!strcmpi(path, name))
931 result = child.FindWithPath(name, includeResources);
940 ProjectNode FindSpecial(char * name, bool recursive, bool includeResources, bool includeFolders)
942 ProjectNode result = null;
947 if(includeResources || child.type != resources)
949 if((includeFolders || child.type != folder) && child.name && !strcmpi(child.name, name))
955 result = child.FindSpecial(name, recursive, includeResources, includeFolders);
964 ProjectNode Add(Project project, char * filePath, ProjectNode after, NodeTypes type, NodeIcons icon, bool checkIfExists)
966 ProjectNode node = null;
967 char temp[MAX_LOCATION];
969 GetLastDirectory(filePath, temp);
970 if(!checkIfExists || !project.topNode.Find(temp, false))
972 // Do the check for folder in the same parent or resource files only here
973 if(type == folder || !checkIfExists)
977 if(node.name && !strcmpi(node.name, temp))
982 node = ProjectNode { parent = this, indent = indent + 1, type = type, icon = icon, name = CopyString(temp) };
986 node.nodeType = folder;
992 StripLastDirectory(filePath, temp);
993 MakePathRelative(temp, project.topNode.path, temp);
994 node.path = CopyUnixPath(temp);
996 node.nodeType = file;
1000 strcpy(temp, (type == NodeTypes::project) ? "" : path);
1001 PathCatSlash(temp, node.name);
1002 node.path = CopyString(temp);
1004 files.Insert(after, node);
1009 #ifndef MAKEFILE_GENERATOR
1010 void OnDisplay(Surface surface, int x, int y, int width, ProjectView projectView, Alignment alignment, DataDisplayFlags displayFlags)
1012 char label[MAX_FILENAME];
1018 bool showConfig = true;
1023 projectView = ide.projectView;
1026 bmp = projectView.icons[icon].bitmap;
1027 xStart = /*indent * indent + */x + (bmp ? (bmp.width + 5) : 0);
1029 GetLastDirectory(name, label);
1030 if(!showConfig || projectView.drawingInProjectSettingsDialogHeader)
1032 if(projectView.drawingInProjectSettingsDialogHeader || (type == project && info))
1034 if(projectView.projectSettingsDialog && projectView.projectSettingsDialog.buildTab)
1037 addendum = projectView.projectSettingsDialog.buildTab.selectedConfigName;
1038 if(strlen(addendum))
1040 strcat(label, " (");
1041 strcat(label, addendum);
1044 addendum = projectView.projectSettingsDialog.buildTab.selectedPlatformName;
1045 if(strlen(addendum))
1047 strcat(label, " (");
1048 strcat(label, addendum);
1054 else if(!projectView.drawingInProjectSettingsDialog)
1057 strcat(label, " *");
1058 if(type == project && info)
1060 int len = strlen(info) + 4;
1061 char * more = new char[len];
1062 sprintf(more, " (%s)", info);
1063 strcat(label, more);
1067 len = strlen(label);
1071 if(type == folder || type == folderOpen)
1072 surface.SetForeground(yellow);
1076 surface.TextOpacity(false);
1077 surface.TextExtent(label, len, &w, &h);
1080 // Draw the current row stipple
1081 if(displayFlags.selected)
1082 //surface.Area(xStart - 1, y, xStart - 1, y + h - 1);
1083 //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1);
1084 surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1);
1086 surface.WriteTextDots(alignment, xStart, y + 2, width, label, len);
1090 if(displayFlags.current)
1092 if(displayFlags.active)
1094 surface.LineStipple(0x5555);
1095 if(displayFlags.selected)
1096 surface.SetForeground(projectView.fileList.stippleColor);
1098 surface.SetForeground(projectView.fileList.foreground);
1102 surface.SetForeground(SELECTION_COLOR);
1104 surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1);
1105 surface.LineStipple(0);
1110 surface.SetForeground(white);
1111 surface.Blit(bmp, x /*+ indent * indent*/,y,0,0, bmp.width, bmp.height);
1117 int OnCompare(ProjectNode b)
1120 if(type == b.type /*|| type >= TYPE_DRIVE*/)
1121 result = strcmpi(name, b.name);
1124 if(type == folder && b.type == file) result = -1;
1125 else if(type == file && b.type == folder) result = 1;
1130 void GenFileFlags(File f, Project project)
1132 ProjectNode node = null;
1133 List<ProjectNode> nodeStack { };
1135 for(node = this; node && node.parent; node = node.parent)
1136 nodeStack.Add(node);
1138 // Should we reverse this stack to give priority to the per-file includes?
1140 while((node = nodeStack.lastIterator.data))
1142 ProjectConfig config = node.config;
1143 if(node.options && node.options.preprocessorDefinitions)
1144 OutputListOption(f, "D", node.options.preprocessorDefinitions, inPlace, false);
1145 if(config && config.options && config.options.preprocessorDefinitions)
1146 OutputListOption(f, "D", config.options.preprocessorDefinitions, inPlace, false);
1147 if(node.options && node.options.includeDirs)
1148 OutputListOption(f, "I", node.options.includeDirs, inPlace, true);
1149 if(config && config.options && config.options.includeDirs)
1150 OutputListOption(f, "I", config.options.includeDirs, inPlace, true);
1152 nodeStack.lastIterator.Remove();
1157 void GenMakefileGetNameCollisionInfo(Map<String, NameCollisionInfo> namesInfo)
1161 char extension[MAX_EXTENSION];
1162 GetExtension(name, extension);
1163 if(!strcmpi(extension, "ec") || !strcmpi(extension, "c") ||
1164 !strcmpi(extension, "cpp") || !strcmpi(extension, "cc") ||
1165 !strcmpi(extension, "cxx") || !strcmpi(extension, "m"))
1167 char moduleName[MAX_FILENAME];
1168 NameCollisionInfo info;
1169 ReplaceSpaces(moduleName, name);
1170 StripExtension(moduleName);
1171 info = namesInfo[moduleName];
1173 info = NameCollisionInfo { };
1174 info.count++; // += 1; unless this is for a bug?
1175 if(!strcmpi(extension, "ec"))
1177 else if(!strcmpi(extension, "c"))
1179 else if(!strcmpi(extension, "cpp"))
1181 else if(!strcmpi(extension, "cc"))
1183 else if(!strcmpi(extension, "cxx"))
1185 else if(!strcmpi(extension, "m"))
1187 namesInfo[moduleName] = info;
1194 if(child.type != resources && (child.type == folder || !child.isExcluded))
1195 child.GenMakefileGetNameCollisionInfo(namesInfo);
1200 int GenMakefilePrintNode(File f, Project project, GenMakefilePrintTypes printType, Map<String, NameCollisionInfo> namesInfo, Array<String> items)
1206 TwoStrings ts = platformSpecificFu;
1207 char moduleName[MAX_FILENAME];
1208 char extension[MAX_EXTENSION];
1209 GetExtension(name, extension);
1210 if(printType == resources)
1213 char tempPath[MAX_LOCATION];
1214 char modulePath[MAX_LOCATION];
1217 if(eString_PathInsideOfMore(path, project.resNode.path, tempPath))
1220 PathCatSlash(tempPath, name);
1225 strcpy(tempPath, path);
1226 PathCatSlash(tempPath, name);
1228 ReplaceSpaces(modulePath, tempPath);
1229 sprintf(s, "%s%s%s%s", ts.a, useRes ? "$(RES)" : "", modulePath, ts.b);
1230 items.Add(CopyString(s));
1232 else if(printType == sources)
1234 if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1235 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
1236 !strcmpi(extension, "ec") || !strcmpi(extension, "m"))
1238 char modulePath[MAX_LOCATION];
1240 ReplaceSpaces(modulePath, path);
1241 ReplaceSpaces(moduleName, name);
1242 sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b);
1243 items.Add(CopyString(s));
1246 else if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1247 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
1248 !strcmpi(extension, "m"))
1250 if(printType == objects)
1253 NameCollisionInfo info;
1254 ReplaceSpaces(moduleName, name);
1255 StripExtension(moduleName);
1256 info = namesInfo[moduleName];
1257 collision = info ? info.IsExtensionColliding(extension) : false;
1258 sprintf(s, "%s$(OBJ)%s%s%s.o%s", ts.a, moduleName, collision ? "." : "", collision ? extension : "", ts.b);
1259 items.Add(CopyString(s));
1262 else if(!strcmpi(extension, "ec"))
1264 ReplaceSpaces(moduleName, name);
1265 StripExtension(moduleName);
1266 if(printType == objects)
1269 if(printType == objects)
1270 sprintf(s, "%s$(OBJ)%s.o%s", ts.a, moduleName, ts.b);
1271 else if(printType == cObjects)
1272 sprintf(s, "%s$(OBJ)%s.c%s", ts.a, moduleName, ts.b);
1273 else if(printType == symbols)
1274 sprintf(s, "%s$(OBJ)%s.sym%s", ts.a, moduleName, ts.b);
1275 else if(printType == imports)
1276 sprintf(s, "%s$(OBJ)%s.imp%s", ts.a, moduleName, ts.b);
1278 items.Add(CopyString(s));
1286 if(child.type != resources && (child.type == folder || !child.isExcluded))
1287 count += child.GenMakefilePrintNode(f, project, printType, namesInfo, items);
1293 void GenMakefilePrintSymbolRules(File f, Project project)
1295 //ProjectNode child;
1296 //char objDir[MAX_LOCATION];
1297 CompilerConfig compiler = GetCompilerConfig();
1298 //ReplaceSpaces(objDir, project.config.objDir.dir);
1300 //eSystem_Log("Printing Symbol Rules\n");
1303 char extension[MAX_EXTENSION];
1304 char modulePath[MAX_LOCATION];
1305 char moduleName[MAX_FILENAME];
1307 GetExtension(name, extension);
1308 if(!strcmpi(extension, "ec"))
1313 ReplaceSpaces(moduleName, name);
1314 StripExtension(moduleName);
1316 ReplaceSpaces(modulePath, path);
1317 if(modulePath[0]) strcat(modulePath, SEPS);
1320 // *** Dependency command ***
1321 sprintf(command, "gcc -MT $(OBJ)%s.o -MM %s%s.%s", moduleName,
1322 modulePath, moduleName, extension);
1324 // System Includes (from global settings)
1325 for(item : compiler.dirs[Includes])
1327 strcat(command, " -isystem ");
1328 if(strchr(item, ' '))
1330 strcat(command, "\"");
1331 strcat(command, item);
1332 strcat(command, "\"");
1335 strcat(command, item);
1338 for(item : project.includeDirs)
1340 strcat(command, " -I");
1341 if(strchr(item, ' '))
1343 strcat(command, "\"");
1344 strcat(command, item);
1345 strcat(command, "\"");
1348 strcat(command, item);
1350 for(item : project.preprocessorDefs)
1352 strcat(command, " -D");
1353 strcat(command, item);
1357 if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
1360 bool firstLine = true;
1363 // To do some time: auto save external dependencies?
1366 if(dep.GetLine(line, sizeof(line)-1))
1370 char * colon = strstr(line, ":");
1371 if(strstr(line, "No such file") || strstr(line, ",") || (colon && strstr(colon+1, ":")))
1385 // If we failed to generate dependencies...
1389 f.Printf("$(OBJ)%s.sym: %s%s.%s\n",
1390 moduleName, modulePath, moduleName, extension);
1396 f.Printf("\t$(ECP) %s%s.%s %s.sym\n\n",
1397 modulePath, moduleName, extension, moduleName);
1400 f.Printf("\t$(ECP) $(CECFLAGS)");
1404 f.Printf(" -memguard");
1405 if(strictNameSpaces)
1406 f.Printf(" -strictns");
1408 char * s = defaultNameSpace;
1410 f.Printf(" -defaultns %s", s);
1414 f.Printf(" $(ECFLAGS)");
1415 f.Printf(" $(CFLAGS)");
1416 GenFileFlags(f, project);
1417 f.Printf(" -c %s%s.%s -o $(OBJ)%s.sym\n\n",
1418 modulePath, moduleName, extension, moduleName);
1425 // TODO: Platform specific options
1426 if(child.type != resources && (child.type == folder || !child.isExcluded))
1427 child.GenMakefilePrintSymbolRules(f, project);
1433 void GenMakefilePrintCObjectRules(File f, Project project)
1435 //ProjectNode child;
1436 //char objDir[MAX_LOCATION];
1437 CompilerConfig compiler = GetCompilerConfig();
1438 //ReplaceSpaces(objDir, project.config.objDir.dir);
1439 //eSystem_Log("Printing C Object Rules\n");
1442 char extension[MAX_EXTENSION];
1443 char modulePath[MAX_LOCATION];
1444 char moduleName[MAX_FILENAME];
1446 GetExtension(name, extension);
1447 if(!strcmpi(extension, "ec"))
1452 ReplaceSpaces(moduleName, name);
1453 StripExtension(moduleName);
1455 ReplaceSpaces(modulePath, path);
1456 if(modulePath[0]) strcat(modulePath, SEPS);
1459 // *** Dependency command ***
1460 sprintf(command, "gcc -MT $(OBJ)%s.o -MM %s%s.%s",
1461 moduleName, modulePath, moduleName, extension);
1463 // System Includes (from global settings)
1464 for(item : compiler.dirs[Includes])
1466 strcat(command, " -isystem ");
1467 if(strchr(item, ' '))
1469 strcat(command, "\"");
1470 strcat(command, item);
1471 strcat(command, "\"");
1474 strcat(command, item);
1477 for(item : project.config.includeDirs)
1479 strcat(command, " -I");
1480 if(strchr(item, ' '))
1482 strcat(command, "\"");
1483 strcat(command, item);
1484 strcat(command, "\"");
1487 strcat(command, item);
1489 for(item : project.config.preprocessorDefs)
1491 strcat(command, " -D");
1492 strcat(command, item);
1496 if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
1500 bool firstLine = true;
1502 // To do some time: auto save external dependencies?
1505 if(dep.GetLine(line, sizeof(line)-1))
1509 char * colon = strstr(line, ":");
1510 if(strstr(line, "No such file") || strstr(line, ",") || (colon && strstr(colon+1, ":")))
1524 // If we failed to generate dependencies...
1527 /* COMMENTED OUT FOR NOW
1528 f.Printf("$(OBJ)%s.c: %s%s.%s $(Symbols)\n",
1529 moduleName, modulePath, moduleName, extension);
1532 f.Printf("$(OBJ)%s.c: %s%s.%s $(OBJ)%s.sym | $(SYMBOLS)\n",
1533 moduleName, modulePath, moduleName, extension, moduleName);
1539 f.Printf("\t$(ECC) %s%s.%s $(OBJ)%s.c\n\n",
1540 modulePath, moduleName, extension, moduleName);
1543 f.Printf("\t$(ECC)");
1546 f.Printf("%s $(CECFLAGS)", noLineNumbers ? " -nolinenumbers" : "");
1548 f.Printf(" -memguard");
1549 if(strictNameSpaces)
1550 f.Printf(" -strictns");
1552 char * s = defaultNameSpace;
1554 f.Printf(" -defaultns %s", s);
1558 f.Printf(" $(CECFLAGS) $(ECFLAGS)");
1559 f.Printf(" $(CFLAGS) $(FVISIBILITY)");
1560 GenFileFlags(f, project);
1561 f.Printf(" -c %s%s.%s -o $(OBJ)%s.c -symbols $(OBJ)\n\n",
1562 modulePath, moduleName, extension, moduleName);
1569 // TODO: Platform specific options
1570 if(child.type != resources && (child.type == folder || !child.isExcluded))
1571 child.GenMakefilePrintCObjectRules(f, project);
1577 void GenMakefilePrintObjectRules(File f, Project project, Map<String, NameCollisionInfo> namesInfo)
1579 //ProjectNode child;
1580 //char objDir[MAX_LOCATION];
1581 CompilerConfig compiler = GetCompilerConfig();
1582 //ReplaceSpaces(objDir, project.config.objDir.dir);
1583 //eSystem_Log("Printing Object Rules\n");
1587 char extension[MAX_EXTENSION];
1588 char modulePath[MAX_LOCATION];
1589 char moduleName[MAX_FILENAME];
1591 GetExtension(name, extension);
1592 /*if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1593 !strcmpi(extension, "ec") || !strcmpi(extension, "cc") ||
1594 !strcmpi(extension, "cxx"))*/
1595 if((!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1596 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx")) ||
1597 !strcmpi(extension, "ec"))
1601 NameCollisionInfo info;
1603 ReplaceSpaces(moduleName, name);
1604 StripExtension(moduleName);
1606 info = namesInfo[moduleName];
1607 collision = info ? info.IsExtensionColliding(extension) : false;
1609 ReplaceSpaces(modulePath, path);
1610 if(modulePath[0]) strcat(modulePath, SEPS);
1612 // *** Dependency command ***
1613 if(!strcmpi(extension, "ec"))
1614 sprintf(command, "%s -MT $(OBJ)%s.o -MM $(OBJ)%s.c", compiler.ccCommand, moduleName, moduleName);
1616 sprintf(command, "%s -MT $(OBJ)%s.o -MM %s%s.%s", compiler.ccCommand, moduleName, modulePath, moduleName, extension);
1618 if(!strcmpi(extension, "ec"))
1619 f.Printf("$(OBJ)%s.o: $(OBJ)%s.c\n", moduleName, moduleName);
1623 // System Includes (from global settings)
1624 for(item : compiler.dirs[includes])
1626 strcat(command, " -isystem ");
1627 if(strchr(item, ' '))
1629 strcat(command, "\"");
1630 strcat(command, item);
1631 strcat(command, "\"");
1634 strcat(command, item);
1637 for(item : project.config.includeDirs)
1639 strcat(command, " -I");
1640 if(strchr(item, ' '))
1642 strcat(command, "\"");
1643 strcat(command, item);
1644 strcat(command, "\"");
1647 strcat(command, item);
1649 for(item : project.config.preprocessorDefs)
1651 strcat(command, " -D");
1652 strcat(command, item);
1656 if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
1659 bool firstLine = true;
1662 // To do some time: auto save external dependencies?
1666 if(dep.GetLine(line, sizeof(line)-1))
1670 char * colon = strstr(line, ":");
1671 if(strstr(line, "No such file") || strstr(line, ",") || (colon && strstr(colon+1, ":")))
1685 // If we failed to generate dependencies...
1689 /*if(!strcmpi(extension, "ec"))
1690 f.Printf("$(OBJ)%s.o: $(OBJ)%s.c\n", moduleName, moduleName);
1692 f.Printf("$(OBJ)%s%s%s.o: %s%s.%s\n", moduleName,
1693 collision ? "." : "", collision ? extension : "", modulePath, moduleName, extension);
1699 f.Printf("\t$(CC) $(CFLAGS)");
1700 GenFileFlags(f, project);
1701 if(!strcmpi(extension, "ec"))
1702 f.Printf(" $(FVISIBILITY) -c $(OBJ)%s.c -o $(OBJ)%s.o\n\n", moduleName, moduleName);
1704 f.Printf(" -c %s%s.%s -o $(OBJ)%s%s%s.o\n\n",
1705 modulePath, moduleName, !strcmpi(extension, "ec") ? "c" : extension, moduleName,
1706 collision ? "." : "", collision ? extension : "");
1713 // TODO: Platform specific options
1714 if(child.type != resources && (child.type == folder || !child.isExcluded))
1715 child.GenMakefilePrintObjectRules(f, project, namesInfo);
1721 void GenMakefileAddResources(File f, String resourcesPath)
1728 //Iterator<ProjectNode> i { files };
1729 //Iterator<ProjectNode> prev { files };
1730 //for(child : files)
1732 for(c = 0; c < files.count; c++)
1734 ProjectNode child = files[c];
1735 TwoStrings ts = child.platformSpecificFu;
1738 if(child.type == file && !child.isExcluded && !(count > 0 && ts))
1741 char tempPath[MAX_LOCATION];
1742 char resPath[MAX_LOCATION];
1746 // $(EAR) aw%s --- /*quiet ? "q" : */""
1748 f.Printf("\t%s$(EAR) aw $(TARGET)", ts.a);
1751 if(eString_PathInsideOfMore(child.path, resourcesPath, tempPath))
1754 PathCatSlash(tempPath, child.name);
1759 strcpy(tempPath, child.path);
1760 PathCatSlash(tempPath, child.name);
1762 ReplaceSpaces(resPath, tempPath);
1763 if(strchr(tempPath, ' '))
1767 f.Printf(" %s%s%s%s", quotes, useRes ? "$(RES)" : "", resPath, quotes);
1770 if(count == 10 || (count > 0 && (ts || !child.next)))
1772 char path[MAX_LOCATION] = "", temp[MAX_LOCATION];
1775 for(parent = this; parent.type == folder; parent = parent.parent)
1778 strcpy(path, parent.name);
1785 f.Printf(" \"%s\"%s\n", path, ts.b);
1797 if(child.type == folder)
1798 child.GenMakefileAddResources(f, resourcesPath);
1804 class NameCollisionInfo
1814 bool IsExtensionColliding(char * extension)
1817 if(count > 1 && ((!strcmpi(extension, "c") && ec) ||
1818 (!strcmpi(extension, "cpp") && (ec || c)) ||
1819 (!strcmpi(extension, "cc") && (ec || c || cpp)) ||
1820 (!strcmpi(extension, "cxx") && (ec || c || cpp || cc)) ||
1821 !strcmpi(extension, "m")))