cleaned all trailing white space from source files.
[sdk] / ide / src / project / ProjectNode.ec
old mode 100755 (executable)
new mode 100644 (file)
index 9e6bb29..cee70a6
@@ -14,6 +14,15 @@ static define app = ((GuiApplication)__thisModule);
 
 #define OPTION(x) ((uint)(&((ProjectOptions)0).x))
 
+static void OutputLog(char * string)
+{
+#ifdef MAKEFILE_GENERATOR
+   printf(string);
+#else
+   ide.outputView.buildBox.Log(string);
+#endif
+}
+
 bool eString_PathInsideOfMore(char * path, char * of, char * pathRest)
 {
    if(!path[0] || !of[0])
@@ -26,7 +35,7 @@ bool eString_PathInsideOfMore(char * path, char * of, char * pathRest)
       strcpy(pathRest, path);
       for(; ofRest[0] && pathRest[0];)
       {
-         SplitDirectory(ofRest, ofPart, ofRest);      
+         SplitDirectory(ofRest, ofPart, ofRest);
          SplitDirectory(pathRest, pathPart, pathRest);
          if(fstrcmp(pathPart, ofPart))
             return false;
@@ -43,8 +52,8 @@ enum NodeTypes { project, file, folder, resources, folderOpen };
 enum NodeIcons
 {
    genFile, ewsFile, epjFile, folder, openFolder, ecFile, ehFile,
-   cFile, hFile, cppFile, hppFile, textFile, webFile, pictureFile, soundFile,
-   archiveFile, packageFile, opticalMediaImageFile, mFile;
+   sFile, cFile, hFile, cppFile, hppFile, textFile, webFile, pictureFile, soundFile,
+   archiveFile, packageFile, opticalMediaImageFile, mFile, mmFile;
 
    NodeIcons ::SelectFileIcon(char * filePath)
    {
@@ -69,12 +78,16 @@ enum NodeIcons
             else if(!strcmpi(extension, "hpp") || !strcmpi(extension, "hh") ||
                   !strcmpi(extension, "hxx"))
                icon = hppFile;
+            else if(!strcmpi(extension, "s"))
+               icon = sFile;
             else if(!strcmpi(extension, "c"))
                icon = cFile;
             else if(!strcmpi(extension, "h"))
                icon = hFile;
             else if(!strcmpi(extension, "m"))
                icon = mFile;
+            else if(!strcmpi(extension, "mm"))
+               icon = mmFile;
             else if(!strcmpi(extension, "txt") || !strcmpi(extension, "text") ||
                   !strcmpi(extension, "nfo") || !strcmpi(extension, "info"))
                icon = textFile;
@@ -164,6 +177,57 @@ class TwoStrings : struct
    }
 }
 
+class DotMain : bool
+{
+   //property char * { set { } }
+   DotMain ::FromFileName(char * fileName)
+   {
+      DotMain dotMain = false;
+      if(fileName && fileName[0])
+      {
+         char ext[MAX_EXTENSION];
+         GetExtension(fileName, ext);
+         if(!strcmp(ext, "c") || !strcmp(ext, "ec"))
+         {
+            char stripExt[MAX_LOCATION];
+            strcpy(stripExt, fileName);
+            StripExtension(stripExt);
+            GetExtension(stripExt, ext);
+            if(!strcmp(ext, "main"))
+               dotMain = true;
+         }
+      }
+      return dotMain;
+   }
+}
+
+enum IntermediateFileType
+{
+   none, ec, c, sym, imp, bowl, o;
+
+   //property char * { set { } }
+   IntermediateFileType ::FromExtension(char * extension)
+   {
+      IntermediateFileType type = none;
+      if(extension && extension[0])
+      {
+         if(!fstrcmp(extension, "ec"))
+            type = ec;
+         else if(!fstrcmp(extension, "c"))
+            type = c;
+         else if(!fstrcmp(extension, "sym"))
+            type = sym;
+         else if(!fstrcmp(extension, "imp"))
+            type = imp;
+         else if(!fstrcmp(extension, "bowl"))
+            type = bowl;
+         else if(!fstrcmp(extension, "o"))
+            type = o;
+      }
+      return type;
+   }
+};
+
 class ProjectNode : ListItem
 {
 public:
@@ -372,17 +436,45 @@ private:
    // For folders, it includes the folder it refers to. If there is a name difference between the
    // file system folder and the grouping folder of the project view, it maps to that folder.
    char * path;
-   
+
    NodeTypes type;
    NodeIcons icon;
    int indent;
    DataRow row;
 
    bool modified;
-   
+
    // This is only set for Top Nodes
    Project project;
 
+   void OpenRulesPlatformExclusionIfs(File f, int * ifCount, Array<Platform> platforms)
+   {
+      if(!platforms.Find(unknown))  // unknown is "Common"
+      {
+         // e.g. ifneq "$(or $(or $(OSX_TARGET),$(LINUX_TARGET)),$(WINDOWS_TARGET))"
+         int i = 0;
+         f.Puts("ifneq \"");
+         for(i = 0; platforms.count && i < platforms.count - 1; i++)
+            f.Puts("$(or ");
+         i = 0;
+         for(p : platforms)
+         {
+            if(i > 0)
+               f.Puts(",");
+            f.Puts("$(");
+            f.Puts(PlatformToMakefileTargetVariable(p));
+            f.Puts(")");
+            if(i > 0)
+               f.Puts(")");
+            i++;
+         }
+         f.Puts("\" \"\"\n");
+         (*ifCount)++;
+      }
+      else
+         *ifCount = 0;
+   }
+
    ProjectConfig GetMatchingNodeConfig(ProjectConfig prjConfig)
    {
       ProjectConfig nodeConfig = null;
@@ -437,6 +529,52 @@ private:
       return buffer;
    }
 
+   char * GetObjectFileName(char * buffer, Map<String, NameCollisionInfo> namesInfo, IntermediateFileType type, bool dotMain)
+   {
+      if(buffer && (this.type == file || (this.type == project && dotMain == true)))
+      {
+         bool collision;
+         char extension[MAX_EXTENSION];
+         char moduleName[MAX_FILENAME];
+         NameCollisionInfo info;
+
+         GetExtension(name, extension);
+         ReplaceSpaces(moduleName, name);
+         StripExtension(moduleName);
+         info = namesInfo[moduleName];
+         collision = info ? info.IsExtensionColliding(extension) : false;
+
+         if(dotMain)
+         {
+            Project prj = property::project;
+            ReplaceSpaces(buffer, prj.moduleName);
+            StripExtension(buffer);
+            strcat(buffer, ".main.ec");
+         }
+         else
+            strcpy(buffer, name);
+         if(!strcmp(extension, "ec") || dotMain)
+         {
+            if(type == c)
+               ChangeExtension(buffer, "c", buffer);
+            else if(type == sym)
+               ChangeExtension(buffer, "sym", buffer);
+            else if(type == imp)
+               ChangeExtension(buffer, "imp", buffer);
+            else if(type == bowl)
+               ChangeExtension(buffer, "bowl", buffer);
+         }
+         if(type == o)
+         {
+            if(collision)
+               strcat(buffer, ".o");
+            else
+               ChangeExtension(buffer, "o", buffer);
+         }
+      }
+      return buffer;
+   }
+
    char * GetFileSysMatchingPath(char * buffer)
    {
       if(buffer)
@@ -506,7 +644,7 @@ private:
          while(n && n.type != project) n = n.parent;
          return n ? (*&n.project) : null;
       }
-   }   
+   }
 
    void RenameConfig(char * oldName, char * newName)
    {
@@ -537,7 +675,7 @@ private:
          {
             ProjectConfig config = c.data;
             if(!strcmp(configToDelete.name, config.name))
-            {               
+            {
                c.Remove();
                delete config;
                break;
@@ -804,7 +942,7 @@ private:
          result.b = exp;
       }
       delete exclusionInfo;
-      
+
       return result;
    }
 
@@ -852,7 +990,7 @@ private:
 
       if(options && options.excludeFromBuild)
          output[unknown] = options.excludeFromBuild;
-      
+
       if(config && config.options && config.options.excludeFromBuild)
          output[unknown] = config.options.excludeFromBuild;
 
@@ -941,6 +1079,17 @@ private:
 
    ProjectNode FindByFullPath(char * path, bool includeResources)
    {
+      if(files)
+      {
+         char name[MAX_FILENAME];
+         GetLastDirectory(path, name);
+         return InternalFindByFullPath(path, includeResources, name);
+      }
+      return null;
+   }
+
+   ProjectNode InternalFindByFullPath(char * path, bool includeResources, char * lastDirName)
+   {
       ProjectNode result = null;
       if(files)
       {
@@ -948,17 +1097,18 @@ private:
          {
             if(includeResources || child.type != resources)
             {
-               if(child.type != folder && child.name)
+               if(child.type != file)
+                  result = child.InternalFindByFullPath(path, includeResources, lastDirName);
+               else if(child.name && !fstrcmp(lastDirName, child.name))
                {
                   char p[MAX_LOCATION];
                   child.GetFullFilePath(p);
-                  if(!strcmpi(p, path))
+                  if(!fstrcmp(p, path))
                   {
                      result = child;
                      break;
                   }
                }
-               result = child.FindByFullPath(path, includeResources);
                if(result)
                   break;
             }
@@ -967,6 +1117,36 @@ private:
       return result;
    }
 
+   ProjectNode FindByObjectFileName(char * fileName, IntermediateFileType type, bool dotMain, Map<String, NameCollisionInfo> namesInfo)
+   {
+      char p[MAX_LOCATION];
+      ProjectNode result = null;
+      if(dotMain == true && this.type == project)
+      {
+         GetObjectFileName(p, namesInfo, type, dotMain);
+         if(!fstrcmp(p, fileName))
+            result = this;
+      }
+      else if(files)
+      {
+         for(child : files; child.type != resources)
+         {
+            if(child.type != file && (result = child.FindByObjectFileName(fileName, type, dotMain, namesInfo)))
+               break;
+            else if(child.type == file && child.name)
+            {
+               child.GetObjectFileName(p, namesInfo, type, dotMain);
+               if(!fstrcmp(p, fileName))
+               {
+                  result = child;
+                  break;
+               }
+            }
+         }
+      }
+      return result;
+   }
+
    ProjectNode FindSpecial(char * name, bool recursive, bool includeResources, bool includeFolders)
    {
       ProjectNode result = null;
@@ -1052,51 +1232,54 @@ private:
    ProjectNode Add(Project project, char * filePath, ProjectNode after, NodeTypes type, NodeIcons icon, bool checkIfExists)
    {
       ProjectNode node = null;
-      char temp[MAX_LOCATION];
-      Map<Platform, SetBool> exclusionInfo { };
-
-      GetLastDirectory(filePath, temp);
-      //if(!checkIfExists || !project.topNode.Find(temp, false))
-      
-      // TOCHECK: Shouldn't this apply either for all configs or none?
-      CollectExclusionInfo(exclusionInfo, project.config);
-      if(!checkIfExists || !project.topNode.FindSameNameConflict(temp, false, exclusionInfo, project.config))
+      if(!project.topNode.FindByFullPath(filePath, true))
       {
-         // Do the check for folder in the same parent or resource files only here
-         if(type == folder || !checkIfExists)
+         char temp[MAX_LOCATION];
+         Map<Platform, SetBool> exclusionInfo { };
+
+         GetLastDirectory(filePath, temp);
+         //if(!checkIfExists || !project.topNode.Find(temp, false))
+
+         // TOCHECK: Shouldn't this apply either for all configs or none?
+         CollectExclusionInfo(exclusionInfo, project.config);
+         if(!checkIfExists || type == folder || !project.topNode.FindSameNameConflict(temp, false, exclusionInfo, project.config))
          {
-            for(node : files)
+            // Do the check for folder in the same parent or resource files only here
+            if(type == folder || !checkIfExists)
             {
-               if(node.name && !strcmpi(node.name, temp))
-                  return null;
+               for(node : files)
+               {
+                  if(node.name && !strcmpi(node.name, temp))
+                     return null;
+               }
             }
-         }
 
-         node = ProjectNode { parent = this, indent = indent + 1, type = type, icon = icon, name = CopyString(temp) };
-         if(type != file)
-         {
-            node.files = { }; 
-            node.nodeType = folder;
-         }
-         if(type != folder)
-         {
-            if(filePath)
+            node = ProjectNode { parent = this, indent = indent + 1, type = type, icon = icon, name = CopyString(temp) };
+            if(type != file)
             {
-               StripLastDirectory(filePath, temp);
-               MakePathRelative(temp, project.topNode.path, temp);
-               node.path = CopyUnixPath(temp);
+               node.files = { };
+               node.nodeType = folder;
             }
-            node.nodeType = file;
-         }
-         else
-         {
-            strcpy(temp, (type == NodeTypes::project) ? "" : path);
-            PathCatSlash(temp, node.name);
-            node.path = CopyString(temp);
+            if(type != folder)
+            {
+               if(filePath)
+               {
+                  StripLastDirectory(filePath, temp);
+                  MakePathRelative(temp, project.topNode.path, temp);
+                  node.path = CopyUnixPath(temp);
+               }
+               node.nodeType = file;
+            }
+            else
+            {
+               strcpy(temp, (type == NodeTypes::project) ? "" : path);
+               PathCatSlash(temp, node.name);
+               node.path = CopyString(temp);
+            }
+            files.Insert(after, node);
          }
-         files.Insert(after, node);
+         delete exclusionInfo;
       }
-      delete exclusionInfo;
       return node;
    }
 
@@ -1115,8 +1298,8 @@ private:
       {
          showConfig = false;
          projectView = ide.projectView;
-      }         
-      
+      }
+
       bmp = projectView.icons[icon].bitmap;
       xStart = /*indent * indent + */x + (bmp ? (bmp.width + 5) : 0);
 
@@ -1159,7 +1342,7 @@ private:
          }
       }
       len = strlen(label);
-      
+
       if(!bmp)
       {
          if(type == folder || type == folderOpen)
@@ -1170,15 +1353,15 @@ private:
       surface.TextOpacity(false);
       surface.TextExtent(label, len, &w, &h);
       h = Max(h, 16);
-    
+
       // Draw the current row stipple
       if(displayFlags.selected)
          //surface.Area(xStart - 1, y, xStart - 1, y + h - 1);
          //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1);
          surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1);
-      
+
       surface.WriteTextDots(alignment, xStart, y + 2, width, label, len);
-      
+
       if(!app.textMode)
       {
          if(displayFlags.current)
@@ -1246,9 +1429,9 @@ private:
       {
          char extension[MAX_EXTENSION];
          GetExtension(name, extension);
-         if(!strcmpi(extension, "ec") || !strcmpi(extension, "c") ||
-               !strcmpi(extension, "cpp") || !strcmpi(extension, "cc") ||
-               !strcmpi(extension, "cxx") || !strcmpi(extension, "m"))
+         if(!strcmpi(extension, "ec") || !strcmpi(extension, "s") || !strcmpi(extension, "c") ||
+               !strcmpi(extension, "rc") || !strcmpi(extension, "cpp") || !strcmpi(extension, "cc") ||
+               !strcmpi(extension, "cxx") || !strcmpi(extension, "m") || !strcmpi(extension, "mm"))
          {
             char moduleName[MAX_FILENAME];
             NameCollisionInfo info;
@@ -1260,8 +1443,12 @@ private:
             info.count++; // += 1; unless this is for a bug?
             if(!strcmpi(extension, "ec"))
                info.ec = true;
+            else if(!strcmpi(extension, "s"))
+               info.s = true;
             else if(!strcmpi(extension, "c"))
                info.c = true;
+            else if(!strcmpi(extension, "rc"))
+               info.rc = true;
             else if(!strcmpi(extension, "cpp"))
                info.cpp = true;
             else if(!strcmpi(extension, "cc"))
@@ -1270,6 +1457,8 @@ private:
                info.cxx = true;
             else if(!strcmpi(extension, "m"))
                info.m = true;
+            else if(!strcmpi(extension, "mm"))
+               info.mm = true;
             namesInfo[moduleName] = info;
          }
       }
@@ -1282,7 +1471,7 @@ private:
          }
       }
    }
-   
+
    int GenMakefilePrintNode(File f, Project project, GenMakefilePrintTypes printType,
       Map<String, NameCollisionInfo> namesInfo, Array<String> items,
       ProjectConfig prjConfig, bool * containsCXX)
@@ -1313,20 +1502,19 @@ private:
                strcpy(tempPath, path);
                PathCatSlash(tempPath, name);
             }
