diff --git a/uppsrc/RichText/EncodeHTML.cpp b/uppsrc/RichText/EncodeHTML.cpp
index 3e77ee02e..009567bf9 100644
--- a/uppsrc/RichText/EncodeHTML.cpp
+++ b/uppsrc/RichText/EncodeHTML.cpp
@@ -106,13 +106,11 @@ void TabBorder(String& style, const char *txt, int border, Color bordercolor, co
<< ColorToHtml(border ? bordercolor : tf.gridcolor) << ';';
}
-
String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css,
const VectorMap& links,
const VectorMap& labels,
- const String& outdir, const String& namebase, Zoom z, int& im,
- const VectorMap& escape,
- int imtolerance)
+ Zoom z, const VectorMap& escape,
+ HtmlObjectSaver& object_saver)
{
String html;
for(int i = 0; i < text.GetPartCount(); i++)
@@ -171,8 +169,7 @@ String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css,
if(c.vspan)
html << " rowspan=" << c.vspan + 1;
html << '>';
- html << AsHtml(c.text, styles, css, links, labels, outdir, namebase, z,
- im, escape, imtolerance);
+ html << AsHtml(c.text, styles, css, links, labels, z, escape, object_saver);
html << "\r\n";
}
}
@@ -221,26 +218,8 @@ String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css,
for(int i = 0; i < p.part.GetCount(); i++) {
const RichPara::Part& part = p.part[i];
int q;
- if(part.object) {
- String name;
- name << namebase << "_" << im++ << ".png";
- Size psz = part.object.GetPixelSize();
- String lname;
- lname << "L$" << name;
- Size sz = z * part.object.GetSize();
- if(abs(100 * (psz.cx - sz.cx) / sz.cx) < imtolerance)
- sz = psz;
- PNGEncoder png;
- png.SaveFile(AppendFileName(outdir, name), part.object.ToImage(sz));
- if(psz.cx * psz.cy)
- html << "";
- html << "
";
- if(psz.cx * psz.cy) {
- html << "";
- PNGEncoder png;
- png.SaveFile(AppendFileName(outdir, lname), part.object.ToImage(psz));
- }
- }
+ if(part.object)
+ html << object_saver.GetHtml(part.object);
else
if(part.format.indexentry.GetCount() &&
(q = escape.Find(part.format.indexentry.ToString())) >= 0)
@@ -342,14 +321,63 @@ String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css,
return html;
}
+class DefaultHtmlObjectSaver : public HtmlObjectSaver
+{
+public:
+ DefaultHtmlObjectSaver(const String& outdir_, const String& namebase_, int imtolerance_, Zoom z_)
+ : outdir(outdir_), namebase(namebase_), imtolerance(imtolerance_), z(z_), im(0) {}
+
+ virtual String GetHtml(const RichObject& object);
+
+private:
+ String outdir;
+ String namebase;
+ Zoom z;
+ int imtolerance;
+ int im;
+};
+
+String DefaultHtmlObjectSaver::GetHtml(const RichObject& object)
+{
+ StringBuffer html;
+ String name;
+ name << namebase << "_" << im++ << ".png";
+ Size psz = object.GetPixelSize();
+ String lname;
+ lname << "L$" << name;
+ Size sz = z * object.GetSize();
+ if(abs(100 * (psz.cx - sz.cx) / sz.cx) < imtolerance)
+ sz = psz;
+ PNGEncoder png;
+ png.SaveFile(AppendFileName(outdir, name), object.ToImage(sz));
+ if(psz.cx * psz.cy)
+ html << "";
+ html << "
";
+ if(psz.cx * psz.cy) {
+ html << "";
+ PNGEncoder png;
+ png.SaveFile(AppendFileName(outdir, lname), object.ToImage(psz));
+ }
+ return html;
+}
+
String EncodeHtml(const RichText& text, Index& css,
const VectorMap& links,
const VectorMap& labels,
const String& outdir, const String& namebase, Zoom z,
const VectorMap& escape, int imt)
{
- int im = 0;
- return AsHtml(text, text.GetStyles(), css, links, labels, outdir, namebase, z, im, escape, imt);
+ DefaultHtmlObjectSaver default_saver(outdir, namebase, imt, z);
+ return AsHtml(text, text.GetStyles(), css, links, labels, z, escape, default_saver);
+}
+
+String EncodeHtml(const RichText& text, Index& css,
+ const VectorMap& links,
+ const VectorMap& labels,
+ HtmlObjectSaver& object_saver, Zoom z,
+ const VectorMap& escape)
+{
+ return AsHtml(text, text.GetStyles(), css, links, labels, z, escape, object_saver);
}
String AsCss(Index& ss)
diff --git a/uppsrc/RichText/RichText.h b/uppsrc/RichText/RichText.h
index 08f85172d..11e96ec1e 100644
--- a/uppsrc/RichText/RichText.h
+++ b/uppsrc/RichText/RichText.h
@@ -455,12 +455,25 @@ Zoom GetRichTextStdScreenZoom();
const Display& QTFDisplay();
const Display& QTFDisplayVCenter();
+class HtmlObjectSaver
+{
+public:
+ virtual ~HtmlObjectSaver() {}
+
+ virtual String GetHtml(const RichObject& object) = 0;
+};
+
String EncodeHtml(const RichText& text, Index& css,
const VectorMap& links,
const VectorMap& labels,
const String& path, const String& base = Null, Zoom z = Zoom(8, 40),
const VectorMap& escape = VectorMap(),
int imtolerance = 0);
+String EncodeHtml(const RichText& text, Index& css,
+ const VectorMap& links,
+ const VectorMap& labels,
+ HtmlObjectSaver& object_saver, Zoom z = Zoom(8, 40),
+ const VectorMap& escape = VectorMap());
String AsCss(Index& ss);
inline //BW - no labels
diff --git a/uppsrc/ide/Builders/MscBuilder.icpp b/uppsrc/ide/Builders/MscBuilder.icpp
index 44a579219..62a616bb0 100644
--- a/uppsrc/ide/Builders/MscBuilder.icpp
+++ b/uppsrc/ide/Builders/MscBuilder.icpp
@@ -1,614 +1,614 @@
-#include "Builders.h"
-
-#include
-
-#ifdef PLATFORM_WIN32
-static bool HasTail(String s, const char *tail)
-{
- int tl = (int)strlen(tail);
- int sl = s.GetLength();
- if(sl < tl)
- return false;
- for(const char *p = s.GetIter(sl - tl); *p; p++, tail++)
- if(*tail != '*' && *tail != *p)
- return false;
- return *tail == 0;
-}
-#endif
-
-static void AddObjectExports(const char *path, Index& out)
-{
-#ifdef PLATFORM_WIN32
- FileMapping mapping;
- if(!mapping.Open(path))
- return;
- const byte *begin = mapping.Begin();
- const COFF_IMAGE_FILE_HEADER *hdr = (const COFF_IMAGE_FILE_HEADER *)begin;
- if(hdr->Machine != COFF_IMAGE_FILE_MACHINE_I386)
- return;
- const COFF_IMAGE_SECTION_HEADER *sechdr = (const COFF_IMAGE_SECTION_HEADER *)(begin
- + sizeof(COFF_IMAGE_FILE_HEADER) + hdr->SizeOfOptionalHeader);
- Index code_sections;
- for(int i = 0; i < hdr->NumberOfSections; i++)
- if(sechdr[i].Characteristics & COFF_IMAGE_SCN_CNT_CODE)
- code_sections.Add(i + 1);
- const COFF_IMAGE_SYMBOL *symtbl = (const COFF_IMAGE_SYMBOL *)(begin + hdr->PointerToSymbolTable);
- const char *strtbl = (const char *)(symtbl + hdr->NumberOfSymbols);
- for(int i = 0; i < (int)hdr->NumberOfSymbols; i++)
- {
- const COFF_IMAGE_SYMBOL& sym = symtbl[i];
- if(sym.StorageClass == COFF_IMAGE_SYM_CLASS_EXTERNAL && code_sections.Find(sym.SectionNumber) >= 0)
- {
- String name = COFFSymbolName(sym, strtbl);
- if(!HasTail(name, "AEPAXI@Z"))
- {
- if(*name == '_' && name.Find('@') < 0)
- name.Remove(0, 1);
- out.FindAdd(name);
- }
- }
- i += sym.NumberOfAuxSymbols;
- }
-#endif
-}
-
-void MscBuilder::AddFlags(Index& cfg)
-{
- cfg.FindAdd("MSC");
-}
-
-String MscBuilder::CmdLine(const String& package, const Package& pkg)
-{
- String cc;
- if(HasFlag("ARM"))
- cc = "clarm";
- else
- if(HasFlag("MIPS"))
- cc = "clmips";
- else
- if(HasFlag("SH3"))
- cc = "shcl /Qsh3";
- else
- if(HasFlag("SH4"))
- cc = "shcl /Qsh4";
- else
- if(HasFlag("MSC8ARM"))
- cc = "cl -GS- ";
- else
- cc = HasFlag("INTEL") ? "icl" : "cl";
-// TRC 080605-documentation says Wp64 works in 32-bit compilation only
-// cc << (IsMsc64() ? " -nologo -Wp64 -W3 -GR -c" : " -nologo -W3 -GR -c");
- cc << " -nologo -W3 -GR -c";
- cc << IncludesDefinesTargetTime(package, pkg);
-
- return cc;
-}
-
-String MscBuilder::MachineName() const
-{
- if(HasFlag("ARM")) return "ARM";
- if(HasFlag("MIPS")) return "MIPS";
- if(HasFlag("SH3")) return "SH3";
- if(HasFlag("SH4")) return "SH4";
- if(IsMscArm()) return "ARM";
- if(IsMsc64()) return "x64";
- if(HasFlag("WIN32")) return "I386";
- return "IX86";
-}
-
-bool MscBuilder::IsMsc89() const
-{
- return IsMsc86() || IsMsc64() || IsMscArm();
-}
-
-bool MscBuilder::IsMsc86() const
-{
- return HasFlag("MSC8") || HasFlag("MSC9") || HasFlag("MSC10");
-}
-
-bool MscBuilder::IsMscArm() const
-{
- return HasFlag("MSC8ARM") || HasFlag("MSC9ARM");
-}
-
-bool MscBuilder::IsMsc64() const
-{
- return HasFlag("MSC8X64") || HasFlag("MSC9X64") || HasFlag("MSC10X64");
-}
-
-String MscBuilder::LinkerName() const
-{
- if(HasFlag("ULD")) return "uld";
- if(HasFlag("INTEL")) return "xilink";
- return "link";
-}
-
-static bool sContainsPchOptions(const String& x)
-{
- Index a(Split(x, ' '));
- return a.Find("-GL") >= 0 || a.Find("/GL") >= 0 || a.Find("-Y-") >= 0 || a.Find("/Y-") >= 0
- || a.Find("-Yc") >= 0 || a.Find("/Yc") >= 0 || a.Find("-Yd") >= 0 || a.Find("/Yd") >= 0
- || a.Find("-Yl") >= 0 || a.Find("/Yl") >= 0 || a.Find("-Yu") >= 0 || a.Find("/Yu") >= 0
- || a.Find("-YX") >= 0 || a.Find("/YX") >= 0;
-}
-
-bool MscBuilder::HasAnyDebug() const
-{
- return HasFlag("DEBUG") || HasFlag("DEBUG_MINIMAL") || HasFlag("DEBUG_FULL");
-}
-
-String MscBuilder::PdbPch(String package, int slot, bool do_pch) const
-{
- String pkg_slot = NFormat("%s-%d", GetAnyFileName(package), slot + 1);
- String pdb = GetHostPathQ(CatAnyPath(outdir, pkg_slot + ".pdb"));
- String cc;
- cc << " -Gy -Fd" << pdb;
- if(do_pch && !IsMsc89()) // MSC8/9 does not support automatic precompiled headers...
- cc << " -YX -Fp" << GetHostPathQ(CatAnyPath(outdir, pkg_slot + ".pch")) << ' ';
- return cc;
-}
-
-bool MscBuilder::BuildPackage(const String& package, Vector& linkfile, String& linkoptions,
- const Vector& all_uses, const Vector& all_libraries, int opt)
-{
- int i;
- String packagepath = PackagePath(package);
- Package pkg;
- pkg.Load(packagepath);
- String packagedir = GetFileFolder(packagepath);
- ChDir(packagedir);
- PutVerbose("cd " + packagedir);
- IdeConsoleBeginGroup(package);
- Vector obj;
-
- bool is_shared = HasFlag("SO"),
- is_clr = HasFlag("CLR");
-
- String cc = CmdLine(package, pkg);
- if(HasFlag("EVC")) {
- if(!HasFlag("SH3") && !HasFlag("SH4"))
- cc << " -Gs8192"; // disable stack checking
- cc << " -GF" // read-only string pooling
- " -GX-"; // turn off exception handling
- }
- else
- if(is_clr)
- cc << " -EHac";
- else
- if(IsMsc89())
- cc << " -EHsc";
- else
- cc << " -GX";
-// String pdb = GetHostPathQ(CatAnyPath(outdir, GetAnyFileName(package) + ".pdb"));
-// String pch;
-// if(!HasFlag("MSC8")) // MSC8 does not support automatic precompiled headers...
-// pch << " -YX -Fp" << GetHostPathQ(CatAnyPath(outdir, GetAnyFileName(package) + ".pch")) << ' ';
-// cc << " -Gy -Fd" << pdb;
- if(HasFlag("SSE2") && !IsMsc64())
- cc << " /arch:SSE2";
- if(HasFlag("DEBUG_MINIMAL"))
- cc << " -Zd";
- if(HasFlag("DEBUG_FULL"))
- cc << " -Zi";
- cc << ' ' << Gather(pkg.option, config.GetKeys());
- cc << (HasFlag("SHARED") || is_shared || is_clr ? " -MD"
- : (HasFlag("MT") || IsMsc89()) ? " -MT" : " -ML");
-
- String cc_size = cc;
- String cc_speed = cc;
- bool release = false;
-
- if(HasFlag("DEBUG"))
- cc << "d " << debug_options;
- else {
- release = true;
- cc << ' ' << release_size_options;
- cc_speed << ' ' << release_options;
- if(opt == R_SPEED || pkg.optimize_speed)
- cc = cc_speed;
- }
-
-
- Vector sfile, isfile;
- Vector soptions, isoptions;
- Vector optimize, ioptimize;
- Vector sobjfile;
- bool error = false;
-
- for(i = 0; i < pkg.GetCount(); i++) {
- if(!IdeIsBuilding())
- return false;
- if(!pkg[i].separator) {
- String gop = Gather(pkg[i].option, config.GetKeys());
- Vector srcfile = CustomStep(pkg[i], package, error);
- if(srcfile.GetCount() == 0)
- error = true;
- for(int j = 0; j < srcfile.GetCount(); j++) {
- String fn = srcfile[j];
- String ext = ToLower(GetFileExt(fn));
- if(ext == ".c" || ext == ".cpp" || ext == ".cc" || ext == ".cxx" || ext == ".rc" || ext == ".brc") {
- sfile.Add(fn);
- soptions.Add(gop);
- optimize.Add(release && pkg[i].optimize_speed && opt == R_OPTIMAL);
- }
- else
- if(ext == ".icpp") {
- isfile.Add(fn);
- isoptions.Add(gop);
- ioptimize.Add(release && pkg[i].optimize_speed && opt == R_OPTIMAL);
- }
- else
- if(ext == ".obj")
- obj.Add(fn);
- else
- if(ext == ".lib")
- linkfile.Add(fn);
- }
- }
- }
-
- if(HasFlag("BLITZ")) {
- Blitz b = BlitzStep(sfile, soptions, obj, ".obj", optimize);
- if(b.build) {
- PutConsole("BLITZ:" + b.info);
- int slot = AllocSlot();
- if(slot < 0 || ! Run(cc + PdbPch(package, slot, false)
- + " -Tp " + GetHostPathQ(b.path) + " -Fo" + GetHostPathQ(b.object), slot, GetHostPath(b.object), b.count))
- error = true;
- }
- }
-
- int first_ifile = sfile.GetCount();
- sfile.AppendPick(isfile);
- soptions.AppendPick(isoptions);
- optimize.AppendPick(ioptimize);
-
- int ccount = 0;
-
-// if(sContainsPchOptions(cc))
-// pch = Null;
-
- for(i = 0; i < sfile.GetCount(); i++) {
- if(!IdeIsBuilding())
- return false;
- String fn = sfile[i];
- String ext = ToLower(GetFileExt(fn));
- bool rc = (ext == ".rc");
- bool brc = (ext == ".brc");
- bool init = (i >= first_ifile);
- String objfile = CatAnyPath(outdir, GetFileTitle(fn) + (rc ? "$rc.obj" : brc ? "$brc.obj" : ".obj"));
- if(HdependFileTime(fn) > GetFileTime(objfile)) {
- int time = GetTickCount();
- bool execerr = false;
- if(rc) {
- PutConsole(GetFileNamePos(fn));
- int slot = AllocSlot();
- if(slot < 0 || !Run("rc /fo" + GetHostPathQ(objfile) + Includes(" /i", package, pkg)
- + ' ' + GetHostPathQ(fn), slot, GetHostPath(objfile), 1))
- execerr = true;
- }
- else
- if(brc) {
- try {
-// String hfn = GetHostPath(fn);
- String brcdata = LoadFile(fn);
- if(brcdata.IsVoid())
- throw Exc(NFormat("error reading file '%s'", fn));
- CParser parser(brcdata, fn);
- String fo = BrcToC(parser, GetFileDirectory(fn));
- String tmpfile = ForceExt(objfile, ".c");
- SaveFile(tmpfile, fo);
- int slot = AllocSlot();
- StringBuffer cmdline;
- cmdline << cc << PdbPch(package, slot, false)
- << " -Tc " << GetHostPathQ(tmpfile) << " -Fo" << GetHostPathQ(objfile);
- if(slot < 0 || !Run(String(cmdline), slot, GetHostPath(objfile), 1))
- throw Exc(NFormat("Error compiling binary object '%s'.", objfile));
- }
- catch(Exc e) {
- PutConsole(e);
- execerr = true;
- }
- }
- else {
- String c = cc;
- if(optimize[i])
- c = cc_speed;
- int slot = AllocSlot();
- if(slot < 0 || !Run(c + PdbPch(package, slot, !sContainsPchOptions(cc) && !sContainsPchOptions(soptions[i]))
- + " " + soptions[i] + (ext == ".c" ? " -Tc " : " -Tp ")
- + GetHostPathQ(fn) + " -Fo" + GetHostPathQ(objfile), slot, GetHostPath(objfile), 1))
- execerr = true;
- }
- if(execerr)
- DeleteFile(objfile);
- error |= execerr;
- PutVerbose("compiled in " + GetPrintTime(time));
- ccount++;
- }
- if(init)
- linkfile.Add(objfile);
- else
- obj.Add(objfile);
- }
- if(error) {
- IdeConsoleEndGroup();
- return false;
- }
-
- Vector pkglibs = Split(Gather(pkg.library, config.GetKeys()), ' ');
- for(int i = 0; i < pkglibs.GetCount(); i++) {
- String libfile = AppendExt(pkglibs[i], ".lib");
- if(!IsFullPath(libfile)) {
- for(int p = 0; p < libpath.GetCount(); p++) {
- String nf = NormalizePath(libfile, libpath[p]);
- if(FileExists(nf)) {
- libfile = nf;
- break;
- }
- }
- }
- linkfile.Add(libfile);
- }
- linkoptions << ' ' << Gather(pkg.link, config.GetKeys());
-
- int linktime = GetTickCount();
- if(!HasFlag("MAIN")) {
- if(HasFlag("BLITZ") || HasFlag("NOLIB")) {
- linkfile.Append(obj);
-// ShowTime(ccount, time);
- IdeConsoleEndGroup();
- return true;
- }
- String product;
- if(is_shared)
- product = GetSharedLibPath(package);
- else
- product = CatAnyPath(outdir, GetAnyFileName(package) + ".lib");
- Time producttime = GetFileTime(product);
- if(obj.GetCount())
- linkfile.Add(ForceExt(product, ".lib"));
- if(!Wait()) {
- IdeConsoleEndGroup();
- return false;
- }
- Vector objinfo = host->GetFileInfo(obj);
- for(int i = 0; i < obj.GetCount(); i++)
- if(objinfo[i] > producttime) {
- String linker, lib;
- if(is_shared) {
- linker << LinkerName() << "-dll -nologo ";
- lib << "-machine:" << MachineName()
- << " -pdb:" << GetHostPathQ(ForceExt(product, ".pdb"))
- << " -out:" << GetHostPathQ(product);
- if(!HasFlag("MSC10") && !HasFlag("MSC10X64"))
- lib << " -incremental:no";
- if(HasFlag("FORCE_SIZE")){
- if(sContainsPchOptions(release_size_options))
- lib << " -ltcg";
- }
- else
- if(HasFlag("FORCE_SPEED"))
- if(sContainsPchOptions(release_options))
- lib << " -ltcg";
- if(HasAnyDebug())
- lib << " -debug -OPT:NOREF";
- else
- lib << " -release -OPT:REF,ICF";
- if(IsMscArm())
- lib << " -subsystem:windowsce,4.20 /ARMPADCODE";
- else
- if(HasFlag("GUI"))
- lib << (HasFlag("WIN32") ? " -subsystem:windows"
- : " -subsystem:windowsce");
- else
- lib << " -subsystem:console";
- Index exports;
- for(int o = 0; o < obj.GetCount(); o++)
- AddObjectExports(obj[o], exports);
- String def;
- def << "LIBRARY " << AsCString(GetFileName(product)) << "\n\n"
- "EXPORTS\n";
- for(int o = 0; o < exports.GetCount(); o++)
- def << '\t' << exports[o] << "\n"; //" @" << (o + 1) << "\n";
- String deffile = ForceExt(product, ".def");
- if(!SaveChangedFile(deffile, def))
- {
- PutConsole(NFormat("%s: error saving file", deffile));
- return false;
- }
- lib << " -def:" << GetHostPathQ(deffile);
- for(int i = 0; i < libpath.GetCount(); i++)
- lib << " -LIBPATH:" << GetHostPathQ(libpath[i]);
- lib << ' ' << Gather(pkg.link, config.GetKeys());
- for(int i = 0; i < all_uses.GetCount(); i++)
- lib << ' ' << GetHostPathQ(ForceExt(GetSharedLibPath(all_uses[i]), ".lib"));
- for(int i = 0; i < all_libraries.GetCount(); i++) {
- String libfile = AppendExt(all_libraries[i], ".lib");
- if(!IsFullPath(libfile)) {
- for(int p = 0; p < libpath.GetCount(); p++) {
- String nf = NormalizePath(libfile, libpath[p]);
- if(FileExists(nf)) {
- libfile = nf;
- break;
- }
- }
- }
- lib << ' ' << GetHostPathQ(libfile);
- }
- }
- else{
- linker << (HasFlag("INTEL") ? "xilib" : "link /lib") << " -nologo ";
- if(HasFlag("FORCE_SIZE")){
- if(sContainsPchOptions(release_size_options))
- lib << " -ltcg";
- }
- else
- if(HasFlag("FORCE_SPEED"))
- if(sContainsPchOptions(release_options))
- lib << " -ltcg";
- lib << " -out:" << GetHostPathQ(product) << ' ' << Gather(pkg.link, config.GetKeys());
- }
- for(int i = 0; i < obj.GetCount(); i++)
- lib << ' ' << GetHostPathQ(obj[i]);
- PutConsole("Creating library...");
- IdeConsoleEndGroup();
- DeleteFile(product);
- String tmpFileName;
- if(linker.GetCount() + lib.GetCount() >= 8192)
- {
- tmpFileName = GetTempFileName();
- // we can't simply put all data on a single line
- // as it has a limit of around 130000 chars too, so we split
- // in multiple lines
- FileOut f(tmpFileName);
- while(lib != "")
- {
- int found = 0;
- bool quotes = false;
- int lim = min(8192, lib.GetCount());
- for(int i = 0; i < lim; i++)
- {
- char c = lib[i];
- if(isspace(c) && !quotes)
- found = i;
- else if(c == '"')
- quotes = !quotes;
- }
- if(!found)
- found = lib.GetCount();
- f.PutLine(lib.Left(found));
- lib.Remove(0, found);
- }
- f.Close();
- linker << "@" << tmpFileName;
- }
- else
- linker << lib;
- bool res = Execute(linker);
- if(tmpFileName != "")
- FileDelete(tmpFileName);
- if(res) {
- DeleteFile(product);
- return false;
- }
- else
- if((IsMsc86() || IsMsc64()) && is_shared) {
- String mt("mt -nologo -manifest ");
- mt << GetHostPathQ(product) << ".manifest -outputresource:" << GetHostPathQ(product) << ";2";
- Execute(mt);
- }
- PutConsole(String().Cat() << product << " (" << GetFileInfo(product).length
- << " B) created in " << GetPrintTime(linktime));
- break;
- }
- return true;
- }
-
- IdeConsoleEndGroup();
- obj.Append(linkfile);
- linkfile = obj;
- return true;
-}
-
-bool MscBuilder::Link(const Vector& linkfile, const String& linkoptions, bool createmap)
-{
- int time = GetTickCount();
- if(!Wait())
- return false;
- for(int i = 0; i < linkfile.GetCount(); i++)
- if(GetFileTime(linkfile[i]) >= targettime) {
- String link;
- link << LinkerName() << " -nologo -machine:" << MachineName()
- << " -pdb:" << GetHostPathQ(ForceExt(target, ".pdb"))
- << " -out:" << GetHostPathQ(target);
- if(HasFlag("FORCE_SIZE")){
- if(sContainsPchOptions(release_size_options))
- link << " -ltcg";
- }
- else
- if(HasFlag("FORCE_SPEED"))
- if(sContainsPchOptions(release_options))
- link << " -ltcg";
- if(!HasFlag("MSC10") && !HasFlag("MSC10X64"))
- if(HasAnyDebug())
- link << " -incremental:yes -debug -OPT:NOREF";
- else
- link << " -incremental:no -release -OPT:REF,ICF";
- else
- if(HasAnyDebug())
- link << " -debug -OPT:NOREF";
- else
- link << " -release -OPT:REF,ICF";
- if(IsMscArm())
- link << " -subsystem:windowsce,4.20 /ARMPADCODE -NODEFAULTLIB:\"oldnames.lib\" ";
- else
- if(HasFlag("GUI") || IsMscArm())
- link << (HasFlag("WIN32") ? " -subsystem:windows" : " -subsystem:windowsce");
- else
- link << " -subsystem:console";
- if(createmap)
- link << " -MAP";
- if(HasFlag("DLL"))
- link << " -DLL";
- for(i = 0; i < libpath.GetCount(); i++)
- link << " -LIBPATH:\"" << libpath[i] << '\"';
- link << ' ' << linkoptions << ' ';
- for(i = 0; i < linkfile.GetCount(); i++)
- link << ' ' << GetHostPathQ(AppendExt(linkfile[i], ".lib"));
- PutConsole("Linking...");
- bool error = false;
- CustomStep(".pre-link", Null, error);
- if(!error && Execute(link) == 0) {
- CustomStep(".post-link", Null, error);
- if((IsMsc86() || IsMsc64()) && HasFlag("SHARED")) {
- String mt("mt -nologo -manifest ");
- mt << GetHostPathQ(target) << ".manifest -outputresource:" << GetHostPathQ(target)
- << (HasFlag("DLL") ? ";2" : ";1");
- Execute(mt);
- }
- PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length
- << " B) linked in " << GetPrintTime(time));
- return !error;
- }
- else {
- DeleteFile(target);
- return false;
- }
- }
- PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length
- << " B) is up to date.");
- return true;
-}
-
-bool MscBuilder::Preprocess(const String& package, const String& file, const String& target, bool)
-{
- FileOut out(target);
- String packagepath = PackagePath(package);
- Package pkg;
- pkg.Load(packagepath);
- return Execute(CmdLine(package, pkg) + " -E " + file, out);
-}
-
-Builder *CreateMscBuilder()
-{
- return new MscBuilder;
-}
-
-INITBLOCK
-{
- RegisterBuilder("MSC71", CreateMscBuilder);
- RegisterBuilder("MSC8", CreateMscBuilder);
- RegisterBuilder("MSC8X64", CreateMscBuilder);
- RegisterBuilder("MSC8ARM", CreateMscBuilder);
- RegisterBuilder("MSC9", CreateMscBuilder);
- RegisterBuilder("MSC9X64", CreateMscBuilder);
- RegisterBuilder("MSC10", CreateMscBuilder);
- RegisterBuilder("MSC10X64", CreateMscBuilder);
- RegisterBuilder("MSC9ARM", CreateMscBuilder);
- RegisterBuilder("EVC_ARM", CreateMscBuilder);
- RegisterBuilder("EVC_MIPS", CreateMscBuilder);
- RegisterBuilder("EVC_SH3", CreateMscBuilder);
- RegisterBuilder("EVC_SH4", CreateMscBuilder);
- RegisterBuilder("INTEL", CreateMscBuilder);
-}
+#include "Builders.h"
+
+#include
+
+#ifdef PLATFORM_WIN32
+static bool HasTail(String s, const char *tail)
+{
+ int tl = (int)strlen(tail);
+ int sl = s.GetLength();
+ if(sl < tl)
+ return false;
+ for(const char *p = s.GetIter(sl - tl); *p; p++, tail++)
+ if(*tail != '*' && *tail != *p)
+ return false;
+ return *tail == 0;
+}
+#endif
+
+static void AddObjectExports(const char *path, Index& out)
+{
+#ifdef PLATFORM_WIN32
+ FileMapping mapping;
+ if(!mapping.Open(path))
+ return;
+ const byte *begin = mapping.Begin();
+ const COFF_IMAGE_FILE_HEADER *hdr = (const COFF_IMAGE_FILE_HEADER *)begin;
+ if(hdr->Machine != COFF_IMAGE_FILE_MACHINE_I386)
+ return;
+ const COFF_IMAGE_SECTION_HEADER *sechdr = (const COFF_IMAGE_SECTION_HEADER *)(begin
+ + sizeof(COFF_IMAGE_FILE_HEADER) + hdr->SizeOfOptionalHeader);
+ Index code_sections;
+ for(int i = 0; i < hdr->NumberOfSections; i++)
+ if(sechdr[i].Characteristics & COFF_IMAGE_SCN_CNT_CODE)
+ code_sections.Add(i + 1);
+ const COFF_IMAGE_SYMBOL *symtbl = (const COFF_IMAGE_SYMBOL *)(begin + hdr->PointerToSymbolTable);
+ const char *strtbl = (const char *)(symtbl + hdr->NumberOfSymbols);
+ for(int i = 0; i < (int)hdr->NumberOfSymbols; i++)
+ {
+ const COFF_IMAGE_SYMBOL& sym = symtbl[i];
+ if(sym.StorageClass == COFF_IMAGE_SYM_CLASS_EXTERNAL && code_sections.Find(sym.SectionNumber) >= 0)
+ {
+ String name = COFFSymbolName(sym, strtbl);
+ if(!HasTail(name, "AEPAXI@Z"))
+ {
+ if(*name == '_' && name.Find('@') < 0)
+ name.Remove(0, 1);
+ out.FindAdd(name);
+ }
+ }
+ i += sym.NumberOfAuxSymbols;
+ }
+#endif
+}
+
+void MscBuilder::AddFlags(Index& cfg)
+{
+ cfg.FindAdd("MSC");
+}
+
+String MscBuilder::CmdLine(const String& package, const Package& pkg)
+{
+ String cc;
+ if(HasFlag("ARM"))
+ cc = "clarm";
+ else
+ if(HasFlag("MIPS"))
+ cc = "clmips";
+ else
+ if(HasFlag("SH3"))
+ cc = "shcl /Qsh3";
+ else
+ if(HasFlag("SH4"))
+ cc = "shcl /Qsh4";
+ else
+ if(HasFlag("MSC8ARM"))
+ cc = "cl -GS- ";
+ else
+ cc = HasFlag("INTEL") ? "icl" : "cl";
+// TRC 080605-documentation says Wp64 works in 32-bit compilation only
+// cc << (IsMsc64() ? " -nologo -Wp64 -W3 -GR -c" : " -nologo -W3 -GR -c");
+ cc << " -nologo -W3 -GR -c";
+ cc << IncludesDefinesTargetTime(package, pkg);
+
+ return cc;
+}
+
+String MscBuilder::MachineName() const
+{
+ if(HasFlag("ARM")) return "ARM";
+ if(HasFlag("MIPS")) return "MIPS";
+ if(HasFlag("SH3")) return "SH3";
+ if(HasFlag("SH4")) return "SH4";
+ if(IsMscArm()) return "ARM";
+ if(IsMsc64()) return "x64";
+ if(HasFlag("WIN32")) return "I386";
+ return "IX86";
+}
+
+bool MscBuilder::IsMsc89() const
+{
+ return IsMsc86() || IsMsc64() || IsMscArm();
+}
+
+bool MscBuilder::IsMsc86() const
+{
+ return HasFlag("MSC8") || HasFlag("MSC9") || HasFlag("MSC10");
+}
+
+bool MscBuilder::IsMscArm() const
+{
+ return HasFlag("MSC8ARM") || HasFlag("MSC9ARM");
+}
+
+bool MscBuilder::IsMsc64() const
+{
+ return HasFlag("MSC8X64") || HasFlag("MSC9X64") || HasFlag("MSC10X64");
+}
+
+String MscBuilder::LinkerName() const
+{
+ if(HasFlag("ULD")) return "uld";
+ if(HasFlag("INTEL")) return "xilink";
+ return "link";
+}
+
+static bool sContainsPchOptions(const String& x)
+{
+ Index a(Split(x, ' '));
+ return a.Find("-GL") >= 0 || a.Find("/GL") >= 0 || a.Find("-Y-") >= 0 || a.Find("/Y-") >= 0
+ || a.Find("-Yc") >= 0 || a.Find("/Yc") >= 0 || a.Find("-Yd") >= 0 || a.Find("/Yd") >= 0
+ || a.Find("-Yl") >= 0 || a.Find("/Yl") >= 0 || a.Find("-Yu") >= 0 || a.Find("/Yu") >= 0
+ || a.Find("-YX") >= 0 || a.Find("/YX") >= 0;
+}
+
+bool MscBuilder::HasAnyDebug() const
+{
+ return HasFlag("DEBUG") || HasFlag("DEBUG_MINIMAL") || HasFlag("DEBUG_FULL");
+}
+
+String MscBuilder::PdbPch(String package, int slot, bool do_pch) const
+{
+ String pkg_slot = NFormat("%s-%d", GetAnyFileName(package), slot + 1);
+ String pdb = GetHostPathQ(CatAnyPath(outdir, pkg_slot + ".pdb"));
+ String cc;
+ cc << " -Gy -Fd" << pdb << ' ';
+ if(do_pch && !IsMsc89()) // MSC8/9 does not support automatic precompiled headers...
+ cc << "-YX -Fp" << GetHostPathQ(CatAnyPath(outdir, pkg_slot + ".pch")) << ' ';
+ return cc;
+}
+
+bool MscBuilder::BuildPackage(const String& package, Vector& linkfile, String& linkoptions,
+ const Vector& all_uses, const Vector& all_libraries, int opt)
+{
+ int i;
+ String packagepath = PackagePath(package);
+ Package pkg;
+ pkg.Load(packagepath);
+ String packagedir = GetFileFolder(packagepath);
+ ChDir(packagedir);
+ PutVerbose("cd " + packagedir);
+ IdeConsoleBeginGroup(package);
+ Vector obj;
+
+ bool is_shared = HasFlag("SO"),
+ is_clr = HasFlag("CLR");
+
+ String cc = CmdLine(package, pkg);
+ if(HasFlag("EVC")) {
+ if(!HasFlag("SH3") && !HasFlag("SH4"))
+ cc << " -Gs8192"; // disable stack checking
+ cc << " -GF" // read-only string pooling
+ " -GX-"; // turn off exception handling
+ }
+ else
+ if(is_clr)
+ cc << " -EHac";
+ else
+ if(IsMsc89())
+ cc << " -EHsc";
+ else
+ cc << " -GX";
+// String pdb = GetHostPathQ(CatAnyPath(outdir, GetAnyFileName(package) + ".pdb"));
+// String pch;
+// if(!HasFlag("MSC8")) // MSC8 does not support automatic precompiled headers...
+// pch << " -YX -Fp" << GetHostPathQ(CatAnyPath(outdir, GetAnyFileName(package) + ".pch")) << ' ';
+// cc << " -Gy -Fd" << pdb;
+ if(HasFlag("SSE2") && !IsMsc64())
+ cc << " /arch:SSE2";
+ if(HasFlag("DEBUG_MINIMAL"))
+ cc << " -Zd";
+ if(HasFlag("DEBUG_FULL"))
+ cc << " -Zi";
+ cc << ' ' << Gather(pkg.option, config.GetKeys());
+ cc << (HasFlag("SHARED") || is_shared || is_clr ? " -MD"
+ : (HasFlag("MT") || IsMsc89()) ? " -MT" : " -ML");
+
+ String cc_size = cc;
+ String cc_speed = cc;
+ bool release = false;
+
+ if(HasFlag("DEBUG"))
+ cc << "d " << debug_options;
+ else {
+ release = true;
+ cc << ' ' << release_size_options;
+ cc_speed << ' ' << release_options;
+ if(opt == R_SPEED || pkg.optimize_speed)
+ cc = cc_speed;
+ }
+
+
+ Vector sfile, isfile;
+ Vector soptions, isoptions;
+ Vector optimize, ioptimize;
+ Vector sobjfile;
+ bool error = false;
+
+ for(i = 0; i < pkg.GetCount(); i++) {
+ if(!IdeIsBuilding())
+ return false;
+ if(!pkg[i].separator) {
+ String gop = Gather(pkg[i].option, config.GetKeys());
+ Vector srcfile = CustomStep(pkg[i], package, error);
+ if(srcfile.GetCount() == 0)
+ error = true;
+ for(int j = 0; j < srcfile.GetCount(); j++) {
+ String fn = srcfile[j];
+ String ext = ToLower(GetFileExt(fn));
+ if(ext == ".c" || ext == ".cpp" || ext == ".cc" || ext == ".cxx" || ext == ".rc" || ext == ".brc") {
+ sfile.Add(fn);
+ soptions.Add(gop);
+ optimize.Add(release && pkg[i].optimize_speed && opt == R_OPTIMAL);
+ }
+ else
+ if(ext == ".icpp") {
+ isfile.Add(fn);
+ isoptions.Add(gop);
+ ioptimize.Add(release && pkg[i].optimize_speed && opt == R_OPTIMAL);
+ }
+ else
+ if(ext == ".obj")
+ obj.Add(fn);
+ else
+ if(ext == ".lib")
+ linkfile.Add(fn);
+ }
+ }
+ }
+
+ if(HasFlag("BLITZ")) {
+ Blitz b = BlitzStep(sfile, soptions, obj, ".obj", optimize);
+ if(b.build) {
+ PutConsole("BLITZ:" + b.info);
+ int slot = AllocSlot();
+ if(slot < 0 || ! Run(cc + PdbPch(package, slot, false)
+ + " -Tp " + GetHostPathQ(b.path) + " -Fo" + GetHostPathQ(b.object), slot, GetHostPath(b.object), b.count))
+ error = true;
+ }
+ }
+
+ int first_ifile = sfile.GetCount();
+ sfile.AppendPick(isfile);
+ soptions.AppendPick(isoptions);
+ optimize.AppendPick(ioptimize);
+
+ int ccount = 0;
+
+// if(sContainsPchOptions(cc))
+// pch = Null;
+
+ for(i = 0; i < sfile.GetCount(); i++) {
+ if(!IdeIsBuilding())
+ return false;
+ String fn = sfile[i];
+ String ext = ToLower(GetFileExt(fn));
+ bool rc = (ext == ".rc");
+ bool brc = (ext == ".brc");
+ bool init = (i >= first_ifile);
+ String objfile = CatAnyPath(outdir, GetFileTitle(fn) + (rc ? "$rc.obj" : brc ? "$brc.obj" : ".obj"));
+ if(HdependFileTime(fn) > GetFileTime(objfile)) {
+ int time = GetTickCount();
+ bool execerr = false;
+ if(rc) {
+ PutConsole(GetFileNamePos(fn));
+ int slot = AllocSlot();
+ if(slot < 0 || !Run("rc /fo" + GetHostPathQ(objfile) + Includes(" /i", package, pkg)
+ + ' ' + GetHostPathQ(fn), slot, GetHostPath(objfile), 1))
+ execerr = true;
+ }
+ else
+ if(brc) {
+ try {
+// String hfn = GetHostPath(fn);
+ String brcdata = LoadFile(fn);
+ if(brcdata.IsVoid())
+ throw Exc(NFormat("error reading file '%s'", fn));
+ CParser parser(brcdata, fn);
+ String fo = BrcToC(parser, GetFileDirectory(fn));
+ String tmpfile = ForceExt(objfile, ".c");
+ SaveFile(tmpfile, fo);
+ int slot = AllocSlot();
+ StringBuffer cmdline;
+ cmdline << cc << PdbPch(package, slot, false)
+ << " -Tc " << GetHostPathQ(tmpfile) << " -Fo" << GetHostPathQ(objfile);
+ if(slot < 0 || !Run(String(cmdline), slot, GetHostPath(objfile), 1))
+ throw Exc(NFormat("Error compiling binary object '%s'.", objfile));
+ }
+ catch(Exc e) {
+ PutConsole(e);
+ execerr = true;
+ }
+ }
+ else {
+ String c = cc;
+ if(optimize[i])
+ c = cc_speed;
+ int slot = AllocSlot();
+ if(slot < 0 || !Run(c + PdbPch(package, slot, !sContainsPchOptions(cc) && !sContainsPchOptions(soptions[i]))
+ + " " + soptions[i] + (ext == ".c" ? " -Tc " : " -Tp ")
+ + GetHostPathQ(fn) + " -Fo" + GetHostPathQ(objfile), slot, GetHostPath(objfile), 1))
+ execerr = true;
+ }
+ if(execerr)
+ DeleteFile(objfile);
+ error |= execerr;
+ PutVerbose("compiled in " + GetPrintTime(time));
+ ccount++;
+ }
+ if(init)
+ linkfile.Add(objfile);
+ else
+ obj.Add(objfile);
+ }
+ if(error) {
+ IdeConsoleEndGroup();
+ return false;
+ }
+
+ Vector pkglibs = Split(Gather(pkg.library, config.GetKeys()), ' ');
+ for(int i = 0; i < pkglibs.GetCount(); i++) {
+ String libfile = AppendExt(pkglibs[i], ".lib");
+ if(!IsFullPath(libfile)) {
+ for(int p = 0; p < libpath.GetCount(); p++) {
+ String nf = NormalizePath(libfile, libpath[p]);
+ if(FileExists(nf)) {
+ libfile = nf;
+ break;
+ }
+ }
+ }
+ linkfile.Add(libfile);
+ }
+ linkoptions << ' ' << Gather(pkg.link, config.GetKeys());
+
+ int linktime = GetTickCount();
+ if(!HasFlag("MAIN")) {
+ if(HasFlag("BLITZ") || HasFlag("NOLIB")) {
+ linkfile.Append(obj);
+// ShowTime(ccount, time);
+ IdeConsoleEndGroup();
+ return true;
+ }
+ String product;
+ if(is_shared)
+ product = GetSharedLibPath(package);
+ else
+ product = CatAnyPath(outdir, GetAnyFileName(package) + ".lib");
+ Time producttime = GetFileTime(product);
+ if(obj.GetCount())
+ linkfile.Add(ForceExt(product, ".lib"));
+ if(!Wait()) {
+ IdeConsoleEndGroup();
+ return false;
+ }
+ Vector objinfo = host->GetFileInfo(obj);
+ for(int i = 0; i < obj.GetCount(); i++)
+ if(objinfo[i] > producttime) {
+ String linker, lib;
+ if(is_shared) {
+ linker << LinkerName() << "-dll -nologo ";
+ lib << "-machine:" << MachineName()
+ << " -pdb:" << GetHostPathQ(ForceExt(product, ".pdb"))
+ << " -out:" << GetHostPathQ(product);
+ if(!HasFlag("MSC10") && !HasFlag("MSC10X64"))
+ lib << " -incremental:no";
+ if(HasFlag("FORCE_SIZE")){
+ if(sContainsPchOptions(release_size_options))
+ lib << " -ltcg";
+ }
+ else
+ if(HasFlag("FORCE_SPEED"))
+ if(sContainsPchOptions(release_options))
+ lib << " -ltcg";
+ if(HasAnyDebug())
+ lib << " -debug -OPT:NOREF";
+ else
+ lib << " -release -OPT:REF,ICF";
+ if(IsMscArm())
+ lib << " -subsystem:windowsce,4.20 /ARMPADCODE";
+ else
+ if(HasFlag("GUI"))
+ lib << (HasFlag("WIN32") ? " -subsystem:windows"
+ : " -subsystem:windowsce");
+ else
+ lib << " -subsystem:console";
+ Index exports;
+ for(int o = 0; o < obj.GetCount(); o++)
+ AddObjectExports(obj[o], exports);
+ String def;
+ def << "LIBRARY " << AsCString(GetFileName(product)) << "\n\n"
+ "EXPORTS\n";
+ for(int o = 0; o < exports.GetCount(); o++)
+ def << '\t' << exports[o] << "\n"; //" @" << (o + 1) << "\n";
+ String deffile = ForceExt(product, ".def");
+ if(!SaveChangedFile(deffile, def))
+ {
+ PutConsole(NFormat("%s: error saving file", deffile));
+ return false;
+ }
+ lib << " -def:" << GetHostPathQ(deffile);
+ for(int i = 0; i < libpath.GetCount(); i++)
+ lib << " -LIBPATH:" << GetHostPathQ(libpath[i]);
+ lib << ' ' << Gather(pkg.link, config.GetKeys());
+ for(int i = 0; i < all_uses.GetCount(); i++)
+ lib << ' ' << GetHostPathQ(ForceExt(GetSharedLibPath(all_uses[i]), ".lib"));
+ for(int i = 0; i < all_libraries.GetCount(); i++) {
+ String libfile = AppendExt(all_libraries[i], ".lib");
+ if(!IsFullPath(libfile)) {
+ for(int p = 0; p < libpath.GetCount(); p++) {
+ String nf = NormalizePath(libfile, libpath[p]);
+ if(FileExists(nf)) {
+ libfile = nf;
+ break;
+ }
+ }
+ }
+ lib << ' ' << GetHostPathQ(libfile);
+ }
+ }
+ else{
+ linker << (HasFlag("INTEL") ? "xilib" : "link /lib") << " -nologo ";
+ if(HasFlag("FORCE_SIZE")){
+ if(sContainsPchOptions(release_size_options))
+ lib << " -ltcg";
+ }
+ else
+ if(HasFlag("FORCE_SPEED"))
+ if(sContainsPchOptions(release_options))
+ lib << " -ltcg";
+ lib << " -out:" << GetHostPathQ(product) << ' ' << Gather(pkg.link, config.GetKeys());
+ }
+ for(int i = 0; i < obj.GetCount(); i++)
+ lib << ' ' << GetHostPathQ(obj[i]);
+ PutConsole("Creating library...");
+ IdeConsoleEndGroup();
+ DeleteFile(product);
+ String tmpFileName;
+ if(linker.GetCount() + lib.GetCount() >= 8192)
+ {
+ tmpFileName = GetTempFileName();
+ // we can't simply put all data on a single line
+ // as it has a limit of around 130000 chars too, so we split
+ // in multiple lines
+ FileOut f(tmpFileName);
+ while(lib != "")
+ {
+ int found = 0;
+ bool quotes = false;
+ int lim = min(8192, lib.GetCount());
+ for(int i = 0; i < lim; i++)
+ {
+ char c = lib[i];
+ if(isspace(c) && !quotes)
+ found = i;
+ else if(c == '"')
+ quotes = !quotes;
+ }
+ if(!found)
+ found = lib.GetCount();
+ f.PutLine(lib.Left(found));
+ lib.Remove(0, found);
+ }
+ f.Close();
+ linker << "@" << tmpFileName;
+ }
+ else
+ linker << lib;
+ bool res = Execute(linker);
+ if(tmpFileName != "")
+ FileDelete(tmpFileName);
+ if(res) {
+ DeleteFile(product);
+ return false;
+ }
+ else
+ if((IsMsc86() || IsMsc64()) && is_shared) {
+ String mt("mt -nologo -manifest ");
+ mt << GetHostPathQ(product) << ".manifest -outputresource:" << GetHostPathQ(product) << ";2";
+ Execute(mt);
+ }
+ PutConsole(String().Cat() << product << " (" << GetFileInfo(product).length
+ << " B) created in " << GetPrintTime(linktime));
+ break;
+ }
+ return true;
+ }
+
+ IdeConsoleEndGroup();
+ obj.Append(linkfile);
+ linkfile = obj;
+ return true;
+}
+
+bool MscBuilder::Link(const Vector& linkfile, const String& linkoptions, bool createmap)
+{
+ int time = GetTickCount();
+ if(!Wait())
+ return false;
+ for(int i = 0; i < linkfile.GetCount(); i++)
+ if(GetFileTime(linkfile[i]) >= targettime) {
+ String link;
+ link << LinkerName() << " -nologo -machine:" << MachineName()
+ << " -pdb:" << GetHostPathQ(ForceExt(target, ".pdb"))
+ << " -out:" << GetHostPathQ(target);
+ if(HasFlag("FORCE_SIZE")){
+ if(sContainsPchOptions(release_size_options))
+ link << " -ltcg";
+ }
+ else
+ if(HasFlag("FORCE_SPEED"))
+ if(sContainsPchOptions(release_options))
+ link << " -ltcg";
+ if(!HasFlag("MSC10") && !HasFlag("MSC10X64"))
+ if(HasAnyDebug())
+ link << " -incremental:yes -debug -OPT:NOREF";
+ else
+ link << " -incremental:no -release -OPT:REF,ICF";
+ else
+ if(HasAnyDebug())
+ link << " -debug -OPT:NOREF";
+ else
+ link << " -release -OPT:REF,ICF";
+ if(IsMscArm())
+ link << " -subsystem:windowsce,4.20 /ARMPADCODE -NODEFAULTLIB:\"oldnames.lib\" ";
+ else
+ if(HasFlag("GUI") || IsMscArm())
+ link << (HasFlag("WIN32") ? " -subsystem:windows" : " -subsystem:windowsce");
+ else
+ link << " -subsystem:console";
+ if(createmap)
+ link << " -MAP";
+ if(HasFlag("DLL"))
+ link << " -DLL";
+ for(i = 0; i < libpath.GetCount(); i++)
+ link << " -LIBPATH:\"" << libpath[i] << '\"';
+ link << ' ' << linkoptions << ' ';
+ for(i = 0; i < linkfile.GetCount(); i++)
+ link << ' ' << GetHostPathQ(AppendExt(linkfile[i], ".lib"));
+ PutConsole("Linking...");
+ bool error = false;
+ CustomStep(".pre-link", Null, error);
+ if(!error && Execute(link) == 0) {
+ CustomStep(".post-link", Null, error);
+ if((IsMsc86() || IsMsc64()) && HasFlag("SHARED")) {
+ String mt("mt -nologo -manifest ");
+ mt << GetHostPathQ(target) << ".manifest -outputresource:" << GetHostPathQ(target)
+ << (HasFlag("DLL") ? ";2" : ";1");
+ Execute(mt);
+ }
+ PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length
+ << " B) linked in " << GetPrintTime(time));
+ return !error;
+ }
+ else {
+ DeleteFile(target);
+ return false;
+ }
+ }
+ PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length
+ << " B) is up to date.");
+ return true;
+}
+
+bool MscBuilder::Preprocess(const String& package, const String& file, const String& target, bool)
+{
+ FileOut out(target);
+ String packagepath = PackagePath(package);
+ Package pkg;
+ pkg.Load(packagepath);
+ return Execute(CmdLine(package, pkg) + " -E " + file, out);
+}
+
+Builder *CreateMscBuilder()
+{
+ return new MscBuilder;
+}
+
+INITBLOCK
+{
+ RegisterBuilder("MSC71", CreateMscBuilder);
+ RegisterBuilder("MSC8", CreateMscBuilder);
+ RegisterBuilder("MSC8X64", CreateMscBuilder);
+ RegisterBuilder("MSC8ARM", CreateMscBuilder);
+ RegisterBuilder("MSC9", CreateMscBuilder);
+ RegisterBuilder("MSC9X64", CreateMscBuilder);
+ RegisterBuilder("MSC10", CreateMscBuilder);
+ RegisterBuilder("MSC10X64", CreateMscBuilder);
+ RegisterBuilder("MSC9ARM", CreateMscBuilder);
+ RegisterBuilder("EVC_ARM", CreateMscBuilder);
+ RegisterBuilder("EVC_MIPS", CreateMscBuilder);
+ RegisterBuilder("EVC_SH3", CreateMscBuilder);
+ RegisterBuilder("EVC_SH4", CreateMscBuilder);
+ RegisterBuilder("INTEL", CreateMscBuilder);
+}