ear/extract; extras; samples: Fixes
[sdk] / ide / src / project / ProjectNode.ec
index ffc3606..9bd4e49 100644 (file)
@@ -12,18 +12,18 @@ import "Project"
 static define app = ((GuiApplication)__thisModule);
 #endif
 
-#define OPTION(x) ((uint)(&((ProjectOptions)0).x))
+#define OPTION(x) ((uint)(uintptr)(&((ProjectOptions)0).x))
 
-static void OutputLog(char * string)
+static void OutputLog(const char * string)
 {
 #ifdef MAKEFILE_GENERATOR
-   printf(string);
+   printf("%s", string);
 #else
    ide.outputView.buildBox.Log(string);
 #endif
 }
 
-bool eString_PathInsideOfMore(char * path, char * of, char * pathRest)
+bool eString_PathInsideOfMore(const char * path, const char * of, char * pathRest)
 {
    if(!path[0] || !of[0])
       return false;  // What to do here? Ever used?
@@ -35,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;
@@ -55,7 +55,7 @@ enum NodeIcons
    sFile, cFile, hFile, cppFile, hppFile, textFile, webFile, pictureFile, soundFile,
    archiveFile, packageFile, opticalMediaImageFile, mFile, mmFile;
 
-   NodeIcons ::SelectFileIcon(char * filePath)
+   NodeIcons ::SelectFileIcon(const char * filePath)
    {
       NodeIcons icon;
       if(filePath && filePath[0])
@@ -177,7 +177,56 @@ class TwoStrings : struct
    }
 }
 