-            ReplaceSpaces(modulePath, tempPath);
+            EscapeForMake(modulePath, tempPath, false, true, false);
             sprintf(s, "%s%s%s%s", ts.a, useRes ? "$(RES)" : "", modulePath, ts.b);
             items.Add(CopyString(s));
          }
          else if(printType == sources)
          {
-            if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
+            if(!strcmpi(extension, "s") || !strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
                   !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
-                  !strcmpi(extension, "m"))
+                  !strcmpi(extension, "m") || !strcmpi(extension, "mm"))
             {
                char modulePath[MAX_LOCATION];
-
-               ReplaceSpaces(modulePath, path);
-               ReplaceSpaces(moduleName, name);
+               EscapeForMake(modulePath, path, false, true, false);
+               EscapeForMake(moduleName, name, false, true, false);
                sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b);
                items.Add(CopyString(s));
             }
@@ -1336,24 +1524,35 @@ private:
             if(!strcmpi(extension, "ec"))
             {
                char modulePath[MAX_LOCATION];
-
-               ReplaceUnwantedMakeChars(modulePath, path);
-               ReplaceUnwantedMakeChars(moduleName, name);
+               EscapeForMake(modulePath, path, true, true, false);
+               EscapeForMake(moduleName, name, true, true, false);
+               sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b);
+               items.Add(CopyString(s));
+               count++;
+            }
+         }
+         else if(printType == rcSources)
+         {
+            if(!strcmpi(extension, "rc"))
+            {
+               char modulePath[MAX_LOCATION];
+               EscapeForMake(modulePath, path, false, true, false);
+               EscapeForMake(moduleName, name, false, true, false);
                sprintf(s, "%s%s%s%s%s", ts.a, modulePath, path[0] ? SEPS : "", moduleName, ts.b);
                items.Add(CopyString(s));
                count++;
             }
          }
