public import "ecere"
#endif
+import "DynamicString"
+
#ifndef MAKEFILE_GENERATOR
import "ide"
// We should have the .sln/.vcproj generation even on other platforms
#ifndef MAKEFILE_GENERATOR
globalSettingsDialog.ideSettings = settings;
ide.UpdateRecentMenus();
- // ide.UpdateMakefiles(); -- can't really regenerate on Load since all recent menus changes will happen
#endif
}
};
#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 };
f.Printf("%s =%s%s", name, prefix ? " " : "", prefix ? prefix : "");
for(c=0; c<numOfBreaks; c++)
f.Printf(" $(%s%d)", name, c+1);
- f.Printf("\n");
+ f.Puts("\n");
}
else
f.Printf("%s =%s%s", name, prefix ? " " : "", prefix ? prefix : "");
f.Printf(" \\\n\t%s", list[n]);
}
offset += itemCount;
- f.Printf("\n");
+ f.Puts("\n");
}
list.Free();
list.count = 0;
}
else
- f.Printf("\n");
- f.Printf("\n");
+ f.Puts("\n");
+ f.Puts("\n");
delete breaks;
return numOfBreaks;
}
if(list.count)
{
if(method == newLine)
- f.Printf(" \\\n\t");
+ f.Puts(" \\\n\t");
for(item : list)
{
if(method == lineEach)
- f.Printf(" \\\n\t");
+ f.Puts(" \\\n\t");
f.Printf(" -%s", option);
if(noSpace)
OutputNoSpace(f, item);
}
}
+void StringNoSpaceToDynamicString(DynamicString s, char * path)
+{
+ char * output = new char[strlen(path)+1024];
+ ReplaceSpaces(output, path);
+ s.concat(output);
+ delete output;
+}
+
static void OutputLibraries(File f, Array<String> libraries)
{
for(item : libraries)
char ext[MAX_EXTENSION];
char temp[MAX_LOCATION];
char * s = item;
+ bool usedFunction = false;
GetExtension(item, ext);
if(!strcmp(ext, "o") || !strcmp(ext, "a"))
- f.Printf(" ");
+ f.Puts(" ");
else
{
if(!strcmp(ext, "so") || !strcmp(ext, "dylib"))
StripExtension(temp);
s = temp;
}
- f.Printf(" -l");
+ f.Puts(" \\\n\t$(call _L,");
+ usedFunction = true;
}
OutputNoSpace(f, s);
+ if(usedFunction)
+ f.Puts(")");
}
}
define localOptimization = config && config.options && config.options.optimization ?
config.options.optimization : options && options.optimization ?
options.optimization : OptimizationStrategy::none;
+define localFastMath = config && config.options && config.options.fastMath ?
+ config.options.fastMath : options && options.fastMath ?
+ options.fastMath : SetBool::unset;
define localDefaultNameSpace = config && config.options && config.options.defaultNameSpace ?
config.options.defaultNameSpace : options && options.defaultNameSpace ?
options.defaultNameSpace : null;
projectPOs.options.targetType : TargetTypes::unset;
-// we should have some kind of direct mapping between a platform and it's makefile variable
-char * PlatformToMakefileVariable(Platform platform)
+char * PlatformToMakefileTargetVariable(Platform platform)
{
- return platform == win32 ? "WINDOWS" :
- platform == tux ? "LINUX" :
- platform == apple ? "OSX"/*"APPLE"*/ :
- platform;
+ return platform == win32 ? "WINDOWS_TARGET" :
+ platform == tux ? "LINUX_TARGET" :
+ platform == apple ? "OSX_TARGET" :
+ "ERROR_BAD_TARGET";
}
char * TargetTypeToMakefileVariable(TargetTypes targetType)
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
String description;
String license;
String compilerConfigsDir;
+#ifndef MAKEFILE_GENERATOR
+ FileMonitor fileMonitor
+ {
+ this, FileChange { modified = true };
+ bool OnFileNotify(FileChange action, char * param)
+ {
+ fileMonitor.StopMonitoring();
+ if(OnProjectModified(action, param))
+ fileMonitor.StartMonitoring();
+ return true;
+ }
+ };
- ~Project()
+ bool StartMonitoring()
{
- /* // THIS IS NOW AUTOMATED WITH A project CHECK IN ProjectNode
- topNode.configurations = null;
- topNode.platforms = null;
- topNode.options = null;
- */
+ fileMonitor.fileName = filePath;
+ fileMonitor.StartMonitoring();
+ return true;
+ }
+
+ bool StopMonitoring()
+ {
+ fileMonitor.StopMonitoring();
+ return true;
+ }
+
+ bool OnProjectModified(FileChange fileChange, char * param)
+ {
+ char temp[4096];
+ sprintf(temp, $"The project %s was modified by another application.\n"
+ "Would you like to reload it and lose your changes?", name);
+ if(MessageBox { type = yesNo, master = ide,
+ text = $"Project has been modified", contents = temp }.Modal() == yes)
+ {
+ Project project = LoadProject(filePath, config.name);
+ if(project)
+ {
+ ProjectView projectView = ide.projectView;
+ DataRow prev = topNode.row ? topNode.row.previous : null;
+ FileMonitor fm = fileMonitor;
+
+ if(projectView) projectView.DeleteNode(topNode);
+
+ *this = *project;
+ delete fileMonitor;
+ fileMonitor = fm;
+ topNode.project = this;
+
+ if(projectView)
+ {
+ CompilerConfig compiler = ideSettings.GetCompilerConfig(projectView.workspace.compiler);
+ projectView.AddNode(topNode, null);
+ topNode.row.Move(prev);
+
+ projectView.ShowOutputBuildLog(true);
+ projectView.DisplayCompiler(compiler, false);
+ projectView.ProjectUpdateMakefileForAllConfigs(this);
+ delete compiler;
+ }
+ eSystem_Delete(project);
+ }
+ return true;
+ }
+ return true;
+ }
+#endif
+
+ // This frees contents without freeing the instance
+ // For use from destructor and for file monitor reloading
+ // (To work around JSON loader (LoadProject) always returning a new instance)
+ void Free()
+ {
if(platforms) { platforms.Free(); delete platforms; }
if(configurations) { configurations.Free(); delete configurations; }
if(files) { files.Free(); delete files; }
delete name;
}
+ ~Project()
+ {
+ /* // THIS IS NOW AUTOMATED WITH A project CHECK IN ProjectNode
+ topNode.configurations = null;
+ topNode.platforms = null;
+ topNode.options = null;
+ */
+ Free();
+ }
+
property ProjectConfig config
{
set
}
- char * GetObjDirExpression(CompilerConfig compiler, ProjectConfig config)
+ char * GetObjDirExpression(ProjectConfig config)
{
// TODO: Support platform options
char * expression = localObjectsDirectory;
DirExpression GetObjDir(CompilerConfig compiler, ProjectConfig config)
{
- char * expression = GetObjDirExpression(compiler, config);
+ char * expression = GetObjDirExpression(config);
DirExpression objDir { type = intermediateObjectsDir };
objDir.Evaluate(expression, this, compiler, config);
return objDir;
}
- char * GetTargetDirExpression(CompilerConfig compiler, ProjectConfig config)
+ char * GetTargetDirExpression(ProjectConfig config)
{
// TODO: Support platform options
char * expression = localTargetDirectory;
DirExpression GetTargetDir(CompilerConfig compiler, ProjectConfig config)
{
- char * expression = GetTargetDirExpression(compiler, config);
+ char * expression = GetTargetDirExpression(config);
DirExpression targetDir { type = DirExpressionType::targetDir /*intermediateObjectsDir*/};
targetDir.Evaluate(expression, this, compiler, config);
return targetDir;
return optimization;
}
+ bool GetFastMath(ProjectConfig config)
+ {
+ SetBool fastMath = localFastMath;
+ return fastMath == true;
+ }
+
String GetDefaultNameSpace(ProjectConfig config)
{
String defaultNameSpace = localDefaultNameSpace;
}
#endif
+ // This method is only called from Debugger, should be moved to Debugger class?
#ifndef MAKEFILE_GENERATOR
bool GetRelativePath(char * filePath, char * relativePath)
{
PathCatSlash(relativePath, node.name);
return true;
}
+ else
+ {
+ // Tweak for automatically resolving symbol loader modules
+ char * sl = strstr(moduleName, ".main.ec");
+ if(sl && (*sl = 0, !strcmpi(moduleName, name)))
+ {
+ char objDir[MAX_LOCATION];
+ DirExpression objDirExp;
+ CompilerConfig compiler = ide.debugger.currentCompiler;
+ ProjectConfig config = ide.debugger.prjConfig;
+ // This is not perfect, as multiple source files exist for the symbol loader module...
+ // We try to set it in the debug config object directory.
+ if(!compiler || !config)
+ {
+ // If we're not currently debugging, set a breakpoint in the active compiler/config
+ compiler = GetCompilerConfig();
+ config = this.config;
+ // If the current config is not debuggable, set it in the first debuggable config found
+ if(config && !config.options.debug)
+ {
+ for(c : configurations; c.options.debug)
+ {
+ config = c;
+ break;
+ }
+ }
+ }
+ objDirExp = GetObjDir(compiler, config);
+ strcpy(objDir, objDirExp.dir);
+ delete objDirExp;
+ ChangeCh(objDir, '\\', '/'); // TODO: this is a hack, paths should never include win32 path seperators - fix this in ProjectSettings and ProjectLoad instead
+ ReplaceSpaces(objDir, objDir);
+ strcpy(relativePath, objDir);
+ *sl = '.';
+ PathCatSlash(relativePath, moduleName);
+ return true;
+ }
+ }
// WARNING: On failure, relative path is uninitialized
return false;
}
}
}
- bool GetProjectCompilerConfigsDir(char * cfDir)
+ bool GetProjectCompilerConfigsDir(char * cfDir, bool replaceSpaces, bool makeRelative)
{
bool result = false;
+ char temp[MAX_LOCATION];
strcpy(cfDir, topNode.path);
if(compilerConfigsDir && compilerConfigsDir[0])
{
PathCatSlash(cfDir, compilerConfigsDir);
result = true;
}
+ if(makeRelative)
+ {
+ strcpy(temp, cfDir);
+ // Using a relative path makes it less likely to run into spaces issues
+ // Even with escaped spaces, there still seems to be issues including a config file
+ // in a path containing spaces
+
+ MakePathRelative(temp, topNode.path, cfDir);
+ }
+
if(cfDir && cfDir[0] && cfDir[strlen(cfDir)-1] != '/')
strcat(cfDir, "/");
+ if(replaceSpaces)
+ {
+ strcpy(temp, cfDir);
+ ReplaceSpaces(cfDir, temp);
+ }
return result;
}
- bool GetIDECompilerConfigsDir(char * cfDir)
+ bool GetIDECompilerConfigsDir(char * cfDir, bool replaceSpaces, bool makeRelative)
{
+ 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;
}
+ else
+ {
+ // Default to <ProjectDir>/.configs if unset
+ PathCatSlash(cfDir, ".configs");
+ result = true;
+ }
+ if(makeRelative)
+ {
+ strcpy(temp, cfDir);
+ // Using a relative path makes it less likely to run into spaces issues
+ // Even with escaped spaces, there still seems to be issues including a config file
+ // in a path containing spaces
+ if(IsPathInsideOf(cfDir, topNode.path))
+ MakePathRelative(temp, topNode.path, cfDir);
+ }
if(cfDir && cfDir[0] && cfDir[strlen(cfDir)-1] != '/')
strcat(cfDir, "/");
+ if(replaceSpaces)
+ {
+ strcpy(temp, cfDir);
+ ReplaceSpaces(cfDir, temp);
+ }
return result;
}
}
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];
int compilingEC = 0;
int numErrors = 0, numWarnings = 0;
bool loggedALine = false;
- char * configName = config.name;
+ char * configName = config ? config.name : "Common";
int lenMakeCommand = strlen(compiler.makeCommand);
-
- char cppCommand[MAX_LOCATION];
- char ccCommand[MAX_LOCATION];
- char ecpCommand[MAX_LOCATION];
- char eccCommand[MAX_LOCATION];
- char ecsCommand[MAX_LOCATION];
- char earCommand[MAX_LOCATION];
-
- char * cc = compiler.ccCommand;
- char * cpp = compiler.cppCommand;
- sprintf(cppCommand, "%s%s%s%s ",
- compiler.ccacheEnabled ? "ccache " : "",
- compiler.ccacheEnabled && !compiler.distccEnabled ? " " : "",
- compiler.distccEnabled ? "distcc " : "",
- 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.ccacheEnabled && !compiler.distccEnabled ? " " : "",
compiler.distccEnabled ? "distcc " : "",
- compiler.ccCommand);
- 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())
{
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 `");
//numErrors++;
//}
}
- else if(strstr(line, "ear ") == line);
- else if(strstr(line, "strip ") == line);
- else if(strstr(line, ccCommand) == 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)
+ 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;
// 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 ");
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
{
}
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");
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;
}
}
}
- 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];
DirExpression objDirExp = GetObjDir(compiler, config);
PathBackup pathBackup { };
+ bool crossCompiling = (compiler.targetPlatform != GetRuntimePlatform());
+ 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);
strcpy(makeFilePath, topNode.path);
CatMakeFileName(makeFile, config);
PathCatSlash(makeFilePath, makeFile);
-
+
// TODO: TEST ON UNIX IF \" around makeTarget is ok
- if(onlyNode)
+ if(onlyNodes)
{
if(compiler.type.isVC)
{
int len;
char pushD[MAX_LOCATION];
char cfDir[MAX_LOCATION];
- GetIDECompilerConfigsDir(cfDir);
+ GetIDECompilerConfigsDir(cfDir, true, true);
GetWorkingDir(pushD, sizeof(pushD));
ChangeWorkingDir(topNode.path);
// Create object dir if it does not exist already
if(!FileExists(objDirExp.dir).isDirectory)
- Execute("%s CF_DIR=%s COMPILER=%s objdir -C \"%s\" -f \"%s\"", compiler.makeCommand, cfDir, compilerName, topNode.path, makeFilePath);
+ {
+ 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, 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);
+ }
+ }
}
}
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);
+ if(justPrint)
+ ide.outputView.buildBox.Logf("%s\n", command);
if((f = DualPipeOpen(PipeOpenMode { output = true, error = true, input = true }, command)))
{
ProcessPipeOutputRaw(f);
else
{
char cfDir[MAX_LOCATION];
- GetIDECompilerConfigsDir(cfDir);
- sprintf(command, "%s CF_DIR=%s COMPILER=%s -j%d %s%s%s -C \"%s\" -f \"%s\"", compiler.makeCommand, cfDir, compilerName, numJobs,
+ GetIDECompilerConfigsDir(cfDir, true, true);
+ 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);
+ (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);
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];
char * compilerName;
DualPipe f;
PathBackup pathBackup { };
+ bool crossCompiling = (compiler.targetPlatform != GetRuntimePlatform());
+ char * targetPlatform = crossCompiling ? (char *)compiler.targetPlatform : "";
compilerName = CopyString(compiler.name);
CamelCase(compilerName);
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);
+ if(justPrint)
+ ide.outputView.buildBox.Logf("%s\n", command);
if((f = DualPipeOpen(PipeOpenMode { output = true, error = true, input = true }, command)))
{
ProcessPipeOutputRaw(f);
else
{
char cfDir[MAX_LOCATION];
- GetIDECompilerConfigsDir(cfDir);
- sprintf(command, "%s CF_DIR=%s COMPILER=%s %sclean -C \"%s\" -f \"%s\"", compiler.makeCommand, cfDir, compilerName, realclean ? "real" : "", topNode.path, makeFilePath);
+ GetIDECompilerConfigsDir(cfDir, true, true);
+ 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, 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");
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);
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
}
}
- bool GenerateCrossPlatformCf()
+ bool GenerateCrossPlatformMk()
{
bool result = false;
char path[MAX_LOCATION];
- if(!GetProjectCompilerConfigsDir(path))
- GetIDECompilerConfigsDir(path);
+ if(!GetProjectCompilerConfigsDir(path, false, false))
+ GetIDECompilerConfigsDir(path, false, false);
if(!FileExists(path).isDirectory)
+ {
MakeDir(path);
+ {
+ char dirName[MAX_FILENAME];
+ GetLastDirectory(path, dirName);
+ if(!strcmp(dirName, ".configs"))
+ FileSetAttribs(path, FileAttribs { isHidden = true });
+ }
+ }
PathCatSlash(path, "crossplatform.mk");
if(FileExists(path))
return result;
}
- bool GenerateCompilerMk(CompilerConfig compiler)
+ bool GenerateCompilerCf(CompilerConfig compiler)
{
bool result = false;
char path[MAX_LOCATION];
char * name;
char * compilerName;
- bool gccCompiler = compiler.ccCommand && strstr(compiler.ccCommand, "gcc") != null;
- Platform platform = GetRuntimePlatform();
+ bool gccCompiler = compiler.ccCommand && (strstr(compiler.ccCommand, "gcc") != null || strstr(compiler.ccCommand, "g++") != null);
+ Platform platform = compiler.targetPlatform;
compilerName = CopyString(compiler.name);
CamelCase(compilerName);
name = PrintString(platform, "-", compilerName, ".cf");
- if(!GetProjectCompilerConfigsDir(path))
- GetIDECompilerConfigsDir(path);
+ if(!GetProjectCompilerConfigsDir(path, false, false))
+ GetIDECompilerConfigsDir(path, false, false);
if(!FileExists(path).isDirectory)
+ {
MakeDir(path);
+ {
+ char dirName[MAX_FILENAME];
+ GetLastDirectory(path, dirName);
+ if(!strcmp(dirName, ".configs"))
+ FileSetAttribs(path, FileAttribs { isHidden = true });
+ }
+ }
PathCatSlash(path, name);
if(FileExists(path))
File f = FileOpen(path, write);
if(f)
{
- bool crossCompiling = compiler.targetPlatform != platform;
+ 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("# TOOLCHAIN\n\n");
+ if(compiler.gccPrefix && compiler.gccPrefix[0])
+ {
+ f.Printf("GCC_PREFIX := %s\n", compiler.gccPrefix);
+ f.Puts("\n");
+ }
+ if(compiler.sysroot && compiler.sysroot[0])
+ {
+ f.Printf("SYSROOT := %s\n", compiler.sysroot);
+ // Moved this to crossplatform.mk
+ //f.Puts("_SYSROOT := $(space)--sysroot=$(SYSROOT)\n");
+ f.Puts("\n");
+ }
- //f.Printf("SHELL := %s\n", "ar"/*compiler.arCommand*/); // is this really needed?
- f.Printf("CPP := $(CCACHE_COMPILE) $(DISTCC_COMPILE) %s\n", compiler.cppCommand);
- f.Printf("CC := $(CCACHE_COMPILE) $(DISTCC_COMPILE) %s\n", compiler.ccCommand);
- f.Printf("ECP := %s\n", compiler.ecpCommand);
- f.Printf("ECC := %s\n", compiler.eccCommand);
- f.Printf("ECS := %s%s%s\n", compiler.ecsCommand,
- crossCompiling ? " -t " : "", crossCompiling ? (char*)compiler.targetPlatform : "");
+ //f.Printf("SHELL := %s\n", "sh"/*compiler.shellCommand*/); // is this really needed?
+ 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 := $(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.Printf("AS := as\n");
- f.Printf("LD := ld\n");
- f.Printf("AR := ar\n");
- f.Printf("STRIP := strip\n");
- f.Printf("UPX := upx\n");
+ f.Puts("AS := $(GCC_PREFIX)as\n");
+ f.Puts("LD := $(GCC_PREFIX)ld\n");
+ f.Puts("AR := $(GCC_PREFIX)ar\n");
+ f.Puts("STRIP := $(GCC_PREFIX)strip\n");
+ f.Puts("UPX := upx\n");
+ f.Puts("\n");
- f.Printf("\n");
+ f.Puts("UPXFLAGS = -9\n"); // TOFEAT: Compression Level Option? Other UPX Options?
+ f.Puts("\n");
- f.Printf("UPXFLAGS = -9\n\n"); // TOFEAT: Compression Level Option? Other UPX Options?
+ f.Puts("EARFLAGS = \n");
+ f.Puts("\n");
- f.Printf("# HARD CODED PLATFORM-SPECIFIC OPTIONS\n");
- f.Printf("ifdef %s\n", PlatformToMakefileVariable(tux));
- f.Printf("OFLAGS += -Wl,--no-undefined\n");
- f.Printf("endif\n\n");
+ f.Puts("# HARD CODED TARGET_PLATFORM-SPECIFIC OPTIONS\n");
+ f.Printf("LDFLAGS +=$(if $(%s), -Wl$(comma)--no-undefined,)\n", PlatformToMakefileTargetVariable(tux));
+ f.Puts("\n");
// JF's
- f.Printf("ifdef %s\n", PlatformToMakefileVariable(apple));
- f.Printf("OFLAGS += -framework cocoa -framework OpenGL\n");
- f.Printf("endif\n\n");
+ f.Printf("LDFLAGS +=$(if $(%s), -framework cocoa -framework OpenGL,)\n", PlatformToMakefileTargetVariable(apple));
- if(crossCompiling)
- f.Printf("PLATFORM = %s\n", (char *)compiler.targetPlatform);
+ if(gccCompiler)
+ {
+ f.Puts("\nCFLAGS += -fmessage-length=0\n");
+ }
- if((compiler.includeDirs && compiler.includeDirs.count) ||
- (compiler.libraryDirs && compiler.libraryDirs.count))
+ if(compiler.includeDirs && compiler.includeDirs.count)
{
- if(compiler.includeDirs && compiler.includeDirs.count)
- {
- f.Printf("CFLAGS +=");
- OutputListOption(f, gccCompiler ? "isystem " : "I", compiler.includeDirs, lineEach, true);
- f.Printf("\n");
- }
- if(compiler.libraryDirs && compiler.libraryDirs.count)
+ f.Puts("\nCFLAGS +=");
+ OutputListOption(f, gccCompiler ? "isystem " : "I", compiler.includeDirs, lineEach, true);
+ f.Puts("\n");
+ }
+ if(compiler.prepDirectives && compiler.prepDirectives.count)
+ {
+ f.Puts("\nCFLAGS +=");
+ OutputListOption(f, "D", compiler.prepDirectives, inPlace, true);
+ f.Puts("\n");
+ }
+ if(compiler.libraryDirs && compiler.libraryDirs.count)
+ {
+ f.Puts("\nLDFLAGS +=");
+ OutputListOption(f, "L", compiler.libraryDirs, lineEach, true);
+ // We would need a bool option to know whether we want to add to rpath as well...
+ // OutputListOption(f, "Wl,-rpath ", compiler.libraryDirs, lineEach, true);
+ f.Puts("\n");
+ }
+ if(compiler.excludeLibs && compiler.excludeLibs.count)
+ {
+ f.Puts("\nEXCLUDED_LIBS =");
+ for(l : compiler.excludeLibs)
{
- f.Printf("OFLAGS +=");
- OutputListOption(f, "L", compiler.libraryDirs, lineEach, true);
- f.Printf("\n");
+ f.Puts(" ");
+ f.Puts(l);
}
- f.Printf("\n");
}
+ if(compiler.linkerFlags && compiler.linkerFlags.count)
+ {
+ f.Puts("\nLDFLAGS +=");
+ OutputListOption(f, "Wl,", compiler.linkerFlags, inPlace, true);
+ f.Puts("\n");
+ }
+ 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;
+
+ result = true;
}
}
delete name;
return result;
}
- bool GenerateMakefile(char * altMakefilePath, bool noResources, char * includemkPath,
- CompilerConfig compiler, ProjectConfig config)
+ bool GenerateMakefile(char * altMakefilePath, bool noResources, char * includemkPath, ProjectConfig config)
{
bool result = false;
char filePath[MAX_LOCATION];
PathCatSlash(filePath, makeFile);
}
-#if defined(__WIN32__) && !defined(MAKEFILE_GENERATOR)
- if(compiler.type.isVC)
- {
- GenerateVSSolutionFile(this, compiler);
- GenerateVCProjectFile(this, compiler);
- }
- else
-#endif
f = FileOpen(altMakefilePath ? altMakefilePath : filePath, write);
/*SetPath(false, compiler, config);
bool test;
int ifCount;
Platform platform;
- Platform runtimePlatform = GetRuntimePlatform();
char targetDir[MAX_LOCATION];
char objDirExpNoSpaces[MAX_LOCATION];
char objDirNoSpaces[MAX_LOCATION];
char targetDirExpNoSpaces[MAX_LOCATION];
char fixedModuleName[MAX_FILENAME];
char fixedConfigName[MAX_FILENAME];
- char fixedCompilerName[MAX_FILENAME];
int c, len;
+ // Non-zero if we're building eC code
+ // We'll have to be careful with this when merging configs where eC files can be excluded in some configs and included in others
int numCObjects = 0;
+ int numObjects = 0;
+ bool containsCXX = false; // True if the project contains a C++ file
bool sameObjTargetDirs;
- DirExpression objDirExp = GetObjDir(compiler, config);
+ String objDirExp = GetObjDirExpression(config);
TargetTypes targetType = GetTargetType(config);
- bool crossCompiling = compiler.targetPlatform != runtimePlatform;
- bool gccCompiler = compiler.ccCommand && strstr(compiler.ccCommand, "gcc") != null;
- bool tccCompiler = compiler.ccCommand && strstr(compiler.ccCommand, "tcc") != null;
- bool defaultPreprocessor = compiler.cppCommand && (strstr(compiler.cppCommand, "gcc") != null || compiler.cppCommand && strstr(compiler.cppCommand, "cpp") != null);
char cfDir[MAX_LOCATION];
- int objectsParts, eCsourcesParts;
+ int objectsParts = 0, eCsourcesParts = 0;
Array<String> listItems { };
Map<String, int> varStringLenDiffs { };
Map<String, NameCollisionInfo> namesInfo { };
+ bool forceBitDepth = false;
+
+ Map<String, int> cflagsVariations { };
+ Map<int, int> nodeCFlagsMapping { };
- ReplaceSpaces(objDirNoSpaces, objDirExp.dir);
- strcpy(targetDir, GetTargetDirExpression(compiler, config));
+ Map<String, int> ecflagsVariations { };
+ Map<int, int> nodeECFlagsMapping { };
+
+ ReplaceSpaces(objDirNoSpaces, objDirExp);
+ strcpy(targetDir, GetTargetDirExpression(config));
ReplaceSpaces(targetDirExpNoSpaces, targetDir);
- strcpy(objDirExpNoSpaces, GetObjDirExpression(compiler, config));
+ strcpy(objDirExpNoSpaces, GetObjDirExpression(config));
ChangeCh(objDirExpNoSpaces, '\\', '/'); // TODO: this is a hack, paths should never include win32 path seperators - fix this in ProjectSettings and ProjectLoad instead
ReplaceSpaces(objDirExpNoSpaces, objDirExpNoSpaces);
ReplaceSpaces(resDirNoSpaces, resNode.path ? resNode.path : "");
- //ReplaceSpaces(fixedPrjName, name);
ReplaceSpaces(fixedModuleName, moduleName);
ReplaceSpaces(fixedConfigName, GetConfigName(config));
- ReplaceSpaces(fixedCompilerName, compiler.name);
- //CamelCase(fixedModuleName); // case is important for static linking
CamelCase(fixedConfigName);
- CamelCase(fixedCompilerName);
sameObjTargetDirs = !fstrcmp(objDirExpNoSpaces, targetDirExpNoSpaces);
- f.Printf(".PHONY: all objdir%s clean realclean\n\n", sameObjTargetDirs ? "" : " targetdir");
+ f.Printf(".PHONY: all objdir%s cleantarget clean realclean distclean\n\n", sameObjTargetDirs ? "" : " targetdir");
- f.Printf("# CONTENT\n\n");
+ f.Puts("# CORE VARIABLES\n\n");
f.Printf("MODULE := %s\n", fixedModuleName);
//f.Printf("VERSION = %s\n", version);
f.Printf("CONFIG := %s\n", fixedConfigName);
- f.Printf("ifndef COMPILER\n");
- f.Printf("COMPILER := default\n");
- f.Printf("endif\n");
- f.Printf("\n");
-
- if(compilerConfigsDir && compilerConfigsDir[0])
- {
- strcpy(cfDir, compilerConfigsDir);
- if(cfDir && cfDir[0] && cfDir[strlen(cfDir)-1] != '/')
- strcat(cfDir, "/");
- }
- else
- strcpy(cfDir, "$(CF_DIR)");
-
- f.Printf("_CF_DIR = %s\n", cfDir);
- f.Printf("\n");
-
- f.Printf("ifndef DEBUG\n");
- f.Printf("OPTIMIZE :=");
- switch(GetOptimization(config))
- {
- case speed:
- f.Printf(" -O2");
- f.Printf(" -ffast-math");
- break;
- case size:
- f.Printf(" -Os");
- break;
- }
- if(GetDebug(config))
- f.Printf(" -g");
- f.Printf("\n");
- f.Printf("else\n");
- f.Printf("OPTIMIZE := -g\n");
- f.Printf("NOSTRIP := y\n");
- f.Printf("endif\n");
+ f.Puts("ifndef COMPILER\n" "COMPILER := default\n" "endif\n");
+ f.Puts("\n");
test = GetTargetTypeIsSetByPlatform(config);
if(test)
if(targetType)
{
if(ifCount)
- f.Printf("else\n");
+ f.Puts("else\n");
ifCount++;
- f.Printf("ifdef %s\n", PlatformToMakefileVariable(platform));
-
- f.Printf("TARGET_TYPE = ");
- f.Printf(TargetTypeToMakefileVariable(targetType));
- f.Printf("\n");
+ f.Printf("ifdef %s\n", PlatformToMakefileTargetVariable(platform));
+ f.Printf("TARGET_TYPE = %s\n", TargetTypeToMakefileVariable(targetType));
}
}
- f.Printf("else\n"); // ifCount should always be > 0
+ f.Puts("else\n");
}
- f.Printf("TARGET_TYPE = ");
- f.Printf(TargetTypeToMakefileVariable(targetType));
- f.Printf("\n");
+ f.Printf("TARGET_TYPE = %s\n", TargetTypeToMakefileVariable(targetType));
if(test)
{
if(ifCount)
{
for(c = 0; c < ifCount; c++)
- f.Printf("endif\n");
+ f.Puts("endif\n");
}
}
- f.Printf("\n");
+ f.Puts("\n");
- f.Printf("# FLAGS\n\n");
+ f.Puts("# FLAGS\n\n");
- f.Printf("CFLAGS =\n");
- f.Printf("CECFLAGS =\n");
- f.Printf("ECFLAGS =\n");
- f.Printf("OFLAGS =\n");
- f.Printf("LIBS =\n");
- f.Printf("\n");
+ 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");
+ f.Puts("\n");
+
+ f.Puts("ifdef DEBUG\n" "NOSTRIP := y\n" "endif\n");
+ f.Puts("\n");
+
+ // Important: We cannot use this ifdef anymore, EXECUTABLE_TARGET is not yet defined. It's embedded in the crossplatform.mk EXECUTABLE
+ //f.Puts("ifdef EXECUTABLE_TARGET\n");
+ f.Printf("CONSOLE = %s\n", GetConsole(config) ? "-mconsole" : "-mwindows");
+ //f.Puts("endif\n");
+ f.Puts("\n");
- f.Printf("# INCLUDES\n\n");
+ f.Puts("# INCLUDES\n\n");
+
+ if(compilerConfigsDir && compilerConfigsDir[0])
+ {
+ strcpy(cfDir, compilerConfigsDir);
+ if(cfDir && cfDir[0] && cfDir[strlen(cfDir)-1] != '/')
+ strcat(cfDir, "/");
+ }
+ else
+ {
+ GetIDECompilerConfigsDir(cfDir, true, true);
+ // Use CF_DIR environment variable for absolute paths only
+ if(cfDir[0] == '/' || (cfDir[0] && cfDir[1] == ':'))
+ strcpy(cfDir, "$(CF_DIR)");
+ }
+
+ f.Printf("_CF_DIR = %s\n", cfDir);
+ f.Puts("\n");
f.Printf("include %s\n", includemkPath ? includemkPath : "$(_CF_DIR)crossplatform.mk");
- f.Printf("include $(_CF_DIR)$(PLATFORM)-$(COMPILER).cf\n", (char*)runtimePlatform, fixedCompilerName);
- f.Printf("\n");
+ f.Puts("include $(_CF_DIR)$(TARGET_PLATFORM)-$(COMPILER).cf\n");
+ f.Puts("\n");
- f.Printf("# VARIABLES\n\n");
+ f.Puts("# POST-INCLUDES VARIABLES\n\n");
- f.Printf("ifndef DEBUG\n");
f.Printf("OBJ = %s%s\n", objDirExpNoSpaces, objDirExpNoSpaces[0] ? "/" : "");
- f.Printf("else\n");
- f.Printf("OBJ = %s.debug%s\n", objDirExpNoSpaces, objDirExpNoSpaces[0] ? "/" : "");
- f.Printf("CFLAGS += _DEBUG\n");
- f.Printf("endif\n\n");
+ f.Puts("\n");
- f.Printf("RES = %s%s\n\n", resDirNoSpaces, resDirNoSpaces[0] ? "/" : "");
+ f.Printf("RES = %s%s\n", resDirNoSpaces, resDirNoSpaces[0] ? "/" : "");
+ f.Puts("\n");
// test = GetTargetTypeIsSetByPlatform(config);
{
char target[MAX_LOCATION];
char targetNoSpaces[MAX_LOCATION];
- if(test)
- {
- TargetTypes type;
- ifCount = 0;
- for(type = (TargetTypes)1; type < TargetTypes::enumSize; type++)
+ if(test)
{
- if(type != targetType)
+ TargetTypes type;
+ ifCount = 0;
+ for(type = (TargetTypes)1; type < TargetTypes::enumSize; type++)
{
- if(ifCount)
- f.Printf("else\n");
- ifCount++;
- f.Printf("ifeq \"$(TARGET_TYPE)\" \"%s\"\n", TargetTypeToMakefileVariable(type));
-
- GetMakefileTargetFileName(type, target, config);
- f.Printf("ifndef DEBUG\n");
- strcpy(targetNoSpaces, targetDir);
- PathCatSlash(targetNoSpaces, target);
- ReplaceSpaces(targetNoSpaces, targetNoSpaces);
- f.Printf("TARGET = %s\n", targetNoSpaces);
- f.Printf("else\n");
- strcpy(targetNoSpaces, targetDir);
- strcat(targetNoSpaces, ".debug");
- PathCatSlash(targetNoSpaces, target);
- ReplaceSpaces(targetNoSpaces, targetNoSpaces);
- f.Printf("TARGET = %s\n", targetNoSpaces);
- f.Printf("endif\n");
+ if(type != targetType)
+ {
+ if(ifCount)
+ f.Puts("else\n");
+ ifCount++;
+ f.Printf("ifeq \"$(TARGET_TYPE)\" \"%s\"\n", TargetTypeToMakefileVariable(type));
+
+ GetMakefileTargetFileName(type, target, config);
+ strcpy(targetNoSpaces, targetDir);
+ PathCatSlash(targetNoSpaces, target);
+ ReplaceSpaces(targetNoSpaces, targetNoSpaces);
+ f.Printf("TARGET = %s\n", targetNoSpaces);
+ }
}
+ f.Puts("else\n");
}
- f.Printf("else\n"); // ifCount should always be > 0
- }
- GetMakefileTargetFileName(targetType, target, config);
- f.Printf("ifndef DEBUG\n");
- strcpy(targetNoSpaces, targetDir);
- PathCatSlash(targetNoSpaces, target);
- ReplaceSpaces(targetNoSpaces, targetNoSpaces);
- f.Printf("TARGET = %s\n", targetNoSpaces);
- f.Printf("else\n");
- strcpy(targetNoSpaces, targetDir);
- strcat(targetNoSpaces, ".debug");
- PathCatSlash(targetNoSpaces, target);
- ReplaceSpaces(targetNoSpaces, targetNoSpaces);
- f.Printf("TARGET = %s\n", targetNoSpaces);
- f.Printf("endif\n");
+ GetMakefileTargetFileName(targetType, target, config);
+ strcpy(targetNoSpaces, targetDir);
+ PathCatSlash(targetNoSpaces, target);
+ ReplaceSpaces(targetNoSpaces, targetNoSpaces);
+ f.Printf("TARGET = %s\n", targetNoSpaces);
- if(test)
- {
- if(ifCount)
+ if(test)
{
- for(c = 0; c < ifCount; c++)
- f.Printf("endif\n");
+ if(ifCount)
+ {
+ for(c = 0; c < ifCount; c++)
+ f.Puts("endif\n");
+ }
}
}
- }
- f.Printf("\n");
+ f.Puts("\n");
- varStringLenDiffs["$(OBJ)"] = strlen(objDirNoSpaces) - 6;
+ // Use something fixed here, to not cause Makefile differences across compilers...
+ varStringLenDiffs["$(OBJ)"] = 30; // strlen("obj/memoryGuard.android.gcc-4.6.2") - 6;
+ // varStringLenDiffs["$(OBJ)"] = strlen(objDirNoSpaces) - 6;
topNode.GenMakefileGetNameCollisionInfo(namesInfo, config);
- numCObjects = topNode.GenMakefilePrintNode(f, this, objects, namesInfo, listItems, config);
- if(numCObjects)
- listItems.Add(CopyString("$(OBJ)$(MODULE).main$(O)"));
- objectsParts = OutputFileList(f, "OBJECTS", listItems, varStringLenDiffs, null);
-
{
int c;
- char * map[3][2] = { { "COBJECTS", "C" }, { "SYMBOLS", "S" }, { "IMPORTS", "I" } };
-
- topNode.GenMakefilePrintNode(f, this, eCsources, namesInfo, listItems, config);
- eCsourcesParts = OutputFileList(f, "_ECSOURCES", listItems, varStringLenDiffs, null);
+ char * map[5][2] = { { "COBJECTS", "C" }, { "SYMBOLS", "S" }, { "IMPORTS", "I" }, { "ECOBJECTS", "O" }, { "BOWLS", "B" } };
- f.Printf("ECSOURCES = $(call shwspace,$(_ECSOURCES))\n");
- if(eCsourcesParts > 1)
+ numCObjects = topNode.GenMakefilePrintNode(f, this, eCsources, namesInfo, listItems, config, null);
+ if(numCObjects)
{
- for(c = 1; c <= eCsourcesParts; c++)
- f.Printf("ECSOURCES%d = $(call shwspace,$(_ECSOURCES%d))\n", c, c);
- }
- f.Printf("\n");
+ eCsourcesParts = OutputFileList(f, "_ECSOURCES", listItems, varStringLenDiffs, null);
- for(c = 0; c < 3; c++)
- {
+ f.Puts("ECSOURCES = $(call shwspace,$(_ECSOURCES))\n");
if(eCsourcesParts > 1)
{
- int n;
- f.Printf("%s =", map[c][0]);
- for(n = 1; n <= eCsourcesParts; n++)
- f.Printf(" $(%s%d)", map[c][0], n);
- f.Printf("\n");
- for(n = 1; n <= eCsourcesParts; n++)
- f.Printf("%s%d = $(call shwspace,$(addprefix $(OBJ),$(patsubst %%.ec,%%$(%s),$(notdir $(_ECSOURCES%d)))))\n", map[c][0], n, map[c][1], n);
+ for(c = 1; c <= eCsourcesParts; c++)
+ f.Printf("ECSOURCES%d = $(call shwspace,$(_ECSOURCES%d))\n", c, c);
+ }
+ f.Puts("\n");
+
+ for(c = 0; c < 5; c++)
+ {
+ if(eCsourcesParts > 1)
+ {
+ int n;
+ f.Printf("%s =", map[c][0]);
+ for(n = 1; n <= eCsourcesParts; n++)
+ f.Printf(" $(%s%d)", map[c][0], n);
+ f.Puts("\n");
+ for(n = 1; n <= eCsourcesParts; n++)
+ f.Printf("%s%d = $(call shwspace,$(addprefix $(OBJ),$(patsubst %%.ec,%%$(%s),$(notdir $(_ECSOURCES%d)))))\n", map[c][0], n, map[c][1], n);
+ }
+ else if(eCsourcesParts == 1)
+ f.Printf("%s = $(call shwspace,$(addprefix $(OBJ),$(patsubst %%.ec,%%$(%s),$(notdir $(_ECSOURCES)))))\n", map[c][0], map[c][1]);
+ f.Puts("\n");
}
- else if(eCsourcesParts == 1)
- f.Printf("%s = $(call shwspace,$(addprefix $(OBJ),$(patsubst %%.ec,%%$(%s),$(notdir $(_ECSOURCES)))))\n", map[c][0], map[c][1]);
- f.Printf("\n");
}
}
- topNode.GenMakefilePrintNode(f, this, sources, null, listItems, config);
- OutputFileList(f, "SOURCES", listItems, varStringLenDiffs, "$(ECSOURCES)");
+ numObjects = topNode.GenMakefilePrintNode(f, this, objects, namesInfo, listItems, config, &containsCXX);
+ if(numObjects)
+ objectsParts = OutputFileList(f, "_OBJECTS", listItems, varStringLenDiffs, null);
+ f.Printf("OBJECTS =%s%s%s\n", numObjects ? " $(_OBJECTS)" : "", numCObjects ? " $(ECOBJECTS)" : "", numCObjects ? " $(OBJ)$(MODULE).main$(O)" : "");
+ f.Puts("\n");
+
+ topNode.GenMakefilePrintNode(f, this, sources, null, listItems, config, null);
+ OutputFileList(f, "SOURCES", listItems, varStringLenDiffs, numCObjects ? "$(ECSOURCES)" : null);
if(!noResources)
- resNode.GenMakefilePrintNode(f, this, resources, null, listItems, config);
+ resNode.GenMakefilePrintNode(f, this, resources, null, listItems, config, null);
OutputFileList(f, "RESOURCES", listItems, varStringLenDiffs, null);
- f.Printf("ifeq \"$(TARGET_TYPE)\" \"%s\"\n", TargetTypeToMakefileVariable(executable));
- f.Printf("CONSOLE = %s\n", GetConsole(config) ? "-mconsole" : "-mwindows");
- f.Printf("endif\n\n");
-
+ f.Puts("LIBS += $(SHAREDLIB) $(EXECUTABLE) $(LINKOPT)\n");
+ f.Puts("\n");
if((config && config.options && config.options.libraries) ||
(options && options.libraries))
{
- f.Printf("ifneq \"$(TARGET_TYPE)\" \"%s\"\n", TargetTypeToMakefileVariable(staticLibrary));
- f.Printf("LIBS +=");
+ f.Puts("ifndef STATIC_LIBRARY_TARGET\n");
+ f.Puts("LIBS +=");
if(config && config.options && config.options.libraries)
OutputLibraries(f, config.options.libraries);
else if(options && options.libraries)
OutputLibraries(f, options.libraries);
- f.Printf("\n");
- f.Printf("endif\n");
- f.Printf("\n");
+ f.Puts("\n");
+ f.Puts("endif\n");
+ f.Puts("\n");
}
- f.Printf("LIBS += $(SHAREDLIB) $(EXECUTABLE) $(LINKOPT)\n\n");
+
+ topNode.GenMakeCollectAssignNodeFlags(config, numCObjects,
+ cflagsVariations, nodeCFlagsMapping,
+ ecflagsVariations, nodeECFlagsMapping, null);
+
+ GenMakePrintCustomFlags(f, "PRJ_CFLAGS", false, cflagsVariations);
+ GenMakePrintCustomFlags(f, "ECFLAGS", true, ecflagsVariations);
if(platforms || (config && config.platforms))
{
//for(platform = firstPlatform; platform <= lastPlatform; platform++)
//for(platform = win32; platform <= apple; platform++)
- f.Printf("# PLATFORM-SPECIFIC OPTIONS\n\n");
+ f.Puts("# PLATFORM-SPECIFIC OPTIONS\n\n");
for(platform = (Platform)1; platform < Platform::enumSize; platform++)
{
PlatformOptions projectPlatformOptions, configPlatformOptions;
if(projectPlatformOptions || configPlatformOptions)
{
if(ifCount)
- f.Printf("else\n");
+ f.Puts("else\n");
ifCount++;
- f.Printf("ifdef ");
- f.Printf(PlatformToMakefileVariable(platform));
- f.Printf("\n\n");
-
- if((projectPlatformOptions && projectPlatformOptions.options.preprocessorDefinitions && projectPlatformOptions.options.preprocessorDefinitions.count) ||
- (configPlatformOptions && configPlatformOptions.options.preprocessorDefinitions && configPlatformOptions.options.preprocessorDefinitions.count) ||
- (projectPlatformOptions && projectPlatformOptions.options.includeDirs && projectPlatformOptions.options.includeDirs.count) ||
- (configPlatformOptions && configPlatformOptions.options.includeDirs && configPlatformOptions.options.includeDirs.count))
+ f.Printf("ifdef %s\n", PlatformToMakefileTargetVariable(platform));
+ f.Puts("\n");
+
+ if((projectPlatformOptions && projectPlatformOptions.options.linkerOptions && projectPlatformOptions.options.linkerOptions.count) ||
+ (configPlatformOptions && configPlatformOptions.options.linkerOptions && configPlatformOptions.options.linkerOptions.count))
{
- f.Printf("CFLAGS +=");
+ f.Puts("OFLAGS +=");
if(projectPlatformOptions && projectPlatformOptions.options.linkerOptions && projectPlatformOptions.options.linkerOptions.count)
{
- f.Printf(" \\\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.Printf(" \\\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);
+ }
}
- if(projectPlatformOptions && projectPlatformOptions.options.preprocessorDefinitions)
- OutputListOption(f, "D", projectPlatformOptions.options.preprocessorDefinitions, newLine, false);
- if(configPlatformOptions && configPlatformOptions.options.preprocessorDefinitions)
- OutputListOption(f, "D", configPlatformOptions.options.preprocessorDefinitions, newLine, false );
- if(configPlatformOptions && configPlatformOptions.options.includeDirs)
- OutputListOption(f, "I", configPlatformOptions.options.includeDirs, lineEach, true);
- if(projectPlatformOptions && projectPlatformOptions.options.includeDirs)
- OutputListOption(f, "I", projectPlatformOptions.options.includeDirs, lineEach, true);
- f.Printf("\n\n");
+ f.Puts("\n");
+ f.Puts("\n");
}
if((projectPlatformOptions && projectPlatformOptions.options.libraryDirs && projectPlatformOptions.options.libraryDirs.count) ||
(projectPlatformOptions && projectPlatformOptions.options.libraries && projectPlatformOptions.options.libraries.count) ||
(configPlatformOptions && configPlatformOptions.options.libraries && configPlatformOptions.options.libraries.count))
{
- f.Printf("ifneq \"$(TARGET_TYPE)\" \"%s\"\n", TargetTypeToMakefileVariable(staticLibrary));
+ f.Puts("ifndef STATIC_LIBRARY_TARGET\n");
if((projectPlatformOptions && projectPlatformOptions.options.libraryDirs && projectPlatformOptions.options.libraryDirs.count) ||
(configPlatformOptions && configPlatformOptions.options.libraryDirs && configPlatformOptions.options.libraryDirs.count))
{
- f.Printf("OFLAGS +=");
+ f.Puts("OFLAGS +=");
if(configPlatformOptions && configPlatformOptions.options.libraryDirs)
OutputListOption(f, "L", configPlatformOptions.options.libraryDirs, lineEach, true);
if(projectPlatformOptions && projectPlatformOptions.options.libraryDirs)
OutputListOption(f, "L", projectPlatformOptions.options.libraryDirs, lineEach, true);
- f.Printf("\n");
+ f.Puts("\n");
}
- if(projectPlatformOptions && projectPlatformOptions.options.libraries &&
- projectPlatformOptions.options.libraries.count)
+ if((configPlatformOptions && configPlatformOptions.options.libraries))
{
- f.Printf("LIBS +=");
- OutputLibraries(f, projectPlatformOptions.options.libraries);
- f.Printf("\n");
+ if(configPlatformOptions.options.libraries.count)
+ {
+ f.Puts("LIBS +=");
+ OutputLibraries(f, configPlatformOptions.options.libraries);
+ f.Puts("\n");
+ }
}
- if((configPlatformOptions && configPlatformOptions.options.libraries &&
- configPlatformOptions.options.libraries.count))
+ else if(projectPlatformOptions && projectPlatformOptions.options.libraries)
{
- f.Printf("LIBS +=");
- OutputLibraries(f, configPlatformOptions.options.libraries);
- f.Printf("\n");
+ if(projectPlatformOptions.options.libraries.count)
+ {
+ f.Puts("LIBS +=");
+ OutputLibraries(f, projectPlatformOptions.options.libraries);
+ f.Puts("\n");
+ }
}
- f.Printf("endif\n\n");
+ f.Puts("endif\n");
+ f.Puts("\n");
}
}
}
if(ifCount)
{
for(c = 0; c < ifCount; c++)
- f.Printf("endif\n");
+ f.Puts("endif\n");
}
- f.Printf("\n");
- }
-
- f.Printf("CFLAGS +=");
- if(gccCompiler)
- {
- f.Printf(" -fmessage-length=0 $(OPTIMIZE)");
- //if(compiler.targetPlatform.is32Bits)
- f.Printf(" -m32");
- //else if(compiler.targetPlatform.is64Bits)
- // f.Printf(" -m64");
- f.Printf(" $(FPIC)");
- //f.Printf(" -fpack-struct");
- }
- switch(GetWarnings(config))
- {
- case all: f.Printf(" -Wall"); break;
- case none: f.Printf(" -w"); break;
- }
- if(GetProfile(config))
- f.Printf(" -pg");
- if(options && options.linkerOptions && options.linkerOptions.count)
- {
- f.Printf(" \\\n\t -Wl");
- for(s : options.linkerOptions)
- f.Printf(",%s", s);
- }
-
- if(options && options.preprocessorDefinitions)
- OutputListOption(f, "D", options.preprocessorDefinitions, newLine, false);
- if(config && config.options && config.options.preprocessorDefinitions)
- OutputListOption(f, "D", config.options.preprocessorDefinitions, newLine, false);
- if(config && config.options && config.options.includeDirs)
- OutputListOption(f, "I", config.options.includeDirs, lineEach, true);
- if(options && options.includeDirs)
- OutputListOption(f, "I", options.includeDirs, lineEach, true);
- f.Printf("\n\n");
-
- f.Printf("CECFLAGS +=%s%s%s%s", defaultPreprocessor ? "" : " -cpp ", defaultPreprocessor ? "" : compiler.cppCommand,
- crossCompiling ? " -t " : "", crossCompiling ? (char*)compiler.targetPlatform : "");
- f.Printf("\n\n");
-
- f.Printf("ECFLAGS +=");
- if(GetMemoryGuard(config))
- f.Printf(" -memguard");
- if(GetStrictNameSpaces(config))
- f.Printf(" -strictns");
- if(GetNoLineNumbers(config))
- f.Printf(" -nolinenumbers");
- {
- char * s;
- if((s = GetDefaultNameSpace(config)) && s[0])
- f.Printf(" -defaultns %s", s);
- }
- f.Printf("\n\n");
-
- f.Printf("OFLAGS +=\n");
- f.Printf("ifneq \"$(TARGET_TYPE)\" \"%s\"\n", TargetTypeToMakefileVariable(staticLibrary));
- f.Printf("OFLAGS += -m32");
- if(GetProfile(config))
- f.Printf(" -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.Printf("\n");
- f.Printf("endif\n\n");
+ f.Puts("\n");
+ }
+
+ if((config && config.options && config.options.linkerOptions && config.options.linkerOptions.count) ||
+ (options && options.linkerOptions && options.linkerOptions.count))
+ {
+ 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("CECFLAGS += -cpp $(_CPP)");
+ f.Puts("\n");
+ f.Puts("\n");
- f.Printf("# TARGETS\n\n");
+ forceBitDepth = (options && options.buildBitDepth) || numCObjects;
+ 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.Printf("all: objdir%s $(TARGET)\n\n", sameObjTargetDirs ? "" : " targetdir");
+ f.Puts("# TARGETS\n");
+ f.Puts("\n");
- f.Printf("objdir:\n");
- f.Printf("\t$(if $(wildcard $(OBJ)),,$(call mkdirq,$(OBJ)))\n");
- //f.Printf("# PRE-BUILD COMMANDS\n");
+ f.Printf("all: objdir%s $(TARGET)\n", sameObjTargetDirs ? "" : " targetdir");
+ f.Puts("\n");
+
+ f.Puts("objdir:\n");
+ f.Puts("\t$(if $(wildcard $(OBJ)),,$(call mkdirq,$(OBJ)))\n");
+ //f.Puts("# PRE-BUILD COMMANDS\n");
if(options && options.prebuildCommands)
{
for(s : options.prebuildCommands)
if(platforms || (config && config.platforms))
{
ifCount = 0;
- //f.Printf("# PLATFORM-SPECIFIC PRE-BUILD COMMANDS\n");
+ //f.Puts("# TARGET_PLATFORM-SPECIFIC PRE-BUILD COMMANDS\n");
for(platform = (Platform)1; platform < Platform::enumSize; platform++)
{
PlatformOptions projectPOs, configPOs;
(configPOs && configPOs.options.prebuildCommands && configPOs.options.prebuildCommands.count))
{
if(ifCount)
- f.Printf("else\n");
+ f.Puts("else\n");
ifCount++;
- f.Printf("ifdef ");
- f.Printf(PlatformToMakefileVariable(platform));
- f.Printf("\n");
+ f.Printf("ifdef %s\n", PlatformToMakefileTargetVariable(platform));
if(projectPOs && projectPOs.options.prebuildCommands && projectPOs.options.prebuildCommands.count)
{
{
int c;
for(c = 0; c < ifCount; c++)
- f.Printf("endif\n");
+ f.Puts("endif\n");
}
}
- f.Printf("\n");
+ f.Puts("\n");
if(!sameObjTargetDirs)
{
- f.Printf("targetdir:\n");
- f.Printf("\t$(if $(wildcard %s),,$(call mkdirq,%s))\n\n", targetDirExpNoSpaces, targetDirExpNoSpaces);
+ f.Puts("targetdir:\n");
+ f.Printf("\t$(if $(wildcard %s),,$(call mkdirq,%s))\n", targetDirExpNoSpaces, targetDirExpNoSpaces);
+ f.Puts("\n");
}
if(numCObjects)
{
// Main Module (Linking) for ECERE C modules
- f.Printf("$(OBJ)$(MODULE).main.ec: $(SYMBOLS) $(COBJECTS)\n");
+ 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\n",
+ f.Printf("\t$(ECS)%s $(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
- f.Printf("$(OBJ)$(MODULE).main.c: $(OBJ)$(MODULE).main.ec\n");
- f.Printf("\t$(ECP) $(CECFLAGS) $(ECFLAGS) $(CFLAGS)"
+ f.Puts("$(OBJ)$(MODULE).main.c: $(OBJ)$(MODULE).main.ec\n");
+ f.Puts("\t$(ECP) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS)"
" -c $(OBJ)$(MODULE).main.ec -o $(OBJ)$(MODULE).main.sym -symbols $(OBJ)\n");
- f.Printf("\t$(ECC) $(CECFLAGS) $(ECFLAGS) $(CFLAGS) $(FVISIBILITY)"
- " -c $(OBJ)$(MODULE).main.ec -o $(OBJ)$(MODULE).main.c -symbols $(OBJ)\n\n");
+ 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");
}
// *** Target ***
// f.Printf("$(TARGET): $(SOURCES) $(RESOURCES) | objdir $(SYMBOLS) $(OBJECTS)%s\n", sameObjTargetDirs ? "" : " targetdir");
// This should fix it for good!
- f.Printf("$(SYMBOLS): | objdir\n");
- f.Printf("$(OBJECTS): | objdir\n");
+ f.Puts("$(SYMBOLS): | objdir\n");
+ f.Puts("$(OBJECTS): | objdir\n");
// This alone was breaking the tarball, object directory does not get created first (order-only rules happen last it seems!)
f.Printf("$(TARGET): $(SOURCES) $(RESOURCES) $(SYMBOLS) $(OBJECTS) | objdir%s\n", sameObjTargetDirs ? "" : " targetdir");
- f.Printf("ifneq \"$(TARGET_TYPE)\" \"%s\"\n", TargetTypeToMakefileVariable(staticLibrary));
- f.Printf("\t$(CC) $(OFLAGS) $(OBJECTS) $(LIBS) -o $(TARGET) $(INSTALLNAME)\n");
+ f.Puts("ifndef STATIC_LIBRARY_TARGET\n");
+ f.Printf("\t$(%s) $(OFLAGS) $(OBJECTS) $(LIBS) %s-o $(TARGET) $(INSTALLNAME)\n", containsCXX ? "CXX" : "CC", containsCXX ? "-lstdc++ " : "");
if(!GetDebug(config))
{
- f.Printf("ifndef NOSTRIP\n");
- f.Printf("\t$(STRIP) $(STRIPOPT) $(TARGET)\n");
- f.Printf("endif\n");
+ f.Puts("ifndef NOSTRIP\n");
+ f.Puts("\t$(STRIP) $(STRIPOPT) $(TARGET)\n");
+ f.Puts("endif\n");
if(GetCompress(config))
{
- f.Printf("ifndef WINDOWS\n");
- f.Printf("ifeq \"$(TARGET_TYPE)\" \"%s\"\n", TargetTypeToMakefileVariable(executable));
- f.Printf("\t$(UPX) $(UPXFLAGS) $(TARGET)\n");
- f.Printf("endif\n");
- f.Printf("else\n");
- f.Printf("\t$(UPX) $(UPXFLAGS) $(TARGET)\n");
- f.Printf("endif\n");
+ f.Printf("ifndef %s\n", PlatformToMakefileTargetVariable(win32));
+ f.Puts("ifdef EXECUTABLE_TARGET\n");
+ f.Puts("\t$(UPX) $(UPXFLAGS) $(TARGET)\n");
+ f.Puts("endif\n");
+ f.Puts("else\n");
+ f.Puts("\t$(UPX) $(UPXFLAGS) $(TARGET)\n");
+ f.Puts("endif\n");
}
}
if(resNode.files && resNode.files.count && !noResources)
resNode.GenMakefileAddResources(f, resNode.path, config);
- f.Printf("else\n");
- f.Printf("\t$(AR) rcs $(TARGET) $(OBJECTS) $(LIBS)\n");
- f.Printf("endif\n");
+ f.Puts("else\n");
+ f.Puts("\t$(AR) rcs $(TARGET) $(OBJECTS) $(LIBS)\n");
+ f.Puts("endif\n");
- //f.Printf("# POST-BUILD COMMANDS\n");
+ //f.Puts("# POST-BUILD COMMANDS\n");
if(options && options.postbuildCommands)
{
for(s : options.postbuildCommands)
if(platforms || (config && config.platforms))
{
ifCount = 0;
- //f.Printf("# PLATFORM-SPECIFIC POST-BUILD COMMANDS\n");
+ //f.Puts("# TARGET_PLATFORM-SPECIFIC POST-BUILD COMMANDS\n");
for(platform = (Platform)1; platform < Platform::enumSize; platform++)
{
PlatformOptions projectPOs, configPOs;
(configPOs && configPOs.options.postbuildCommands && configPOs.options.postbuildCommands.count))
{
if(ifCount)
- f.Printf("else\n");
+ f.Puts("else\n");
ifCount++;
- f.Printf("ifdef ");
- f.Printf(PlatformToMakefileVariable(platform));
- f.Printf("\n");
+ f.Printf("ifdef %s\n", PlatformToMakefileTargetVariable(platform));
if(projectPOs && projectPOs.options.postbuildCommands && projectPOs.options.postbuildCommands.count)
{
{
int c;
for(c = 0; c < ifCount; c++)
- f.Printf("endif\n");
+ f.Puts("endif\n");
}
}
- f.Printf("\n");
+ f.Puts("\n");
- f.Printf("# SYMBOL RULES\n\n");
- {
- Map<Platform, bool> excludedPlatforms { };
- topNode.GenMakefilePrintSymbolRules(f, this, compiler, config, excludedPlatforms);
- delete excludedPlatforms;
- }
+ f.Puts("# SYMBOL RULES\n");
+ f.Puts("\n");
- f.Printf("# C OBJECT RULES\n\n");
- {
- Map<Platform, bool> excludedPlatforms { };
- topNode.GenMakefilePrintCObjectRules(f, this, compiler, config, excludedPlatforms);
- delete excludedPlatforms;
- }
+ topNode.GenMakefilePrintSymbolRules(f, this, config, nodeCFlagsMapping, nodeECFlagsMapping);
+
+ f.Puts("# C OBJECT RULES\n");
+ f.Puts("\n");
- f.Printf("# OBJECT RULES\n\n");
+ 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, compiler, config, excludedPlatforms);
- delete excludedPlatforms;
- }
+ topNode.GenMakefilePrintObjectRules(f, this, namesInfo, config, nodeCFlagsMapping, nodeECFlagsMapping);
if(numCObjects)
- GenMakefilePrintMainObjectRule(f, compiler, config);
+ GenMakefilePrintMainObjectRule(f, config);
+
+ f.Printf("cleantarget: objdir%s\n", sameObjTargetDirs ? "" : " targetdir");
+ f.Puts("\t$(call rmq,$(TARGET))\n");
+ f.Puts("\n");
- f.Printf("clean: objdir%s\n", sameObjTargetDirs ? "" : " targetdir");
- f.Printf("\t$(call rmq,%s$(TARGET))\n", numCObjects ? "$(OBJ)$(MODULE).main.c $(OBJ)$(MODULE).main.ec $(OBJ)$(MODULE).main$(I) $(OBJ)$(MODULE).main$(S) " : "");
- OutputCleanActions(f, "OBJECTS", objectsParts);
- OutputCleanActions(f, "COBJECTS", eCsourcesParts);
+ 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);
OutputCleanActions(f, "IMPORTS", eCsourcesParts);
OutputCleanActions(f, "SYMBOLS", eCsourcesParts);
}
- f.Printf("\n");
+ f.Puts("\n");
- f.Printf("realclean: clean\n");
- f.Printf("\t$(call rmrq,$(OBJ))\n");
+ f.Puts("realclean: cleantarget\n");
+ f.Puts("\t$(call rmrq,$(OBJ))\n");
if(!sameObjTargetDirs)
f.Printf("\t$(call rmdirq,%s)\n", targetDirExpNoSpaces);
- f.Printf("\n");
+ f.Puts("\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;
- delete objDirExp;
+
listItems.Free();
delete listItems;
varStringLenDiffs.Free();
namesInfo.Free();
delete namesInfo;
+ delete cflagsVariations;
+ delete nodeCFlagsMapping;
+ delete ecflagsVariations;
+ delete nodeECFlagsMapping;
+
result = true;
}
return result;
}
- void GenMakefilePrintMainObjectRule(File f, CompilerConfig compiler, ProjectConfig config)
+ void GenMakefilePrintMainObjectRule(File f, ProjectConfig config)
{
char extension[MAX_EXTENSION] = "c";
char modulePath[MAX_LOCATION];
DualPipe dep;
char command[2048];
char objDirNoSpaces[MAX_LOCATION];
- DirExpression objDirExp = GetObjDir(compiler, config);
+ String objDirExp = GetObjDirExpression(config);
- ReplaceSpaces(objDirNoSpaces, objDirExp.dir);
+ ReplaceSpaces(objDirNoSpaces, objDirExp);
ReplaceSpaces(fixedModuleName, moduleName);
//sprintf(fixedModuleName, "%s.main", fixedPrjName);
if(!result)
{
#endif
- f.Printf("$(OBJ)$(MODULE).main$(O): $(OBJ)$(MODULE).main.c\n");
+ 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\n", extension);
-
- delete objDirExp;
+ void GenMakePrintCustomFlags(File f, String variableName, bool printNonCustom, Map<String, int> cflagsVariations)
+ {
+ int c;
+ for(c = printNonCustom ? 0 : 1; c <= cflagsVariations.count; c++)
+ {
+ for(v : cflagsVariations)
+ {
+ if(v == c)
+ {
+ if(v == 1)
+ f.Printf("%s +=", variableName);
+ else
+ f.Printf("CUSTOM%d_%s =", v-1, variableName);
+ f.Puts(&v ? &v : "");
+ f.Puts("\n");
+ f.Puts("\n");
+ break;
+ }
+ }
+ }
+ f.Puts("\n");
}
void MatchProjectAndConfigPlatformOptions(ProjectConfig config, Platform platform,
TrimLSpaces(equal, equal);
if(!strcmpi(section, "Target") && !strcmpi(subSection, "LibraryDirs"))
{
- if(!project.config.options.libraryDirs) project.config.options.libraryDirs = { };
- project.config.options.libraryDirs.Add(CopyString(equal));
+ if(!project.config.options.libraryDirs)
+ project.config.options.libraryDirs = { [ CopyString(equal) ] };
+ else
+ project.config.options.libraryDirs.Add(CopyString(equal));
}
else if(!strcmpi(section, "Target") && !strcmpi(subSection, "IncludeDirs"))
{
- if(!project.config.options.includeDirs) project.config.options.includeDirs = { };
- project.config.options.includeDirs.Add(CopyString(equal));
+ if(!project.config.options.includeDirs)
+ project.config.options.includeDirs = { [ CopyString(equal) ] };
+ else
+ project.config.options.includeDirs.Add(CopyString(equal));
}
else if(!strcmpi(section, "Target") && (!strcmpi(subSection, "Files") || !strcmpi(subSection, "Resources")))
{
}
}
-Project LoadProject(char * filePath)
+Project LoadProject(char * filePath, char * activeConfigName)
{
Project project = null;
File f = FileOpen(filePath, read);
if(project)
{
if(!project.options) project.options = { };
+ if(activeConfigName && activeConfigName[0] && project.configurations)
+ {
+ for(cfg : project.configurations)
+ {
+ if(!strcmpi(cfg.name, activeConfigName))
+ {
+ project.config = cfg;
+ break;
+ }
+ }
+ }
if(!project.config && project.configurations)
project.config = project.configurations.firstIterator.data;