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 char * GetFullFilePath(char * buffer)
382 strcpy(buffer, root.path);
383 PathCatSlash(buffer, path);
384 PathCatSlash(buffer, name);
389 char * GetFileSysMatchingPath(char * buffer)
393 ProjectNode n, root = this.root;
394 for(n = this; n && (n.type == folder || n.type == project); n = n.parent)
396 strcpy(buffer, root.path);
398 PathCatSlash(buffer, n.path);
399 if(FileExists(buffer).isDirectory)
402 if(!(n && (n.type == folder || n.type == project)))
408 void CollectPerFileAndDirOptions(ProjectConfig projectConfig, Array<String> perFilePreprocessorDefs, Array<DirPath> perFileIncludeDirs)
410 ProjectNode node = null;
411 ProjectConfig config = GetMatchingNodeConfig(projectConfig);
412 List<ProjectNode> nodeStack { };
414 for(node = this; node && node.parent; node = node.parent)
417 // Should we reverse this stack to give priority to the per-file includes? Does the following technique already reverse?
419 // TODO: Check how to fix duplication of following options when configuration is made per-config-per-file
420 while((node = nodeStack.lastIterator.data))
422 if(node.options && node.options.preprocessorDefinitions)
424 for(def : node.options.preprocessorDefinitions)
425 perFilePreprocessorDefs.Add(CopyString(def));
427 if(config && config.options && config.options.preprocessorDefinitions)
429 for(def : config.options.preprocessorDefinitions)
430 perFilePreprocessorDefs.Add(CopyString(def));
432 if(node.options && node.options.includeDirs)
434 for(dir : node.options.includeDirs)
435 perFileIncludeDirs.Add(CopySystemPath(dir));
437 if(config && config.options && config.options.includeDirs)
439 for(dir : config.options.includeDirs)
440 perFileIncludeDirs.Add(CopySystemPath(dir));
442 nodeStack.lastIterator.Remove();
448 ProjectNodeType nodeType;
453 // This holds the absolute path of the .epj for the project topnode (without the filename)
454 // It holds a relative path to the topNode (project) for other nodes (folders and files)
455 // For folders, it includes the folder it refers to. If there is a name difference between the
456 // file system folder and the grouping folder of the project view, it maps to that folder.
466 // This is only set for Top Nodes
469 property Project project
473 ProjectNode n = this;
474 while(n && n.type != project) n = n.parent;
475 return n ? (*&n.project) : null;
479 void RenameConfig(char * oldName, char * newName)
483 for(f : files; (f.configurations || f.files)) { f.RenameConfig(oldName, newName); }
487 for(c : configurations; !strcmp(c.name, oldName))
490 c.name = CopyString(newName);
495 void DeleteConfig(ProjectConfig configToDelete)
499 for(f : files; (f.configurations || f.files)) { f.DeleteConfig(configToDelete); }
503 Iterator<ProjectConfig> c { configurations };
506 ProjectConfig config = c.data;
507 if(!strcmp(configToDelete.name, config.name))
514 if(!configurations.count)
516 delete configurations;
523 ProjectNode backupNode { };
527 backupNode.files = { };
528 for(f : files) backupNode.files.Add(f.Backup());
531 backupNode.options = options.Copy();
535 backupNode.platforms = { };
537 backupNode.platforms.Add(p.Copy());
542 backupNode.configurations = { };
543 for(c : configurations)
544 backupNode.configurations.Add(c.Copy());
549 void Revert(ProjectNode backupNode)
553 Iterator<ProjectNode> it { backupNode.files };
569 configurations.Free();
570 delete configurations;
573 options = backupNode.options ? backupNode.options.Copy() : null;
574 if(backupNode.platforms)
577 for(p : backupNode.platforms)
578 platforms.Add(p.Copy());
580 if(backupNode.configurations)
582 configurations = { };
583 for(c : backupNode.configurations)
584 configurations.Add(c.Copy());
588 void FixupNode(char * parentPath)
594 else if(nodeType == file)
599 path = CopyString((parent.type == folder || parent.type == resources) ? parentPath : "");
602 else if(nodeType == folder)
608 char temp[MAX_LOCATION];
609 strcpy(temp, (parent.type == folder || parent.type == resources) ? parentPath : "");
610 PathCatSlash(temp, name);
611 path = CopyString(temp);
615 indent = parent ? parent.indent + 1 : 0;
618 icon = NodeIcons::SelectFileIcon(name);
620 icon = NodeIcons::SelectNodeIcon(type);
629 parentPath[0] = '\0';
630 else if(type == resources || type == folder)
631 strcpy(parentPath, path);
633 f.FixupNode(parentPath);
638 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
642 // TOCHECK: Called from JSON writer
643 if(nodeType == file && !options && !configurations && !platforms && name)
645 strcpy(tempString, "\"");
646 strcat(tempString, property::fileName);
647 strcat(tempString, "\"");
654 // TOCHECK: Called from ProjectView rendering
655 return name ? name : "";
674 configurations.Free();
675 delete configurations;
678 /////////////////////////////
684 property bool isInResources
689 for(node = this; node; node = node.parent)
691 if(node.type == resources)
698 property TwoStrings platformSpecificExclusionFu
702 // TODO: Proper folder exclusion fix: collect platform names across parents and then build exclusion expression
703 // Find solution to excluding a drivers folder for all platforms and overriting that exclusion on children files/folders
704 TwoStrings result { };
705 int nestingCount = 0, c, len;
707 ProjectConfig config = property::config;
708 Map<String, bool> platformNames { };
712 if(p.options.excludeFromBuild == true)
713 platformNames[p.name] = true;
715 if(config && config.platforms)
717 for(p : config.platforms)
718 if(p.options.excludeFromBuild == true)
719 platformNames[p.name] = true;
721 if(platformNames.count)
724 result.a = new char[1];
726 for(s : platformNames)
728 for(platform = (Platform)1; platform < Platform::enumSize; platform++)
729 if(!strcmpi(&s, platform))
731 if(platform < Platform::enumSize)
733 const char * opening = "$(if $(";
734 const char * close = "),,";
735 char * t = PlatformToMakefileVariable(platform);
737 len += strlen(t) + strlen(opening) + strlen(close);
738 result.a = renew result.a char[len + 1];
739 strcat(result.a, opening);
741 strcat(result.a, close);
744 result.b = new char[nestingCount + 1];
745 for(c = 0; c < nestingCount; c++)
747 result.b[nestingCount] = '\0';
751 result.a = CopyString("");
752 result.b = CopyString("");
754 delete platformNames;
757 TwoStrings parentResult = parent.platformSpecificExclusionFu;
758 if(parentResult.a && parentResult.a[0])
760 len = strlen(result.a) + strlen(parentResult.a);
761 result.a = renew result.a char[len + 1];
762 strcat(result.a, parentResult.a);
763 len = strlen(result.b) + strlen(parentResult.b);
764 result.b = renew result.b char[len + 1];
765 strcat(result.b, parentResult.b);
773 property bool isExcluded
777 // THIS IS THE GENERIC (ALL PLATFORMS) EXCLUDED FROM BUILD
778 // TODO: We can also have platform specific exclusion...
779 ProjectConfig config = property::config;
780 if(config && config.options && config.options.excludeFromBuild)
781 return config.options.excludeFromBuild == true;
782 if(options && options.excludeFromBuild)
783 return options.excludeFromBuild == true;
785 return parent.isExcluded;
793 parent.EnsureVisible();
794 row.collapsed = false;
800 parent.files.Delete(this);
803 ProjectNode Find(char * name, bool includeResources)
805 ProjectNode result = null;
810 if(includeResources || child.type != resources)
812 if(child.type != folder && child.name && !strcmpi(child.name, name))
817 result = child.Find(name, includeResources);
826 ProjectNode FindWithPath(char * name, bool includeResources)
828 ProjectNode result = null;
833 if(includeResources || child.type != resources)
835 char path[MAX_LOCATION];
836 strcpy(path, child.path);
837 if(child.type != folder && child.name)
839 PathCatSlash(path, child.name);
840 if(!strcmpi(path, name))
846 result = child.FindWithPath(name, includeResources);
855 ProjectNode FindSpecial(char * name, bool recursive, bool includeResources, bool includeFolders)
857 ProjectNode result = null;
862 if(includeResources || child.type != resources)
864 if((includeFolders || child.type != folder) && child.name && !strcmpi(child.name, name))
870 result = child.FindSpecial(name, recursive, includeResources, includeFolders);
879 ProjectNode Add(Project project, char * filePath, ProjectNode after, NodeTypes type, NodeIcons icon, bool checkIfExists)
881 ProjectNode node = null;
882 char temp[MAX_LOCATION];
884 GetLastDirectory(filePath, temp);
885 if(!checkIfExists || !project.topNode.Find(temp, false))
887 // Do the check for folder in the same parent or resource files only here
888 if(type == folder || !checkIfExists)
892 if(node.name && !strcmpi(node.name, temp))
897 node = ProjectNode { parent = this, indent = indent + 1, type = type, icon = icon, name = CopyString(temp) };
901 node.nodeType = folder;
907 StripLastDirectory(filePath, temp);
908 MakePathRelative(temp, project.topNode.path, temp);
909 node.path = CopyUnixPath(temp);
911 node.nodeType = file;
915 strcpy(temp, (type == NodeTypes::project) ? "" : path);
916 PathCatSlash(temp, node.name);
917 node.path = CopyString(temp);
919 files.Insert(after, node);
924 #ifndef MAKEFILE_GENERATOR
925 void OnDisplay(Surface surface, int x, int y, int width, ProjectView projectView, Alignment alignment, DataDisplayFlags displayFlags)
927 char label[MAX_FILENAME];
933 bool showConfig = true;
938 projectView = ide.projectView;
941 bmp = projectView.icons[icon].bitmap;
942 xStart = /*indent * indent + */x + (bmp ? (bmp.width + 5) : 0);
944 GetLastDirectory(name, label);
945 if(!showConfig || projectView.drawingInProjectSettingsDialogHeader)
947 if(projectView.drawingInProjectSettingsDialogHeader || (type == project && info))
949 if(projectView.projectSettingsDialog && projectView.projectSettingsDialog.buildTab)
952 addendum = projectView.projectSettingsDialog.buildTab.selectedConfigName;
956 strcat(label, addendum);
959 addendum = projectView.projectSettingsDialog.buildTab.selectedPlatformName;
963 strcat(label, addendum);
969 else if(!projectView.drawingInProjectSettingsDialog)
973 if(type == project && info)
975 int len = strlen(info) + 4;
976 char * more = new char[len];
977 sprintf(more, " (%s)", info);
986 if(type == folder || type == folderOpen)
987 surface.SetForeground(yellow);
991 surface.TextOpacity(false);
992 surface.TextExtent(label, len, &w, &h);
995 // Draw the current row stipple
996 if(displayFlags.selected)
997 //surface.Area(xStart - 1, y, xStart - 1, y + h - 1);
998 //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1);
999 surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1);
1001 surface.WriteTextDots(alignment, xStart, y + 2, width, label, len);
1005 if(displayFlags.current)
1007 if(displayFlags.active)
1009 surface.LineStipple(0x5555);
1010 if(displayFlags.selected)
1011 surface.SetForeground(0xFFFFFF80);
1013 surface.SetForeground(black);
1017 surface.SetForeground(SELECTION_COLOR);
1019 surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1);
1020 surface.LineStipple(0);
1025 surface.SetForeground(white);
1026 surface.Blit(bmp, x /*+ indent * indent*/,y,0,0, bmp.width, bmp.height);
1032 int OnCompare(ProjectNode b)
1035 if(type == b.type /*|| type >= TYPE_DRIVE*/)
1036 result = strcmpi(name, b.name);
1039 if(type == folder && b.type == file) result = -1;
1040 else if(type == file && b.type == folder) result = 1;
1045 void GenFileFlags(File f, Project project)
1047 ProjectNode node = null;
1048 List<ProjectNode> nodeStack { };
1050 for(node = this; node && node.parent; node = node.parent)
1051 nodeStack.Add(node);
1053 // Should we reverse this stack to give priority to the per-file includes?
1055 while((node = nodeStack.lastIterator.data))
1057 ProjectConfig config = node.config;
1058 if(node.options && node.options.preprocessorDefinitions)
1059 OutputListOption(f, "D", node.options.preprocessorDefinitions, inPlace, false);
1060 if(config && config.options && config.options.preprocessorDefinitions)
1061 OutputListOption(f, "D", config.options.preprocessorDefinitions, inPlace, false);
1062 if(node.options && node.options.includeDirs)
1063 OutputListOption(f, "I", node.options.includeDirs, inPlace, true);
1064 if(config && config.options && config.options.includeDirs)
1065 OutputListOption(f, "I", config.options.includeDirs, inPlace, true);
1067 nodeStack.lastIterator.Remove();
1072 void GenMakefileGetNameCollisionInfo(Map<String, NameCollisionInfo> namesInfo)
1076 char extension[MAX_EXTENSION];
1077 GetExtension(name, extension);
1078 if(!strcmpi(extension, "ec") || !strcmpi(extension, "c") ||
1079 !strcmpi(extension, "cpp") || !strcmpi(extension, "cc") ||
1080 !strcmpi(extension, "cxx") || !strcmpi(extension, "m"))
1082 char moduleName[MAX_FILENAME];
1083 NameCollisionInfo info;
1084 ReplaceSpaces(moduleName, name);
1085 StripExtension(moduleName);
1086 info = namesInfo[moduleName];
1088 info = NameCollisionInfo { };
1089 info.count++; // += 1; unless this is for a bug?
1090 if(!strcmpi(extension, "ec"))
1092 else if(!strcmpi(extension, "c"))
1094 else if(!strcmpi(extension, "cpp"))
1096 else if(!strcmpi(extension, "cc"))
1098 else if(!strcmpi(extension, "cxx"))
1100 else if(!strcmpi(extension, "m"))
1102 namesInfo[moduleName] = info;
1109 if(child.type != resources && (child.type == folder || !child.isExcluded))
1110 child.GenMakefileGetNameCollisionInfo(namesInfo);
1115 int GenMakefilePrintNode(File f, Project project, GenMakefilePrintTypes printType, Map<String, NameCollisionInfo> namesInfo, Array<String> items)
1121 // TOCHECK: Does this take care of parent folder platform specific exclusions?
1122 TwoStrings ts = platformSpecificExclusionFu;
1123 char moduleName[MAX_FILENAME];
1124 char extension[MAX_EXTENSION];
1125 GetExtension(name, extension);
1126 if(printType == resources)
1129 char tempPath[MAX_LOCATION];
1130 char modulePath[MAX_LOCATION];
1133 if(eString_PathInsideOfMore(path, project.resNode.path, tempPath))
1136 PathCatSlash(tempPath, name);
1141 strcpy(tempPath, path);
1142 PathCatSlash(tempPath, name);
1144 ReplaceSpaces(modulePath, tempPath);
1145 sprintf(s, "%s%s%s%s", ts.a, useRes ? "$(RES)" : "", modulePath, ts.b);
1146 items.Add(CopyString(s));
1148 else if(printType == sources)
1150 if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1151 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
1152 !strcmpi(extension, "ec") || !strcmpi(extension, "m"))
1154 char modulePath[MAX_LOCATION];
1156 ReplaceSpaces(modulePath, path);
1157 ReplaceSpaces(moduleName, name);
1158 sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b);
1159 items.Add(CopyString(s));
1162 else if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1163 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
1164 !strcmpi(extension, "m"))
1166 if(printType == objects)
1169 NameCollisionInfo info;
1170 ReplaceSpaces(moduleName, name);
1171 StripExtension(moduleName);
1172 info = namesInfo[moduleName];
1173 collision = info ? info.IsExtensionColliding(extension) : false;
1174 sprintf(s, "%s$(OBJ)%s%s%s.o%s", ts.a, moduleName, collision ? "." : "", collision ? extension : "", ts.b);
1175 items.Add(CopyString(s));
1178 else if(!strcmpi(extension, "ec"))
1180 ReplaceSpaces(moduleName, name);
1181 StripExtension(moduleName);
1182 if(printType == objects)
1185 if(printType == objects)
1186 sprintf(s, "%s$(OBJ)%s.o%s", ts.a, moduleName, ts.b);
1187 else if(printType == cObjects)
1188 sprintf(s, "%s$(OBJ)%s.c%s", ts.a, moduleName, ts.b);
1189 else if(printType == symbols)
1190 sprintf(s, "%s$(OBJ)%s.sym%s", ts.a, moduleName, ts.b);
1191 else if(printType == imports)
1192 sprintf(s, "%s$(OBJ)%s.imp%s", ts.a, moduleName, ts.b);
1194 items.Add(CopyString(s));
1202 if(child.type != resources && (child.type == folder || !child.isExcluded))
1203 count += child.GenMakefilePrintNode(f, project, printType, namesInfo, items);
1209 void GenMakefilePrintSymbolRules(File f, Project project)
1211 //ProjectNode child;
1212 //char objDir[MAX_LOCATION];
1213 CompilerConfig compiler = GetCompilerConfig();
1214 //ReplaceSpaces(objDir, project.config.objDir.dir);
1216 //eSystem_Log("Printing Symbol Rules\n");
1219 char extension[MAX_EXTENSION];
1220 char modulePath[MAX_LOCATION];
1221 char moduleName[MAX_FILENAME];
1223 GetExtension(name, extension);
1224 if(!strcmpi(extension, "ec"))
1229 ReplaceSpaces(moduleName, name);
1230 StripExtension(moduleName);
1232 ReplaceSpaces(modulePath, path);
1233 if(modulePath[0]) strcat(modulePath, SEPS);
1236 // *** Dependency command ***
1237 sprintf(command, "gcc -MT $(OBJ)%s.o -MM %s%s.%s", moduleName,
1238 modulePath, moduleName, extension);
1240 // System Includes (from global settings)
1241 for(item : compiler.dirs[Includes])
1243 strcat(command, " -isystem ");
1244 if(strchr(item, ' '))
1246 strcat(command, "\"");
1247 strcat(command, item);
1248 strcat(command, "\"");
1251 strcat(command, item);
1254 for(item : project.includeDirs)
1256 strcat(command, " -I");
1257 if(strchr(item, ' '))
1259 strcat(command, "\"");
1260 strcat(command, item);
1261 strcat(command, "\"");
1264 strcat(command, item);
1266 for(item : project.preprocessorDefs)
1268 strcat(command, " -D");
1269 strcat(command, item);
1273 if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
1276 bool firstLine = true;
1279 // To do some time: auto save external dependencies?
1282 if(dep.GetLine(line, sizeof(line)-1))
1286 char * colon = strstr(line, ":");
1287 if(strstr(line, "No such file") || strstr(line, ",") || (colon && strstr(colon+1, ":")))
1301 // If we failed to generate dependencies...
1305 f.Printf("$(OBJ)%s.sym: %s%s.%s\n",
1306 moduleName, modulePath, moduleName, extension);
1312 f.Printf("\t$(ECP) %s%s.%s %s.sym\n\n",
1313 modulePath, moduleName, extension, moduleName);
1316 f.Printf("\t$(ECP) $(CECFLAGS)");
1320 f.Printf(" -memguard");
1321 if(strictNameSpaces)
1322 f.Printf(" -strictns");
1324 char * s = defaultNameSpace;
1326 f.Printf(" -defaultns %s", s);
1330 f.Printf(" $(ECFLAGS)");
1331 f.Printf(" $(CFLAGS)");
1332 GenFileFlags(f, project);
1333 f.Printf(" -c %s%s.%s -o $(OBJ)%s.sym\n\n",
1334 modulePath, moduleName, extension, moduleName);
1341 // TODO: Platform specific options
1342 if(child.type != resources && (child.type == folder || !child.isExcluded))
1343 child.GenMakefilePrintSymbolRules(f, project);
1349 void GenMakefilePrintCObjectRules(File f, Project project)
1351 //ProjectNode child;
1352 //char objDir[MAX_LOCATION];
1353 CompilerConfig compiler = GetCompilerConfig();
1354 //ReplaceSpaces(objDir, project.config.objDir.dir);
1355 //eSystem_Log("Printing C Object Rules\n");
1358 char extension[MAX_EXTENSION];
1359 char modulePath[MAX_LOCATION];
1360 char moduleName[MAX_FILENAME];
1362 GetExtension(name, extension);
1363 if(!strcmpi(extension, "ec"))
1368 ReplaceSpaces(moduleName, name);
1369 StripExtension(moduleName);
1371 ReplaceSpaces(modulePath, path);
1372 if(modulePath[0]) strcat(modulePath, SEPS);
1375 // *** Dependency command ***
1376 sprintf(command, "gcc -MT $(OBJ)%s.o -MM %s%s.%s",
1377 moduleName, modulePath, moduleName, extension);
1379 // System Includes (from global settings)
1380 for(item : compiler.dirs[Includes])
1382 strcat(command, " -isystem ");
1383 if(strchr(item, ' '))
1385 strcat(command, "\"");
1386 strcat(command, item);
1387 strcat(command, "\"");
1390 strcat(command, item);
1393 for(item : project.config.includeDirs)
1395 strcat(command, " -I");
1396 if(strchr(item, ' '))
1398 strcat(command, "\"");
1399 strcat(command, item);
1400 strcat(command, "\"");
1403 strcat(command, item);
1405 for(item : project.config.preprocessorDefs)
1407 strcat(command, " -D");
1408 strcat(command, item);
1412 if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
1416 bool firstLine = true;
1418 // To do some time: auto save external dependencies?
1421 if(dep.GetLine(line, sizeof(line)-1))
1425 char * colon = strstr(line, ":");
1426 if(strstr(line, "No such file") || strstr(line, ",") || (colon && strstr(colon+1, ":")))
1440 // If we failed to generate dependencies...
1443 /* COMMENTED OUT FOR NOW
1444 f.Printf("$(OBJ)%s.c: %s%s.%s $(Symbols)\n",
1445 moduleName, modulePath, moduleName, extension);
1448 f.Printf("$(OBJ)%s.c: %s%s.%s $(OBJ)%s.sym | $(SYMBOLS)\n",
1449 moduleName, modulePath, moduleName, extension, moduleName);
1455 f.Printf("\t$(ECC) %s%s.%s $(OBJ)%s.c\n\n",
1456 modulePath, moduleName, extension, moduleName);
1459 f.Printf("\t$(ECC)");
1462 f.Printf("%s $(CECFLAGS)", noLineNumbers ? " -nolinenumbers" : "");
1464 f.Printf(" -memguard");
1465 if(strictNameSpaces)
1466 f.Printf(" -strictns");
1468 char * s = defaultNameSpace;
1470 f.Printf(" -defaultns %s", s);
1474 f.Printf(" $(CECFLAGS) $(ECFLAGS)");
1475 f.Printf(" $(CFLAGS) $(FVISIBILITY)");
1476 GenFileFlags(f, project);
1477 f.Printf(" -c %s%s.%s -o $(OBJ)%s.c -symbols $(OBJ)\n\n",
1478 modulePath, moduleName, extension, moduleName);
1485 // TODO: Platform specific options
1486 if(child.type != resources && (child.type == folder || !child.isExcluded))
1487 child.GenMakefilePrintCObjectRules(f, project);
1493 void GenMakefilePrintObjectRules(File f, Project project, Map<String, NameCollisionInfo> namesInfo)
1495 //ProjectNode child;
1496 //char objDir[MAX_LOCATION];
1497 CompilerConfig compiler = GetCompilerConfig();
1498 //ReplaceSpaces(objDir, project.config.objDir.dir);
1499 //eSystem_Log("Printing Object Rules\n");
1503 char extension[MAX_EXTENSION];
1504 char modulePath[MAX_LOCATION];
1505 char moduleName[MAX_FILENAME];
1507 GetExtension(name, extension);
1508 /*if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1509 !strcmpi(extension, "ec") || !strcmpi(extension, "cc") ||
1510 !strcmpi(extension, "cxx"))*/
1511 if((!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
1512 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx")) ||
1513 !strcmpi(extension, "ec"))
1517 NameCollisionInfo info;
1519 ReplaceSpaces(moduleName, name);
1520 StripExtension(moduleName);
1522 info = namesInfo[moduleName];
1523 collision = info ? info.IsExtensionColliding(extension) : false;
1525 ReplaceSpaces(modulePath, path);
1526 if(modulePath[0]) strcat(modulePath, SEPS);
1528 // *** Dependency command ***
1529 if(!strcmpi(extension, "ec"))
1530 sprintf(command, "%s -MT $(OBJ)%s.o -MM $(OBJ)%s.c", compiler.ccCommand, moduleName, moduleName);
1532 sprintf(command, "%s -MT $(OBJ)%s.o -MM %s%s.%s", compiler.ccCommand, moduleName, modulePath, moduleName, extension);
1534 if(!strcmpi(extension, "ec"))
1535 f.Printf("$(OBJ)%s.o: $(OBJ)%s.c\n", moduleName, moduleName);
1539 // System Includes (from global settings)
1540 for(item : compiler.dirs[includes])
1542 strcat(command, " -isystem ");
1543 if(strchr(item, ' '))
1545 strcat(command, "\"");
1546 strcat(command, item);
1547 strcat(command, "\"");
1550 strcat(command, item);
1553 for(item : project.config.includeDirs)
1555 strcat(command, " -I");
1556 if(strchr(item, ' '))
1558 strcat(command, "\"");
1559 strcat(command, item);
1560 strcat(command, "\"");
1563 strcat(command, item);
1565 for(item : project.config.preprocessorDefs)
1567 strcat(command, " -D");
1568 strcat(command, item);
1572 if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
1575 bool firstLine = true;
1578 // To do some time: auto save external dependencies?
1582 if(dep.GetLine(line, sizeof(line)-1))
1586 char * colon = strstr(line, ":");
1587 if(strstr(line, "No such file") || strstr(line, ",") || (colon && strstr(colon+1, ":")))
1601 // If we failed to generate dependencies...
1605 /*if(!strcmpi(extension, "ec"))
1606 f.Printf("$(OBJ)%s.o: $(OBJ)%s.c\n", moduleName, moduleName);
1608 f.Printf("$(OBJ)%s%s%s.o: %s%s.%s\n", moduleName,
1609 collision ? "." : "", collision ? extension : "", modulePath, moduleName, extension);
1615 f.Printf("\t$(CC) $(CFLAGS)");
1616 GenFileFlags(f, project);
1617 if(!strcmpi(extension, "ec"))
1618 f.Printf(" $(FVISIBILITY) -c $(OBJ)%s.c -o $(OBJ)%s.o\n\n", moduleName, moduleName);
1620 f.Printf(" -c %s%s.%s -o $(OBJ)%s%s%s.o\n\n",
1621 modulePath, moduleName, !strcmpi(extension, "ec") ? "c" : extension, moduleName,
1622 collision ? "." : "", collision ? extension : "");
1629 // TODO: Platform specific options
1630 if(child.type != resources && (child.type == folder || !child.isExcluded))
1631 child.GenMakefilePrintObjectRules(f, project, namesInfo);
1637 void GenMakefileAddResources(File f, String resourcesPath)
1644 //Iterator<ProjectNode> i { files };
1645 //Iterator<ProjectNode> prev { files };
1646 //for(child : files)
1648 for(c = 0; c < files.count; c++)
1650 ProjectNode child = files[c];
1651 TwoStrings ts = child.platformSpecificExclusionFu;
1654 if(child.type == file && !child.isExcluded && !(count > 0 && ts))
1657 char tempPath[MAX_LOCATION];
1658 char resPath[MAX_LOCATION];
1662 // $(EAR) aw%s --- /*quiet ? "q" : */""
1664 f.Printf("\t%s$(EAR) aw $(TARGET)", ts.a);
1667 if(eString_PathInsideOfMore(child.path, resourcesPath, tempPath))
1670 PathCatSlash(tempPath, child.name);
1675 strcpy(tempPath, child.path);
1676 PathCatSlash(tempPath, child.name);
1678 ReplaceSpaces(resPath, tempPath);
1679 if(strchr(tempPath, ' '))
1683 f.Printf(" %s%s%s%s", quotes, useRes ? "$(RES)" : "", resPath, quotes);
1686 if(count == 10 || (count > 0 && (ts || !child.next)))
1688 char path[MAX_LOCATION] = "", temp[MAX_LOCATION];
1691 for(parent = this; parent.type == folder; parent = parent.parent)
1694 strcpy(path, parent.name);
1701 f.Printf(" \"%s\"%s\n", path, ts.b);
1713 if(child.type == folder)
1714 child.GenMakefileAddResources(f, resourcesPath);
1720 class NameCollisionInfo
1730 bool IsExtensionColliding(char * extension)
1733 if(count > 1 && ((!strcmpi(extension, "c") && ec) ||
1734 (!strcmpi(extension, "cpp") && (ec || c)) ||
1735 (!strcmpi(extension, "cc") && (ec || c || cpp)) ||
1736 (!strcmpi(extension, "cxx") && (ec || c || cpp || cc)) ||
1737 !strcmpi(extension, "m")))