mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
774 lines
22 KiB
C++
774 lines
22 KiB
C++
#include "Builders.h"
|
|
|
|
#include "coff.h"
|
|
|
|
String MaxLenString(const byte *b, int maxlen)
|
|
{
|
|
const byte *e = b + maxlen;
|
|
while(e > b && e[-1] == 0)
|
|
e--;
|
|
return String(b, int(e - b));
|
|
}
|
|
|
|
String COFFSymbolName(const COFF_IMAGE_SYMBOL& sym, const char *strtbl)
|
|
{
|
|
String name;
|
|
if(sym.N.Name.Short)
|
|
name = MaxLenString(sym.N.ShortName, 8);
|
|
else
|
|
name = strtbl + sym.N.Name.Long;
|
|
return name;
|
|
}
|
|
|
|
#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<String>& out)
|
|
{
|
|
#ifdef PLATFORM_WIN32
|
|
FileMapping mapping;
|
|
if(!mapping.Open(path))
|
|
return;
|
|
const byte *begin = mapping.Begin();
|
|
if(!begin)
|
|
return;
|
|
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<int> 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<String>& 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 -W" << (pkg.nowarnings ? "0" : "3") << " -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") || HasFlag("MSC11")
|
|
|| HasFlag("MSC12") || HasFlag("MSC15") || HasFlag("MSC14") || HasFlag("MSC17")
|
|
|| HasFlag("MSC19") || HasFlag("MSC22");
|
|
}
|
|
|
|
bool MscBuilder::IsMscArm() const
|
|
{
|
|
return HasFlag("MSC8ARM") || HasFlag("MSC9ARM");
|
|
}
|
|
|
|
bool MscBuilder::IsMsc64() const
|
|
{
|
|
return HasFlag("MSC8X64") || HasFlag("MSC9X64") || HasFlag("MSC10X64") || HasFlag("MSC11X64")
|
|
|| HasFlag("MSC12X64") || HasFlag("MSC14X64") || HasFlag("MSC15X64") || HasFlag("MSC17X64")
|
|
|| HasFlag("MSC19X64") || HasFlag("MSC22X64");
|
|
}
|
|
|
|
String MscBuilder::LinkerName() const
|
|
{
|
|
if(HasFlag("ULD")) return "uld";
|
|
if(HasFlag("INTEL")) return "xilink";
|
|
return "link";
|
|
}
|
|
|
|
static bool sContainsPchOptions(const String& x)
|
|
{
|
|
Index<String> 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;
|
|
}
|
|
|
|
String MscBuilder::Pdb(String package, int slot, bool separate_pdb) const
|
|
{
|
|
String pdb_name = GetAnyFileName(package);
|
|
if(separate_pdb)
|
|
pdb_name << '-' << (slot + 1);
|
|
return " -Gy -Fd" + GetPathQ(CatAnyPath(outdir, pdb_name + ".pdb"));
|
|
}
|
|
|
|
void DeletePCHFile(const String& pch_file)
|
|
{
|
|
DeleteFile(pch_file);
|
|
PutVerbose("Deleting precompiled header: " + pch_file);
|
|
}
|
|
|
|
bool MscBuilder::BuildPackage(const String& package, Vector<String>& linkfile, Vector<String>& immfile,
|
|
String& linkoptions, const Vector<String>& all_uses, const Vector<String>& all_libraries, int opt)
|
|
{
|
|
if(HasFlag("MAKE_MLIB") && !HasFlag("MAIN"))
|
|
return true;
|
|
|
|
SaveBuildInfo(package);
|
|
|
|
int i;
|
|
String packagepath = PackagePath(package);
|
|
Package pkg;
|
|
pkg.Load(packagepath);
|
|
String packagedir = GetFileFolder(packagepath);
|
|
ChDir(packagedir);
|
|
PutVerbose("cd " + packagedir);
|
|
IdeConsoleBeginGroup(package);
|
|
Vector<String> obj;
|
|
|
|
bool is_shared = HasFlag("SO"),
|
|
is_clr = HasFlag("CLR");
|
|
|
|
Vector<String> sfile, isfile;
|
|
Vector<String> soptions, isoptions;
|
|
Vector<String> sobjfile;
|
|
bool error = false;
|
|
|
|
String pch_header;
|
|
|
|
Index<String> nopch, noblitz;
|
|
|
|
bool blitz = HasFlag("BLITZ");
|
|
bool release = !HasFlag("DEBUG");
|
|
|
|
for(i = 0; i < pkg.GetCount(); i++) {
|
|
if(!IdeIsBuilding())
|
|
return false;
|
|
if(!pkg[i].separator) {
|
|
String gop = Gather(pkg[i].option, config.GetKeys());
|
|
Vector<String> srcfile = CustomStep(pkg[i], package, error);
|
|
if(srcfile.GetCount() == 0)
|
|
error = true;
|
|
for(int j = 0; j < srcfile.GetCount(); j++) {
|
|
String fn = NormalizePath(srcfile[j]);
|
|
String ext = ToLower(GetFileExt(fn));
|
|
if(findarg(ext, ".c", ".cpp", ".cc", ".cxx", ".rc", ".brc") >= 0 ||
|
|
ext == ".cu" && HasFlag("CUDA") ||
|
|
(!release && blitz && ext == ".icpp")) {
|
|
if(FindIndex(sfile, fn) < 0) {
|
|
sfile.Add(fn);
|
|
soptions.Add(gop);
|
|
}
|
|
}
|
|
else
|
|
if(ext == ".icpp") {
|
|
isfile.Add(fn);
|
|
isoptions.Add(gop);
|
|
}
|
|
else
|
|
if(ext == ".obj")
|
|
obj.Add(fn);
|
|
else
|
|
if(ext == ".lib")
|
|
linkfile.Add(fn);
|
|
else
|
|
if(IsHeaderExt(ext) && pkg[i].pch && allow_pch && IsMsc89() && release && !HasAnyDebug() && !blitz) {
|
|
if(pch_header.GetCount())
|
|
PutConsole(GetFileName(fn) + ": multiple PCHs are not allowed. Check your package configuration");
|
|
else
|
|
pch_header = fn;
|
|
}
|
|
if(pkg[i].nopch) {
|
|
nopch.Add(fn);
|
|
if(allow_pch && release)
|
|
noblitz.Add(fn);
|
|
}
|
|
if(pkg[i].noblitz)
|
|
noblitz.Add(fn);
|
|
if(ext == ".c")
|
|
nopch.Add(fn);
|
|
}
|
|
}
|
|
}
|
|
|
|
String nvcc = "nvcc -c " + IncludesDefinesTargetTime(package, pkg) + " ";
|
|
|
|
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 = GetPathQ(CatAnyPath(outdir, GetAnyFileName(package) + ".pdb"));
|
|
// String pch;
|
|
// if(!HasFlag("MSC8")) // MSC8 does not support automatic precompiled headers...
|
|
// pch << " -YX -Fp" << GetPathQ(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" : " -MT");
|
|
|
|
String cc_size = cc;
|
|
String cc_speed = cc;
|
|
|
|
if(release)
|
|
cc << ' ' << release_options;
|
|
else
|
|
cc << "d " << debug_options;
|
|
|
|
int recompile = 0;
|
|
Blitz b;
|
|
if(blitz) {
|
|
BlitzBuilderComponent bc(this);
|
|
b = bc.MakeBlitzStep(*this, sfile, soptions, obj, immfile, ".obj", noblitz, package);
|
|
recompile = b.build;
|
|
}
|
|
|
|
for(i = 0; i < sfile.GetCount(); i++) {
|
|
String fn = sfile[i];
|
|
String ext = ToLower(GetFileExt(fn));
|
|
if(findarg(ext, ".rc", ".brc", ".c") < 0 && HdependFileTime(sfile[i]) > GetFileTime(CatAnyPath(outdir, GetFileTitle(fn) + ".obj")))
|
|
recompile++;
|
|
}
|
|
|
|
String pch_use;
|
|
String pch_file;
|
|
|
|
if(pch_header.GetCount()) {
|
|
String pch_obj = CatAnyPath(outdir, GetFileTitle(pch_header) + "$pch.obj");
|
|
pch_file = CatAnyPath(outdir, GetFileTitle(pch_header) + ".pch");
|
|
RegisterPCHFile(pch_file);
|
|
String pch_common = GetPathQ(pch_header) + " -Fp" + GetPathQ(pch_file) + " -FI" + GetPathQ(pch_header);
|
|
|
|
if(blitz) // enable MK__s macros
|
|
pch_common.Cat(" -DBLITZ_INDEX__=FPCH");
|
|
|
|
if(recompile > 0 || !FileExists(pch_file)) {
|
|
int pch_slot = AllocSlot();
|
|
StringBuffer sb;
|
|
sb << Join(cc, cpp_options) << Pdb(package, pch_slot, false) << " -Yc" << pch_common
|
|
<< " -Tp " << GetPathQ(pch_header) << " -Fo" + GetPathQ(pch_obj);
|
|
PutConsole("Precompiling header: " + GetFileName(pch_header));
|
|
if(pch_slot < 0 || !Run(~sb, pch_slot, pch_obj, 1))
|
|
error = true;
|
|
Wait();
|
|
}
|
|
|
|
pch_use = " -Yu" + pch_common;
|
|
obj.Add(pch_obj);
|
|
}
|
|
|
|
if(blitz && b.build) {
|
|
PutConsole("BLITZ:" + b.info);
|
|
int slot = AllocSlot();
|
|
String c = Join(cc, cpp_options);
|
|
if(HasAnyDebug())
|
|
c << Pdb(package, slot, false);
|
|
if(slot < 0 ||
|
|
!Run(c + " -Tp " + GetPathQ(b.path) + " -Fo" + GetPathQ(b.object),
|
|
slot, b.object, b.count))
|
|
error = true;
|
|
}
|
|
|
|
int first_ifile = sfile.GetCount();
|
|
sfile.AppendPick(pick(isfile));
|
|
soptions.AppendPick(pick(isoptions));
|
|
|
|
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, SourceToObjName(package, fn) + (rc ? "$rc.obj" : brc ? "$brc.obj" : ".obj"));
|
|
if(HdependFileTime(fn) > GetFileTime(objfile)) {
|
|
int time = msecs();
|
|
bool execerr = false;
|
|
if(rc) {
|
|
PutConsole(GetFileNamePos(fn));
|
|
int slot = AllocSlot();
|
|
if(slot < 0 || !Run("rc /fo" + GetPathQ(objfile) + Includes(" /i", package, pkg)
|
|
+ DefinesTargetTime(" /d", package, pkg) + (HasFlag("DEBUG")?" /d_DEBUG":"")
|
|
+ ' ' + GetPathQ(fn), slot, objfile, 1))
|
|
execerr = true;
|
|
}
|
|
else
|
|
if(brc) {
|
|
try {
|
|
// String hfn = GetHostPath(fn);
|
|
String brcdata = LoadFile(fn);
|
|
if(brcdata.IsVoid())
|
|
throw Exc(Format("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 << Pdb(package, slot, false)
|
|
<< " -Tc " << GetPathQ(tmpfile) << " -Fo" << GetPathQ(objfile);
|
|
if(slot < 0 || !Run(String(cmdline), slot, objfile, 1))
|
|
throw Exc(Format("Error compiling binary object '%s'.", objfile));
|
|
}
|
|
catch(Exc e) {
|
|
PutConsole(e);
|
|
execerr = true;
|
|
}
|
|
}
|
|
else {
|
|
int slot = AllocSlot();
|
|
String c;
|
|
if(ext == ".cu")
|
|
c << nvcc << (release ? release_cuda : debug_cuda) << " " << soptions[i]
|
|
<< " -o " << GetPathQ(objfile) << " " << GetPathQ(fn);
|
|
else {
|
|
c = cc;
|
|
if(HasAnyDebug())
|
|
c << Pdb(package, slot, !sContainsPchOptions(cc) && !sContainsPchOptions(soptions[i]));
|
|
c << " " + soptions[i] + (ext == ".c" ? Join(c_options, " -Tc") : Join(cpp_options, " -Tp")) + ' '
|
|
+ GetPathQ(fn) + " -Fo" + GetPathQ(objfile);
|
|
if(nopch.Find(fn) < 0)
|
|
c << pch_use;
|
|
}
|
|
if(slot < 0 || !Run(c, slot, objfile, 1))
|
|
execerr = true;
|
|
}
|
|
if(execerr)
|
|
DeleteFile(objfile);
|
|
error |= execerr;
|
|
PutVerbose("compiled in " + GetPrintTime(time));
|
|
}
|
|
if(init)
|
|
linkfile.Add(objfile);
|
|
else
|
|
obj.Add(objfile);
|
|
immfile.Add(objfile);
|
|
}
|
|
if(error) {
|
|
IdeConsoleEndGroup();
|
|
return false;
|
|
}
|
|
|
|
bool making_lib = HasFlag("MAKE_LIB") || HasFlag("MAKE_MLIB");
|
|
|
|
if(!making_lib) {
|
|
Vector<String> 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());
|
|
|
|
// if(pch_file.GetCount())
|
|
// OnFinish(callback1(DeletePCHFile, pch_file));
|
|
|
|
if(!HasFlag("MAIN")) {
|
|
if(HasFlag("BLITZ") || HasFlag("NOLIB") || making_lib) {
|
|
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()) {
|
|
String h = ForceExt(product, ".lib");
|
|
linkfile.Add(h);
|
|
immfile.Add(h);
|
|
}
|
|
if(!Wait()) {
|
|
IdeConsoleEndGroup();
|
|
return false;
|
|
}
|
|
Vector<Host::FileInfo> objinfo = host->GetFileInfo(obj);
|
|
for(int i = 0; i < obj.GetCount(); i++)
|
|
if(objinfo[i] > producttime)
|
|
return CreateLib(product, obj, all_uses, all_libraries, Gather(pkg.link, config.GetKeys()));
|
|
return true;
|
|
}
|
|
|
|
IdeConsoleEndGroup();
|
|
obj.Append(linkfile);
|
|
linkfile = pick(obj);
|
|
return true;
|
|
}
|
|
|
|
bool MscBuilder::CreateLib(const String& product, const Vector<String>& obj,
|
|
const Vector<String>& all_uses, const Vector<String>& all_libraries,
|
|
const String& link_options)
|
|
{
|
|
int linktime = msecs();
|
|
bool isgemsc10 = HasFlag("MSC10") || HasFlag("MSC10X64")
|
|
|| HasFlag("MSC11") || HasFlag("MSC11X64")
|
|
|| HasFlag("MSC12") || HasFlag("MSC12X64")
|
|
|| HasFlag("MSC14") || HasFlag("MSC14X64")
|
|
|| HasFlag("MSC15") || HasFlag("MSC15X64")
|
|
|| HasFlag("MSC17") || HasFlag("MSC17X64")
|
|
|| HasFlag("MSC19") || HasFlag("MSC19X64")
|
|
|| HasFlag("MSC22") || HasFlag("MSC22X64")
|
|
;
|
|
bool is_shared = HasFlag("SO");
|
|
String linker, lib;
|
|
if(is_shared) {
|
|
linker << LinkerName() << " -dll -nologo ";
|
|
lib << "-machine:" << MachineName()
|
|
<< " -pdb:" << GetPathQ(ForceExt(product, ".pdb"))
|
|
<< " -out:" << GetPathQ(product);
|
|
if(!isgemsc10)
|
|
lib << " -incremental:no";
|
|
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<String> 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(Format("%s: error saving file", deffile));
|
|
return false;
|
|
}
|
|
lib << " -def:" << GetPathQ(deffile);
|
|
for(int i = 0; i < libpath.GetCount(); i++)
|
|
lib << " -LIBPATH:" << GetPathQ(libpath[i]);
|
|
lib << ' ' << link_options;
|
|
for(int i = 0; i < all_uses.GetCount(); i++)
|
|
lib << ' ' << GetPathQ(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 << ' ' << GetPathQ(libfile);
|
|
}
|
|
}
|
|
else{
|
|
linker << (HasFlag("INTEL") ? "xilib" : "link /lib") << " -nologo ";
|
|
lib << " -out:" << GetPathQ(product) << ' ' << link_options;
|
|
}
|
|
for(int i = 0; i < obj.GetCount(); i++)
|
|
lib << ' ' << GetPathQ(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 << GetPathQ(product) << ".manifest -outputresource:" << GetPathQ(product) << ";2";
|
|
Execute(mt);
|
|
}
|
|
PutConsole(String().Cat() << product << " (" << GetFileInfo(product).length
|
|
<< " B) created in " << GetPrintTime(linktime));
|
|
return true;
|
|
}
|
|
|
|
bool MscBuilder::Link(const Vector<String>& linkfile, const String& linkoptions, bool createmap)
|
|
{
|
|
int time = msecs();
|
|
if(!Wait())
|
|
return false;
|
|
|
|
PutLinking();
|
|
|
|
if(HasFlag("MAKE_MLIB") || HasFlag("MAKE_LIB"))
|
|
return CreateLib(ForceExt(target, ".lib"), linkfile, Vector<String>(), Vector<String>(), linkoptions);
|
|
|
|
bool isgemsc10 = HasFlag("MSC10") || HasFlag("MSC10X64")
|
|
|| HasFlag("MSC11") || HasFlag("MSC11X64")
|
|
|| HasFlag("MSC12") || HasFlag("MSC12X64")
|
|
|| HasFlag("MSC14") || HasFlag("MSC14X64")
|
|
|| HasFlag("MSC15") || HasFlag("MSC15X64")
|
|
|| HasFlag("MSC17") || HasFlag("MSC17X64")
|
|
|| HasFlag("MSC19") || HasFlag("MSC19X64")
|
|
|| HasFlag("MSC22") || HasFlag("MSC22X64")
|
|
;
|
|
for(int i = 0; i < linkfile.GetCount(); i++)
|
|
if(GetFileTime(linkfile[i]) > targettime) {
|
|
String link, lib;
|
|
link << LinkerName() << " -nologo -machine:" << MachineName()
|
|
<< " -pdb:" << GetPathQ(ForceExt(target, ".pdb"))
|
|
<< " -out:" << GetPathQ(target);
|
|
if(!isgemsc10)
|
|
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 << " -subsystem:windows";
|
|
else
|
|
link << " -subsystem:console";
|
|
if(!IsMsc64())
|
|
link << ",5.01"; //,5.01 needed to support WindowsXP
|
|
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++)
|
|
lib << ' ' << GetPathQ(AppendExt(linkfile[i], ".lib"));
|
|
PutConsole("Linking...");
|
|
bool error = false;
|
|
|
|
String tmpFileName;
|
|
if(link.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();
|
|
link << "@" << tmpFileName;
|
|
}
|
|
else
|
|
link << lib;
|
|
|
|
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 << GetPathQ(target) << ".manifest -outputresource:" << GetPathQ(target)
|
|
<< (HasFlag("DLL") ? ";2" : ";1");
|
|
Execute(mt);
|
|
}
|
|
PutConsole(String().Cat() << target << " (" << GetFileInfo(target).length
|
|
<< " B) linked in " << GetPrintTime(time));
|
|
}
|
|
else {
|
|
DeleteFile(target);
|
|
error = true;
|
|
}
|
|
if(tmpFileName != "")
|
|
FileDelete(tmpFileName);
|
|
return !error;
|
|
}
|
|
PutConsole(String().Cat() << 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;
|
|
}
|
|
|
|
INITIALIZER(MscBuilder)
|
|
{
|
|
RegisterBuilder("MSC71", CreateMscBuilder);
|
|
RegisterBuilder("MSC8", CreateMscBuilder);
|
|
RegisterBuilder("MSC8X64", CreateMscBuilder);
|
|
RegisterBuilder("MSC8ARM", CreateMscBuilder);
|
|
RegisterBuilder("MSC9", CreateMscBuilder);
|
|
RegisterBuilder("MSC9X64", CreateMscBuilder);
|
|
RegisterBuilder("MSC9ARM", CreateMscBuilder);
|
|
RegisterBuilder("MSC10", CreateMscBuilder);
|
|
RegisterBuilder("MSC10X64", CreateMscBuilder);
|
|
RegisterBuilder("MSC11", CreateMscBuilder);
|
|
RegisterBuilder("MSC11X64", CreateMscBuilder);
|
|
RegisterBuilder("MSC12", CreateMscBuilder);
|
|
RegisterBuilder("MSC12X64", CreateMscBuilder);
|
|
RegisterBuilder("MSC14", CreateMscBuilder);
|
|
RegisterBuilder("MSC14X64", CreateMscBuilder);
|
|
RegisterBuilder("MSC15", CreateMscBuilder);
|
|
RegisterBuilder("MSC15X64", CreateMscBuilder);
|
|
RegisterBuilder("MSC17", CreateMscBuilder);
|
|
RegisterBuilder("MSC17X64", CreateMscBuilder);
|
|
RegisterBuilder("MSC19", CreateMscBuilder);
|
|
RegisterBuilder("MSC19X64", CreateMscBuilder);
|
|
RegisterBuilder("MSC22", CreateMscBuilder);
|
|
RegisterBuilder("MSC22X64", CreateMscBuilder);
|
|
RegisterBuilder("EVC_ARM", CreateMscBuilder);
|
|
RegisterBuilder("EVC_MIPS", CreateMscBuilder);
|
|
RegisterBuilder("EVC_SH3", CreateMscBuilder);
|
|
RegisterBuilder("EVC_SH4", CreateMscBuilder);
|
|
RegisterBuilder("INTEL", CreateMscBuilder);
|
|
}
|