-         else if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
+         else if(!strcmpi(extension, "s") || !strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
                !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
-               !strcmpi(extension, "m"))
+               !strcmpi(extension, "m") || !strcmpi(extension, "mm"))
          {
             if(printType == objects)
             {
                bool collision;
                NameCollisionInfo info;
                count++;
-               ReplaceSpaces(moduleName, name);
+               EscapeForMake(moduleName, name, false, true, false);
                StripExtension(moduleName);
                info = namesInfo[moduleName];
                collision = info ? info.IsExtensionColliding(extension) : false;
@@ -1377,11 +1576,11 @@ private:
    }
 
    void GenMakefilePrintSymbolRules(File f, Project project,
-         ProjectConfig prjConfig, Map<Platform, bool> parentExcludedPlatforms,
-         Map<int, int> nodeCFlagsMapping, Map<int, int> nodeECFlagsMapping)
+         ProjectConfig prjConfig, //Map<Platform, bool> parentExcludedPlatforms,
+         Map<intptr, int> nodeCFlagsMapping, Map<intptr, int> nodeECFlagsMapping)
    {
       int ifCount = 0;
-      Array<Platform> platforms = GetPlatformsArrayFromExcluisionInfo(prjConfig);
+      Array<Platform> platforms = GetPlatformsArrayFromExclusionInfo(prjConfig);
       //ProjectNode child;
       //char objDir[MAX_LOCATION];
       //ReplaceSpaces(objDir, config.objDir.dir);
@@ -1405,6 +1604,7 @@ private:
             ReplaceSpaces(modulePath, path);
             if(modulePath[0]) strcat(modulePath, SEPS);
 
+            OpenRulesPlatformExclusionIfs(f, &ifCount, platforms);
 #if 0
             // *** Dependency command ***
             sprintf(command, "gcc -MT $(OBJ)%s.o -MM %s%s.%s", moduleName,
@@ -1443,7 +1643,7 @@ private:
             }
 
             // Execute it
-            if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
+            if((dep = DualPipeOpen(PipeOpenMode { output = true, error = true/*, input = true*/ }, command)))
             {
                char line[1024];
                bool firstLine = true;
@@ -1475,28 +1675,25 @@ private:
                if(!result)
                {
 #endif
-               OpenRulesPlatformExclusionIfs(f, &ifCount, platforms[0], parentExcludedPlatforms, null);
                   f.Printf("$(OBJ)%s.sym: %s%s.%s\n",
                      moduleName, modulePath, moduleName, extension);
-#if 0
-               }
-            }
-#endif
-         /*
-            f.Printf("\t$(ECP) %s%s.%s %s.sym\n\n",
-               modulePath, moduleName, extension, moduleName);
-            */
 
-            f.Puts("\t$(ECP)");
+                  f.Puts("\t$(ECP)");
 
-            f.Puts(" $(CECFLAGS)"); // tocheck: what of this? should this stuff be per-file customized?
+                  f.Puts(" $(CFLAGS)");
+                  f.Puts(" $(CECFLAGS)"); // tocheck: what of this? should this stuff be per-file customized?
 
-            GenMakePrintNodeFlagsVariable(this, nodeECFlagsMapping, "ECFLAGS", f);
-            GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "CFLAGS", f);
+                  GenMakePrintNodeFlagsVariable(this, nodeECFlagsMapping, "ECFLAGS", f);
+                  GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "PRJ_CFLAGS", f);
 
-            f.Printf(" -c %s%s.%s -o $(OBJ)%s.sym\n\n",
-               modulePath, moduleName, extension, moduleName);
-            CloseRulesPlatformExclusionIfs(f, ifCount);
+                  f.Printf(" -c $(call quote_path,%s%s.%s) -o $(call quote_path,$@)\n",
+                     modulePath, moduleName, extension);
+                  if(ifCount) f.Puts("endif\n");
+                  f.Puts("\n");
+#if 0
+               }
+            }
+#endif
          }
       }
       if(files)
@@ -1515,32 +1712,24 @@ private:
          }
          if(needed)
          {
-            Map<Platform, bool> excludedPlatforms { };
-            for(mn : parentExcludedPlatforms) if(mn) excludedPlatforms[&mn] = true;
-            for(platform : platforms)
+            for(child : files)
             {
-               OpenRulesPlatformExclusionIfs(f, &ifCount, platform, parentExcludedPlatforms, excludedPlatforms);
-               for(child : files)
-               {
-                  if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
-                     child.GenMakefilePrintSymbolRules(f, project, prjConfig, excludedPlatforms,
-                           nodeCFlagsMapping, nodeECFlagsMapping);
-               }
+               if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
+                  child.GenMakefilePrintSymbolRules(f, project, prjConfig, /*excludedPlatforms,*/
+                        nodeCFlagsMapping, nodeECFlagsMapping);
             }
-            CloseRulesPlatformExclusionIfs(f, ifCount);
-            delete excludedPlatforms;
          }
       }
       delete platforms;
    }
 
    void GenMakefilePrintPrepecsRules(File f, Project project,
-         ProjectConfig prjConfig, Map<Platform, bool> parentExcludedPlatforms,
-         Map<int, int> nodeCFlagsMapping, Map<int, int> nodeECFlagsMapping)
+         ProjectConfig prjConfig, /*Map<Platform, bool> parentExcludedPlatforms,*/
+         Map<intptr, int> nodeCFlagsMapping, Map<intptr, int> nodeECFlagsMapping)
    {
       int ifCount = 0;
       ProjectConfig config = GetMatchingNodeConfig(prjConfig);
-      Array<Platform> platforms = GetPlatformsArrayFromExcluisionInfo(prjConfig);
+      Array<Platform> platforms = GetPlatformsArrayFromExclusionInfo(prjConfig);
       //ProjectNode child;
       //char objDir[MAX_LOCATION];
       //ReplaceSpaces(objDir, config.objDir.dir);
@@ -1564,22 +1753,23 @@ private:
             ReplaceSpaces(modulePath, path);
             if(modulePath[0]) strcat(modulePath, SEPS);
 
-            OpenRulesPlatformExclusionIfs(f, &ifCount, platforms[0], parentExcludedPlatforms, null);
+            OpenRulesPlatformExclusionIfs(f, &ifCount, platforms);
             f.Printf("$(OBJ)%s$(EC): %s%s.%s\n",
                moduleName, modulePath, moduleName, extension);
-            //$(CPP) -x c -E ../extras/gui/controls/DirectoriesBox.ec -o $(OBJ)DirectoriesBox$(EC)
             /*f.Printf("\t$(CPP) %s%s.%s %s$(S)\n\n",
                modulePath, moduleName, extension, moduleName);*/
 
             f.Puts("\t$(CPP)");
 
+            f.Puts(" $(CFLAGS)");
             //f.Puts(" $(CECFLAGS)");
             //GenMakePrintNodeFlagsVariable(this, nodeECFlagsMapping, "ECFLAGS", f);
-            GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "CFLAGS", f);
+            GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "PRJ_CFLAGS", f);
 
