ide/sdk: Fixed forcing bit depth option not invoked for static libraries
[sdk] / ide / src / project / Project.ec
old mode 100755 (executable)
new mode 100644 (file)
index 3159e7f..e65519d
@@ -373,6 +373,36 @@ define PEEK_RESOLUTION = (18.2 * 10);
 #define SEPS    "/"
 #define SEP     '/'
 
+static Array<String> notLinkerOptions
+{ [
+   "-static-libgcc",
+   "-shared",
+   "-static",
+   "-s",
+   "-shared-libgcc",
+   "-nostartfiles",
+   "-nodefaultlibs",
+   "-nostdlib",
+   "-pie",
+   "-rdynamic",
+   "-static-libasan",
+   "-static-libtsan",
+   "-static libstdc++",
+   "-symbolic",
+   "-Wl,"
+   //"-T ",
+   //"-Xlinker ",
+   //"-u "
+] };
+
+static bool IsLinkerOption(String s)
+{
+   for(i : notLinkerOptions)
+      if(strstr(s, "-Wl,") || !strcmp(s, i))
+         return false;
+   return true;
+}
+
 static byte epjSignature[] = { 'E', 'P', 'J', 0x04, 0x01, 0x12, 0x03, 0x12 };
 
 enum GenMakefilePrintTypes { objects, cObjects, symbols, imports, sources, resources, eCsources };
@@ -696,6 +726,8 @@ char * GetConfigName(ProjectConfig config)
    return config ? config.name : "Common";
 }
 
+public enum SingleFileCompileMode { normal, debugPrecompile, debugCompile, debugGenerateSymbols };
+
 class Project : struct
 {
    class_no_expansion;  // To use Find on the Container<Project> in Workspace::projects
@@ -1216,7 +1248,7 @@ private:
       char temp[MAX_LOCATION];
       bool result = false;
       strcpy(cfDir, topNode.path);
-      if(ideSettings.compilerConfigsDir && ideSettings.compilerConfigsDir[0])
+      if(ideSettings && ideSettings.compilerConfigsDir && ideSettings.compilerConfigsDir[0])
       {
          PathCatSlash(cfDir, ideSettings.compilerConfigsDir);
          result = true;
@@ -1310,6 +1342,7 @@ private:
          }
 
          property::config = cfg.data;
+         ide.UpdateToolBarActiveConfigs(true);
          ide.workspace.modified = true;
          ide.projectView.Update(null);
       }
@@ -1349,7 +1382,7 @@ private:
       }
    }
 
