From a987957ddd18fea9111017345c3d2e56ed54207c Mon Sep 17 00:00:00 2001 From: dolik Date: Fri, 12 Feb 2010 00:34:11 +0000 Subject: [PATCH] ide: Makefiles (more standard, added LDFLAGS support) git-svn-id: svn://ultimatepp.org/upp/trunk@2061 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/ide/Builders/Build.cpp | 1420 +++++++++++++++--------------- uppsrc/ide/Builders/MakeFile.cpp | 471 +++++----- uppsrc/ide/Core/Core.h | 798 ++++++++--------- 3 files changed, 1346 insertions(+), 1343 deletions(-) diff --git a/uppsrc/ide/Builders/Build.cpp b/uppsrc/ide/Builders/Build.cpp index 3be49c69e..587b9bb19 100644 --- a/uppsrc/ide/Builders/Build.cpp +++ b/uppsrc/ide/Builders/Build.cpp @@ -1,709 +1,711 @@ -#include "Builders.h" - -#include - -#define LDUMP(x) // DUMP(x) - -String GetDefaultMethod() -{ - return LoadFile(ConfigFile("default_method")); -} - -VectorMap GetMethodVars(const String& method) -{ - VectorMap map; - LoadVarFile(ConfigFile((String)~method + ".bm"), map); - return map; -} - -MakeBuild::MakeBuild() -{ - targetmode = 0; - stoponerrors = true; - use_target = false; -} - -const TargetMode& MakeBuild::GetTargetMode() -{ - return (targetmode == 0 ? debug : release); -} - -Index MakeBuild::PackageConfig(const Workspace& wspc, int package, - const VectorMap& bm, String mainparam, - Host& host, Builder& b, String *target) -{ - String packagepath = PackagePath(wspc[package]); - const Package& pkg = wspc.package[package]; - Index cfg; - mainparam << ' ' << bm.Get(targetmode ? "RELEASE_FLAGS" : "DEBUG_FLAGS", NULL); - cfg = SplitFlags(mainparam, package == 0, wspc.GetAllAccepts(package)); - cfg.FindAdd(bm.Get("BUILDER", "GCC")); - const TargetMode& m = GetTargetMode(); - if(targetmode == 0) - cfg.FindAdd("DEBUG"); - switch(m.linkmode) { - case 2: - cfg.FindAdd("SO"); - case 1: - cfg.FindAdd("SHARED"); - } - if(targetmode == 2) - cfg.FindAdd("FORCE_SPEED"); - if(targetmode == 3) - cfg.FindAdd("FORCE_SIZE"); - int q = m.package.Find(wspc[package]); - if(q >= 0) { - const PackageMode& p = m.package[q]; - switch(p.debug >= 0 ? p.debug : m.def.debug) { - case 1: cfg.FindAdd("DEBUG_MINIMAL"); break; - case 2: cfg.FindAdd("DEBUG_FULL"); break; - } - if(!pkg.noblitz && (p.blitz >= 0 ? p.blitz : m.def.blitz)) - cfg.FindAdd("BLITZ"); - } - else { - switch(m.def.debug) { - case 1: cfg.FindAdd("DEBUG_MINIMAL"); break; - case 2: cfg.FindAdd("DEBUG_FULL"); break; - } - if(!pkg.noblitz && m.def.blitz) - cfg.FindAdd("BLITZ"); - } - host.AddFlags(cfg); - b.AddFlags(cfg); - if(target) - *target = Gather(pkg.target, cfg.GetKeys(), true); - return cfg; -} - -String NoCr(const char *s) -{ - String out; - while(*s) - { - const char *b = s; - while(*s && *s != '\r') - s++; - out.Cat(b, int(s - b)); - if(*s == '\r') - s++; - } - return out; -} - -bool MakeBuild::SyncHostFiles(RemoteHost& host) -{ - HdependTimeDirty(); - String query = "<"; -// Vector remotepath; - Vector fdata; - ArrayMap info; - Vector nocrsize; - const Workspace& wspc = GetIdeWorkspace(); - int p; - for(p = 0; p < wspc.GetCount(); p++) { - const Package& pkg = wspc.GetPackage(p); - String pn = wspc[p]; - for(int f = -1; f < pkg.file.GetCount(); f++) - if(f < 0 || !pkg.file[f].separator) { - Vector pkgfiles; - String pk = (f >= 0 ? SourcePath(pn, pkg.file[f]) : PackagePath(pn)); - if(!FindFile(pk).IsFile()) - continue; - pkgfiles.Add(f >= 0 ? SourcePath(pn, pkg.file[f]) : PackagePath(pn)); - pkgfiles.AppendPick(HdependGetDependencies(pkgfiles[0])); - for(int d = 0; d < pkgfiles.GetCount(); d++) { - TransferFileInfo newinfo; - newinfo.sourcepath = pkgfiles[d]; - String rp = host.GetHostPath(newinfo.sourcepath); - if(info.Find(rp) >= 0 || (d && UnixPath(rp) == UnixPath(newinfo.sourcepath))) - continue; - FindFile ff(newinfo.sourcepath); - newinfo.filetime = (int)(Time(ff.GetLastWriteTime()) - RemoteHost::TimeBase()); - newinfo.filesize = (int)ff.GetLength(); - int pos = transferfilecache.Find(rp); - if(pos < 0 || transferfilecache[pos].filetime != newinfo.filetime - || transferfilecache[pos].filesize != newinfo.filesize) - { - String content = NoCr(LoadFile(newinfo.sourcepath)); - query << rp << '\t' << newinfo.filetime << '\t' << content.GetLength() << '\n'; - // remotepath.Add(rp); - fdata.Add(content); - info.Add(rp, newinfo); - nocrsize.Add(content.GetLength()); - PutVerbose("Checking remote " + rp); - /* - if(msecs(ticks) >= 0) - { - ShowConsole(); - console.Sync(); - ticks = msecs(-200); - } - */ } - } - } - } - if(info.IsEmpty()) - return true; -// String host = GetVar("REMOTE_HOST"); -// int port = 2346; -// int ppos = host.Find(':'); -// if(ppos >= 0) -// { -// port = ScanInt(host.GetIter(ppos + 1)); -// host.Trim(ppos); -// } - - Index ignore; - { - PutConsole(NFormat("Retrieving update list for remote filesystem %s", host.host)); - ConsoleShow(); - String out = host.RemoteExec(query); - if(out[0] != 'O' || out[1] != 'K') { - PutConsole(out); - return false; - } - - const char *s = out; - while(*s && *s++ != '\n') - ; - while(*s) - { - const char *b = s; - while(*s && *s != '\n') - s++; - ignore.FindAdd(NormalizePath(NativePath(String(b, s)))); - if(*s) - s++; - } - if(ignore.GetCount() == info.GetCount()) - PutConsole("Remote source tree is up to date."); - else - { - PutConsole(NFormat("%d file(s) missing in remote source tree:", info.GetCount() - ignore.GetCount())); - for(p = 0; p < info.GetCount(); p++) - { -// console << " " << remotepath[p] << " - " -// << FormatInt(p) << " @ " << FormatInt(ignore.Find(remotepath[p])) << "\n"; - if(ignore.Find(NormalizePath(NativePath(info.GetKey(p)))) < 0) - PutConsole(String().Cat() << " " << info.GetKey(p)); - } - } - } - - Vector update; - for(p = 0; p < info.GetCount(); p++) - if(ignore.Find(NormalizePath(NativePath(info.GetKey(p)))) < 0) - { - String rawdata = fdata[p]; - PutConsole(String().Cat() << "Compressing " << info[p].sourcepath << " (" << FormatInt(rawdata.GetLength()) << " B)\n"); - ConsoleSync(); - String bzdata = BZ2Compress(rawdata); - String comp = ASCII85Encode(bzdata); - if(update.IsEmpty() || update.Top().GetLength() + comp.GetLength() >= 500000) - update.Add(">"); - update.Top() << info.GetKey(p) << '\t' << info[p].filetime << '\t' << nocrsize[p] << '\t' << comp << '\n'; - } - - for(p = 0; p < update.GetCount(); p++) - { - PutConsole(NFormat("Uploading block %d / %d (%d B)", p + 1, update.GetCount(), update[p].GetLength())); - ConsoleShow(); - String result = host.RemoteExec(update[p]); - if(result[0] != 'O' || result[1] != 'K') { - PutConsole(result); - return false; - } - } - - for(p = 0; p < info.GetCount(); p++) - transferfilecache.GetAdd(info.GetKey(p)) = info[p]; - return true; -} - -One MakeBuild::CreateHost(bool sync_files) -{ - SetupDefaultMethod(); - VectorMap bm = GetMethodVars(method); - String rm = bm.Get("REMOTE_HOST", Null); - One outhost; - if(!IsNull(rm)) { - One host = new RemoteHost; - host->host = rm; - host->port = 2346; - int f = rm.Find(':'); - if(f >= 0) { - host->host = rm.Left(f); - host->port = Nvl(ScanInt(rm.GetIter(f + 1)), host->port); - } - host->os_type = bm.Get("REMOTE_OS", "UNIX"); - Vector path_map = Split(bm.Get("REMOTE_MAP", Null), ';'); - for(int p = 0; p < path_map.GetCount(); p++) { - f = path_map[p].Find('>'); - if(f >= 0) { - host->path_map_local.Add(path_map[p].Left(f)); - host->path_map_remote.Add(path_map[p].Mid(f + 1)); - } - } - VectorMap env(Environment(), 1); - Vector exedirs = SplitDirs(bm.Get("PATH", "") + ';' + env.Get("PATH", "")); - env.GetAdd("PATH") = Join(exedirs, ";"); - for(int i = 0; i < env.GetCount(); i++) - host->environment << env.GetKey(i) << '=' << env[i] << '\0'; - host->environment.Cat(0); - if(sync_files && bm.Get("REMOTE_TRANSFER", Null) != "0") - SyncHostFiles(*host); - outhost = -host; - } - else { - One host = new LocalHost; - VectorMap env(Environment(), 1); - host->exedirs = SplitDirs(bm.Get("PATH", "") + ';' + env.Get("PATH", "")); - env.GetAdd("PATH") = Join(host->exedirs, ";"); - env.GetAdd("UPP_MAIN__") = GetFileDirectory(PackagePath(GetMain())); - for(int i = 0; i < env.GetCount(); i++) { - LDUMP(env.GetKey(i)); - LDUMP(env[i]); - host->environment << env.GetKey(i) << '=' << env[i] << '\0'; - } - host->environment.Cat(0); - host->cmdout = &cmdout; - outhost = -host; - } - return outhost; -} - -One MakeBuild::CreateBuilder(Host *host) -{ - SetupDefaultMethod(); - VectorMap bm = GetMethodVars(method); - String builder = bm.Get("BUILDER", "GCC"); - One b = (*BuilderMap().Get(builder))(); - b->host = host; - b->compiler = bm.Get("COMPILER", ""); - b->include = SplitDirs(GetVar("UPP") + ';' + bm.Get("INCLUDE", "")); - const Workspace& wspc = GetIdeWorkspace(); - for(int i = 0; i < wspc.GetCount(); i++) { - const Package& pkg = wspc.GetPackage(i); - for(int j = 0; j < pkg.include.GetCount(); j++) - b->include.Add(SourcePath(wspc[i], pkg.include[j].text)); - } - b->libpath = SplitDirs(bm.Get("LIB", "")); - b->debug_options = bm.Get("DEBUG_OPTIONS", ""); - b->release_options = bm.Get("RELEASE_OPTIONS", ""); - b->release_size_options = bm.Get("RELEASE_SIZE_OPTIONS", ""); - b->script = bm.Get("SCRIPT", ""); - return b; -} - -int CharFilterSlash(int c) -{ - return c == '\\' ? '/' : c; -} - -String MakeBuild::OutDir(const Index& cfg, const String& package, const VectorMap& bm, - bool use_target) -{ - Index excl; - excl.Add(bm.Get("BUILDER", "GCC")); - excl.Add("MSC"); - LocalHost().AddFlags(excl); - Vector x; - bool dbg = cfg.Find("DEBUG_FULL") >= 0 || cfg.Find("DEBUG_MINIMAL") >= 0; - if(cfg.Find("DEBUG") >= 0) { - excl.Add("BLITZ"); - if(cfg.Find("BLITZ") < 0) - x.Add("NOBLITZ"); - } - else - if(dbg) - x.Add("RELEASE"); - if(use_target) - excl.Add("MAIN"); - for(int i = 0; i < cfg.GetCount(); i++) - if(excl.Find(cfg[i]) < 0) - x.Add(cfg[i]); - Sort(x); - for(int i = 0; i < x.GetCount(); i++) - x[i] = InitCaps(x[i]); - String outdir = GetVar("OUTPUT"); - if(!use_target) - outdir = AppendFileName(outdir, package); - outdir = AppendFileName(outdir, method + "." + Join(x, ".")); - outdir = Filter(outdir, CharFilterSlash); - return outdir; -} - -struct OneFileHost : Host { - One host; - String onefile; - - virtual String GetEnvironment() { return host->GetEnvironment(); } - virtual String GetHostPath(const String& path) { return host->GetHostPath(path); } - virtual String GetLocalPath(const String& path) { return host->GetLocalPath(path); } - virtual String NormalizePath(const String& path) { return host->NormalizePath(path); } - virtual void DeleteFile(const Vector& path) { host->DeleteFile(path); } - virtual void DeleteFolderDeep(const String& folder) { host->DeleteFolderDeep(folder); } - virtual void ChDir(const String& path) { host->ChDir(path); } - virtual void RealizeDir(const String& path) { host->RealizeDir(path); } - virtual void SaveFile(const String& path, const String& data) { host->SaveFile(path, data); } - virtual String LoadFile(const String& path) { return host->LoadFile(path); } - virtual int Execute(const char *c) { return host->Execute(c); } - virtual int ExecuteWithInput(const char *c) { return host->ExecuteWithInput(c); } - virtual int Execute(const char *c, Stream& o) { return host->Execute(c, o); } - virtual int AllocSlot() { return host->AllocSlot(); } - virtual bool Run(const char *cmdline, int slot, String key, int blitz_count) { return host->Run(cmdline, slot, key, blitz_count); } - virtual bool Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count) { return host->Run(cmdline, out, slot, key, blitz_count); } - virtual bool Wait() { return host->Wait(); } - virtual One StartProcess(const char *c) { return host->StartProcess(c); } - virtual void Launch(const char *cmdline, bool) { host->Launch(cmdline); } - virtual void AddFlags(Index& cfg) { host->AddFlags(cfg); } - - virtual Vector GetFileInfo(const Vector& path) { - Vector fi = host->GetFileInfo(path); - for(int i = 0; i < path.GetCount(); i++) - if(path[i] == onefile) - (Time &)fi[i] = GetSysTime(); - else - (Time &)fi[i] = Time::Low(); - return fi; - } -}; - -bool MakeBuild::BuildPackage(const Workspace& wspc, int pkindex, int pknumber, int pkcount, - String mainparam, String outfile, Vector& linkfile, String& linkopt, bool link) -{ - String package = wspc[pkindex]; - String mainpackage = wspc[0]; - const Package& pkg = wspc.package[pkindex]; - VectorMap bm = GetMethodVars(method); - if(bm.GetCount() == 0) { - PutConsole("Invalid build method"); - return false; - } - One host = CreateHost(false); - if(!IsNull(onefile)) { - OneFileHost *h = new OneFileHost; - h->host = host; - h->onefile = onefile; - host = h; - } - One b = CreateBuilder(~host); - b->config = PackageConfig(wspc, pkindex, bm, mainparam, *host, *b); - const TargetMode& m = targetmode == 0 ? debug : release; - b->version = m.version; - b->method = method; - b->outdir = OutDir(b->config, package, bm); - host->RealizeDir(b->outdir); - String mainfn = Null; - Index mcfg = PackageConfig(wspc, 0, bm, mainparam, *host, *b, &mainfn); - HdependClearDependencies(); - for(int i = 0; i < pkg.GetCount(); i++) { - const Array& f = pkg[i].depends; - for(int j = 0; j < f.GetCount(); j++) - if(MatchWhen(f[j].when, mcfg.GetKeys())) - HdependAddDependency(SourcePath(package, pkg[i]), SourcePath(package, f[j].text)); - } - String tout = OutDir(mcfg, mainpackage, bm, use_target); - host->RealizeDir(tout); - if(IsNull(mainfn)) - mainfn = GetFileTitle(mainpackage) + b->GetTargetExt(); - if(!IsNull(outfile)) - target = NormalizePath(outfile, tout); - else { - if(m.target_override && !IsNull(m.target) && IsFolder(m.target)) - target = host->NormalizePath(AppendFileName(m.target, mainfn)); - else - if(m.target_override && (IsFullPath(m.target) || *m.target == '/' || *m.target == '\\')) - target = m.target; - else - if(m.target_override && !IsNull(m.target)) - target = host->NormalizePath(AppendFileName(tout, m.target)); - else - if(IsFullPath(mainfn)) - target = mainfn; - else - target = host->NormalizePath(AppendFileName(tout, mainfn)); - } - b->target = target; - if(IsNull(onefile)) { - String out; - out << "----- " << package << " ( " << Join(b->config.GetKeys(), " ") << " )"; - if(pkcount > 1) - out << " (" << (pknumber + 1) << " / " << pkcount << ')'; - PutConsole(out); - } - else - b->config.FindAdd("NOLIB"); - bool ok = b->BuildPackage(package, linkfile, linkopt, - GetAllUses(wspc, pkindex), - GetAllLibraries(wspc, pkindex, bm, mainparam, *host, *b), - targetmode - 1); - Vector errors = PickErrors(); - host->DeleteFile(errors); - if(!ok || !errors.IsEmpty()) - return false; - if(link) { - ok = b->Link(linkfile, linkopt, GetTargetMode().createmap); - errors = PickErrors(); - host->DeleteFile(errors); - if(!ok || !errors.IsEmpty()) - return false; - } - return true; -} - -void MakeBuild::SetHdependDirs() -{ - HdependSetDirs(SplitDirs(GetVar("UPP") + ';' - + GetMethodVars(method).Get("INCLUDE", "") + ';' - + Environment().Get("INCLUDE", ""))); -} - -Vector MakeBuild::GetAllUses(const Workspace& wspc, int f) -{ - String package = wspc[f]; - Index all_uses; - bool warn = true; - int n = 0; - while(f >= 0) { - const Package& p = wspc.package[f]; - for(int fu = 0; fu < p.uses.GetCount(); fu++) - if(p.uses[fu].text != package) - all_uses.FindAdd(p.uses[fu].text); - else if(warn) { - PutConsole(NFormat("%s: circular 'uses' chain", package)); - warn = false; - } - f = -1; - while(n < all_uses.GetCount() && (f = wspc.package.Find(all_uses[n++])) < 0) - ; - } - return all_uses.PickKeys(); -} - -Vector MakeBuild::GetAllLibraries(const Workspace& wspc, int index, - const VectorMap& bm, String mainparam, - Host& host, Builder& builder) -{ - Vector uses = GetAllUses(wspc, index); - uses.Add(wspc[index]); - Index libraries; - for(int i = 0; i < uses.GetCount(); i++) { - int f = wspc.package.Find(uses[i]); - if(f >= 0) { - const Package& pk = wspc.package[f]; - Index config = PackageConfig(wspc, f, bm, mainparam, host, builder); - Vector pklibs = Split(Gather(pk.library, config.GetKeys()), ' '); - FindAppend(libraries, pklibs); - } - } - return libraries.PickKeys(); -} - -bool MakeBuild::Build(const Workspace& wspc, String mainparam, String outfile, bool clear_console) -{ - ClearErrorEditor(); - BeginBuilding(true, clear_console); - bool ok = true; - if(wspc.GetCount()) { - Vector build_order; - if(GetTargetMode().linkmode != 2) { - for(int i = 1; i < wspc.GetCount(); i++) - build_order.Add(i); - } - else { - Index remaining; - for(int i = 1; i < wspc.GetCount(); i++) - remaining.Add(i); - while(!remaining.IsEmpty()) { - int t; - for(t = 0; t < remaining.GetCount(); t++) { - const Package& pk = wspc.package[remaining[t]]; - bool delay = false; - for(int u = 0; u < pk.uses.GetCount(); u++) - if(remaining.Find(wspc.package.Find(pk.uses[u].text)) >= 0) { - delay = true; - break; - } - if(!delay) - break; - } - if(t >= remaining.GetCount()) - t = 0; - build_order.Add(remaining[t]); - remaining.Remove(t); - } - } - String mainpackage = wspc[0]; - Vector linkfile; - String linkopt = GetMethodVars(method).Get(targetmode ? "RELEASE_LINK" : "DEBUG_LINK", Null); - if(linkopt.GetCount()) - linkopt << ' '; - ok = true; - int ms = msecs(); - for(int i = 0; i < build_order.GetCount() && (ok || !stoponerrors); i++) { - int px = build_order[i]; - ok = BuildPackage(wspc, px, i, build_order.GetCount() + 1, - mainparam, Null, linkfile, linkopt) && ok; - if(msecs() - ms >= 200) { - DoProcessEvents(); - ms = msecs(); - } - } - if(ok || !stoponerrors) - ok = BuildPackage(wspc, 0, build_order.GetCount(), build_order.GetCount() + 1, - mainparam, outfile, linkfile, linkopt, ok) && ok; - } - EndBuilding(ok); - ReQualifyCodeBase(); - SetErrorEditor(); - return ok; -} - -bool MakeBuild::Build() -{ - VectorMap bm = GetMethodVars(method); - if(bm.GetCount() == 0) { - PutConsole("Invalid build method"); - return false; - } - One host = CreateHost(false); - Index p = PackageConfig(GetIdeWorkspace(), 0, bm, mainconfigparam, - *host, *CreateBuilder(~host)); - Workspace wspc; - wspc.Scan(GetMain(), p.GetKeys()); - return Build(wspc, mainconfigparam, Null); -} - -void MakeBuild::CleanPackage(const Workspace& wspc, int package) -{ - PutConsole(NFormat("Cleaning %s", wspc[package])); - One host = CreateHost(false); - host->DeleteFolderDeep(OutDir(PackageConfig(wspc, package, GetMethodVars(method), mainconfigparam, - *host, *CreateBuilder(~host)), wspc[package], GetMethodVars(method))); -} - -void MakeBuild::Clean() -{ - ConsoleClear(); - const Workspace& wspc = GetIdeWorkspace(); - for(int i = 0; i < wspc.GetCount(); i++) - CleanPackage(wspc, i); - PutConsole("...done"); -} - -void MakeBuild::RebuildAll() -{ - Clean(); - Build(); -} - -void MakeBuild::SaveMakeFile(const String& fn, bool exporting) -{ - const Workspace& wspc = GetIdeWorkspace(); - - BeginBuilding(false, true); - - VectorMap bm = GetMethodVars(method); - One host = CreateHost(false); - One b = CreateBuilder(~host); - const TargetMode& tm = GetTargetMode(); - - String makefile; - - Vector uppdirs = GetUppDirs(); - String uppout = exporting ? host->GetHostPath(GetVar("OUTPUT")) : "_out/"; - String inclist; - - Index allconfig = PackageConfig(wspc, 0, bm, mainconfigparam, *host, *b); - bool win32 = allconfig.Find("WIN32") >= 0; - - for(int i = 1; i < wspc.GetCount(); i++) { - Index modconfig = PackageConfig(wspc, i, bm, mainconfigparam, *host, *b); - for(int a = allconfig.GetCount(); --a >= 0;) - if(modconfig.Find(allconfig[a]) < 0) - allconfig.Remove(a); - } - - if(!exporting) - for(int i = 0; i < uppdirs.GetCount(); i++) { - String srcdir = GetMakePath(AdjustMakePath(host->GetHostPath(AppendFileName(uppdirs[i], ""))), win32); - makefile << "UPPDIR" << (i + 1) << " = " << srcdir << "\n"; - inclist << " -I$(UPPDIR" << (i + 1) << ")"; - } - else - inclist << "-I./"; - Vector includes = SplitDirs(bm.Get("INCLUDE","")); - for(int i = 0; i < includes.GetCount(); i++) - inclist << " -I" << includes[i]; - - makefile << "\n" - "UPPOUT = " << (exporting ? "_out/" : GetMakePath(AdjustMakePath(host->GetHostPath(AppendFileName(uppout, ""))), win32)) << "\n" - "CINC = " << inclist << "\n" - "Macro = "; - - for(int i = 0; i < allconfig.GetCount(); i++) - makefile << " -Dflag" << allconfig[i]; - makefile << "\n"; - - String output, config, install, rules, linkdep, linkfiles, linkfileend; - - for(int i = 0; i < wspc.GetCount(); i++) { - b->config = PackageConfig(wspc, i, bm, mainconfigparam, *host, *b); - b->version = tm.version; - b->method = method; - MakeFile mf; - b->AddMakeFile(mf, wspc[i], GetAllUses(wspc, i), - GetAllLibraries(wspc, i, bm, mainconfigparam, *host, *b), allconfig, - exporting); - if(!i) { - String tdir = mf.outdir; - String trg; - if(tm.target_override) { - trg = GetMakePath(AdjustMakePath(tm.target), win32); - if(!trg.IsEmpty() && *trg.Last() == (win32 ? '\\' : '/')) - trg << mf.outfile; - else if(trg.Find(win32 ? '\\' : '/') < 0) - trg.Insert(0, "$(OutDir)"); - } - output = Nvl(trg, mf.output); - if(exporting) - output = wspc[i] + ".out"; - install << "\n" - "OutDir = " << tdir << "\n" - "OutFile = " << output << "\n" - "\n" - ".PHONY: all\n" - "all: prepare $(OutFile)\n" - "\n" - ".PHONY: prepare\n" - "prepare:\n"; - } - config << mf.config; - install << mf.install; - rules << mf.rules; - linkdep << mf.linkdep; - linkfiles << mf.linkfiles; - linkfileend << mf.linkfileend; - } - - makefile - << config - << install - << "\n" - "$(OutFile): " << linkdep << "\n\t" << linkfiles << linkfileend << "\n" - << rules - << ".PHONY: clean\n" - << "clean:\n" - << "\tif [ -d $(UPPOUT) ]; then rm -rf $(UPPOUT); fi;\n"; - - bool sv = ::SaveFile(fn, makefile); - if(!exporting) - if(sv) - PutConsole(NFormat("%s(1): makefile generation complete", fn)); - else - PutConsole(NFormat("%s: error writing makefile", fn)); - - EndBuilding(true); -} +#include "Builders.h" + +#include + +#define LDUMP(x) // DUMP(x) + +String GetDefaultMethod() +{ + return LoadFile(ConfigFile("default_method")); +} + +VectorMap GetMethodVars(const String& method) +{ + VectorMap map; + LoadVarFile(ConfigFile((String)~method + ".bm"), map); + return map; +} + +MakeBuild::MakeBuild() +{ + targetmode = 0; + stoponerrors = true; + use_target = false; +} + +const TargetMode& MakeBuild::GetTargetMode() +{ + return (targetmode == 0 ? debug : release); +} + +Index MakeBuild::PackageConfig(const Workspace& wspc, int package, + const VectorMap& bm, String mainparam, + Host& host, Builder& b, String *target) +{ + String packagepath = PackagePath(wspc[package]); + const Package& pkg = wspc.package[package]; + Index cfg; + mainparam << ' ' << bm.Get(targetmode ? "RELEASE_FLAGS" : "DEBUG_FLAGS", NULL); + cfg = SplitFlags(mainparam, package == 0, wspc.GetAllAccepts(package)); + cfg.FindAdd(bm.Get("BUILDER", "GCC")); + const TargetMode& m = GetTargetMode(); + if(targetmode == 0) + cfg.FindAdd("DEBUG"); + switch(m.linkmode) { + case 2: + cfg.FindAdd("SO"); + case 1: + cfg.FindAdd("SHARED"); + } + if(targetmode == 2) + cfg.FindAdd("FORCE_SPEED"); + if(targetmode == 3) + cfg.FindAdd("FORCE_SIZE"); + int q = m.package.Find(wspc[package]); + if(q >= 0) { + const PackageMode& p = m.package[q]; + switch(p.debug >= 0 ? p.debug : m.def.debug) { + case 1: cfg.FindAdd("DEBUG_MINIMAL"); break; + case 2: cfg.FindAdd("DEBUG_FULL"); break; + } + if(!pkg.noblitz && (p.blitz >= 0 ? p.blitz : m.def.blitz)) + cfg.FindAdd("BLITZ"); + } + else { + switch(m.def.debug) { + case 1: cfg.FindAdd("DEBUG_MINIMAL"); break; + case 2: cfg.FindAdd("DEBUG_FULL"); break; + } + if(!pkg.noblitz && m.def.blitz) + cfg.FindAdd("BLITZ"); + } + host.AddFlags(cfg); + b.AddFlags(cfg); + if(target) + *target = Gather(pkg.target, cfg.GetKeys(), true); + return cfg; +} + +String NoCr(const char *s) +{ + String out; + while(*s) + { + const char *b = s; + while(*s && *s != '\r') + s++; + out.Cat(b, int(s - b)); + if(*s == '\r') + s++; + } + return out; +} + +bool MakeBuild::SyncHostFiles(RemoteHost& host) +{ + HdependTimeDirty(); + String query = "<"; +// Vector remotepath; + Vector fdata; + ArrayMap info; + Vector nocrsize; + const Workspace& wspc = GetIdeWorkspace(); + int p; + for(p = 0; p < wspc.GetCount(); p++) { + const Package& pkg = wspc.GetPackage(p); + String pn = wspc[p]; + for(int f = -1; f < pkg.file.GetCount(); f++) + if(f < 0 || !pkg.file[f].separator) { + Vector pkgfiles; + String pk = (f >= 0 ? SourcePath(pn, pkg.file[f]) : PackagePath(pn)); + if(!FindFile(pk).IsFile()) + continue; + pkgfiles.Add(f >= 0 ? SourcePath(pn, pkg.file[f]) : PackagePath(pn)); + pkgfiles.AppendPick(HdependGetDependencies(pkgfiles[0])); + for(int d = 0; d < pkgfiles.GetCount(); d++) { + TransferFileInfo newinfo; + newinfo.sourcepath = pkgfiles[d]; + String rp = host.GetHostPath(newinfo.sourcepath); + if(info.Find(rp) >= 0 || (d && UnixPath(rp) == UnixPath(newinfo.sourcepath))) + continue; + FindFile ff(newinfo.sourcepath); + newinfo.filetime = (int)(Time(ff.GetLastWriteTime()) - RemoteHost::TimeBase()); + newinfo.filesize = (int)ff.GetLength(); + int pos = transferfilecache.Find(rp); + if(pos < 0 || transferfilecache[pos].filetime != newinfo.filetime + || transferfilecache[pos].filesize != newinfo.filesize) + { + String content = NoCr(LoadFile(newinfo.sourcepath)); + query << rp << '\t' << newinfo.filetime << '\t' << content.GetLength() << '\n'; + // remotepath.Add(rp); + fdata.Add(content); + info.Add(rp, newinfo); + nocrsize.Add(content.GetLength()); + PutVerbose("Checking remote " + rp); + /* + if(msecs(ticks) >= 0) + { + ShowConsole(); + console.Sync(); + ticks = msecs(-200); + } + */ } + } + } + } + if(info.IsEmpty()) + return true; +// String host = GetVar("REMOTE_HOST"); +// int port = 2346; +// int ppos = host.Find(':'); +// if(ppos >= 0) +// { +// port = ScanInt(host.GetIter(ppos + 1)); +// host.Trim(ppos); +// } + + Index ignore; + { + PutConsole(NFormat("Retrieving update list for remote filesystem %s", host.host)); + ConsoleShow(); + String out = host.RemoteExec(query); + if(out[0] != 'O' || out[1] != 'K') { + PutConsole(out); + return false; + } + + const char *s = out; + while(*s && *s++ != '\n') + ; + while(*s) + { + const char *b = s; + while(*s && *s != '\n') + s++; + ignore.FindAdd(NormalizePath(NativePath(String(b, s)))); + if(*s) + s++; + } + if(ignore.GetCount() == info.GetCount()) + PutConsole("Remote source tree is up to date."); + else + { + PutConsole(NFormat("%d file(s) missing in remote source tree:", info.GetCount() - ignore.GetCount())); + for(p = 0; p < info.GetCount(); p++) + { +// console << " " << remotepath[p] << " - " +// << FormatInt(p) << " @ " << FormatInt(ignore.Find(remotepath[p])) << "\n"; + if(ignore.Find(NormalizePath(NativePath(info.GetKey(p)))) < 0) + PutConsole(String().Cat() << " " << info.GetKey(p)); + } + } + } + + Vector update; + for(p = 0; p < info.GetCount(); p++) + if(ignore.Find(NormalizePath(NativePath(info.GetKey(p)))) < 0) + { + String rawdata = fdata[p]; + PutConsole(String().Cat() << "Compressing " << info[p].sourcepath << " (" << FormatInt(rawdata.GetLength()) << " B)\n"); + ConsoleSync(); + String bzdata = BZ2Compress(rawdata); + String comp = ASCII85Encode(bzdata); + if(update.IsEmpty() || update.Top().GetLength() + comp.GetLength() >= 500000) + update.Add(">"); + update.Top() << info.GetKey(p) << '\t' << info[p].filetime << '\t' << nocrsize[p] << '\t' << comp << '\n'; + } + + for(p = 0; p < update.GetCount(); p++) + { + PutConsole(NFormat("Uploading block %d / %d (%d B)", p + 1, update.GetCount(), update[p].GetLength())); + ConsoleShow(); + String result = host.RemoteExec(update[p]); + if(result[0] != 'O' || result[1] != 'K') { + PutConsole(result); + return false; + } + } + + for(p = 0; p < info.GetCount(); p++) + transferfilecache.GetAdd(info.GetKey(p)) = info[p]; + return true; +} + +One MakeBuild::CreateHost(bool sync_files) +{ + SetupDefaultMethod(); + VectorMap bm = GetMethodVars(method); + String rm = bm.Get("REMOTE_HOST", Null); + One outhost; + if(!IsNull(rm)) { + One host = new RemoteHost; + host->host = rm; + host->port = 2346; + int f = rm.Find(':'); + if(f >= 0) { + host->host = rm.Left(f); + host->port = Nvl(ScanInt(rm.GetIter(f + 1)), host->port); + } + host->os_type = bm.Get("REMOTE_OS", "UNIX"); + Vector path_map = Split(bm.Get("REMOTE_MAP", Null), ';'); + for(int p = 0; p < path_map.GetCount(); p++) { + f = path_map[p].Find('>'); + if(f >= 0) { + host->path_map_local.Add(path_map[p].Left(f)); + host->path_map_remote.Add(path_map[p].Mid(f + 1)); + } + } + VectorMap env(Environment(), 1); + Vector exedirs = SplitDirs(bm.Get("PATH", "") + ';' + env.Get("PATH", "")); + env.GetAdd("PATH") = Join(exedirs, ";"); + for(int i = 0; i < env.GetCount(); i++) + host->environment << env.GetKey(i) << '=' << env[i] << '\0'; + host->environment.Cat(0); + if(sync_files && bm.Get("REMOTE_TRANSFER", Null) != "0") + SyncHostFiles(*host); + outhost = -host; + } + else { + One host = new LocalHost; + VectorMap env(Environment(), 1); + host->exedirs = SplitDirs(bm.Get("PATH", "") + ';' + env.Get("PATH", "")); + env.GetAdd("PATH") = Join(host->exedirs, ";"); + env.GetAdd("UPP_MAIN__") = GetFileDirectory(PackagePath(GetMain())); + for(int i = 0; i < env.GetCount(); i++) { + LDUMP(env.GetKey(i)); + LDUMP(env[i]); + host->environment << env.GetKey(i) << '=' << env[i] << '\0'; + } + host->environment.Cat(0); + host->cmdout = &cmdout; + outhost = -host; + } + return outhost; +} + +One MakeBuild::CreateBuilder(Host *host) +{ + SetupDefaultMethod(); + VectorMap bm = GetMethodVars(method); + String builder = bm.Get("BUILDER", "GCC"); + One b = (*BuilderMap().Get(builder))(); + b->host = host; + b->compiler = bm.Get("COMPILER", ""); + b->include = SplitDirs(GetVar("UPP") + ';' + bm.Get("INCLUDE", "")); + const Workspace& wspc = GetIdeWorkspace(); + for(int i = 0; i < wspc.GetCount(); i++) { + const Package& pkg = wspc.GetPackage(i); + for(int j = 0; j < pkg.include.GetCount(); j++) + b->include.Add(SourcePath(wspc[i], pkg.include[j].text)); + } + b->libpath = SplitDirs(bm.Get("LIB", "")); + b->debug_options = bm.Get("DEBUG_OPTIONS", ""); + b->release_options = bm.Get("RELEASE_OPTIONS", ""); + b->release_size_options = bm.Get("RELEASE_SIZE_OPTIONS", ""); + b->debug_link = bm.Get("DEBUG_LINK", ""); + b->release_link = bm.Get("RELEASE_LINK", ""); + b->script = bm.Get("SCRIPT", ""); + return b; +} + +int CharFilterSlash(int c) +{ + return c == '\\' ? '/' : c; +} + +String MakeBuild::OutDir(const Index& cfg, const String& package, const VectorMap& bm, + bool use_target) +{ + Index excl; + excl.Add(bm.Get("BUILDER", "GCC")); + excl.Add("MSC"); + LocalHost().AddFlags(excl); + Vector x; + bool dbg = cfg.Find("DEBUG_FULL") >= 0 || cfg.Find("DEBUG_MINIMAL") >= 0; + if(cfg.Find("DEBUG") >= 0) { + excl.Add("BLITZ"); + if(cfg.Find("BLITZ") < 0) + x.Add("NOBLITZ"); + } + else + if(dbg) + x.Add("RELEASE"); + if(use_target) + excl.Add("MAIN"); + for(int i = 0; i < cfg.GetCount(); i++) + if(excl.Find(cfg[i]) < 0) + x.Add(cfg[i]); + Sort(x); + for(int i = 0; i < x.GetCount(); i++) + x[i] = InitCaps(x[i]); + String outdir = GetVar("OUTPUT"); + if(!use_target) + outdir = AppendFileName(outdir, package); + outdir = AppendFileName(outdir, method + "." + Join(x, ".")); + outdir = Filter(outdir, CharFilterSlash); + return outdir; +} + +struct OneFileHost : Host { + One host; + String onefile; + + virtual String GetEnvironment() { return host->GetEnvironment(); } + virtual String GetHostPath(const String& path) { return host->GetHostPath(path); } + virtual String GetLocalPath(const String& path) { return host->GetLocalPath(path); } + virtual String NormalizePath(const String& path) { return host->NormalizePath(path); } + virtual void DeleteFile(const Vector& path) { host->DeleteFile(path); } + virtual void DeleteFolderDeep(const String& folder) { host->DeleteFolderDeep(folder); } + virtual void ChDir(const String& path) { host->ChDir(path); } + virtual void RealizeDir(const String& path) { host->RealizeDir(path); } + virtual void SaveFile(const String& path, const String& data) { host->SaveFile(path, data); } + virtual String LoadFile(const String& path) { return host->LoadFile(path); } + virtual int Execute(const char *c) { return host->Execute(c); } + virtual int ExecuteWithInput(const char *c) { return host->ExecuteWithInput(c); } + virtual int Execute(const char *c, Stream& o) { return host->Execute(c, o); } + virtual int AllocSlot() { return host->AllocSlot(); } + virtual bool Run(const char *cmdline, int slot, String key, int blitz_count) { return host->Run(cmdline, slot, key, blitz_count); } + virtual bool Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count) { return host->Run(cmdline, out, slot, key, blitz_count); } + virtual bool Wait() { return host->Wait(); } + virtual One StartProcess(const char *c) { return host->StartProcess(c); } + virtual void Launch(const char *cmdline, bool) { host->Launch(cmdline); } + virtual void AddFlags(Index& cfg) { host->AddFlags(cfg); } + + virtual Vector GetFileInfo(const Vector& path) { + Vector fi = host->GetFileInfo(path); + for(int i = 0; i < path.GetCount(); i++) + if(path[i] == onefile) + (Time &)fi[i] = GetSysTime(); + else + (Time &)fi[i] = Time::Low(); + return fi; + } +}; + +bool MakeBuild::BuildPackage(const Workspace& wspc, int pkindex, int pknumber, int pkcount, + String mainparam, String outfile, Vector& linkfile, String& linkopt, bool link) +{ + String package = wspc[pkindex]; + String mainpackage = wspc[0]; + const Package& pkg = wspc.package[pkindex]; + VectorMap bm = GetMethodVars(method); + if(bm.GetCount() == 0) { + PutConsole("Invalid build method"); + return false; + } + One host = CreateHost(false); + if(!IsNull(onefile)) { + OneFileHost *h = new OneFileHost; + h->host = host; + h->onefile = onefile; + host = h; + } + One b = CreateBuilder(~host); + b->config = PackageConfig(wspc, pkindex, bm, mainparam, *host, *b); + const TargetMode& m = targetmode == 0 ? debug : release; + b->version = m.version; + b->method = method; + b->outdir = OutDir(b->config, package, bm); + host->RealizeDir(b->outdir); + String mainfn = Null; + Index mcfg = PackageConfig(wspc, 0, bm, mainparam, *host, *b, &mainfn); + HdependClearDependencies(); + for(int i = 0; i < pkg.GetCount(); i++) { + const Array& f = pkg[i].depends; + for(int j = 0; j < f.GetCount(); j++) + if(MatchWhen(f[j].when, mcfg.GetKeys())) + HdependAddDependency(SourcePath(package, pkg[i]), SourcePath(package, f[j].text)); + } + String tout = OutDir(mcfg, mainpackage, bm, use_target); + host->RealizeDir(tout); + if(IsNull(mainfn)) + mainfn = GetFileTitle(mainpackage) + b->GetTargetExt(); + if(!IsNull(outfile)) + target = NormalizePath(outfile, tout); + else { + if(m.target_override && !IsNull(m.target) && IsFolder(m.target)) + target = host->NormalizePath(AppendFileName(m.target, mainfn)); + else + if(m.target_override && (IsFullPath(m.target) || *m.target == '/' || *m.target == '\\')) + target = m.target; + else + if(m.target_override && !IsNull(m.target)) + target = host->NormalizePath(AppendFileName(tout, m.target)); + else + if(IsFullPath(mainfn)) + target = mainfn; + else + target = host->NormalizePath(AppendFileName(tout, mainfn)); + } + b->target = target; + if(IsNull(onefile)) { + String out; + out << "----- " << package << " ( " << Join(b->config.GetKeys(), " ") << " )"; + if(pkcount > 1) + out << " (" << (pknumber + 1) << " / " << pkcount << ')'; + PutConsole(out); + } + else + b->config.FindAdd("NOLIB"); + bool ok = b->BuildPackage(package, linkfile, linkopt, + GetAllUses(wspc, pkindex), + GetAllLibraries(wspc, pkindex, bm, mainparam, *host, *b), + targetmode - 1); + Vector errors = PickErrors(); + host->DeleteFile(errors); + if(!ok || !errors.IsEmpty()) + return false; + if(link) { + ok = b->Link(linkfile, linkopt, GetTargetMode().createmap); + errors = PickErrors(); + host->DeleteFile(errors); + if(!ok || !errors.IsEmpty()) + return false; + } + return true; +} + +void MakeBuild::SetHdependDirs() +{ + HdependSetDirs(SplitDirs(GetVar("UPP") + ';' + + GetMethodVars(method).Get("INCLUDE", "") + ';' + + Environment().Get("INCLUDE", ""))); +} + +Vector MakeBuild::GetAllUses(const Workspace& wspc, int f) +{ + String package = wspc[f]; + Index all_uses; + bool warn = true; + int n = 0; + while(f >= 0) { + const Package& p = wspc.package[f]; + for(int fu = 0; fu < p.uses.GetCount(); fu++) + if(p.uses[fu].text != package) + all_uses.FindAdd(p.uses[fu].text); + else if(warn) { + PutConsole(NFormat("%s: circular 'uses' chain", package)); + warn = false; + } + f = -1; + while(n < all_uses.GetCount() && (f = wspc.package.Find(all_uses[n++])) < 0) + ; + } + return all_uses.PickKeys(); +} + +Vector MakeBuild::GetAllLibraries(const Workspace& wspc, int index, + const VectorMap& bm, String mainparam, + Host& host, Builder& builder) +{ + Vector uses = GetAllUses(wspc, index); + uses.Add(wspc[index]); + Index libraries; + for(int i = 0; i < uses.GetCount(); i++) { + int f = wspc.package.Find(uses[i]); + if(f >= 0) { + const Package& pk = wspc.package[f]; + Index config = PackageConfig(wspc, f, bm, mainparam, host, builder); + Vector pklibs = Split(Gather(pk.library, config.GetKeys()), ' '); + FindAppend(libraries, pklibs); + } + } + return libraries.PickKeys(); +} + +bool MakeBuild::Build(const Workspace& wspc, String mainparam, String outfile, bool clear_console) +{ + ClearErrorEditor(); + BeginBuilding(true, clear_console); + bool ok = true; + if(wspc.GetCount()) { + Vector build_order; + if(GetTargetMode().linkmode != 2) { + for(int i = 1; i < wspc.GetCount(); i++) + build_order.Add(i); + } + else { + Index remaining; + for(int i = 1; i < wspc.GetCount(); i++) + remaining.Add(i); + while(!remaining.IsEmpty()) { + int t; + for(t = 0; t < remaining.GetCount(); t++) { + const Package& pk = wspc.package[remaining[t]]; + bool delay = false; + for(int u = 0; u < pk.uses.GetCount(); u++) + if(remaining.Find(wspc.package.Find(pk.uses[u].text)) >= 0) { + delay = true; + break; + } + if(!delay) + break; + } + if(t >= remaining.GetCount()) + t = 0; + build_order.Add(remaining[t]); + remaining.Remove(t); + } + } + String mainpackage = wspc[0]; + Vector linkfile; + String linkopt = GetMethodVars(method).Get(targetmode ? "RELEASE_LINK" : "DEBUG_LINK", Null); + if(linkopt.GetCount()) + linkopt << ' '; + ok = true; + int ms = msecs(); + for(int i = 0; i < build_order.GetCount() && (ok || !stoponerrors); i++) { + int px = build_order[i]; + ok = BuildPackage(wspc, px, i, build_order.GetCount() + 1, + mainparam, Null, linkfile, linkopt) && ok; + if(msecs() - ms >= 200) { + DoProcessEvents(); + ms = msecs(); + } + } + if(ok || !stoponerrors) + ok = BuildPackage(wspc, 0, build_order.GetCount(), build_order.GetCount() + 1, + mainparam, outfile, linkfile, linkopt, ok) && ok; + } + EndBuilding(ok); + ReQualifyCodeBase(); + SetErrorEditor(); + return ok; +} + +bool MakeBuild::Build() +{ + VectorMap bm = GetMethodVars(method); + if(bm.GetCount() == 0) { + PutConsole("Invalid build method"); + return false; + } + One host = CreateHost(false); + Index p = PackageConfig(GetIdeWorkspace(), 0, bm, mainconfigparam, + *host, *CreateBuilder(~host)); + Workspace wspc; + wspc.Scan(GetMain(), p.GetKeys()); + return Build(wspc, mainconfigparam, Null); +} + +void MakeBuild::CleanPackage(const Workspace& wspc, int package) +{ + PutConsole(NFormat("Cleaning %s", wspc[package])); + One host = CreateHost(false); + host->DeleteFolderDeep(OutDir(PackageConfig(wspc, package, GetMethodVars(method), mainconfigparam, + *host, *CreateBuilder(~host)), wspc[package], GetMethodVars(method))); +} + +void MakeBuild::Clean() +{ + ConsoleClear(); + const Workspace& wspc = GetIdeWorkspace(); + for(int i = 0; i < wspc.GetCount(); i++) + CleanPackage(wspc, i); + PutConsole("...done"); +} + +void MakeBuild::RebuildAll() +{ + Clean(); + Build(); +} + +void MakeBuild::SaveMakeFile(const String& fn, bool exporting) +{ + const Workspace& wspc = GetIdeWorkspace(); + + BeginBuilding(false, true); + + VectorMap bm = GetMethodVars(method); + One host = CreateHost(false); + One b = CreateBuilder(~host); + const TargetMode& tm = GetTargetMode(); + + String makefile; + + Vector uppdirs = GetUppDirs(); + String uppout = exporting ? host->GetHostPath(GetVar("OUTPUT")) : "_out/"; + String inclist; + + Index allconfig = PackageConfig(wspc, 0, bm, mainconfigparam, *host, *b); + bool win32 = allconfig.Find("WIN32") >= 0; + + for(int i = 1; i < wspc.GetCount(); i++) { + Index modconfig = PackageConfig(wspc, i, bm, mainconfigparam, *host, *b); + for(int a = allconfig.GetCount(); --a >= 0;) + if(modconfig.Find(allconfig[a]) < 0) + allconfig.Remove(a); + } + + if(!exporting) + for(int i = 0; i < uppdirs.GetCount(); i++) { + String srcdir = GetMakePath(AdjustMakePath(host->GetHostPath(AppendFileName(uppdirs[i], ""))), win32); + makefile << "UPPDIR" << (i + 1) << " = " << srcdir << "\n"; + inclist << " -I$(UPPDIR" << (i + 1) << ")"; + } + else + inclist << "-I./"; + Vector includes = SplitDirs(bm.Get("INCLUDE","")); + for(int i = 0; i < includes.GetCount(); i++) + inclist << " -I" << includes[i]; + + makefile << "\n" + "UPPOUT = " << (exporting ? "_out/" : GetMakePath(AdjustMakePath(host->GetHostPath(AppendFileName(uppout, ""))), win32)) << "\n" + "CINC = " << inclist << "\n" + "Macro = "; + + for(int i = 0; i < allconfig.GetCount(); i++) + makefile << " -Dflag" << allconfig[i]; + makefile << "\n"; + + String output, config, install, rules, linkdep, linkfiles, linkfileend; + + for(int i = 0; i < wspc.GetCount(); i++) { + b->config = PackageConfig(wspc, i, bm, mainconfigparam, *host, *b); + b->version = tm.version; + b->method = method; + MakeFile mf; + b->AddMakeFile(mf, wspc[i], GetAllUses(wspc, i), + GetAllLibraries(wspc, i, bm, mainconfigparam, *host, *b), allconfig, + exporting); + if(!i) { + String tdir = mf.outdir; + String trg; + if(tm.target_override) { + trg = GetMakePath(AdjustMakePath(tm.target), win32); + if(!trg.IsEmpty() && *trg.Last() == (win32 ? '\\' : '/')) + trg << mf.outfile; + else if(trg.Find(win32 ? '\\' : '/') < 0) + trg.Insert(0, "$(OutDir)"); + } + output = Nvl(trg, mf.output); + if(exporting) + output = wspc[i] + ".out"; + install << "\n" + "OutDir = " << tdir << "\n" + "OutFile = " << output << "\n" + "\n" + ".PHONY: all\n" + "all: prepare $(OutFile)\n" + "\n" + ".PHONY: prepare\n" + "prepare:\n"; + } + config << mf.config; + install << mf.install; + rules << mf.rules; + linkdep << mf.linkdep; + linkfiles << mf.linkfiles; + linkfileend << mf.linkfileend; + } + + makefile + << config + << install + << "\n" + "$(OutFile): " << linkdep << "\n\t" << linkfiles << linkfileend << "\n" + << rules + << ".PHONY: clean\n" + << "clean:\n" + << "\tif [ -d $(UPPOUT) ]; then rm -rf $(UPPOUT); fi;\n"; + + bool sv = ::SaveFile(fn, makefile); + if(!exporting) + if(sv) + PutConsole(NFormat("%s(1): makefile generation complete", fn)); + else + PutConsole(NFormat("%s: error writing makefile", fn)); + + EndBuilding(true); +} diff --git a/uppsrc/ide/Builders/MakeFile.cpp b/uppsrc/ide/Builders/MakeFile.cpp index 55a16b3ef..ca1324a39 100644 --- a/uppsrc/ide/Builders/MakeFile.cpp +++ b/uppsrc/ide/Builders/MakeFile.cpp @@ -1,236 +1,235 @@ -#include "Builders.h" - -static String MakeIdent(const char *name) -{ - String out; - for(; *name; name++) - out << (iscid(*name) ? *name : '_'); - return out; -} - -static String MakeSourcePath(const Vector& dirs, String fn, bool raw, bool exporting) -{ - fn = UnixPath(fn); - for(int i = 0; i < dirs.GetCount(); i++) - { - int dl = dirs[i].GetLength(); - if(fn.GetLength() >= dl + 2 && !memcmp(fn, dirs[i], dl) && fn[dl] == '/') { - String s; - if(!exporting) - s << "$(UPPDIR" << (i + 1) << ")"; - s << AdjustMakePath(fn.GetIter(dl + 1)); - return s; - } - } - return raw ? String() : AdjustMakePath(fn); -} - -String CppBuilder::GetMakePath(String fn) const -{ - return ::GetMakePath(fn, HasFlag("WIN32")); -} - -void CppBuilder::AddMakeFile(MakeFile& makefile, String package, - const Vector& all_uses, const Vector& all_libraries, - const Index& common_config, bool exporting) -{ - String packagepath = PackagePath(package); - Package pkg; - pkg.Load(packagepath); - String packagedir = GetFileFolder(packagepath); - Vector src = GetUppDirs(); - for(int i = 0; i < src.GetCount(); i++) - src[i] = UnixPath(src[i]); - - bool main = HasFlag("MAIN"); - bool is_shared = HasFlag("SO"); - bool libout = !main && !HasFlag("NOLIB"); - bool win32 = HasFlag("WIN32"); - - String pack_ident = MakeIdent(package); - String outdir = "OutDir_" + pack_ident; - String macros = "Macro_" + pack_ident; - String macdef = "$(Macro)"; - String objext = (HasFlag("MSC") || HasFlag("EVC") ? ".obj" : ".o"); - - Vector x(config.GetKeys(), 1); - Sort(x); - for(int i = 0; i < x.GetCount(); i++) { - if(common_config.Find(x[i]) < 0) - macdef << " -Dflag" << x[i]; - x[i] = InitCaps(x[i]); - } - - makefile.outdir << "$(" << outdir << ")"; - makefile.outfile << AdjustMakePath(GetFileTitle(NativePath(package))); - if(main) - makefile.outfile << GetTargetExt(); - else if(is_shared) - makefile.outfile << (win32 ? ".dll" : ".so"); - else - makefile.outfile << (win32 && HasFlag("MSC") ? ".lib" : ".a"); - makefile.output << (main ? String("$(OutDir)") : makefile.outdir) << makefile.outfile; - - if(main) { - String cc = "c++ -c"; - if(HasFlag("DEBUG")) - cc << " -D_DEBUG " << debug_options; - else - cc << ' ' << release_options; - if(HasFlag("DEBUG_MINIMAL")) - cc << " -ggdb -g1"; - if(HasFlag("DEBUG_FULL")) - cc << " -ggdb -g2"; - if(is_shared && !win32) - cc << " -fPIC "; - cc << ' ' << Gather(pkg.option, config.GetKeys()); - makefile.config << "CC = " << cc << "\n" - "CFLAGS = $(CC) -x c\n" - "CPPFLAGS = $(CC) -x c++ \n" - "LIBPATH = "; - for(int i = 0; i < libpath.GetCount(); i++) - makefile.config << " -L" << GetMakePath(AdjustMakePath(GetHostPathQ(libpath[i]))); - makefile.config << "\n" - "AR = ar -sr\n"; - - makefile.install << "\t-mkdir -p $(OutDir)\n"; - - Vector lib; - String lnk; - lnk << "c++"; - if(!HasFlag("SHARED")) - lnk << " -static"; - if(HasFlag("WIN32")) { - lnk << " -mwindows"; - if(!HasFlag("GUI")) - makefile.linkfiles << " -mconsole"; - } - lnk << " -o $(OutFile)"; - if(HasFlag("DEBUG") || HasFlag("DEBUG_MINIMAL") || HasFlag("DEBUG_FULL")) - lnk << " -ggdb"; - else - lnk << (!HasFlag("OSX11") ? " -Wl,-s" : ""); - - lnk << " $(LIBPATH)"; - if (!HasFlag("OSX11")) - lnk << " -Wl,-O,2"; - lnk << " $(LINKOPTIONS)"; - - makefile.linkfiles = lnk; - } - - makefile.config << outdir << " = $(UPPOUT)" - << GetMakePath(AdjustMakePath(String().Cat() << package << '/' << method << '-' << Join(x, "-") << '/')) << "\n" - << macros << " = " << macdef << "\n"; - - makefile.install << "\t-mkdir -p $(" << outdir << ")\n"; - - String libdep, libfiles; - - libdep << makefile.output << ":"; - if(is_shared) - { - libfiles = "c++ -shared -fPIC"; // -v"; - Point p = ExtractVersion(); - if(!IsNull(p.x)) { - libfiles << " -Xlinker --major-image-version -Xlinker " << p.x; - if(!IsNull(p.y)) - libfiles << " -Xlinker --minor-image-version -Xlinker " << p.y; - } - libfiles << " -o "; - } - else - libfiles = "$(AR) "; - libfiles << makefile.output; - - for(int i = 0; i < pkg.GetCount(); i++) - if(!pkg[i].separator) { - String gop = Gather(pkg[i].option, config.GetKeys()); - String fn = SourcePath(package, pkg[i]); - String ext = ToLower(GetFileExt(fn)); - bool isc = ext == ".c"; - bool isrc = (ext == ".rc" && HasFlag("WIN32")); - bool iscpp = (ext == ".cpp" || ext == ".cc" || ext == ".cxx"); - bool isicpp = (ext == ".icpp"); - if(isc || isrc || iscpp || isicpp) { - String outfile; - outfile << makefile.outdir << AdjustMakePath(GetFileTitle(fn)) << (isrc ? "_rc" : "") << objext; - String srcfile = GetMakePath(MakeSourcePath(src, fn, false, exporting)); - makefile.rules << outfile << ": " << srcfile; - Vector dep = HdependGetDependencies(fn); - Sort(dep, GetLanguageInfo()); - for(int d = 0; d < dep.GetCount(); d++) { - String dfn = MakeSourcePath(src, dep[d], true, exporting); - if(!IsNull(dfn)) - makefile.rules << " \\\n\t" << GetMakePath(dfn); - } - makefile.rules << "\n" - "\t" << (isc ? "$(CFLAGS)" : "$(CPPFLAGS)") << " $(CINC) $(" << macros << ") " - << gop << " " << srcfile << " -o " << outfile << "\n\n"; - if(!libout || isicpp) { - makefile.linkdep << " \\\n\t" << outfile; - makefile.linkfiles << " \\\n\t\t" << outfile; - } - else { - libdep << " \\\n\t" << outfile; - libfiles << " \\\n\t\t" << outfile; - } - } - else - if(ext == ".o" || ext == ".obj" || ext == ".a" || ext == ".so" || ext == ".lib" || ext == ".dll") { - makefile.linkdep << " \\\n\t" << fn; - makefile.linkfiles << ' ' << fn; - } - } - - if(libout) { - makefile.rules << libdep << "\n\t" << libfiles << "\n\n"; - makefile.linkdep << " \\\n\t" << makefile.output; - makefile.linkfiles << " \\\n\t\t\t" << makefile.output; - } - - if(main) { - if(!HasFlag("SOLARIS")&&!HasFlag("OSX11")) - makefile.linkfiles << " \\\n\t\t-Wl,--start-group "; - for(int i = 0; i < all_libraries.GetCount(); i++) { - String ln = all_libraries[i]; - String ext = ToLower(GetFileExt(ln)); - if(ext == ".a" || ext == ".so" || ext == ".dll") - makefile.linkfileend << " \\\n\t\t\t" << GetHostPathQ(FindInDirs(libpath, ln)); - else - makefile.linkfileend << " \\\n\t\t\t-l" << ln; - } - if(!HasFlag("SOLARIS")&&!HasFlag("OSX11")) - makefile.linkfileend << " \\\n\t\t-Wl,--end-group\n\n"; - } -} - -Point CppBuilder::ExtractVersion() -{ - Point v = Point(Null, Null); - CParser p(version); - while(!p.IsEof()) { - if(p.IsNumber()) { - v.x = p.ReadNumber(); - break; - } - p.GetChar(); - p.Spaces(); - } - while(!p.IsEof()) { - if(p.IsNumber()) { - v.y = p.ReadNumber(); - break; - } - p.GetChar(); - p.Spaces(); - } - return v; -} - -void CppBuilder::ShowTime(int count, int start_time) -{ - if(count) - PutConsole(NFormat("%d file(s) compiled in %s %d msec/file", - count, GetPrintTime(start_time), msecs(start_time) / count)); -} +#include "Builders.h" + +static String MakeIdent(const char *name) +{ + String out; + for(; *name; name++) + out << (iscid(*name) ? *name : '_'); + return out; +} + +static String MakeSourcePath(const Vector& dirs, String fn, bool raw, bool exporting) +{ + fn = UnixPath(fn); + for(int i = 0; i < dirs.GetCount(); i++) + { + int dl = dirs[i].GetLength(); + if(fn.GetLength() >= dl + 2 && !memcmp(fn, dirs[i], dl) && fn[dl] == '/') { + String s; + if(!exporting) + s << "$(UPPDIR" << (i + 1) << ")"; + s << AdjustMakePath(fn.GetIter(dl + 1)); + return s; + } + } + return raw ? String() : AdjustMakePath(fn); +} + +String CppBuilder::GetMakePath(String fn) const +{ + return ::GetMakePath(fn, HasFlag("WIN32")); +} + +void CppBuilder::AddMakeFile(MakeFile& makefile, String package, + const Vector& all_uses, const Vector& all_libraries, + const Index& common_config, bool exporting) +{ + String packagepath = PackagePath(package); + Package pkg; + pkg.Load(packagepath); + String packagedir = GetFileFolder(packagepath); + Vector src = GetUppDirs(); + for(int i = 0; i < src.GetCount(); i++) + src[i] = UnixPath(src[i]); + + bool main = HasFlag("MAIN"); + bool is_shared = HasFlag("SO"); + bool libout = !main && !HasFlag("NOLIB"); + bool win32 = HasFlag("WIN32"); + + String pack_ident = MakeIdent(package); + String outdir = "OutDir_" + pack_ident; + String macros = "Macro_" + pack_ident; + String macdef = "$(Macro)"; + String objext = (HasFlag("MSC") || HasFlag("EVC") ? ".obj" : ".o"); + + Vector x(config.GetKeys(), 1); + Sort(x); + for(int i = 0; i < x.GetCount(); i++) { + if(common_config.Find(x[i]) < 0) + macdef << " -Dflag" << x[i]; + x[i] = InitCaps(x[i]); + } + + makefile.outdir << "$(" << outdir << ")"; + makefile.outfile << AdjustMakePath(GetFileTitle(NativePath(package))); + if(main) + makefile.outfile << GetTargetExt(); + else if(is_shared) + makefile.outfile << (win32 ? ".dll" : ".so"); + else + makefile.outfile << (win32 && HasFlag("MSC") ? ".lib" : ".a"); + makefile.output << (main ? String("$(OutDir)") : makefile.outdir) << makefile.outfile; + + if(main) { + makefile.config << "CC = c++\n"; + String flags; + if(HasFlag("DEBUG")) + flags << " -D_DEBUG " << debug_options; + else + flags << ' ' << release_options; + if(HasFlag("DEBUG_MINIMAL")) + flags << " -ggdb -g1"; + if(HasFlag("DEBUG_FULL")) + flags << " -ggdb -g2"; + if(is_shared && !win32) + flags << " -fPIC "; + flags << ' ' << Gather(pkg.option, config.GetKeys()); + makefile.config << "CFLAGS =" << flags << "\n" + "CXXFLAGS =" << flags << "\n" + "LDFLAGS = " << (HasFlag("DEBUG") ? debug_link : release_link) << " $(LINKOPTIONS)\n" + "LIBPATH ="; + for(int i = 0; i < libpath.GetCount(); i++) + makefile.config << " -L" << GetMakePath(AdjustMakePath(GetHostPathQ(libpath[i]))); + makefile.config << "\n" + "AR = ar -sr\n\n"; + makefile.install << "\t-mkdir -p $(OutDir)\n"; + Vector lib; + String lnk; + lnk << "c++"; + if(!HasFlag("SHARED")) + lnk << " -static"; + if(HasFlag("WIN32")) { + lnk << " -mwindows"; + if(!HasFlag("GUI")) + makefile.linkfiles << " -mconsole"; + } + lnk << " -o $(OutFile)"; + if(HasFlag("DEBUG") || HasFlag("DEBUG_MINIMAL") || HasFlag("DEBUG_FULL")) + lnk << " -ggdb"; + else + lnk << (!HasFlag("OSX11") ? " -Wl,-s" : ""); + + lnk << " $(LIBPATH)"; + if (!HasFlag("OSX11")) + lnk << " -Wl,-O,2"; + lnk << " $(LDFLAGS)"; + + makefile.linkfiles = lnk; + } + + makefile.config << outdir << " = $(UPPOUT)" + << GetMakePath(AdjustMakePath(String().Cat() << package << '/' << method << '-' << Join(x, "-") << '/')) << "\n" + << macros << " = " << macdef << "\n"; + + makefile.install << "\t-mkdir -p $(" << outdir << ")\n"; + + String libdep, libfiles; + + libdep << makefile.output << ":"; + if(is_shared) + { + libfiles = "c++ -shared -fPIC"; // -v"; + Point p = ExtractVersion(); + if(!IsNull(p.x)) { + libfiles << " -Xlinker --major-image-version -Xlinker " << p.x; + if(!IsNull(p.y)) + libfiles << " -Xlinker --minor-image-version -Xlinker " << p.y; + } + libfiles << " -o "; + } + else + libfiles = "$(AR) "; + libfiles << makefile.output; + + for(int i = 0; i < pkg.GetCount(); i++) + if(!pkg[i].separator) { + String gop = Gather(pkg[i].option, config.GetKeys()); + String fn = SourcePath(package, pkg[i]); + String ext = ToLower(GetFileExt(fn)); + bool isc = ext == ".c"; + bool isrc = (ext == ".rc" && HasFlag("WIN32")); + bool iscpp = (ext == ".cpp" || ext == ".cc" || ext == ".cxx"); + bool isicpp = (ext == ".icpp"); + if(isc || isrc || iscpp || isicpp) { + String outfile; + outfile << makefile.outdir << AdjustMakePath(GetFileTitle(fn)) << (isrc ? "_rc" : "") << objext; + String srcfile = GetMakePath(MakeSourcePath(src, fn, false, exporting)); + makefile.rules << outfile << ": " << srcfile; + Vector dep = HdependGetDependencies(fn); + Sort(dep, GetLanguageInfo()); + for(int d = 0; d < dep.GetCount(); d++) { + String dfn = MakeSourcePath(src, dep[d], true, exporting); + if(!IsNull(dfn)) + makefile.rules << " \\\n\t" << GetMakePath(dfn); + } + makefile.rules << "\n" + "\t$(CC) -c " << (isc ? "-x c $(CFLAGS)" : "-x c++ $(CXXFLAGS)") << " $(CINC) $(" << macros << ") " + << gop << " " << srcfile << " -o " << outfile << "\n\n"; + if(!libout || isicpp) { + makefile.linkdep << " \\\n\t" << outfile; + makefile.linkfiles << " \\\n\t\t" << outfile; + } + else { + libdep << " \\\n\t" << outfile; + libfiles << " \\\n\t\t" << outfile; + } + } + else + if(ext == ".o" || ext == ".obj" || ext == ".a" || ext == ".so" || ext == ".lib" || ext == ".dll") { + makefile.linkdep << " \\\n\t" << fn; + makefile.linkfiles << ' ' << fn; + } + } + + if(libout) { + makefile.rules << libdep << "\n\t" << libfiles << "\n\n"; + makefile.linkdep << " \\\n\t" << makefile.output; + makefile.linkfiles << " \\\n\t\t\t" << makefile.output; + } + + if(main) { + if(!HasFlag("SOLARIS")&&!HasFlag("OSX11")) + makefile.linkfiles << " \\\n\t\t-Wl,--start-group "; + for(int i = 0; i < all_libraries.GetCount(); i++) { + String ln = all_libraries[i]; + String ext = ToLower(GetFileExt(ln)); + if(ext == ".a" || ext == ".so" || ext == ".dll") + makefile.linkfileend << " \\\n\t\t\t" << GetHostPathQ(FindInDirs(libpath, ln)); + else + makefile.linkfileend << " \\\n\t\t\t-l" << ln; + } + if(!HasFlag("SOLARIS")&&!HasFlag("OSX11")) + makefile.linkfileend << " \\\n\t\t-Wl,--end-group\n\n"; + } +} + +Point CppBuilder::ExtractVersion() +{ + Point v = Point(Null, Null); + CParser p(version); + while(!p.IsEof()) { + if(p.IsNumber()) { + v.x = p.ReadNumber(); + break; + } + p.GetChar(); + p.Spaces(); + } + while(!p.IsEof()) { + if(p.IsNumber()) { + v.y = p.ReadNumber(); + break; + } + p.GetChar(); + p.Spaces(); + } + return v; +} + +void CppBuilder::ShowTime(int count, int start_time) +{ + if(count) + PutConsole(NFormat("%d file(s) compiled in %s %d msec/file", + count, GetPrintTime(start_time), msecs(start_time) / count)); +} diff --git a/uppsrc/ide/Core/Core.h b/uppsrc/ide/Core/Core.h index 8e8d51969..e789a1de3 100644 --- a/uppsrc/ide/Core/Core.h +++ b/uppsrc/ide/Core/Core.h @@ -1,398 +1,400 @@ -#ifndef COMMON_H -#define COMMON_H - -#include -#include - -using namespace Upp; - -int CharFilterCid(int c); - -int ReadLNG(CParser& p); -String MakeLNG(int lang); - -bool OldLang(); - -String PrintTime(int msecs); -inline String GetPrintTime(dword time0) { return PrintTime(msecs(time0)); } - -bool SaveChangedFile(const char *path, String data, bool delete_empty = false); - -class Workspace; - -struct Ide; - -namespace Upp { -class Ctrl; -class Image; -}; - -class IdeContext -{ -public: - virtual void PutConsole(const char *s) = 0; - virtual void PutVerbose(const char *s) = 0; - - virtual const Workspace& IdeWorkspace() const = 0; - virtual bool IdeIsBuilding() const = 0; - virtual String IdeGetOneFile() const = 0; - virtual int IdeConsoleExecute(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false) = 0; - virtual int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet) = 0; - virtual int IdeConsoleExecute(One process, const char *cmdline, Stream *out = NULL, bool quiet = false) = 0; - virtual int IdeConsoleAllocSlot() = 0; - virtual bool IdeConsoleRun(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1) = 0; - virtual bool IdeConsoleRun(One process, const char *cmdline, Stream *out = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1) = 0; - virtual void IdeConsoleFlush() = 0; - virtual void IdeConsoleBeginGroup(String group) = 0; - virtual void IdeConsoleEndGroup() = 0; - virtual bool IdeConsoleWait() = 0; - - virtual bool IdeIsDebug() const = 0; - virtual void IdeEndDebug() = 0; - virtual void IdeSetBottom(Ctrl& ctrl) = 0; - virtual void IdeActivateBottom() = 0; - virtual void IdeRemoveBottom(Ctrl& ctrl) = 0; - virtual void IdeSetRight(Ctrl& ctrl) = 0; - virtual void IdeRemoveRight(Ctrl& ctrl) = 0; - - virtual String IdeGetFileName() const = 0; - virtual int IdeGetFileLine() = 0; - virtual String IdeGetLine(int i) const = 0; - - virtual void IdeSetDebugPos(const String& fn, int line, const Image& img, int i) = 0; - virtual void IdeHidePtr() = 0; - virtual bool IdeDebugLock() = 0; - virtual bool IdeDebugUnLock() = 0; - virtual bool IdeIsDebugLock() const = 0; - virtual void IdeSetBar() = 0; - virtual void IdeGotoCodeRef(String link) = 0; - virtual void IdeOpenTopicFile(const String& file) = 0; - virtual void IdeFlushFile() = 0; - virtual String IdeGetFileName() = 0; - virtual String IdeGetNestFolder() = 0; - - virtual ~IdeContext() {} -}; - -IdeContext *TheIde(); -void TheIde(IdeContext *context); - -void PutConsole(const char *s); -void PutVerbose(const char *s); - -const Workspace& GetIdeWorkspace(); -bool IdeIsBuilding(); -String IdeGetOneFile(); -int IdeConsoleExecute(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false); -int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet); -int IdeConsoleExecute(One process, const char *cmdline, Stream *out = NULL, bool quiet = false); -int IdeConsoleAllocSlot(); -bool IdeConsoleRun(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1); -bool IdeConsoleRun(One process, const char *cmdline, Stream *out = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1); -void IdeConsoleFlush(); -void IdeConsoleBeginGroup(String group); -void IdeConsoleEndGroup(); -bool IdeConsoleWait(); -void IdeGotoCodeRef(String s); - -bool IdeIsDebug(); -void IdeEndDebug(); -void IdeSetBottom(Ctrl& ctrl); -void IdeActivateBottom(); -void IdeRemoveBottom(Ctrl& ctrl); -void IdeSetRight(Ctrl& ctrl); -void IdeRemoveRight(Ctrl& ctrl); - -String IdeGetFileName(); -int IdeGetFileLine(); -String IdeGetLine(int i); - -void IdeSetDebugPos(const String& fn, int line, const Image& img, int i); -void IdeHidePtr(); -bool IdeDebugLock(); -bool IdeDebugUnLock(); -bool IdeIsDebugLock(); - -void IdeSetBar(); - -#include "Host.h" - -struct IdeMacro { - IdeMacro(); - - int hotkey; - String menu; - String submenu; - EscValue code; -}; - -ArrayMap& UscGlobal(); -Array& UscMacros(); - -void UscSetCleanModules(void (*CleanModules)()); -void SetIdeModuleUsc(bool (*IdeModuleUsc)(CParser& p)); -void UscSetReadMacro(void (*ReadMacro)(CParser& p)); - -void CleanUsc(); -void ParseUscFile(const char *filename) throw(CParser::Error); - -Point ReadNums(CParser& p); -Point ReadPoint(CParser& p); - -struct SemiTextTest : public TextTest { - virtual const char *Accept(const char *s) const; -}; - -Vector SplitDirs(const char *s); - -class Nest { - VectorMap var; - VectorMap package_cache; - - String PackagePath0(const String& name); - -public: - bool Save(const char *path); - bool Load(const char *path); - String Get(const String& id); - void Set(const String& id, const String& val); - - void InvalidatePackageCache(); - String PackagePath(const String& name); -}; - -String VarFilePath(); -String VarFilePath(String name); - -bool SaveVarFile(const char *filename, const VectorMap& var); -bool LoadVarFile(const char *name, VectorMap& var); -bool SaveVars(const char *name); -bool LoadVars(const char *name); -String GetVar(const String& var); -String GetVarsName(); -String VarFilePath(); -Vector GetUppDirs(); -String GetUppDir(); -void SetVar(const String& var, const String& value); - -String GetAnyFileName(const char *path); -String GetAnyFileTitle(const char *path); -String CatAnyPath(String path, const char *more); - -void InvalidatePackageCache(); -String PackagePath(const String& name); -String SourcePath(const String& package, const String& name); -inline -String PackageDirectory(const String& name) { return GetFileDirectory(PackagePath(name)); } -bool IsNestReadOnly(const String& path); - -String GetLocalDir(); -String LocalPath(const String& filename); - -Vector IgnoreList(); - -bool IsFullDirectory(const String& d); -bool IsFolder(const String& path); - -bool IsCSourceFile(const char *path); -bool IsCHeaderFile(const char *path); - -String FollowCygwinSymlink(const String& filename); - -void SplitPathMap(const char *path_map, Vector& local, Vector& remote); -String JoinPathMap(const Vector& local, const Vector& remote); -void SplitHostName(const char *hostname, String& host, int& port); - -Vector SplitFlags0(const char *flags); -Vector SplitFlags(const char *flags, bool main = false); -Vector SplitFlags(const char *flags, bool main, const Vector& accepts); - -bool MatchWhen(const String& when, const Vector& flag); -String ReadWhen(CParser& p); -String AsStringWhen(const String& when); - -struct OptItem { - String when; - String text; -}; - -struct CustomStep { - String when; - String ext; - String command; - String output; - - void Load(CParser& p) throw(CParser::Error); - String AsString() const; - - String GetExt() const; - bool MatchExt(const char *fn) const; -}; - -Vector Combine(const Vector& conf, const char *flags); -String Gather(const Array& set, const Vector& conf, bool nospace = false); - -bool HasFlag(const Vector& conf, const char *flag); - -enum { - FLAG_MISMATCH = -2, - FLAG_UNDEFINED = -1, -}; - -int GetType(const Vector& conf, const char *flags); -int GetType(const Vector& conf, const char *flags, int def); -bool GetFlag(const Vector& conf, const char *flag); -String RemoveType(Vector& conf, const char *flags); - -class Package { - void Reset(); - -public: - struct File : public String { - Array option; - Array depends; - bool readonly; - bool separator; - int tabsize; - byte charset; - int font; - String highlight; - int optimize_speed; - - void operator=(const String& s) { String::operator=(s); readonly = separator = false; } - void Init() { readonly = separator = false; tabsize = Null; charset = 0; font = 0; - optimize_speed = false; } - - File() { Init(); } - File(const String& s) : String(s) { Init(); } - }; - struct Config { - String name; - String param; - }; - byte charset; - bool optimize_speed; - bool noblitz; - String description; - Vector accepts; - Array flag; - Array uses; - Array target; - Array library; - Array link; - Array option; - Array include; - Array file; - Array config; - Array custom; - Time time; - bool bold, italic; - Color ink; - - int GetCount() const { return file.GetCount(); } - File& operator[](int i) { return file[i]; } - const File& operator[](int i) const { return file[i]; } - - void Load(const char *path); - bool Save(const char *file) const; - - static void SetPackageResolver(bool (*Resolve)(const String& error, const String& path, int line)); - - Package(); -}; - -class Workspace { - void AddUses(Package& p, bool match, const Vector& flag); - void AddLoad(const String& name, bool match, const Vector& flag); - -public: - ArrayMap package; - - void Clear() { package.Clear(); } - String operator[](int i) const { return package.GetKey(i); } - Package& GetPackage(int i) { return package[i]; } - const Package& GetPackage(int i) const { return package[i]; } - int GetCount() const { return package.GetCount(); } - - void Scan(const char *prjname); - void Scan(const char *prjname, const Vector& flag); - - Vector GetAllAccepts(int pk) const; - - void Dump(); -}; - -struct Ide; - -String FindInDirs(const Vector& dir, const String& file); -String FindCommand(const Vector& exedir, const String& cmdline); - -struct MakeFile { - String outdir; - String outfile; - String output; - String config; - String install; - String rules; - String linkdep; - String linkfiles; - String linkfileend; -}; - -String GetMakePath(String fn, bool win32); -String AdjustMakePath(const char *fn); - -enum { - R_OPTIMAL, - R_SPEED, - R_SIZE -}; - -struct Builder { - Host *host; - Index config; - String compiler; - String method; - String outdir; - Vector include; - Vector libpath; - String target; - String debug_options; - String release_options; - String release_size_options; - String version; - String script; - bool doall; - - virtual bool BuildPackage(const String& package, Vector& linkfile, String& linkoptions, - const Vector& all_uses, const Vector& all_libraries, int optimize) - { return false; } - virtual bool Link(const Vector& linkfile, const String& linkoptions, bool createmap) - { return false; } - virtual bool Preprocess(const String& package, const String& file, const String& result, bool asmout) - { return false; } - virtual void AddFlags(Index& cfg) {} - virtual void AddMakeFile(MakeFile& mfinfo, String package, - const Vector& all_uses, const Vector& all_libraries, - const Index& common_config, bool exporting) {} - virtual String GetTargetExt() const = 0; - - Builder() { doall = false; } - virtual ~Builder() {} -}; - -VectorMap& BuilderMap(); -void RegisterBuilder(const char *name, Builder *(*create)()); - -void HdependSetDirs(pick_ Vector& id); -void HdependTimeDirty(); -void HdependClearDependencies(); -void HdependAddDependency(const String& file, const String& depends); -Time HdependFileTime(const String& path); -Vector HdependGetDependencies(const String& path); -String FindIncludeFile(const char *s, const String& filedir); -bool HdependBlitzApproved(const String& path); -const Vector& HdependGetDefines(const String& path); -const Vector& HdependGetAllFiles(); - -#endif +#ifndef COMMON_H +#define COMMON_H + +#include +#include + +using namespace Upp; + +int CharFilterCid(int c); + +int ReadLNG(CParser& p); +String MakeLNG(int lang); + +bool OldLang(); + +String PrintTime(int msecs); +inline String GetPrintTime(dword time0) { return PrintTime(msecs(time0)); } + +bool SaveChangedFile(const char *path, String data, bool delete_empty = false); + +class Workspace; + +struct Ide; + +namespace Upp { +class Ctrl; +class Image; +}; + +class IdeContext +{ +public: + virtual void PutConsole(const char *s) = 0; + virtual void PutVerbose(const char *s) = 0; + + virtual const Workspace& IdeWorkspace() const = 0; + virtual bool IdeIsBuilding() const = 0; + virtual String IdeGetOneFile() const = 0; + virtual int IdeConsoleExecute(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false) = 0; + virtual int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet) = 0; + virtual int IdeConsoleExecute(One process, const char *cmdline, Stream *out = NULL, bool quiet = false) = 0; + virtual int IdeConsoleAllocSlot() = 0; + virtual bool IdeConsoleRun(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1) = 0; + virtual bool IdeConsoleRun(One process, const char *cmdline, Stream *out = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1) = 0; + virtual void IdeConsoleFlush() = 0; + virtual void IdeConsoleBeginGroup(String group) = 0; + virtual void IdeConsoleEndGroup() = 0; + virtual bool IdeConsoleWait() = 0; + + virtual bool IdeIsDebug() const = 0; + virtual void IdeEndDebug() = 0; + virtual void IdeSetBottom(Ctrl& ctrl) = 0; + virtual void IdeActivateBottom() = 0; + virtual void IdeRemoveBottom(Ctrl& ctrl) = 0; + virtual void IdeSetRight(Ctrl& ctrl) = 0; + virtual void IdeRemoveRight(Ctrl& ctrl) = 0; + + virtual String IdeGetFileName() const = 0; + virtual int IdeGetFileLine() = 0; + virtual String IdeGetLine(int i) const = 0; + + virtual void IdeSetDebugPos(const String& fn, int line, const Image& img, int i) = 0; + virtual void IdeHidePtr() = 0; + virtual bool IdeDebugLock() = 0; + virtual bool IdeDebugUnLock() = 0; + virtual bool IdeIsDebugLock() const = 0; + virtual void IdeSetBar() = 0; + virtual void IdeGotoCodeRef(String link) = 0; + virtual void IdeOpenTopicFile(const String& file) = 0; + virtual void IdeFlushFile() = 0; + virtual String IdeGetFileName() = 0; + virtual String IdeGetNestFolder() = 0; + + virtual ~IdeContext() {} +}; + +IdeContext *TheIde(); +void TheIde(IdeContext *context); + +void PutConsole(const char *s); +void PutVerbose(const char *s); + +const Workspace& GetIdeWorkspace(); +bool IdeIsBuilding(); +String IdeGetOneFile(); +int IdeConsoleExecute(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false); +int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet); +int IdeConsoleExecute(One process, const char *cmdline, Stream *out = NULL, bool quiet = false); +int IdeConsoleAllocSlot(); +bool IdeConsoleRun(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1); +bool IdeConsoleRun(One process, const char *cmdline, Stream *out = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1); +void IdeConsoleFlush(); +void IdeConsoleBeginGroup(String group); +void IdeConsoleEndGroup(); +bool IdeConsoleWait(); +void IdeGotoCodeRef(String s); + +bool IdeIsDebug(); +void IdeEndDebug(); +void IdeSetBottom(Ctrl& ctrl); +void IdeActivateBottom(); +void IdeRemoveBottom(Ctrl& ctrl); +void IdeSetRight(Ctrl& ctrl); +void IdeRemoveRight(Ctrl& ctrl); + +String IdeGetFileName(); +int IdeGetFileLine(); +String IdeGetLine(int i); + +void IdeSetDebugPos(const String& fn, int line, const Image& img, int i); +void IdeHidePtr(); +bool IdeDebugLock(); +bool IdeDebugUnLock(); +bool IdeIsDebugLock(); + +void IdeSetBar(); + +#include "Host.h" + +struct IdeMacro { + IdeMacro(); + + int hotkey; + String menu; + String submenu; + EscValue code; +}; + +ArrayMap& UscGlobal(); +Array& UscMacros(); + +void UscSetCleanModules(void (*CleanModules)()); +void SetIdeModuleUsc(bool (*IdeModuleUsc)(CParser& p)); +void UscSetReadMacro(void (*ReadMacro)(CParser& p)); + +void CleanUsc(); +void ParseUscFile(const char *filename) throw(CParser::Error); + +Point ReadNums(CParser& p); +Point ReadPoint(CParser& p); + +struct SemiTextTest : public TextTest { + virtual const char *Accept(const char *s) const; +}; + +Vector SplitDirs(const char *s); + +class Nest { + VectorMap var; + VectorMap package_cache; + + String PackagePath0(const String& name); + +public: + bool Save(const char *path); + bool Load(const char *path); + String Get(const String& id); + void Set(const String& id, const String& val); + + void InvalidatePackageCache(); + String PackagePath(const String& name); +}; + +String VarFilePath(); +String VarFilePath(String name); + +bool SaveVarFile(const char *filename, const VectorMap& var); +bool LoadVarFile(const char *name, VectorMap& var); +bool SaveVars(const char *name); +bool LoadVars(const char *name); +String GetVar(const String& var); +String GetVarsName(); +String VarFilePath(); +Vector GetUppDirs(); +String GetUppDir(); +void SetVar(const String& var, const String& value); + +String GetAnyFileName(const char *path); +String GetAnyFileTitle(const char *path); +String CatAnyPath(String path, const char *more); + +void InvalidatePackageCache(); +String PackagePath(const String& name); +String SourcePath(const String& package, const String& name); +inline +String PackageDirectory(const String& name) { return GetFileDirectory(PackagePath(name)); } +bool IsNestReadOnly(const String& path); + +String GetLocalDir(); +String LocalPath(const String& filename); + +Vector IgnoreList(); + +bool IsFullDirectory(const String& d); +bool IsFolder(const String& path); + +bool IsCSourceFile(const char *path); +bool IsCHeaderFile(const char *path); + +String FollowCygwinSymlink(const String& filename); + +void SplitPathMap(const char *path_map, Vector& local, Vector& remote); +String JoinPathMap(const Vector& local, const Vector& remote); +void SplitHostName(const char *hostname, String& host, int& port); + +Vector SplitFlags0(const char *flags); +Vector SplitFlags(const char *flags, bool main = false); +Vector SplitFlags(const char *flags, bool main, const Vector& accepts); + +bool MatchWhen(const String& when, const Vector& flag); +String ReadWhen(CParser& p); +String AsStringWhen(const String& when); + +struct OptItem { + String when; + String text; +}; + +struct CustomStep { + String when; + String ext; + String command; + String output; + + void Load(CParser& p) throw(CParser::Error); + String AsString() const; + + String GetExt() const; + bool MatchExt(const char *fn) const; +}; + +Vector Combine(const Vector& conf, const char *flags); +String Gather(const Array& set, const Vector& conf, bool nospace = false); + +bool HasFlag(const Vector& conf, const char *flag); + +enum { + FLAG_MISMATCH = -2, + FLAG_UNDEFINED = -1, +}; + +int GetType(const Vector& conf, const char *flags); +int GetType(const Vector& conf, const char *flags, int def); +bool GetFlag(const Vector& conf, const char *flag); +String RemoveType(Vector& conf, const char *flags); + +class Package { + void Reset(); + +public: + struct File : public String { + Array option; + Array depends; + bool readonly; + bool separator; + int tabsize; + byte charset; + int font; + String highlight; + int optimize_speed; + + void operator=(const String& s) { String::operator=(s); readonly = separator = false; } + void Init() { readonly = separator = false; tabsize = Null; charset = 0; font = 0; + optimize_speed = false; } + + File() { Init(); } + File(const String& s) : String(s) { Init(); } + }; + struct Config { + String name; + String param; + }; + byte charset; + bool optimize_speed; + bool noblitz; + String description; + Vector accepts; + Array flag; + Array uses; + Array target; + Array library; + Array link; + Array option; + Array include; + Array file; + Array config; + Array custom; + Time time; + bool bold, italic; + Color ink; + + int GetCount() const { return file.GetCount(); } + File& operator[](int i) { return file[i]; } + const File& operator[](int i) const { return file[i]; } + + void Load(const char *path); + bool Save(const char *file) const; + + static void SetPackageResolver(bool (*Resolve)(const String& error, const String& path, int line)); + + Package(); +}; + +class Workspace { + void AddUses(Package& p, bool match, const Vector& flag); + void AddLoad(const String& name, bool match, const Vector& flag); + +public: + ArrayMap package; + + void Clear() { package.Clear(); } + String operator[](int i) const { return package.GetKey(i); } + Package& GetPackage(int i) { return package[i]; } + const Package& GetPackage(int i) const { return package[i]; } + int GetCount() const { return package.GetCount(); } + + void Scan(const char *prjname); + void Scan(const char *prjname, const Vector& flag); + + Vector GetAllAccepts(int pk) const; + + void Dump(); +}; + +struct Ide; + +String FindInDirs(const Vector& dir, const String& file); +String FindCommand(const Vector& exedir, const String& cmdline); + +struct MakeFile { + String outdir; + String outfile; + String output; + String config; + String install; + String rules; + String linkdep; + String linkfiles; + String linkfileend; +}; + +String GetMakePath(String fn, bool win32); +String AdjustMakePath(const char *fn); + +enum { + R_OPTIMAL, + R_SPEED, + R_SIZE +}; + +struct Builder { + Host *host; + Index config; + String compiler; + String method; + String outdir; + Vector include; + Vector libpath; + String target; + String debug_options; + String release_options; + String release_size_options; + String debug_link; + String release_link; + String version; + String script; + bool doall; + + virtual bool BuildPackage(const String& package, Vector& linkfile, String& linkoptions, + const Vector& all_uses, const Vector& all_libraries, int optimize) + { return false; } + virtual bool Link(const Vector& linkfile, const String& linkoptions, bool createmap) + { return false; } + virtual bool Preprocess(const String& package, const String& file, const String& result, bool asmout) + { return false; } + virtual void AddFlags(Index& cfg) {} + virtual void AddMakeFile(MakeFile& mfinfo, String package, + const Vector& all_uses, const Vector& all_libraries, + const Index& common_config, bool exporting) {} + virtual String GetTargetExt() const = 0; + + Builder() { doall = false; } + virtual ~Builder() {} +}; + +VectorMap& BuilderMap(); +void RegisterBuilder(const char *name, Builder *(*create)()); + +void HdependSetDirs(pick_ Vector& id); +void HdependTimeDirty(); +void HdependClearDependencies(); +void HdependAddDependency(const String& file, const String& depends); +Time HdependFileTime(const String& path); +Vector HdependGetDependencies(const String& path); +String FindIncludeFile(const char *s, const String& filedir); +bool HdependBlitzApproved(const String& path); +const Vector& HdependGetDefines(const String& path); +const Vector& HdependGetAllFiles(); + +#endif