#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 };
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
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;
}
property::config = cfg.data;
+ ide.UpdateToolBarActiveConfigs(true);
ide.workspace.modified = true;
ide.projectView.Update(null);
}
}
}
- 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];
}
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");
}
}
- bool Build(bool isARun, ProjectNode onlyNode, CompilerConfig compiler, ProjectConfig config, bool justPrint)
+ 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];
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);
PathCatSlash(makeFilePath, makeFile);
// TODO: TEST ON UNIX IF \" around makeTarget is ok
- if(onlyNode)
+ if(onlyNodes)
{
if(compiler.type.isVC)
{
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);
+ }
+ }
}
}
{
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\"%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, justPrint ? " -n" : "", makeFilePath);
+ (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)))
{
+ 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, onlyNode, compiler, config);
+ 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);
delete pathBackup;
delete objDirExp;
delete compilerName;
+ delete makeTargets;
return result;
}
delete target;
}
- void Compile(ProjectNode node, CompilerConfig compiler, ProjectConfig config, bool justPrint)
+ void Compile(List<ProjectNode> nodes, CompilerConfig compiler, ProjectConfig config, bool justPrint, SingleFileCompileMode mode)
{
- Build(false, node, compiler, config, justPrint);
+ Build(false, nodes, compiler, config, justPrint, mode);
}
#endif
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");
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");
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");
if((projectPlatformOptions && projectPlatformOptions.options.linkerOptions && projectPlatformOptions.options.linkerOptions.count) ||
(configPlatformOptions && configPlatformOptions.options.linkerOptions && configPlatformOptions.options.linkerOptions.count))
{
- f.Puts("PRJ_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");
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("PRJ_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");
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("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");
// Main Module (Linking) for ECERE C modules
f.Puts("$(OBJ)$(MODULE).main.ec: $(SYMBOLS) $(COBJECTS)\n");
// use of objDirExpNoSpaces used instead of $(OBJ) to prevent problematic joining of arguments in ecs
- f.Printf("\t$(ECS)%s $(ECSLIBOPT) $(SYMBOLS) $(IMPORTS) -symbols %s -o $(OBJ)$(MODULE).main.ec\n",
+ f.Printf("\t$(ECS)%s $(FORCE_32_BIT) $(ECSLIBOPT) $(SYMBOLS) $(IMPORTS) -symbols %s -o $(OBJ)$(MODULE).main.ec\n",
GetConsole(config) ? " -console" : "", objDirExpNoSpaces);
f.Puts("\n");
// Main Module (Linking) for ECERE C modules