-            f.Printf(" -x c -E %s%s.%s -o $(OBJ)%s$(EC)\n\n",
+            f.Printf(" -x c -E %s%s.%s -o $(OBJ)%s$(EC)\n",
                modulePath, moduleName, extension, moduleName);
-            CloseRulesPlatformExclusionIfs(f, ifCount);
+            if(ifCount) f.Puts("endif\n");
+            f.Puts("\n");
          }
       }
       if(files)
@@ -1598,32 +1788,24 @@ private:
          }
          if(needed)
          {
-            Map<Platform, bool> excludedPlatforms { };
-            for(mn : parentExcludedPlatforms) if(mn) excludedPlatforms[&mn] = true;
-            for(platform : platforms)
+            for(child : files)
             {
-               OpenRulesPlatformExclusionIfs(f, &ifCount, platform, parentExcludedPlatforms, excludedPlatforms);
-               for(child : files)
-               {
-                  if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
-                     child.GenMakefilePrintPrepecsRules(f, project, prjConfig, excludedPlatforms,
-                           nodeCFlagsMapping, nodeECFlagsMapping);
-               }
+               if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
+                  child.GenMakefilePrintPrepecsRules(f, project, prjConfig, /*excludedPlatforms,*/
+                        nodeCFlagsMapping, nodeECFlagsMapping);
             }
-            CloseRulesPlatformExclusionIfs(f, ifCount);
-            delete excludedPlatforms;
          }
       }
       delete platforms;
    }
 
    void GenMakefilePrintCObjectRules(File f, Project project,
-      ProjectConfig prjConfig, Map<Platform, bool> parentExcludedPlatforms,
-      Map<int, int> nodeCFlagsMapping, Map<int, int> nodeECFlagsMapping)
+      ProjectConfig prjConfig, /*Map<Platform, bool> parentExcludedPlatforms,*/
+      Map<intptr, int> nodeCFlagsMapping, Map<intptr, int> nodeECFlagsMapping)
    {
       int ifCount = 0;
       ProjectConfig config = GetMatchingNodeConfig(prjConfig);
-      Array<Platform> platforms = GetPlatformsArrayFromExcluisionInfo(prjConfig);
+      Array<Platform> platforms = GetPlatformsArrayFromExclusionInfo(prjConfig);
       //ProjectNode child;
       //char objDir[MAX_LOCATION];
       //ReplaceSpaces(objDir, config.objDir.dir);
@@ -1646,6 +1828,7 @@ private:
             ReplaceSpaces(modulePath, path);
             if(modulePath[0]) strcat(modulePath, SEPS);
 
+            OpenRulesPlatformExclusionIfs(f, &ifCount, platforms);
 #if 0
             // *** Dependency command ***
             sprintf(command, "gcc -MT $(OBJ)%s.o -MM %s%s.%s",
@@ -1684,7 +1867,7 @@ private:
             }
 
             // Execute it
-            if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
+            if((dep = DualPipeOpen(PipeOpenMode { output = true, error = true/*, input = true*/ }, command)))
             {
                char line[1024];
                bool result = true;
@@ -1720,7 +1903,6 @@ private:
                      moduleName, modulePath, moduleName, extension);
                   */
 #endif
-            OpenRulesPlatformExclusionIfs(f, &ifCount, platforms[0], parentExcludedPlatforms, null);
                   f.Printf("$(OBJ)%s.c: %s%s.%s $(OBJ)%s.sym | $(SYMBOLS)\n",
                      moduleName, modulePath, moduleName, extension, moduleName);
 #if 0
@@ -1734,14 +1916,16 @@ private:
 
             f.Puts("\t$(ECC)");
 
+            f.Puts(" $(CFLAGS)");
             f.Puts(" $(CECFLAGS)"); // what of this? should this stuff be per-file customized?
             GenMakePrintNodeFlagsVariable(this, nodeECFlagsMapping, "ECFLAGS", f);
-            GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "CFLAGS", f);
+            GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "PRJ_CFLAGS", f);
             f.Puts(" $(FVISIBILITY)");
 
-            f.Printf(" -c %s%s.%s -o $(OBJ)%s.c -symbols $(OBJ)\n\n",
-               modulePath, moduleName, extension, moduleName);
-            CloseRulesPlatformExclusionIfs(f, ifCount);
+            f.Printf(" -c $(call quote_path,%s%s.%s) -o $(call quote_path,$@) -symbols $(OBJ)\n",
+               modulePath, moduleName, extension);
+            if(ifCount) f.Puts("endif\n");
+            f.Puts("\n");
          }
       }
       if(files)
@@ -1760,20 +1944,12 @@ private:
          }
          if(needed)
          {
-            Map<Platform, bool> excludedPlatforms { };
-            for(mn : parentExcludedPlatforms) if(mn) excludedPlatforms[&mn] = true;
-            for(platform : platforms)
+            for(child : files)
             {
-               OpenRulesPlatformExclusionIfs(f, &ifCount, platform, parentExcludedPlatforms, excludedPlatforms);
-               for(child : files)
-               {
-                  if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
-                     child.GenMakefilePrintCObjectRules(f, project, prjConfig, excludedPlatforms,
-                           nodeCFlagsMapping, nodeECFlagsMapping);
-               }
+               if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
+                  child.GenMakefilePrintCObjectRules(f, project, prjConfig, /*excludedPlatforms,*/
+                        nodeCFlagsMapping, nodeECFlagsMapping);
             }
-            CloseRulesPlatformExclusionIfs(f, ifCount);
-            delete excludedPlatforms;
          }
       }
       delete platforms;