-   bool ProcessBuildPipeOutput(DualPipe f, DirExpression objDirExp, bool isARun, ProjectNode onlyNode,
+   bool ProcessBuildPipeOutput(DualPipe f, DirExpression objDirExp, bool isARun, List<ProjectNode> onlyNodes,
       CompilerConfig compiler, ProjectConfig config)
    {
       char line[65536];
@@ -1359,43 +1392,49 @@ private:
       bool loggedALine = false;
       char * configName = config ? config.name : "Common";
       int lenMakeCommand = strlen(compiler.makeCommand);
-
-      char cppCommand[MAX_LOCATION];
-      char ccCommand[MAX_LOCATION];
-      char cxxCommand[MAX_LOCATION];
-      char stripCommand[MAX_LOCATION];
-      char ecpCommand[MAX_LOCATION];
-      char eccCommand[MAX_LOCATION];
-      char ecsCommand[MAX_LOCATION];
-      char earCommand[MAX_LOCATION];
-
-      char * cc = compiler.ccCommand;
-      char * cxx = compiler.cxxCommand;
-      char * cpp = compiler.cppCommand;
-      char * strip = compiler.cppCommand;
-      sprintf(cppCommand, "%s%s%s%s ",
-            compiler.ccacheEnabled ? "ccache " : "",
-            compiler.distccEnabled ? "distcc " : "",
-            compiler.gccPrefix ? compiler.gccPrefix : "",
-            compiler.cppCommand);
-      sprintf(ccCommand, "%s%s%s%s ",
+      int testLen = 0;
+
+      char * gccPrefix = compiler.gccPrefix ? compiler.gccPrefix : "";
+
+      DynamicString test { };
+      DynamicString ecp { };
+      DynamicString ecc { };
+      DynamicString ecs { };
+      DynamicString ear { };
+      DynamicString prefix { };
+      DynamicString cpp { };
+      DynamicString cc { };
+      DynamicString cxx { };
+      DynamicString strip { };
+      DynamicString ar { };
+
+      ecp.concatx(compiler.ecpCommand, " ");
+      ecc.concatx(compiler.eccCommand, " ");
+      ecs.concatx(compiler.ecsCommand, " ");
+      ear.concatx(compiler.earCommand, " ");
+
+      prefix.concatx(
             compiler.ccacheEnabled ? "ccache " : "",
             compiler.distccEnabled ? "distcc " : "",
-            compiler.gccPrefix ? compiler.gccPrefix : "",
-            compiler.ccCommand);
-      sprintf(cxxCommand, "%s%s%s%s ",
-            compiler.ccacheEnabled ? "ccache " : "",
-            compiler.distccEnabled ? "distcc " : "",
-            compiler.gccPrefix ? compiler.gccPrefix : "",
-            compiler.cxxCommand);
-
-      sprintf(stripCommand, "%sstrip ",
-            compiler.gccPrefix ? compiler.gccPrefix : "");
-
-      sprintf(ecpCommand, "%s ", compiler.ecpCommand);
-      sprintf(eccCommand, "%s ", compiler.eccCommand);
-      sprintf(ecsCommand, "%s ", compiler.ecsCommand);
-      sprintf(earCommand, "%s ", compiler.earCommand);
+            gccPrefix);
+
+      cpp.concatx((String)prefix, compiler.cppCommand, " ");
+      cc.concatx((String)prefix, compiler.ccCommand,  " ");
+      cxx.concatx((String)prefix, compiler.cxxCommand, " ");
+
+      strip.concatx(gccPrefix, "strip ");
+      ar.concatx(gccPrefix, "ar rcs");
+
+      testLen = Max(testLen, ecp.size);
+      testLen = Max(testLen, ecc.size);
+      testLen = Max(testLen, ecs.size);
+      testLen = Max(testLen, ear.size);
+      testLen = Max(testLen, cpp.size);
+      testLen = Max(testLen, cc.size);
+      testLen = Max(testLen, cxx.size);
+      testLen = Max(testLen, strip.size);
+      testLen = Max(testLen, ar.size);
+      testLen++;
 
       while(!f.Eof() && !ide.ShouldStopBuild())
       {
@@ -1408,6 +1447,7 @@ private:
             if((result = f.Peek()) && (result = f.GetLine(line, sizeof(line)-1)))
             {
                char * inFileIncludedFrom = strstr(line, stringInFileIncludedFrom);
+               test.copyLenSingleBlankReplTrim(line, ' ', true, testLen);
                if(strstr(line, compiler.makeCommand) == line && line[lenMakeCommand] == ':')
                {
                   char * module = strstr(line, "No rule to make target `");
@@ -1430,21 +1470,21 @@ private:
                      //numErrors++;
                   //}
                }
-               else if(strstr(line, "ear ") == line);
-               else if(strstr(line, stripCommand) == line);
-               else if(strstr(line, ccCommand) == line || strstr(line, cxxCommand) == line || strstr(line, ecpCommand) == line || strstr(line, eccCommand) == line)
+               else if(strstr(test, ear) == test);
+               else if(strstr(test, strip) == test);
+               else if(strstr(test, cc) == test || strstr(test, cxx) == test || strstr(test, ecp) == test || strstr(test, ecc) == test)
                {
                   char moduleName[MAX_FILENAME];
                   byte * tokens[1];
                   char * module;
                   bool isPrecomp = false;
 
-                  if(strstr(line, ccCommand) == line || strstr(line, cxxCommand) == line)
+                  if(strstr(test, cc) == test || strstr(test, cxx) == test)
                   {
                      module = strstr(line, " -c ");
                      if(module) module += 4;
                   }
-                  else if(strstr(line, eccCommand) == line)
+                  else if(strstr(test, ecc) == test)
                   {
                      module = strstr(line, " -c ");
                      if(module) module += 4;
@@ -1452,7 +1492,7 @@ private:
                      // Don't show GCC warnings about generated C code because it does not compile clean yet...
                      compilingEC = 3;//2;
                   }
-                  else if(strstr(line, ecpCommand) == line)
+                  else if(strstr(test, ecp) == test)
                   {
                      // module = line + 8;
                      module = strstr(line, " -c ");
@@ -1495,9 +1535,9 @@ private:
 
                   if(compilingEC) compilingEC--;
                }
-               else if(strstr(line, "ar rcs") == line)
+               else if(strstr(test, ar) == test)
                   ide.outputView.buildBox.Logf($"Building library...\n");
-               else if(strstr(line, ecsCommand) == line)
+               else if(strstr(test, ecs) == test)
                   ide.outputView.buildBox.Logf($"Writing symbol loader...\n");
                else
                {
@@ -1624,7 +1664,7 @@ private:
          }
          else
          {
-            if(!onlyNode)
+            if(!onlyNodes)
                ide.outputView.buildBox.Logf("\n%s (%s) - ", GetTargetFileName(config), configName);
             if(numErrors)
                ide.outputView.buildBox.Logf("%d %s, ", numErrors, (numErrors > 1) ? $"errors" : $"error");
@@ -1637,6 +1677,19 @@ private:
                ide.outputView.buildBox.Logf($"no warning\n");
          }
       }
+
+      delete test;
+      delete ecp;
+      delete ecc;
+      delete ecs;
+      delete ear;
+      delete prefix;
+      delete cpp;
+      delete cc;
+      delete cxx;
+      delete strip;
+      delete ar;
+
       return numErrors == 0;
    }
 
@@ -1675,12 +1728,12 @@ private:
       }
    }
 
-   bool Build(bool isARun, ProjectNode onlyNode, CompilerConfig compiler, ProjectConfig config)
+   bool Build(bool isARun, List<ProjectNode> onlyNodes, CompilerConfig compiler, ProjectConfig config, bool justPrint, SingleFileCompileMode mode)
    {
       bool result = false;
       DualPipe f;
       char targetFileName[MAX_LOCATION] = "";
-      char makeTarget[MAX_LOCATION] = "";
+      DynamicString makeTargets { };
       char makeFile[MAX_LOCATION];
       char makeFilePath[MAX_LOCATION];
       char configName[MAX_LOCATION];
@@ -1690,7 +1743,7 @@ private:
       char * targetPlatform = crossCompiling ? (char *)compiler.targetPlatform : "";
 
       int numJobs = compiler.numJobs;
-      char command[MAX_LOCATION];
+      char command[MAX_F_STRING];
       char * compilerName;
 
       compilerName = CopyString(compiler.name);
@@ -1706,7 +1759,7 @@ private:
       PathCatSlash(makeFilePath, makeFile);
 
       // TODO: TEST ON UNIX IF \" around makeTarget is ok
-      if(onlyNode)
+      if(onlyNodes)
       {
          if(compiler.type.isVC)
          {
@@ -1723,27 +1776,27 @@ private:
             // Create object dir if it does not exist already
             if(!FileExists(objDirExp.dir).isDirectory)
             {
-               sprintf(command, "%s CF_DIR=\"%s\"%s%s COMPILER=%s objdir -C \"%s\" -f \"%s\"",
+               sprintf(command, "%s CF_DIR=\"%s\"%s%s COMPILER=%s objdir -C \"%s\"%s -f \"%s\"",
                      compiler.makeCommand, cfDir,
                      crossCompiling ? " TARGET_PLATFORM=" : "", targetPlatform,
-                     compilerName, topNode.path, makeFilePath);
-#ifdef _DEBUG
-               PrintLn(command);
-               ide.outputView.buildBox.Logf("command: %s\n", command);
-#endif
+                     compilerName, topNode.path, justPrint ? " -n" : "", makeFilePath);
+               if(justPrint)
+                  ide.outputView.buildBox.Logf("%s\n", command);
                Execute(command);
             }
 
             ChangeWorkingDir(pushD);
 
-            PathCatSlash(makeTarget+1, objDirExp.dir);
-            PathCatSlash(makeTarget+1, onlyNode.name);
-            StripExtension(makeTarget+1);
-            strcat(makeTarget+1, ".o");
-            makeTarget[0] = '\"';
-            len = strlen(makeTarget);
-            makeTarget[len++] = '\"';
-            makeTarget[len++] = '\0';
+            for(node : onlyNodes)
+            {
+               if(node.GetIsExcluded(config))
+                  ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
+               else
+               {
+                  node.DeleteIntermediateFiles(compiler, config);
+                  node.GetTargets(config, objDirExp.dir, makeTargets);
+               }
+            }
          }
       }
 
@@ -1754,12 +1807,10 @@ private:
          GetWorkingDir(oldwd, sizeof(oldwd));
          ChangeWorkingDir(topNode.path);
 
+         // TODO: support justPrint
          sprintf(command, "%s /useenv /nologo /logcommands %s.sln %s|Win32", compiler.makeCommand, name, config.name);
-         ide.outputView.buildBox.Logf("command: %s\n", command);
-#ifdef _DEBUG
-         PrintLn(command);
-         ide.outputView.buildBox.Logf("command: %s\n", command);
-#endif
+         if(justPrint)
+            ide.outputView.buildBox.Logf("%s\n", command);
          if((f = DualPipeOpen(PipeOpenMode { output = true, error = true, input = true }, command)))
          {
             ProcessPipeOutputRaw(f);
@@ -1772,38 +1823,62 @@ private:
       {
          char cfDir[MAX_LOCATION];
          GetIDECompilerConfigsDir(cfDir, true, true);
-         sprintf(command, "%s CF_DIR=\"%s\"%s%s COMPILER=%s -j%d %s%s%s -C \"%s\" -f \"%s\"",
-               compiler.makeCommand, cfDir,
+         sprintf(command, "%s %sCF_DIR=\"%s\"%s%s COMPILER=%s -j%d %s%s%s -C \"%s\"%s -f \"%s\"",
+               compiler.makeCommand,
+               mode == normal ? "" : (mode == debugPrecompile ? "ECP_DEBUG=y " : mode == debugCompile ? "ECC_DEBUG=y " : mode == debugGenerateSymbols ? "ECS_DEBUG=y " : ""),
+               cfDir,
                crossCompiling ? " TARGET_PLATFORM=" : "", targetPlatform,
                compilerName, numJobs,
                compiler.ccacheEnabled ? "CCACHE=y " : "",
                compiler.distccEnabled ? "DISTCC=y " : "",
-               makeTarget, topNode.path, makeFilePath);
-#ifdef _DEBUG
-         PrintLn(command);
-         ide.outputView.buildBox.Logf("command: %s\n", command);
-#endif
+               (String)makeTargets, topNode.path, (justPrint || mode != normal) ? " -n" : "", makeFilePath);
+         if(justPrint)
+            ide.outputView.buildBox.Logf("%s\n", command);
          if((f = DualPipeOpen(PipeOpenMode { output = true, error = true, input = true }, command)))
          {
-            result = ProcessBuildPipeOutput(f, objDirExp, isARun, onlyNode, compiler, config);
+            bool found = false;
+            if(justPrint)
+            {
+               ProcessPipeOutputRaw(f);
+               result = true;
+            }
+            else if(mode != normal)
+            {
+               char line[65536];
+               while(!f.Eof())
+               {
+                  bool result = true;
+                  while(result)
+                  {
+                     if((result = f.Peek()) && (result = f.GetLine(line, sizeof(line)-1)))
+                     {
+                        if(!found && strstr(line, "ide ") == line)
+                        {
+                           strcpy(command, line);
+                           found = true;
+                        }
+                     }
+                  }
+               }
+            }
+            else
+               result = ProcessBuildPipeOutput(f, objDirExp, isARun, onlyNodes, compiler, config);
             delete f;
+            if(found)
+               Execute(command);
          }
          else
-         {
             ide.outputView.buildBox.Logf($"Error executing make (%s) command\n", compiler.makeCommand);
-#ifndef _DEBUG
-            ide.outputView.buildBox.Logf("command: %s\n", command);
-#endif
-         }
       }
 
       delete pathBackup;
       delete objDirExp;
       delete compilerName;
+      delete makeTargets;
       return result;
    }
 
-   void Clean(CompilerConfig compiler, ProjectConfig config, bool realclean)
+   void Clean(CompilerConfig compiler, ProjectConfig config, bool realclean, bool justPrint)
    {
       char makeFile[MAX_LOCATION];
       char makeFilePath[MAX_LOCATION];
@@ -1830,12 +1905,10 @@ private:
          GetWorkingDir(oldwd, sizeof(oldwd));
          ChangeWorkingDir(topNode.path);
          
+         // TODO: justPrint support
          sprintf(command, "%s /useenv /clean /nologo /logcommands %s.sln %s|Win32", compiler.makeCommand, name, config.name);
-         ide.outputView.buildBox.Logf("command: %s\n", command);
-#ifdef _DEBUG
-         PrintLn(command);
-         ide.outputView.buildBox.Logf("command: %s\n", command);
-#endif
+         if(justPrint)
+            ide.outputView.buildBox.Logf("%s\n", command);
          if((f = DualPipeOpen(PipeOpenMode { output = true, error = true, input = true }, command)))
          {
             ProcessPipeOutputRaw(f);
@@ -1849,18 +1922,19 @@ private:
       {
          char cfDir[MAX_LOCATION];
          GetIDECompilerConfigsDir(cfDir, true, true);
-         sprintf(command, "%s CF_DIR=\"%s\"%s%s COMPILER=%s %sclean -C \"%s\" -f \"%s\"",
+         sprintf(command, "%s CF_DIR=\"%s\"%s%s COMPILER=%s %sclean -C \"%s\"%s -f \"%s\"",
                compiler.makeCommand, cfDir,
                crossCompiling ? " TARGET_PLATFORM=" : "", targetPlatform,
-               compilerName, realclean ? "real" : "", topNode.path, makeFilePath);
-#ifdef _DEBUG
-         PrintLn(command);
-         ide.outputView.buildBox.Logf("command: %s\n", command);
-#endif
+               compilerName, realclean ? "real" : "", topNode.path, justPrint ? " -n": "", makeFilePath);
+         if(justPrint)
+            ide.outputView.buildBox.Logf("%s\n", command);
          if((f = DualPipeOpen(PipeOpenMode { output = 1, error = 1, input = 2 }, command)))
          {
             ide.outputView.buildBox.Tell($"Deleting target and object files...");
-            ProcessCleanPipeOutput(f, compiler, config);
+            if(justPrint)
+               ProcessPipeOutputRaw(f);
+            else
+               ProcessCleanPipeOutput(f, compiler, config);
             delete f;
 
             ide.outputView.buildBox.Logf($"Target and object files deleted\n");
@@ -1878,7 +1952,7 @@ private:
       DirExpression targetDirExp = GetTargetDir(compiler, config);
       PathBackup pathBackup { };
 
-      // Build(project, ideMain, true, null);
+      // Build(project, ideMain, true, null, false);
 
    #if defined(__WIN32__)
       strcpy(target, topNode.path);
@@ -1921,9 +1995,9 @@ private:
       delete target;
    }
 
-   void Compile(ProjectNode node, CompilerConfig compiler, ProjectConfig config)
+   void Compile(List<ProjectNode> nodes, CompilerConfig compiler, ProjectConfig config, bool justPrint, SingleFileCompileMode mode)
    {
-      Build(false, node, compiler, config);
+      Build(false, nodes, compiler, config, justPrint, mode);
    }
 #endif
 
@@ -2028,6 +2102,16 @@ private:
          File f = FileOpen(path, write);
          if(f)
          {
+            if(compiler.environmentVars && compiler.environmentVars.count)
+            {
+               f.Puts("# ENVIRONMENT VARIABLES\n");
+               f.Puts("\n");
+               for(e : compiler.environmentVars)
+               {
+                  f.Printf("export %s := %s\n", e.name, e.string);
+               }
+            }
+
             f.Puts("# TOOLCHAIN\n");
             f.Puts("\n");
 
@@ -2039,7 +2123,8 @@ private:
             if(compiler.sysroot && compiler.sysroot[0])
             {
                f.Printf("SYSROOT := %s\n", compiler.sysroot);
-               f.Puts("_SYSROOT := $(space)--sysroot=$(SYSROOT)\n");
+               // Moved this to crossplatform.mk
+               //f.Puts("_SYSROOT := $(space)--sysroot=$(SYSROOT)\n");
                f.Puts("\n");
             }
 
@@ -2047,9 +2132,9 @@ private:
             f.Printf("CPP := $(CCACHE_COMPILE)$(DISTCC_COMPILE)$(GCC_PREFIX)%s$(_SYSROOT)\n", compiler.cppCommand);
             f.Printf("CC := $(CCACHE_COMPILE)$(DISTCC_COMPILE)$(GCC_PREFIX)%s$(_SYSROOT)\n", compiler.ccCommand);
             f.Printf("CXX := $(CCACHE_COMPILE)$(DISTCC_COMPILE)$(GCC_PREFIX)%s$(_SYSROOT)\n", compiler.cxxCommand);
-            f.Printf("ECP := %s\n", compiler.ecpCommand);
-            f.Printf("ECC := %s$(if $(CROSS_TARGET), -t $(TARGET_PLATFORM),)\n", compiler.eccCommand);
-            f.Printf("ECS := %s$(if $(CROSS_TARGET), -t $(TARGET_PLATFORM),)\n", compiler.ecsCommand);
+            f.Printf("ECP := $(if $(ECP_DEBUG),ide -debug-start $(ECERE_SDK_SRC)/compiler/ecp/ecp.epj -@,%s)\n", compiler.ecpCommand);
+            f.Printf("ECC := $(if $(ECC_DEBUG),ide -debug-start $(ECERE_SDK_SRC)/compiler/ecc/ecc.epj -@,%s)$(if $(CROSS_TARGET), -t $(TARGET_PLATFORM),)\n", compiler.eccCommand);
+            f.Printf("ECS := $(if $(ECS_DEBUG),ide -debug-start $(ECERE_SDK_SRC)/compiler/ecs/ecs.epj -@,%s)$(if $(CROSS_TARGET), -t $(TARGET_PLATFORM),)\n", compiler.ecsCommand);
             f.Printf("EAR := %s\n", compiler.earCommand);
 
             f.Puts("AS := $(GCC_PREFIX)as\n");
@@ -2059,20 +2144,10 @@ private:
             f.Puts("UPX := upx\n");
             f.Puts("\n");
 
-            if(compiler.environmentVars && compiler.environmentVars.count)
-            {
-               f.Puts("# ENVIRONMENT VARIABLES\n");
-               f.Puts("\n");
-               for(e : compiler.environmentVars)
-               {
-                  f.Printf("export %s := %s\n", e.name, e.string);
-               }
-            }
-
             f.Puts("UPXFLAGS = -9\n"); // TOFEAT: Compression Level Option? Other UPX Options?
             f.Puts("\n");
 
-            f.Puts("EARFLAGS = aw\n");
+            f.Puts("EARFLAGS = \n");
             f.Puts("\n");
 
             f.Puts("# HARD CODED TARGET_PLATFORM-SPECIFIC OPTIONS\n");
@@ -2125,6 +2200,8 @@ private:
             f.Printf("\nFORCE_64_BIT := %s", compiler.supportsBitDepth ? "-m64" : "");
             f.Printf("\nFORCE_32_BIT := %s", compiler.supportsBitDepth ? "-m32" : "");
             f.Puts("\n");
+            f.Puts("\nOFLAGS += $(LDFLAGS)");
+            f.Puts("\n");
 
             delete f;
 
@@ -2207,7 +2284,7 @@ private:
 
          sameObjTargetDirs = !fstrcmp(objDirExpNoSpaces, targetDirExpNoSpaces);
 
-         f.Printf(".PHONY: all objdir%s clean realclean distclean\n\n", sameObjTargetDirs ? "" : " targetdir");
+         f.Printf(".PHONY: all objdir%s cleantarget clean realclean distclean\n\n", sameObjTargetDirs ? "" : " targetdir");
 
          f.Puts("# CORE VARIABLES\n\n");
 
@@ -2253,6 +2330,7 @@ private:
 
          f.Puts("ECFLAGS =\n");
          f.Puts("ifndef DEBIAN_PACKAGE\n" "CFLAGS =\n" "LDFLAGS =\n" "endif\n");
+         f.Puts("PRJ_CFLAGS =\n");
          f.Puts("CECFLAGS =\n");
          f.Puts("OFLAGS =\n");
          f.Puts("LIBS =\n");
@@ -2416,7 +2494,7 @@ private:
                cflagsVariations, nodeCFlagsMapping,
                ecflagsVariations, nodeECFlagsMapping, null);
 
-         GenMakePrintCustomFlags(f, "CFLAGS", false, cflagsVariations);
+         GenMakePrintCustomFlags(f, "PRJ_CFLAGS", false, cflagsVariations);
          GenMakePrintCustomFlags(f, "ECFLAGS", true, ecflagsVariations);
 
          if(platforms || (config && config.platforms))
@@ -2442,19 +2520,44 @@ private:
                   if((projectPlatformOptions && projectPlatformOptions.options.linkerOptions && projectPlatformOptions.options.linkerOptions.count) ||
                      (configPlatformOptions && configPlatformOptions.options.linkerOptions && configPlatformOptions.options.linkerOptions.count))
                   {
-                     f.Puts("CFLAGS +=");
-                     // tocheck: does any of that -Wl stuff from linkerOptions have any business being in CFLAGS?
+                     f.Puts("OFLAGS +=");
                      if(projectPlatformOptions && projectPlatformOptions.options.linkerOptions && projectPlatformOptions.options.linkerOptions.count)
                      {
-                        f.Puts(" \\\n\t -Wl");
+                        bool needWl = false;
+                        f.Puts(" \\\n\t ");
                         for(s : projectPlatformOptions.options.linkerOptions)
-                           f.Printf(",%s", s);
+                        {
+                           if(!IsLinkerOption(s))
+                              f.Printf(" %s", s);
+                           else
+                              needWl = true;
+                        }
+                        if(needWl)
+                        {
+                           f.Puts(" -Wl");
+                           for(s : projectPlatformOptions.options.linkerOptions)
+                              if(IsLinkerOption(s))
+                                 f.Printf(",%s", s);
+                        }
                      }
                      if(configPlatformOptions && configPlatformOptions.options.linkerOptions && configPlatformOptions.options.linkerOptions.count)
                      {
-                        f.Puts(" \\\n\t -Wl");
+                        bool needWl = false;
+                        f.Puts(" \\\n\t ");
                         for(s : configPlatformOptions.options.linkerOptions)
-                           f.Printf(",%s", s);
+                        {
+                           if(IsLinkerOption(s))
+                              f.Printf(" %s", s);
+                           else
+                              needWl = true;
+                        }
+                        if(needWl)
+                        {
+                           f.Puts(" -Wl");
+                           for(s : configPlatformOptions.options.linkerOptions)
+                              if(!IsLinkerOption(s))
+                                 f.Printf(",%s", s);
+                        }
                      }
                      f.Puts("\n");
                      f.Puts("\n");
@@ -2508,13 +2611,48 @@ private:
             f.Puts("\n");
          }
 
-         // tocheck: does any of that -Wl stuff from linkerOptions have any business being in CFLAGS?
-         if(options && options.linkerOptions && options.linkerOptions.count)
+         if((config && config.options && config.options.linkerOptions && config.options.linkerOptions.count) ||
+               (options && options.linkerOptions && options.linkerOptions.count))
          {
-            f.Puts("CFLAGS +=");
-            f.Puts(" \\\n\t -Wl");
-            for(s : options.linkerOptions)
-               f.Printf(",%s", s);
+            f.Puts("OFLAGS +=");
+            f.Puts(" \\\n\t");
+
+            if(config && config.options && config.options.linkerOptions && config.options.linkerOptions.count)
+            {
+               bool needWl = false;
+               for(s : config.options.linkerOptions)
+               {
+                  if(!IsLinkerOption(s))
+                     f.Printf(" %s", s);
+                  else
+                     needWl = true;
+               }
+               if(needWl)
+               {
+                  f.Puts(" -Wl");
+                  for(s : config.options.linkerOptions)
+                     if(IsLinkerOption(s))
+                        f.Printf(",%s", s);
+               }
+            }
+            if(options && options.linkerOptions && options.linkerOptions.count)
+            {
+               bool needWl = false;
+               for(s : options.linkerOptions)
+               {
+                  if(!IsLinkerOption(s))
+                     f.Printf(" %s", s);
+                  else
+                     needWl = true;
+               }
+               if(needWl)
+               {
+                  f.Puts(" -Wl");
+                  for(s : options.linkerOptions)
+                     if(IsLinkerOption(s))
+                        f.Printf(",%s", s);
+               }
+            }
          }
          f.Puts("\n");
          f.Puts("\n");
@@ -2523,22 +2661,30 @@ private:
          f.Puts("\n");
          f.Puts("\n");
 
-         f.Puts("ifndef STATIC_LIBRARY_TARGET\n");
-         f.Puts("OFLAGS +=");
          forceBitDepth = (options && options.buildBitDepth) || numCObjects;
-         if(forceBitDepth)
-            f.Puts((!options || !options.buildBitDepth || options.buildBitDepth == bits32) ? " $(FORCE_32_BIT)" : " $(FORCE_64_BIT) \\\n");
-
-         if(GetProfile(config))
-            f.Puts(" -pg");
-         if(config && config.options && config.options.libraryDirs)
-            OutputListOption(f, "L", config.options.libraryDirs, lineEach, true);
-         if(options && options.libraryDirs)
-            OutputListOption(f, "L", options.libraryDirs, lineEach, true);
-         f.Puts("\n");
-         f.Puts("OFLAGS += $(LDFLAGS)\n");
-         f.Puts("endif\n");
-         f.Puts("\n");
+         if(forceBitDepth || GetProfile(config))
+         {
+            f.Puts("OFLAGS +=");
+            if(forceBitDepth)
+               f.Puts((!options || !options.buildBitDepth || options.buildBitDepth == bits32) ? " $(FORCE_32_BIT)" : " $(FORCE_64_BIT)");
+            if(GetProfile(config))
+               f.Puts(" -pg");
+            f.Puts("\n");
+            f.Puts("\n");
+         }
+
+         if((config && config.options && config.options.libraryDirs) || (options && options.libraryDirs))
+         {
+            f.Puts("ifndef STATIC_LIBRARY_TARGET\n");
+            f.Puts("OFLAGS +=");
+            if(config && config.options && config.options.libraryDirs)
+               OutputListOption(f, "L", config.options.libraryDirs, lineEach, true);
+            if(options && options.libraryDirs)
+               OutputListOption(f, "L", options.libraryDirs, lineEach, true);
+            f.Puts("\n");
+            f.Puts("endif\n");
+            f.Puts("\n");
+         }
 
          f.Puts("# TARGETS\n");
          f.Puts("\n");
@@ -2614,9 +2760,9 @@ private:
             f.Puts("\n");
             // Main Module (Linking) for ECERE C modules
             f.Puts("$(OBJ)$(MODULE).main.c: $(OBJ)$(MODULE).main.ec\n");
-            f.Puts("\t$(ECP) $(CECFLAGS) $(ECFLAGS) $(CFLAGS)"
+            f.Puts("\t$(ECP) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS)"
                   " -c $(OBJ)$(MODULE).main.ec -o $(OBJ)$(MODULE).main.sym -symbols $(OBJ)\n");
-            f.Puts("\t$(ECC) $(CECFLAGS) $(ECFLAGS) $(CFLAGS) $(FVISIBILITY)"
+            f.Puts("\t$(ECC) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) $(FVISIBILITY)"
                   " -c $(OBJ)$(MODULE).main.ec -o $(OBJ)$(MODULE).main.c -symbols $(OBJ)\n");
             f.Puts("\n");
          }
@@ -2709,41 +2855,32 @@ private:
 
          f.Puts("# SYMBOL RULES\n");
          f.Puts("\n");
-         {
-            Map<Platform, bool> excludedPlatforms { };
-            topNode.GenMakefilePrintSymbolRules(f, this, config, excludedPlatforms,
-                  nodeCFlagsMapping, nodeECFlagsMapping);
-            delete excludedPlatforms;
-         }
+
+         topNode.GenMakefilePrintSymbolRules(f, this, config, nodeCFlagsMapping, nodeECFlagsMapping);
 
          f.Puts("# C OBJECT RULES\n");
          f.Puts("\n");
-         {
-            Map<Platform, bool> excludedPlatforms { };
-            topNode.GenMakefilePrintCObjectRules(f, this, config, excludedPlatforms,
-                  nodeCFlagsMapping, nodeECFlagsMapping);
-            delete excludedPlatforms;
-         }
+
+         topNode.GenMakefilePrintCObjectRules(f, this, config, nodeCFlagsMapping, nodeECFlagsMapping);
 
          f.Puts("# OBJECT RULES\n");
          f.Puts("\n");
          // todo call this still but only generate rules whith specific options
          // see we-have-file-specific-options in ProjectNode.ec
-         {
-            Map<Platform, bool> excludedPlatforms { };
-            topNode.GenMakefilePrintObjectRules(f, this, namesInfo, config, excludedPlatforms,
-                  nodeCFlagsMapping, nodeECFlagsMapping);
-            delete excludedPlatforms;
-         }
+         topNode.GenMakefilePrintObjectRules(f, this, namesInfo, config, nodeCFlagsMapping, nodeECFlagsMapping);
 
          if(numCObjects)
             GenMakefilePrintMainObjectRule(f, config);
 
-         f.Printf("clean: objdir%s\n", sameObjTargetDirs ? "" : " targetdir");
-         f.Printf("\t$(call rmq,%s$(TARGET))\n", numCObjects ? "$(OBJ)$(MODULE).main.o $(OBJ)$(MODULE).main.c $(OBJ)$(MODULE).main.ec $(OBJ)$(MODULE).main$(I) $(OBJ)$(MODULE).main$(S) " : "");
+         f.Printf("cleantarget: objdir%s\n", sameObjTargetDirs ? "" : " targetdir");
+         f.Puts("\t$(call rmq,$(TARGET))\n");
+         f.Puts("\n");
+
+         f.Puts("clean: cleantarget\n");
          OutputCleanActions(f, "_OBJECTS", objectsParts);
          if(numCObjects)
          {
+            f.Printf("\t$(call rmq,%s)\n", "$(OBJ)$(MODULE).main.o $(OBJ)$(MODULE).main.c $(OBJ)$(MODULE).main.ec $(OBJ)$(MODULE).main$(I) $(OBJ)$(MODULE).main$(S)");
             OutputCleanActions(f, "ECOBJECTS", eCsourcesParts);
             OutputCleanActions(f, "COBJECTS", eCsourcesParts);
             OutputCleanActions(f, "BOWLS", eCsourcesParts);
@@ -2752,13 +2889,15 @@ private:
          }
          f.Puts("\n");
 
-         f.Puts("realclean: clean\n");
+         f.Puts("realclean: cleantarget\n");
          f.Puts("\t$(call rmrq,$(OBJ))\n");
          if(!sameObjTargetDirs)
             f.Printf("\t$(call rmdirq,%s)\n", targetDirExpNoSpaces);
          f.Puts("\n");
 
-         f.Puts("distclean:\n");
+         f.Puts("distclean: cleantarget\n");
+         if(!sameObjTargetDirs)
+            f.Printf("\t$(call rmdirq,%s)\n", targetDirExpNoSpaces);
          f.Puts("\t$(call rmrq,obj/)\n");
 
          delete f;
@@ -2872,13 +3011,12 @@ private:
          {
 #endif
             f.Puts("$(OBJ)$(MODULE).main$(O): $(OBJ)$(MODULE).main.c\n");
+            f.Printf("\t$(CC) $(CFLAGS) $(PRJ_CFLAGS) $(FVISIBILITY) -c $(OBJ)$(MODULE).main.%s -o $(OBJ)$(MODULE).main$(O)\n", extension);
+            f.Puts("\n");
 #if 0
          }
       }
 #endif
-
-      f.Printf("\t$(CC) $(CFLAGS) $(FVISIBILITY) -c $(OBJ)$(MODULE).main.%s -o $(OBJ)$(MODULE).main$(O)\n", extension);
-      f.Puts("\n");
    }
 
    void GenMakePrintCustomFlags(File f, String variableName, bool printNonCustom, Map<String, int> cflagsVariations)