-enum IntermediateFileType { none, ec, c, sym, imp, bowl, o };
+class DotMain : bool
+{
+   //property char * { set { } }
+   DotMain ::FromFileName(const 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
 {
@@ -225,7 +274,7 @@ public:
       }
       isset { return nodeType == folder; }
    };
-   property String fileName
+   property const String fileName
    {
       set
       {
@@ -387,14 +436,14 @@ 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;
 
@@ -450,7 +499,7 @@ private:
    {
       get
       {
-         bool result;
+         bool result = false;
          if(files)
          {
             for(child : files)
@@ -497,7 +546,8 @@ private:
 
          if(dotMain)
          {
-            ReplaceSpaces(buffer, project.moduleName);
+            Project prj = property::project;
+            ReplaceSpaces(buffer, prj.moduleName);
             StripExtension(buffer);
             strcat(buffer, ".main.ec");
          }
@@ -558,7 +608,6 @@ private:
       // TODO: Check how to fix duplication of following options when configuration is made per-config-per-file
       while((node = nodeStack.lastIterator.data))
       {
-         ProjectConfig config = GetMatchingNodeConfig(prjConfig);
          ProjectOptions nodeOptions = node.property::options;
          if(nodeOptions && nodeOptions.preprocessorDefinitions)
          {
@@ -594,9 +643,9 @@ private:
          while(n && n.type != project) n = n.parent;
          return n ? (*&n.project) : null;
       }
-   }   
+   }
 
-   void RenameConfig(char * oldName, char * newName)
+   void RenameConfig(const char * oldName, const char * newName)
    {
       if(files)
       {
@@ -625,7 +674,7 @@ private:
          {
             ProjectConfig config = c.data;
             if(!strcmp(configToDelete.name, config.name))
-            {               
+            {
                c.Remove();
                delete config;
                break;
@@ -744,7 +793,7 @@ private:
       }
    }
 
-   char * OnGetString(char * tempString, void * fieldData, bool * needClass)
+   const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
    {
       if(!needClass)
       {
@@ -811,7 +860,8 @@ private:
       // note: unknown platform is for common
       Map<Platform, SetBool> exclusionInfo { };
       MapNode<Platform, SetBool> mn;
-      char * exp, * var;
+      char * exp;
+      const char * var;
       int len;
       SetBool common;
 
@@ -843,7 +893,7 @@ private:
             {
                if(mn.key != unknown)
                {
-                  char * comma = mn.next ? "," : "";
+                  const char * comma = mn.next ? "," : "";
 
                   var = PlatformToMakefileTargetVariable(mn.key);
 
@@ -892,7 +942,7 @@ private:
          result.b = exp;
       }
       delete exclusionInfo;
-      
+
       return result;
    }
 
@@ -931,7 +981,6 @@ private:
       ProjectConfig config = GetMatchingNodeConfig(prjConfig);
       ProjectOptions options = property::options;
       Array<PlatformOptions> platforms = property::platforms;
-      List<ProjectConfig> configurations = property::configurations;
 
       if(parent)
          parent.CollectExclusionInfo(output, prjConfig);
@@ -940,7 +989,7 @@ private:
 
       if(options && options.excludeFromBuild)
          output[unknown] = options.excludeFromBuild;
-      
+
       if(config && config.options && config.options.excludeFromBuild)
          output[unknown] = config.options.excludeFromBuild;
 
@@ -975,7 +1024,7 @@ private:
          parent.files.Delete(this);
    }
 
-   ProjectNode Find(char * name, bool includeResources)
+   ProjectNode Find(const char * name, bool includeResources)
    {
       ProjectNode result = null;
       if(files)
@@ -998,7 +1047,7 @@ private:
       return result;
    }
 
-   ProjectNode FindWithPath(char * name, bool includeResources)
+   ProjectNode FindWithPath(const char * name, bool includeResources)
    {
       ProjectNode result = null;
       if(files)
@@ -1027,7 +1076,7 @@ private:
       return result;
    }
 
-   ProjectNode FindByFullPath(char * path, bool includeResources)
+   ProjectNode FindByFullPath(const char * path, bool includeResources)
    {
       if(files)
       {
@@ -1038,7 +1087,7 @@ private:
       return null;
    }
 
-   ProjectNode InternalFindByFullPath(char * path, bool includeResources, char * lastDirName)
+   ProjectNode InternalFindByFullPath(const char * path, bool includeResources, const char * lastDirName)
    {
       ProjectNode result = null;
       if(files)
@@ -1049,11 +1098,11 @@ private:
             {
                if(child.type != file)
                   result = child.InternalFindByFullPath(path, includeResources, lastDirName);
-               else if(child.name && !strcmpi(lastDirName, child.name))
+               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;
@@ -1067,14 +1116,14 @@ private:
       return result;
    }
 
-   ProjectNode FindByObjectFileName(char * fileName, IntermediateFileType type, bool dotMain, Map<String, NameCollisionInfo> namesInfo)
+   ProjectNode FindByObjectFileName(const 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(!strcmpi(p, fileName))
+         if(!fstrcmp(p, fileName))
             result = this;
       }
       else if(files)
@@ -1086,7 +1135,7 @@ private:
             else if(child.type == file && child.name)
             {
                child.GetObjectFileName(p, namesInfo, type, dotMain);
-               if(!strcmpi(p, fileName))
+               if(!fstrcmp(p, fileName))
                {
                   result = child;
                   break;
@@ -1097,7 +1146,7 @@ private:
       return result;
    }
 
-   ProjectNode FindSpecial(char * name, bool recursive, bool includeResources, bool includeFolders)
+   ProjectNode FindSpecial(const char * name, bool recursive, bool includeResources, bool includeFolders)
    {
       ProjectNode result = null;
       if(files)
@@ -1121,7 +1170,7 @@ private:
       return result;
    }
 
-   ProjectNode FindSameNameConflict(char * name, bool includeResources,
+   ProjectNode FindSameNameConflict(const char * name, bool includeResources,
       Map<Platform, SetBool> exclusionInfo, ProjectConfig prjConfig)
    {
       ProjectNode result = null;
@@ -1179,7 +1228,7 @@ private:
       return result;
    }
 
-   ProjectNode Add(Project project, char * filePath, ProjectNode after, NodeTypes type, NodeIcons icon, bool checkIfExists)
+   ProjectNode Add(Project project, const char * filePath, ProjectNode after, NodeTypes type, NodeIcons icon, bool checkIfExists)
    {
       ProjectNode node = null;
       if(!project.topNode.FindByFullPath(filePath, true))
@@ -1237,7 +1286,6 @@ private:
    void OnDisplay(Surface surface, int x, int y, int width, ProjectView projectView, Alignment alignment, DataDisplayFlags displayFlags)
    {
       char label[MAX_FILENAME];
-      int indent = 16;
       int xStart;
       int len;
       int w, h;
@@ -1248,10 +1296,10 @@ private:
       {
          showConfig = false;
          projectView = ide.projectView;
-      }         
-      
+      }
+
       bmp = projectView.icons[icon].bitmap;
-      xStart = /*indent * indent + */x + (bmp ? (bmp.width + 5) : 0);
+      xStart = x + (bmp ? (bmp.width + 5) : 0);
 
       GetLastDirectory(name, label);
       if(!showConfig || projectView.drawingInProjectSettingsDialogHeader)
@@ -1260,8 +1308,7 @@ private:
          {
             if(projectView.projectSettingsDialog && projectView.projectSettingsDialog.buildTab)
             {
-               char * addendum;
-               addendum = projectView.projectSettingsDialog.buildTab.selectedConfigName;
+               const char * addendum = projectView.projectSettingsDialog.buildTab.selectedConfigName;
                if(strlen(addendum))
                {
                   strcat(label, " (");
@@ -1292,7 +1339,7 @@ private:
          }
       }
       len = strlen(label);
-      
+
       if(!bmp)
       {
          if(type == folder || type == folderOpen)
@@ -1303,15 +1350,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)
@@ -1343,7 +1390,7 @@ private:
 
    int OnCompare(ProjectNode b)
    {
-      int result;
+      int result = 0;
       if(type == b.type /*|| type >= TYPE_DRIVE*/)
          result = strcmpi(name, b.name);
       else
@@ -1354,7 +1401,7 @@ private:
       return result;
    }
 
-   bool ContainsFilesWithExtension(char * extension)
+   bool ContainsFilesWithExtension(const char * extension, ProjectConfig prjConfig)
    {
       if(type == file)
       {
@@ -1365,10 +1412,14 @@ private:
       }
       else if(files)
       {
-         bool needed = false;
          for(child : files)
-            if(child.ContainsFilesWithExtension(extension))
-               return true;
+         {
+            if(child.type != resources && (child.type == folder || !prjConfig || !child.GetIsExcluded(prjConfig)))
+            {
+               if(child.ContainsFilesWithExtension(extension, prjConfig))
+                  return true;
+            }
+         }
       }
       return false;
    }
@@ -1421,7 +1472,7 @@ private:
          }
       }
    }
-   
+
    int GenMakefilePrintNode(File f, Project project, GenMakefilePrintTypes printType,
       Map<String, NameCollisionInfo> namesInfo, Array<String> items,
       ProjectConfig prjConfig, bool * containsCXX)
@@ -1545,8 +1596,8 @@ private:
          GetExtension(name, extension);
          if(!strcmpi(extension, "ec"))
          {
-            DualPipe dep;
-            char command[2048];
+            //DualPipe dep;
+            //char command[2048];
 
             ReplaceSpaces(moduleName, name);
             StripExtension(moduleName);
@@ -1593,7 +1644,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;
@@ -1636,7 +1687,7 @@ private:
                   GenMakePrintNodeFlagsVariable(this, nodeECFlagsMapping, "ECFLAGS", f);
                   GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "PRJ_CFLAGS", f);
 
-                  f.Printf(" -c %s%s.%s -o $(call escspace,$@)\n",
+                  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");
@@ -1648,19 +1699,7 @@ private:
       }
       if(files)
       {
-         bool needed = false;
-         if(ContainsFilesWithExtension("ec"))
-         {
-            for(child : files)
-            {
-               if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
-               {
-                  needed = true;
-                  break;
-               }
-            }
-         }
-         if(needed)
+         if(ContainsFilesWithExtension("ec", prjConfig))
          {
             for(child : files)
             {
@@ -1678,7 +1717,6 @@ private:
          Map<intptr, int> nodeCFlagsMapping, Map<intptr, int> nodeECFlagsMapping)
    {
       int ifCount = 0;
-      ProjectConfig config = GetMatchingNodeConfig(prjConfig);
       Array<Platform> platforms = GetPlatformsArrayFromExclusionInfo(prjConfig);
       //ProjectNode child;
       //char objDir[MAX_LOCATION];
@@ -1694,9 +1732,6 @@ private:
          GetExtension(name, extension);
          if(!strcmpi(extension, "ec"))
          {
-            DualPipe dep;
-            char command[2048];
-
             ReplaceSpaces(moduleName, name);
             StripExtension(moduleName);
 
@@ -1724,19 +1759,7 @@ private:
       }
       if(files)
       {
-         bool needed = false;
-         if(ContainsFilesWithExtension("ec"))
-         {
-            for(child : files)
-            {
-               if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
-               {
-                  needed = true;
-                  break;
-               }
-            }
-         }
-         if(needed)
+         if(ContainsFilesWithExtension("ec", prjConfig))
          {
             for(child : files)
             {
@@ -1754,7 +1777,6 @@ private:
       Map<intptr, int> nodeCFlagsMapping, Map<intptr, int> nodeECFlagsMapping)
    {
       int ifCount = 0;
-      ProjectConfig config = GetMatchingNodeConfig(prjConfig);
       Array<Platform> platforms = GetPlatformsArrayFromExclusionInfo(prjConfig);
       //ProjectNode child;
       //char objDir[MAX_LOCATION];
@@ -1769,8 +1791,8 @@ private:
          GetExtension(name, extension);
          if(!strcmpi(extension, "ec"))
          {
-            DualPipe dep;
-            char command[2048];
+            //DualPipe dep;
+            //char command[2048];
 
             ReplaceSpaces(moduleName, name);
             StripExtension(moduleName);
@@ -1817,7 +1839,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;
@@ -1872,7 +1894,7 @@ private:
             GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "PRJ_CFLAGS", f);
             f.Puts(" $(FVISIBILITY)");
 
-            f.Printf(" -c %s%s.%s -o $(call escspace,$@) -symbols $(OBJ)\n",
+            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");
@@ -1880,19 +1902,7 @@ private:
       }
       if(files)
       {
-         bool needed = false;
-         if(ContainsFilesWithExtension("ec"))
-         {
-            for(child : files)
-            {
-               if(child.type != resources && (child.type == folder || !child.GetIsExcluded(prjConfig)))
-               {
-                  needed = true;
-                  break;
-               }
-            }
-         }
-         if(needed)
+         if(ContainsFilesWithExtension("ec", prjConfig))
          {
             for(child : files)
             {
@@ -1912,7 +1922,6 @@ private:
       Map<intptr, int> nodeCFlagsMapping, Map<intptr, int> nodeECFlagsMapping)
    {
       int ifCount = 0;
-      ProjectConfig config = GetMatchingNodeConfig(prjConfig);
       Array<Platform> platforms = GetPlatformsArrayFromExclusionInfo(prjConfig);
       //ProjectNode child;
       //char objDir[MAX_LOCATION];
@@ -1930,8 +1939,8 @@ private:
                !strcmpi(extension, "cpp") || !strcmpi(extension, "cc") || !strcmpi(extension, "cxx") ||
                !strcmpi(extension, "m") || !strcmpi(extension, "mm") || !strcmpi(extension, "ec"))
          {
-            DualPipe dep;
-            char command[2048];
+            //DualPipe dep;
+            //char command[2048];
             NameCollisionInfo info;
 
             ReplaceSpaces(moduleName, name);
@@ -1939,7 +1948,7 @@ private:
 
             info = namesInfo[moduleName];
             collision = info ? info.IsExtensionColliding(extension) : false;
-            
+
             ReplaceSpaces(modulePath, path);
             if(modulePath[0]) strcat(modulePath, SEPS);
 
@@ -1991,7 +2000,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;
@@ -2040,12 +2049,12 @@ private:
             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, 
+               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,$@)\n");
+               f.Printf("\t$(WINDRES) $(WINDRES_FLAGS) $< \"$(call escspace,$(call quote_path,$@))\"\n");
             else
                f.Printf("\t$(CC)");
 
@@ -2055,9 +2064,9 @@ private:
                GenMakePrintNodeFlagsVariable(this, nodeCFlagsMapping, "PRJ_CFLAGS", f);
 
                if(!strcmpi(extension, "ec"))
-                  f.Printf(" $(FVISIBILITY) -c $(OBJ)%s.c -o $(call escspace,$@)\n", moduleName);
+                  f.Printf(" $(FVISIBILITY) -c $(call quote_path,$(OBJ)%s.c) -o $(call quote_path,$@)\n", moduleName);
                else
-                  f.Printf(" -c %s%s.%s -o $(call escspace,$@)\n",
+                  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");
@@ -2394,10 +2403,10 @@ private:
          char extension[MAX_EXTENSION];
          NameCollisionInfo info;
          Project prj = property::project;
-         Map<String, String> headerToSource { [ { "eh", "ec" }, { "h", "c" }, { "hh", "cc" }, { "hpp", "cpp" }, { "hxx", "cxx" } ] };
+         Map<String, const String> headerToSource { [ { "eh", "ec" }, { "h", "c" }, { "hh", "cc" }, { "hpp", "cpp" }, { "hxx", "cxx" } ] };
 
          GetExtension(name, extension);
-         ReplaceSpaces(moduleName, name);
+         strcpy(moduleName, name);
          StripExtension(moduleName);
          info = namesInfo[moduleName];
          collision = info ? info.IsExtensionColliding(extension) : false;
@@ -2444,7 +2453,7 @@ private:
             output.concat("\"");
          }
       }
-      else if(type == project && ContainsFilesWithExtension("ec"))
+      else if(type == project && ContainsFilesWithExtension("ec", prjConfig))
       {
          Project prj = property::project;
 
@@ -2563,12 +2572,11 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
    //         p Platform
    //         u Utility (GenericOptionTools)
 
-   int e;
    int o;
    int priority = 0;
    int includeDirsOption = OPTION(includeDirs);
    ProjectNode n;
-   char * platformName = platform ? platform.OnGetString(0,0,0) : null;
+   const char * platformName = platform ? platform.OnGetString(0,0,0) : null;
 
    // OPTION(ProjectOptions' last member) for size
    Array<bool> optionConfigXplatformSet   { size = OPTION(installCommands) };
@@ -2609,7 +2617,7 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
       void LoadOption(ProjectOptions options, int option, int priority, Array<Array<String>> optionTempStrings, ProjectOptions output) {
          if(mergeValues)
          {
-            Array<String> strings = options ? *((Array<String>*)((byte *)options + option) : null;
+            Array<String> strings = options ? *(Array<String>*)((byte *)options + option) : null;
             if(strings)
             {
                int order = 0;
@@ -2788,9 +2796,7 @@ static ProjectOptions BlendFileConfigPlatformProjectOptions(ProjectNode node, Pr
 
 static void CollectPlatformsCommonOptions(Map<Platform, ProjectOptions> byPlatformOptions, ProjectOptions * platformsCommonOptions)
 {
-   char * s;
-   int i;
-   ProjectOptions first;
+   ProjectOptions first = null;
    ProjectOptions commonOptions;
 
    Map<String, int> countIncludeDirs { };
@@ -2800,7 +2806,7 @@ static void CollectPlatformsCommonOptions(Map<Platform, ProjectOptions> byPlatfo
 
    for(options : byPlatformOptions) { first = options; break; }
 
-   *platformsCommonOptions = commonOptions = first.Copy();
+   *platformsCommonOptions = commonOptions = first ? first.Copy() : { };
 
    if(commonOptions.includeDirs)
       commonOptions.includeDirs.Free();
@@ -2996,7 +3002,7 @@ static void GetPlatformsCommonStrings(Map<String, int> counts, int goodCount, Ma
       int i = it;
       if(i == goodCount)
       {
-         char * s = &it;
+         const char * s = &it;
          strings.Add(CopyString(s));
          common[s] = true;
       }
@@ -3026,7 +3032,7 @@ static void RemovePlatformsCommonStrings(Map<String, bool> common, Array<String>
    }
 }
 
-static void GenMakePrintNodeFlagsVariable(ProjectNode node, Map<intptr, int> nodeFlagsMapping, String variableName, File f)
+static void GenMakePrintNodeFlagsVariable(ProjectNode node, Map<intptr, int> nodeFlagsMapping, const String variableName, File f)
 {
    int customFlags;
    customFlags = nodeFlagsMapping[(intptr)node];
@@ -3036,7 +3042,7 @@ static void GenMakePrintNodeFlagsVariable(ProjectNode node, Map<intptr, int> nod
       f.Printf(" $(%s)", variableName);
 }
 
-static void DynStringPrintNodeFlagsVariable(ProjectNode node, Map<intptr, int> nodeFlagsMapping, String variableName, DynamicString s)
+static void DynStringPrintNodeFlagsVariable(ProjectNode node, Map<intptr, int> nodeFlagsMapping, const String variableName, DynamicString s)
 {
    int customFlags;
    customFlags = nodeFlagsMapping[(intptr)node];
@@ -3085,6 +3091,8 @@ static void GenCFlagsFromProjectOptions(ProjectOptions options, bool prjWithEcFi
       }
       if(options.profile)
          s.concat(" -pg");
+      if(commonOptions)
+         s.concat(" -DREPOSITORY_VERSION=\"\\\"$(REPOSITORY_VER)\\\"\"");
    }
 
    if(options && options.preprocessorDefinitions)
@@ -3106,7 +3114,7 @@ static void GenECFlagsFromProjectOptions(ProjectOptions options, bool prjWithEcF
 }
 
 static void ListOptionToDynamicString(DynamicString output, ToolchainFlag flag, Array<String> list, bool prioritize,
-      LineOutputMethod lineMethod, String newLineStart)
+      LineOutputMethod lineMethod, const String newLineStart)
 {
    if(list.count)
    {