@@ -1782,12 +1958,12 @@ private:
    void GenMakefilePrintObjectRules(File f, Project project,
       Map<String, NameCollisionInfo> namesInfo,
       ProjectConfig prjConfig,
-      Map<Platform, bool> parentExcludedPlatforms,
-      Map<int, int> nodeCFlagsMapping, Map<int, int> nodeECFlagsMapping)
+      //Map<Platform, bool> parentExcludedPlatforms,
+      Map<intptr, int> nodeCFlagsMapping, Map<intptr, int> nodeECFlagsMapping)
    {
       int ifCount = 0;
       ProjectConfig config = GetMatchingNodeConfig(prjConfig);
-      Array<Platform> platforms = GetPlatformsArrayFromExcluisionInfo(prjConfig);
+      Array<Platform> platforms = GetPlatformsArrayFromExclusionInfo(prjConfig);
       //ProjectNode child;
       //char objDir[MAX_LOCATION];
       //ReplaceSpaces(objDir, config.objDir.dir);
@@ -1800,12 +1976,9 @@ private:
          char moduleName[MAX_FILENAME];
 
          GetExtension(name, extension);
-         /*if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
-               !strcmpi(extension, "ec") || !strcmpi(extension, "cc") ||
-               !strcmpi(extension, "cxx"))*/
-         if(!strcmpi(extension, "c") || !strcmpi(extension, "cpp") ||
-               !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
-               !strcmpi(extension, "m") || !strcmpi(extension, "ec"))
+         if(!strcmpi(extension, "s") || !strcmpi(extension, "c") || !strcmpi(extension, "rc") ||
+               !strcmpi(extension, "cpp") || !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
+               !strcmpi(extension, "m") || !strcmpi(extension, "mm") || !strcmpi(extension, "ec"))
          {
             DualPipe dep;
             char command[2048];
@@ -1816,10 +1989,12 @@ private:
 
             info = namesInfo[moduleName];
             collision = info ? info.IsExtensionColliding(extension) : false;
-            
+
             ReplaceSpaces(modulePath, path);
             if(modulePath[0]) strcat(modulePath, SEPS);
 
+            /*
+#if 0
             // *** Dependency command ***
             if(!strcmpi(extension, "ec"))
                sprintf(command, "%s -MT $(OBJ)%s.o -MM $(OBJ)%s.c", "$(CPP)", moduleName, moduleName);
@@ -1828,10 +2003,11 @@ private:
                   moduleName, modulePath, moduleName, extension);
 
             if(!strcmpi(extension, "ec"))
+            {
                f.Printf("$(OBJ)%s.o: $(OBJ)%s.c\n", moduleName, moduleName);
+            }
             else
             {
-#if 0
                // System Includes (from global settings)
                for(item : compiler.dirs[includes])
                {
@@ -1865,7 +2041,7 @@ private:
                }
 
                // Execute it
-               if((dep = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
+               if((dep = DualPipeOpen(PipeOpenMode { output = true, error = true, input = false }, command)))
                {
                   char line[1024];
                   bool firstLine = true;
@@ -1897,30 +2073,45 @@ private:
                   // If we failed to generate dependencies...
                   if(!result)
                   {
-#endif
-            OpenRulesPlatformExclusionIfs(f, &ifCount, platforms[0], parentExcludedPlatforms, null);
 
-                     /*if(!strcmpi(extension, "ec"))
-                        f.Printf("$(OBJ)%s.o: $(OBJ)%s.c\n", moduleName, moduleName);
-                     else*/
-                        f.Printf("$(OBJ)%s%s%s.o: %s%s.%s\n", moduleName, 
-                              collision ? "." : "", collision ? extension : "", modulePath, moduleName, extension);
-#if 0
                   }
                }
+            }
 #endif
+         */
+            if(!strcmpi(extension, "rc"))
+            {
+               ifCount++;
+               f.Puts("ifdef WINDOWS_TARGET\n\n");
             }
-            f.Printf("\t$(%s)", (!strcmpi(extension, "cc") || !strcmpi(extension, "cpp") || !strcmpi(extension, "cxx")) ? "CXX" : "CC");
-
-            GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "CFLAGS", f);
+            else
+               OpenRulesPlatformExclusionIfs(f, &ifCount, platforms);
 
             if(!strcmpi(extension, "ec"))
-               f.Printf(" $(FVISIBILITY) -c $(OBJ)%s.c -o $(OBJ)%s.o\n\n", moduleName, moduleName);
+               f.Printf("$(OBJ)%s.o: $(OBJ)%s.c\n", moduleName, moduleName);
             else
-               f.Printf(" -c %s%s.%s -o $(OBJ)%s%s%s.o\n\n",
-                     modulePath, moduleName, !strcmpi(extension, "ec") ? "c" : extension, moduleName,
-                     collision ? "." : "", collision ? extension : "");
-            CloseRulesPlatformExclusionIfs(f, ifCount);
+               f.Printf("$(OBJ)%s%s%s.o: %s%s.%s\n", moduleName,
+                     collision ? "." : "", collision ? extension : "", modulePath, moduleName, extension);
+            if(!strcmpi(extension, "cc") || !strcmpi(extension, "cpp") || !strcmpi(extension, "cxx"))
+               f.Printf("\t$(CXX)");
+            else if(!strcmpi(extension, "rc"))
+               f.Printf("\t$(WINDRES) $(WINDRES_FLAGS) $< \"$(call escspace,$(call quote_path,$@))\"\n");
+            else
+               f.Printf("\t$(CC)");
+
+            if(strcmpi(extension, "rc") != 0)
+            {
+               f.Puts(" $(CFLAGS)");
+               GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "PRJ_CFLAGS", f);
+
+               if(!strcmpi(extension, "ec"))
+                  f.Printf(" $(FVISIBILITY) -c $(call quote_path,$(OBJ)%s.c) -o $(call quote_path,$@)\n", moduleName);
+               else
+                  f.Printf(" -c $(call quote_path,%s%s.%s) -o $(call quote_path,$@)\n",
+                        modulePath, moduleName, !strcmpi(extension, "ec") ? "c" : extension);
+            }
+            if(ifCount) f.Puts("endif\n");
+            f.Puts("\n");
          }
       }
       if(files)
@@ -1936,20 +2127,12 @@ private:
          }
          if(needed)
          {
-            Map<Platform, bool> excludedPlatforms { };
-            for(mn : parentExcludedPlatforms) if(mn) excludedPlatforms[&mn] = true;
-            for(platform : platforms)
+            for(child : files)
             {
-               OpenRulesPlatformExclusionIfs(f, &ifCount, platform, parentExcludedPlatforms, excludedPlatforms);
-               for(child : files)
-               {
-                  if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
-                     child.GenMakefilePrintObjectRules(f, project, namesInfo, prjConfig, excludedPlatforms,
-                           nodeCFlagsMapping, nodeECFlagsMapping);
-               }
+               if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
+                  child.GenMakefilePrintObjectRules(f, project, namesInfo, prjConfig, /*excludedPlatforms,*/
+                        nodeCFlagsMapping, nodeECFlagsMapping);
             }
-            CloseRulesPlatformExclusionIfs(f, ifCount);
-            delete excludedPlatforms;
          }
       }
       delete platforms;
@@ -1978,11 +2161,9 @@ private:
                char tempPath[MAX_LOCATION];
                char resPath[MAX_LOCATION];
 
-               char * quotes;
-
                // $(EAR) aw%s --- /*quiet ? "q" : */""
                if(count == 0)
-                  f.Printf("\t%s$(EAR) $(EARFLAGS) $(TARGET)", ts.a);
+                  f.Printf("\t%s$(EAR) aw$(EARFLAGS) $(TARGET)", ts.a);
 
                tempPath[0] = '\0';
                if(eString_PathInsideOfMore(child.path, resourcesPath, tempPath))
@@ -1996,12 +2177,8 @@ private:
                   strcpy(tempPath, child.path);
                   PathCatSlash(tempPath, child.name);
                }
-               ReplaceSpaces(resPath, tempPath);
-               if(strchr(tempPath, ' '))
-                  quotes = "\"";
-               else
-                  quotes = "";
-               f.Printf(" %s%s%s%s", quotes, useRes ? "$(RES)" : "", tempPath, quotes);
+               EscapeForMake(resPath, tempPath, false, true, false);
+               f.Printf(" %s%s", useRes ? "$(RES)" : "", resPath);
                count++;
             }
             if(count == 10 || (count > 0 && (ts || !child.next)))
@@ -2038,8 +2215,8 @@ private:
    }
 
    void GenMakeCollectAssignNodeFlags(ProjectConfig prjConfig, bool prjWithEcFiles,
-         Map<String, int> cflagsVariations, Map<int, int> nodeCFlagsMapping,
-         Map<String, int> ecflagsVariations, Map<int, int> nodeECFlagsMapping,
+         Map<String, int> cflagsVariations, Map<intptr, int> nodeCFlagsMapping,
+         Map<String, int> ecflagsVariations, Map<intptr, int> nodeECFlagsMapping,
          Map<Platform, ProjectOptions> parentByPlatformOptions)
    {
       Map<Platform, ProjectOptions> byPlatformOptions = parentByPlatformOptions;
@@ -2124,12 +2301,6 @@ private:
 
             if(!isEqual)
             {
-               if(!isGreater)
-               {
-                  // absolutely common stuff outside of platform only, stuff that can't be changed by platform
-                  cflags.concatf(" \\\n\t $(if $(DEBIAN_PACKAGE),$(CPPFLAGS),) $(if $(DEBUG), -D_DEBUG,)");
-               }
-
                for(platform = (Platform)1; platform < Platform::enumSize; platform++)
                {
                   byFileConfigPlatformProjectOptions = isGreater ? additionsByPlatformOptions[platform] : byPlatformOptions[platform];
@@ -2149,18 +2320,24 @@ private:
                s = { };
                GenCFlagsFromProjectOptions(platformsCommonOptions, prjWithEcFiles, true, isGreater, s);
                if(s.count > 1)
-                  cflags.concatf(isGreater ? "%s" : " \\\n\t%s", (String)s);
+               {
+                  if(!isGreater) cflags.concat(" \\\n\t");
+                  cflags.concat(s);
+               }
                delete s;
                s = { };
                GenECFlagsFromProjectOptions(platformsCommonOptions, prjWithEcFiles, s);
                if(s.count > 1)
-                  ecflags.concatf(" \\\n\t%s", (String)s);
+               {
+                  ecflags.concat(" \\\n\t");
+                  ecflags.concat(s);
+               }
                delete s;
 
                if(isGreater)
                {
-                  cflags.concatf(" \\\n\t");
-                  DynStringPrintNodeFlagsVariable(parent, nodeCFlagsMapping, "CFLAGS", cflags);
+                  cflags.concat(" \\\n\t");
+                  DynStringPrintNodeFlagsVariable(parent, nodeCFlagsMapping, "PRJ_CFLAGS", cflags);
                }
             }
 
@@ -2171,8 +2348,8 @@ private:
             {
                if(isEqual)
                {
-                  nodeCFlagsMapping[(int)this] = nodeCFlagsMapping[(int)parent];
-                  nodeECFlagsMapping[(int)this] = nodeECFlagsMapping[(int)parent];
+                  nodeCFlagsMapping[(intptr)this] = nodeCFlagsMapping[(intptr)parent];
+                  nodeECFlagsMapping[(intptr)this] = nodeECFlagsMapping[(intptr)parent];
                }
                else
                {
@@ -2182,12 +2359,12 @@ private:
                   variationNum = 1;
                   if((s = cflags) && s[0] && !(variationNum = cflagsVariations[s]))
                      cflagsVariations[s] = variationNum = cflagsVariations.count;
-                  nodeCFlagsMapping[(int)this] = variationNum;
+                  nodeCFlagsMapping[(intptr)this] = variationNum;
 
                   variationNum = 1;
                   if((s = ecflags) && s[0] && !(variationNum = ecflagsVariations[s]))
                      ecflagsVariations[s] = variationNum = ecflagsVariations.count;
-                  nodeECFlagsMapping[(int)this] = variationNum;
+                  nodeECFlagsMapping[(intptr)this] = variationNum;
                }
             }
 
@@ -2198,8 +2375,8 @@ private:
          {
             // output
             {
-               nodeCFlagsMapping[(int)this] = nodeCFlagsMapping[(int)parent];
-               nodeECFlagsMapping[(int)this] = nodeECFlagsMapping[(int)parent];
+               nodeCFlagsMapping[(intptr)this] = nodeCFlagsMapping[(intptr)parent];
+               nodeECFlagsMapping[(intptr)this] = nodeECFlagsMapping[(intptr)parent];
             }
          }
 
@@ -2222,19 +2399,204 @@ private:
       }
    }
 
-   Array<Platform> GetPlatformsArrayFromExcluisionInfo(ProjectConfig prjConfig)
+   Array<Platform> GetPlatformsArrayFromExclusionInfo(ProjectConfig prjConfig)
    {
       Array<Platform> platforms { };
       Map<Platform, SetBool> exclusionInfo { };
       CollectExclusionInfo(exclusionInfo, prjConfig);
-      if(exclusionInfo[unknown] == true && exclusionInfo.count > 1)
-         for(mn : exclusionInfo; mn == false)
-            platforms.Add(&mn);
+
+      if(exclusionInfo[unknown] == true)
+      {
+         if(exclusionInfo.count > 1)
+            for(p : exclusionInfo; p == false)
+               platforms.Add(&p);
+      }
       else
-         platforms.Add(unknown);
+      {
+         bool onlyOnknown = true;
+         for(p : exclusionInfo)
+            if(&p != unknown && p == true)
+            {
+               onlyOnknown = false;
+               break;
+            }
+         if(onlyOnknown)
+            platforms.Add(unknown);
+         else
+         {
+            Platform p;
+            for(p = unknown + 1; p < Platform::enumSize; p++)
+               if(exclusionInfo[p] != true)
+                  platforms.Add(p);
+         }
+      }
       delete exclusionInfo;
       return platforms;
    }
+
+   void GetTargets(ProjectConfig prjConfig, Map<String, NameCollisionInfo> namesInfo, char * objDir, DynamicString output)
+   {
+      char moduleName[MAX_FILENAME];
+      if(type == file)
+      {
+         bool headerAltFailed = false;
+         bool collision;
+         char extension[MAX_EXTENSION];
+         NameCollisionInfo info;
+         Project prj = property::project;
+         Map<String, String> headerToSource { [ { "eh", "ec" }, { "h", "c" }, { "hh", "cc" }, { "hpp", "cpp" }, { "hxx", "cxx" } ] };
+
+         GetExtension(name, extension);
+         strcpy(moduleName, name);
+         StripExtension(moduleName);
+         info = namesInfo[moduleName];
+         collision = info ? info.IsExtensionColliding(extension) : false;
+
+         for(h2s : headerToSource)
+         {
+            if(!strcmpi(extension, &h2s))
+            {
+               char filePath[MAX_LOCATION];
+               GetFullFilePath(filePath);
+               OutputLog($"No compilation required for header file "); OutputLog(filePath); OutputLog("\n");
+               ChangeExtension(moduleName, h2s, moduleName);
+               if(prj.topNode.Find(moduleName, false))
+               {
+                  strcpy(extension, h2s);
+                  collision = info ? info.IsExtensionColliding(extension) : false;
+                  ChangeExtension(filePath, h2s, filePath);
+                  OutputLog($"Compiling source file "); OutputLog(filePath); OutputLog($" instead\n");
+                  StripExtension(moduleName);
+               }
+               else
+               {
+                  headerAltFailed = true;
+                  OutputLog($"Unable to locate source file "); OutputLog(moduleName); OutputLog($" to compile instead of "); OutputLog(filePath); OutputLog($"\n");
+                  StripExtension(moduleName);
+               }
+               break;
+            }
+         }
+
+         if(!headerAltFailed)
+         {
+            output.concat(" \"");
+            output.concat(objDir); //.concat(" $(OBJ)");
+            output.concat("/");
+
+            if(collision)
+            {
+               strcat(moduleName, ".");
+               strcat(moduleName, extension);
+            }
+            strcat(moduleName, ".o");
+            output.concat(moduleName);
+            output.concat("\"");
+         }
+      }
+      else if(type == project && ContainsFilesWithExtension("ec"))
+      {
+         Project prj = property::project;
+
+         ReplaceSpaces(moduleName, prj.moduleName);
+         strcat(moduleName, ".main.ec");
+         output.concat(" \"");
+         output.concat(objDir);
+         output.concat("/");
+         output.concat(moduleName);
+         output.concat("\"");
+
+         ChangeExtension(moduleName, "c", moduleName);
+         output.concat(" \"");
+         output.concat(objDir);
+         output.concat("/");
+         output.concat(moduleName);
+         output.concat("\"");
+
+         ChangeExtension(moduleName, "o", moduleName);
+         output.concat(" \"");
+         output.concat(objDir);
+         output.concat("/");
+         output.concat(moduleName);
+         output.concat("\"");
+      }
+      else if(files)
+      {
+         for(child : files)
+         {
+            if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
+               child.GetTargets(prjConfig, namesInfo, objDir, output);
+         }
+      }
+   }
+
+   void DeleteIntermediateFiles(CompilerConfig compiler, ProjectConfig prjConfig, int bitDepth, Map<String, NameCollisionInfo> namesInfo, bool onlyCObject)
+   {
+      if(type == file)
+      {
+         bool collision;
+         char extension[MAX_EXTENSION];
+         char fileName[MAX_FILENAME];
+         char moduleName[MAX_FILENAME];
+         NameCollisionInfo info;
+         Project prj = property::project;
+         DirExpression objDir = prj.GetObjDir(compiler, prjConfig, bitDepth);
+
+         GetExtension(name, extension);
+         ReplaceSpaces(moduleName, name);
+         StripExtension(moduleName);
+         info = namesInfo[moduleName];
+         collision = info ? info.IsExtensionColliding(extension) : false;
+
+         strcpy(fileName, prj.topNode.path);
+         PathCatSlash(fileName, objDir.dir);
+         PathCatSlash(fileName, name);
+
+         if(!onlyCObject && !strcmp(extension, "ec"))
+         {
+            ChangeExtension(fileName, "c", fileName);
+            if(FileExists(fileName)) DeleteFile(fileName);
+            ChangeExtension(fileName, "sym", fileName);
+            if(FileExists(fileName)) DeleteFile(fileName);
+            ChangeExtension(fileName, "imp", fileName);
+            if(FileExists(fileName)) DeleteFile(fileName);
+            ChangeExtension(fileName, "bowl", fileName);
+            if(FileExists(fileName)) DeleteFile(fileName);
+            ChangeExtension(fileName, "ec", fileName);
+         }
+
+         if(collision)
+            strcat(fileName, ".o");
+         else
+            ChangeExtension(fileName, "o", fileName);
+         if(FileExists(fileName)) DeleteFile(fileName);
+
+         delete objDir;
+      }
+      else if(files)
+      {
+         for(child : files)
+         {
+            if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
+               child.DeleteIntermediateFiles(compiler, prjConfig, bitDepth, namesInfo, onlyCObject);
+         }
+      }
+   }
+
+   bool IsInNode(ProjectNode node)
+   {
+      bool result = false;
+      ProjectNode n;
+      for(n = this; n; n = n.parent)
+      {
+         if(n == node)
+         {
+            result = true;
+            break;
+         }
+      }
+      return result;
+   }
 }
 
 // the code in this function is closely matched to OptionsBox::Load
@@ -2258,9 +2620,10 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
    ProjectNode n;
    char * platformName = platform ? platform.OnGetString(0,0,0) : null;
 
-   Array<bool> optionConfigXplatformSet   { size = OPTION(postbuildCommands) };
-   Array<bool> optionDone                 { size = OPTION(postbuildCommands) };
-   Array<Array<String>> optionTempStrings { size = OPTION(postbuildCommands) };
+   // OPTION(ProjectOptions' last member) for size
+   Array<bool> optionConfigXplatformSet   { size = OPTION(installCommands) };
+   Array<bool> optionDone                 { size = OPTION(installCommands) };
+   Array<Array<String>> optionTempStrings { size = OPTION(installCommands) };
 
    GenericOptionTools<SetBool>              utilSetBool {
       bool OptionCheck(ProjectOptions options, int option) {
@@ -2283,8 +2646,8 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
       mergeValues = true;
       caseSensitive = true;
       bool OptionCheck(ProjectOptions options, int option) {
-         String string = *(String*)((byte *)options + option);
-         return string && string[0];
+         Array<String> strings = *(Array<String>*)((byte *)options + option);
+         return strings && strings.count;
       }
       bool OptionSet(ProjectOptions options, int option) {
          Array<String> strings = *(Array<String>*)((byte *)options + option);
@@ -2309,7 +2672,7 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
                   char priorityMark[10];
                   order++;
                   if(priority)
-                     sprintf(priorityMark, "%04d\n", priority * 100 + order);
+                     sprintf(priorityMark, "%06d\n", priority * 1000 + order);
                   for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
                   if(!found) tempStrings.Add(priority ? PrintString(priorityMark, s) : CopyString(s));
                }
@@ -2354,16 +2717,6 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
          *(OptimizationStrategy*)((byte *)output + option) = value;
       }
    };
-   GenericOptionTools<BuildBitDepth>        utilBuildBitDepth {
-      bool OptionCheck(ProjectOptions options, int option) {
-         BuildBitDepth value = *(BuildBitDepth*)((byte *)options + option);
-         return value && value != all;
-      }
-      void LoadOption(ProjectOptions options, int option, int priority, Array<Array<String>> optionTempStrings, ProjectOptions output) {
-         BuildBitDepth value = options ? *(BuildBitDepth*)((byte *)options + option) : (BuildBitDepth)0;
-         *(BuildBitDepth*)((byte *)output + option) = value;
-      }
-   };
 
    Map<int, GenericOptionTools> ot { };
 
@@ -2385,15 +2738,13 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
 
    ot[OPTION(optimization)] =            utilOptimizationStrategy;
 
-   ot[OPTION(buildBitDepth)] =           utilBuildBitDepth;
-
    for(n = node; n; n = n.parent)
    {
       ProjectConfig nodeConfig = null;
       if(n.parent)
-         priority++;
+         priority = (priority / 10 + 1) * 10;
       else
-         priority = 99;
+         priority = 9990;
       if(projectConfig && n.configurations)
       {
          for(c : n.configurations; !strcmpi(c.name, projectConfig.name))
@@ -2432,7 +2783,7 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
                {
                   if(p.options && (u.mergeValues ? u.OptionCheck(p.options, o) : u.OptionSet(p.options, o)))
                   {
-                     u.LoadOption(p.options, o, o == includeDirsOption ? priority : 0, optionTempStrings, output);
+                     u.LoadOption(p.options, o, o == includeDirsOption ? priority + 1 : 0, optionTempStrings, output);
                      if(!u.mergeValues) { u.FinalizeLoading(o, optionTempStrings, output); optionDone[o] = true; }
                   }
                   break;
@@ -2450,12 +2801,12 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
             {
                if(n.options && (u.mergeValues ? u.OptionCheck(n.options, o) : u.OptionSet(n.options, o)))
                {
-                  u.LoadOption(n.options, o, o == includeDirsOption ? priority : 0, optionTempStrings, output);
+                  u.LoadOption(n.options, o, o == includeDirsOption ? priority + 1 : 0, optionTempStrings, output);
                   if(!u.mergeValues) { u.FinalizeLoading(o, optionTempStrings, output); optionDone[o] = true; }
                }
                else if(!n.parent)
                {
-                  u.LoadOption(null, o, o == includeDirsOption ? priority : 0, optionTempStrings, output);
+                  u.LoadOption(null, o, o == includeDirsOption ? priority + 1 : 0, optionTempStrings, output);
                   if(!u.mergeValues) { u.FinalizeLoading(o, optionTempStrings, output); optionDone[o] = true; }
                }
             }
@@ -2479,7 +2830,6 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
    delete utilStringArrays;
    delete utilWarningsOption;
    delete utilOptimizationStrategy;
-   delete utilBuildBitDepth;
 
    delete ot;
 
@@ -2528,8 +2878,6 @@ static void CollectPlatformsCommonOptions(Map<Platform, ProjectOptions> byPlatfo
             commonOptions.warnings = unset;
          if(commonOptions.optimization && options.optimization != commonOptions.optimization)
             commonOptions.optimization = unset;
-         if(commonOptions.buildBitDepth && options.buildBitDepth != commonOptions.buildBitDepth)
-            commonOptions.buildBitDepth = all;
 
          if(commonOptions.defaultNameSpace && strcmp(options.defaultNameSpace, commonOptions.defaultNameSpace))
             delete commonOptions.defaultNameSpace;
@@ -2563,8 +2911,6 @@ static void CollectPlatformsCommonOptions(Map<Platform, ProjectOptions> byPlatfo
          options.warnings = unset;
       if(options.optimization && options.optimization == commonOptions.optimization)
          options.optimization = unset;
-      if(options.buildBitDepth && options.buildBitDepth == commonOptions.buildBitDepth)
-         options.buildBitDepth = all;
 
       if(options.defaultNameSpace && !strcmp(options.defaultNameSpace, commonOptions.defaultNameSpace))
          delete options.defaultNameSpace;
@@ -2730,20 +3076,20 @@ static void RemovePlatformsCommonStrings(Map<String, bool> common, Array<String>
    }
 }
 
-static void GenMakePrintNodeFlagsVariable(ProjectNode node, Map<int, int> nodeFlagsMapping, String variableName, File f)
+static void GenMakePrintNodeFlagsVariable(ProjectNode node, Map<intptr, int> nodeFlagsMapping, String variableName, File f)
 {
    int customFlags;
-   customFlags = nodeFlagsMapping[(int)node];
+   customFlags = nodeFlagsMapping[(intptr)node];
    if(customFlags > 1)
       f.Printf(" $(CUSTOM%d_%s)", customFlags-1, variableName);
    else
       f.Printf(" $(%s)", variableName);
 }
 
-static void DynStringPrintNodeFlagsVariable(ProjectNode node, Map<int, int> nodeFlagsMapping, String variableName, DynamicString s)
+static void DynStringPrintNodeFlagsVariable(ProjectNode node, Map<intptr, int> nodeFlagsMapping, String variableName, DynamicString s)
 {
    int customFlags;
-   customFlags = nodeFlagsMapping[(int)node];
+   customFlags = nodeFlagsMapping[(intptr)node];
    if(customFlags > 1)
       s.concatf(" $(CUSTOM%d_%s)", customFlags-1, variableName);
    else
@@ -2761,42 +3107,42 @@ static void GenCFlagsFromProjectOptions(ProjectOptions options, bool prjWithEcFi
          {
             if(options.debug != true)
             {
-               s.concatf(" $(if $(DEBUG),");
-               s.concatf(" -g");
-               s.concatf(",");
+               s.concat(" $(if $(DEBUG),");
+               s.concat(" -g");
+               s.concat(",");
             }
             switch(options.optimization)
             {
-               case speed: s.concatf(" -O2"); break;
-               case size: s.concatf(" -Os"); break;
+               case speed: s.concat(" -O2"); break;
+               case size: s.concat(" -Os"); break;
             }
             if(options.fastMath == true)
-               s.concatf(" -ffast-math");
+               s.concat(" -ffast-math");
             if(options.debug == true)
-               s.concatf(" -g");
+               s.concat(" -g");
             if(options.debug != true)
-               s.concatf(")");
+               s.concat(")");
          }
          else if(commonOptions)
-            s.concatf(" $(if $(DEBUG),-g)");
-         if(options.buildBitDepth || (commonOptions && prjWithEcFiles))
-            s.concatf(" %s", (!options || !options.buildBitDepth || options.buildBitDepth == bits32) ? "$(FORCE_32_BIT)" : "$(FORCE_64_BIT)");
+            s.concat(" $(if $(DEBUG),-g)");
          if(commonOptions)
-            s.concatf(" $(FPIC)");
+            s.concat(" $(FPIC)");
       }
       switch(options.warnings)
       {
-         case all: s.concatf(" -Wall"); break;
-         case none: s.concatf(" -w"); break;
+         case all: s.concat(" -Wall"); break;
+         case none: s.concat(" -w"); break;
       }
       if(options.profile)
-         s.concatf(" -pg");
+         s.concat(" -pg");
+      if(commonOptions)
+         s.concat(" -DREPOSITORY_VERSION=\"\\\"$(REPOSITORY_VER)\\\"\"");
    }
 
    if(options && options.preprocessorDefinitions)
-      ListOptionToDynamicString("D", options.preprocessorDefinitions, false, lineEach, "\t\t\t", false, s);
+      ListOptionToDynamicString(s, _D, options.preprocessorDefinitions, false, lineEach, "\t\t\t");
    if(options && options.includeDirs)
-      ListOptionToDynamicString("I", options.includeDirs, true, lineEach, "\t\t\t", true, s);
+      ListOptionToDynamicString(s, _I, options.includeDirs, true, lineEach, "\t\t\t");
 }
 
 static void GenECFlagsFromProjectOptions(ProjectOptions options, bool prjWithEcFiles, DynamicString s)
@@ -2811,13 +3157,16 @@ static void GenECFlagsFromProjectOptions(ProjectOptions options, bool prjWithEcF
       s.concatf(" -defaultns %s", options.defaultNameSpace);
 }
 
-static void ListOptionToDynamicString(char * option, Array<String> list, bool prioritize,
-      ListOutputMethod method, String newLineStart, bool noSpace, DynamicString s)
+static void ListOptionToDynamicString(DynamicString output, ToolchainFlag flag, Array<String> list, bool prioritize,
+      LineOutputMethod lineMethod, String newLineStart)
 {
    if(list.count)
    {
-      if(method == newLine)
-         s.concatf(" \\\n%s", newLineStart);
+      if(lineMethod == newLine)
+      {
+         output.concat(" \\\n");
+         output.concat(newLineStart);
+      }
       if(prioritize)
       {
          Map<String, int> sortedList { };
@@ -2827,13 +3176,14 @@ static void ListOptionToDynamicString(char * option, Array<String> list, bool pr
          for(mn = sortedList.root.minimum; mn; mn = mn.next)
          {
             char * start = strstr(mn.key, "\n");
-            if(method == lineEach)
-               s.concatf(" \\\n%s", newLineStart);
-            s.concatf(" -%s", option);
-            if(noSpace)
-               StringNoSpaceToDynamicString(s, start ? start+1 : mn.key);
-            else
-               s.concat(start ? start+1 : mn.key);
+            if(lineMethod == lineEach)
+            {
+               output.concat(" \\\n");
+               output.concat(newLineStart);
+            }
+            output.concat(" ");
+            output.concat(flagNames[flag]);
+            EscapeForMakeToDynString(output, start ? start+1 : mn.key, false, true, flag == _D);
          }
          delete sortedList;
       }
@@ -2841,13 +3191,14 @@ static void ListOptionToDynamicString(char * option, Array<String> list, bool pr
       {
          for(item : list)
          {
-            if(method == lineEach)
-               s.concatf(" \\\n%s", newLineStart);
-            s.concatf(" -%s", option);
-            if(noSpace)
-               StringNoSpaceToDynamicString(s, item);
-            else
-               s.concat(item);
+            if(lineMethod == lineEach)
+            {
+               output.concat(" \\\n");
+               output.concat(newLineStart);
+            }
+            output.concat(" ");
+            output.concat(flagNames[flag]);
+            EscapeForMakeToDynString(output, item, false, true, flag == _D);
          }
       }
    }
@@ -2881,49 +3232,31 @@ class StringArrayOptionTools : GenericOptionTools<Array<String>>
 class NameCollisionInfo
 {
    bool ec;
+   bool s;
    bool c;
+   bool rc;
    bool cpp;
    bool cc;
    bool cxx;
    bool m;
+   bool mm;
    byte count;
 
    bool IsExtensionColliding(char * extension)
    {
       bool colliding;
-      if(count > 1 && ((!strcmpi(extension, "c") && ec) ||
-            (!strcmpi(extension, "cpp") && (ec || c)) ||
-            (!strcmpi(extension, "cc") && (ec || c || cpp)) ||
-            (!strcmpi(extension, "cxx") && (ec || c || cpp || cc)) ||
-            !strcmpi(extension, "m")))
+      if(count > 1 &&
+            ((!strcmpi(extension, "c")   && ec) ||
+             (!strcmpi(extension, "rc")  && (ec || c)) ||
+             (!strcmpi(extension, "s")   && (ec || c || rc)) ||
+             (!strcmpi(extension, "cpp") && (ec || c || rc || s)) ||
+             (!strcmpi(extension, "cc")  && (ec || c || rc || s || cpp)) ||
+             (!strcmpi(extension, "cxx") && (ec || c || rc || s || cpp || cc)) ||
+             (!strcmpi(extension, "m")   && (ec || c || rc || s || cpp || cc || m)) ||
+              !strcmpi(extension, "mm")))
          colliding = true;
       else
          colliding = false;
      return colliding;
    }
 }
-
-static inline void OpenRulesPlatformExclusionIfs(File f, int * ifCount, Platform platform,
-      Map<Platform, bool> parentExcludedPlatforms, Map<Platform, bool> excludedPlatforms)
-{
-   if(platform != unknown && !parentExcludedPlatforms[platform])
-   {
-      if(*ifCount)             // we really need a if defined(a) || defined(b) here
-         f.Puts("else\n");     // instead of repeating the rules for each platform
-      (*ifCount)++;            // hmm... what?
-      f.Printf("ifdef %s\n\n", PlatformToMakefileTargetVariable(platform));
-      if(excludedPlatforms)
-         excludedPlatforms[platform] = true;
-   }
-}
-
-static inline void CloseRulesPlatformExclusionIfs(File f, int ifCount)
-{
-   if(ifCount)
-   {
-      int c;
-      for(c = 0; c < ifCount; c++)
-         f.Puts("endif\n");
-      f.Puts("\n");
-   }
-}